[MIRROR] Fixes the body designer [WIP] (#10105)

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-02-08 15:50:15 -07:00
committed by GitHub
parent ad572707e5
commit 116219bee6
46 changed files with 1634 additions and 2380 deletions

View File

@@ -587,3 +587,6 @@ GLOBAL_LIST_INIT(all_volume_channels, list(
#define RESIZE_A_BIGNORMAL (RESIZE_BIG + RESIZE_NORMAL) / 2 #define RESIZE_A_BIGNORMAL (RESIZE_BIG + RESIZE_NORMAL) / 2
#define RESIZE_A_NORMALSMALL (RESIZE_NORMAL + RESIZE_SMALL) / 2 #define RESIZE_A_NORMALSMALL (RESIZE_NORMAL + RESIZE_SMALL) / 2
#define RESIZE_A_SMALLTINY (RESIZE_SMALL + RESIZE_TINY) / 2 #define RESIZE_A_SMALLTINY (RESIZE_SMALL + RESIZE_TINY) / 2
#define WEIGHT_MIN 70
#define WEIGHT_MAX 500

View File

@@ -376,7 +376,8 @@ var/global/list/PDA_Manifest = list()
else else
M.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" M.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]"
M.fields["b_type"] = H.b_type M.fields["b_type"] = H.b_type
M.fields["blood_reagent"] = H.species.blood_reagents M.fields["blood_reagent"] = H.dna.blood_reagents
M.fields["blood_color"] = H.dna.blood_color
M.fields["b_dna"] = H.dna.unique_enzymes M.fields["b_dna"] = H.dna.unique_enzymes
M.fields["id_gender"] = gender2text(H.identifying_gender) M.fields["id_gender"] = gender2text(H.identifying_gender)
if(H.get_FBP_type()) if(H.get_FBP_type())

View File

@@ -257,7 +257,6 @@
H.custom_ask = dna.custom_ask H.custom_ask = dna.custom_ask
H.custom_whisper = dna.custom_whisper H.custom_whisper = dna.custom_whisper
H.custom_exclaim = dna.custom_exclaim H.custom_exclaim = dna.custom_exclaim
H.species.blood_color = dna.blood_color
H.fuzzy = dna.scale_appearance H.fuzzy = dna.scale_appearance
H.offset_override = dna.offset_override H.offset_override = dna.offset_override
H.synth_markings = dna.synth_markings H.synth_markings = dna.synth_markings
@@ -269,10 +268,12 @@
H.custom_heat = dna.custom_heat H.custom_heat = dna.custom_heat
H.custom_cold = dna.custom_cold H.custom_cold = dna.custom_cold
var/datum/species/S = H.species var/datum/species/S = H.species
S.produceCopy(dna.species_traits, H, dna.base_species/*, FALSE*/) // Traitgenes edit - reset_dna flag required, or genes get reset on resleeve S.produceCopy(dna.species_traits, H, dna.base_species, FALSE) // Traitgenes edit - reset_dna flag required, or genes get reset on resleeve
H.dna.blood_reagents = dna.blood_reagents
H.dna.blood_color = dna.blood_color
H.species.blood_reagents = H.dna.blood_reagents
H.species.blood_color = H.dna.blood_color
// VOREStation Edit End // VOREStation Edit End
H.species.blood_reagents = dna.blood_reagents
// CHOMPEnable Start // CHOMPEnable Start
H.species.species_sounds = dna.species_sounds H.species.species_sounds = dna.species_sounds
H.species.gender_specific_species_sounds = dna.gender_specific_species_sounds H.species.gender_specific_species_sounds = dna.gender_specific_species_sounds
@@ -280,9 +281,9 @@
H.species.species_sounds_female = dna.species_sounds_female H.species.species_sounds_female = dna.species_sounds_female
// CHOMPEnable ENd // CHOMPEnable ENd
H.force_update_organs() //VOREStation Add - Gotta do this too H.force_update_organs()
H.force_update_limbs() H.force_update_limbs()
//H.update_body(0) //VOREStation Edit - Done in force_update_limbs already //H.update_body(0) //Done in force_update_limbs already
H.update_eyes() H.update_eyes()
H.update_hair() H.update_hair()

View File

@@ -812,7 +812,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if (isnull(pref.body_markings[M]["color"])) if (isnull(pref.body_markings[M]["color"]))
if (tgui_alert(user, "You currently have customized marking colors. This will reset each bodypart's color. Are you sure you want to continue?","Reset Bodypart Colors",list("Yes","No")) != "Yes") if (tgui_alert(user, "You currently have customized marking colors. This will reset each bodypart's color. Are you sure you want to continue?","Reset Bodypart Colors",list("Yes","No")) != "Yes")
return TOPIC_NOACTION return TOPIC_NOACTION
var/mark_color = tgui_color_picker(user, "Choose the [M] color: ", "Character Preference", pref.body_markings[M]["color"]) var/current = pref.body_markings[M] ? pref.body_markings[M]["color"] : "#000000"
var/mark_color = tgui_color_picker(user, "Choose the [M] color: ", "Character Preference", current)
if(mark_color && CanUseTopic(user)) if(mark_color && CanUseTopic(user))
pref.body_markings[M] = pref.mass_edit_marking_list(M,FALSE,TRUE,pref.body_markings[M],color="[mark_color]") pref.body_markings[M] = pref.mass_edit_marking_list(M,FALSE,TRUE,pref.body_markings[M],color="[mark_color]")
return TOPIC_REFRESH_UPDATE_PREVIEW return TOPIC_REFRESH_UPDATE_PREVIEW

View File

@@ -1,6 +1,4 @@
// Body weight limits on a character. // Body weight limits on a character.
#define WEIGHT_MIN 70
#define WEIGHT_MAX 500
#define WEIGHT_CHANGE_MIN 0 #define WEIGHT_CHANGE_MIN 0
#define WEIGHT_CHANGE_MAX 100 #define WEIGHT_CHANGE_MAX 100
@@ -373,7 +371,5 @@
// CHOMPEdit End // CHOMPEdit End
return ..(); return ..();
#undef WEIGHT_MIN
#undef WEIGHT_MAX
#undef WEIGHT_CHANGE_MIN #undef WEIGHT_CHANGE_MIN
#undef WEIGHT_CHANGE_MAX #undef WEIGHT_CHANGE_MAX

View File

@@ -106,7 +106,6 @@
if(H.dna && reset_dna) if(H.dna && reset_dna)
H.dna.ready_dna(H) H.dna.ready_dna(H)
handle_base_eyes(H, custom_base) handle_base_eyes(H, custom_base)
return new_copy return new_copy

View File

@@ -9,6 +9,7 @@ Includes things like facial spines for unathi
*/ */
/datum/sprite_accessory/facial_hair /datum/sprite_accessory/facial_hair
name = DEVELOPER_WARNING_NAME
icon = 'icons/mob/Human_face.dmi' icon = 'icons/mob/Human_face.dmi'
color_blend_mode = ICON_ADD color_blend_mode = ICON_ADD
em_block = TRUE em_block = TRUE

View File

@@ -28,25 +28,13 @@
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_L_ARM,BP_R_ARM) body_parts = list(BP_L_ARM,BP_R_ARM)
species_allowed = list(SPECIES_AKULA) species_allowed = list(SPECIES_AKULA)
/* //I can't make out what this icon_state was ever supposed to be. There is no 'zan' 'mon' or anything like that in the ch.dmi file...
/datum/sprite_accessory/marking/ch/zangoose_belly /datum/sprite_accessory/marking/ch/zangoose_belly
name = "Mongoose Cat Belly Marking" name = "Mongoose Cat Belly Marking"
icon_state = "test" icon_state = "test"
body_parts = list(BP_TORSO) body_parts = list(BP_TORSO)
species_allowed = list(SPECIES_HUMAN, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE) //This lets all races use the default hairstyles. species_allowed = list(SPECIES_HUMAN, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE) //This lets all races use the default hairstyles.
*/
/datum/sprite_accessory/marking/ch/head_paint_front
name = "Head Paint Front"
icon_state = "paintfront"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_HEAD)
/datum/sprite_accessory/marking/ch/head_paint_back
name = "Head Paint"
icon_state = "paint"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_HEAD)
/datum/sprite_accessory/marking/ch/athena_lights /datum/sprite_accessory/marking/ch/athena_lights
name = "Hephaestus - Athena lights" name = "Hephaestus - Athena lights"
icon_state = "athena" icon_state = "athena"
@@ -119,18 +107,6 @@
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_HEAD) body_parts = list(BP_HEAD)
/datum/sprite_accessory/marking/ch/manedwolf1
name = "Maned Wolf Primary Markings"
icon_state = "manedwolf1"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_HEAD,BP_TORSO,BP_R_ARM,BP_L_ARM,BP_R_HAND,BP_L_HAND,BP_R_LEG,BP_L_LEG,BP_R_FOOT,BP_L_FOOT)
/datum/sprite_accessory/marking/ch/manedwolf2
name = "Maned Wolf Secondary Markings"
icon_state = "manedwolf2"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_HEAD,BP_TORSO,BP_GROIN)
/datum/sprite_accessory/marking/ch/voxbeak2 /datum/sprite_accessory/marking/ch/voxbeak2
name = "Vox Beak (Normal)" name = "Vox Beak (Normal)"
icon_state = "vox_beak" icon_state = "vox_beak"

View File

@@ -7,7 +7,8 @@
*/ */
/datum/sprite_accessory/hair /datum/sprite_accessory/hair
icon = 'icons/mob/Human_face_m.dmi' // default icon for all hairs name = DEVELOPER_WARNING_NAME
icon = 'icons/mob/human_face_m.dmi' // default icon for all hairs
var/icon_add = 'icons/mob/human_face.dmi' var/icon_add = 'icons/mob/human_face.dmi'
var/flags var/flags
@@ -339,6 +340,34 @@
icon_state = "hair_celebcurls" icon_state = "hair_celebcurls"
flags = HAIR_TIEABLE flags = HAIR_TIEABLE
/* CHOMPRemove Start
/datum/sprite_accessory/hair/citheronia
name = "Citheronia Hair (Kira72)"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "citheronia_hair"
ckeys_allowed = list("Kira72")
do_colouration = 0
/datum/sprite_accessory/hair/taramaw
name = "Hairmaw (Liquidfirefly)"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "maw_hair"
ckeys_allowed = list("liquidfirefly")
do_colouration = 0
*/// CHOMPRemove End
/datum/sprite_accessory/hair/twindrillslong
name = "Twin Drills Long"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hair_twincurllong"
/datum/sprite_accessory/hair/crescent_moon
name = "Crescent-Moon"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "crescent_moon"
/datum/sprite_accessory/hair/citheronia_colorable /datum/sprite_accessory/hair/citheronia_colorable
name = "Citheronia" name = "Citheronia"
icon = 'icons/mob/human_face_alt.dmi' icon = 'icons/mob/human_face_alt.dmi'
@@ -1317,6 +1346,12 @@
icon_add = 'icons/mob/human_face_alt_add.dmi' icon_add = 'icons/mob/human_face_alt_add.dmi'
icon_state = "soghun_hood" icon_state = "soghun_hood"
/datum/sprite_accessory/hair/una_quinthorns
name = "Quintiple Unathi Horns"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "unathi_quintiple_horns"
/datum/sprite_accessory/hair/una_doublehorns /datum/sprite_accessory/hair/una_doublehorns
name = "Double Unathi Horns" name = "Double Unathi Horns"
icon = 'icons/mob/human_face_alt.dmi' icon = 'icons/mob/human_face_alt.dmi'
@@ -1450,37 +1485,37 @@
//xeno stuffs //xeno stuffs
/datum/sprite_accessory/hair/xeno_head_drone_color /datum/sprite_accessory/hair/xeno_head_drone_color
name = "Drone dome" name = "Drone dome"
icon = 'icons/mob/human_face_alt.dmi' icon = 'modular_chomp/icons/mob/human_face_ch.dmi' //chompstation edit
icon_add = 'icons/mob/human_face_alt_add.dmi' icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi' //chompstation edit
icon_state = "cxeno_drone" icon_state = "cxeno_drone"
gender = NEUTER gender = NEUTER
// figure this one out for better coloring // figure this one out for better coloring
/datum/sprite_accessory/hair/xeno_head_sentinel_color /datum/sprite_accessory/hair/xeno_head_sentinel_color
name = "Sentinal dome" name = "Sentinal dome"
icon = 'icons/mob/human_face_alt.dmi' icon = 'modular_chomp/icons/mob/human_face_ch.dmi'//chompstation edit
icon_add = 'icons/mob/human_face_alt_add.dmi' icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi'//chompstation edit
icon_state = "cxeno_sentinel" icon_state = "cxeno_sentinel"
gender = NEUTER gender = NEUTER
/datum/sprite_accessory/hair/xeno_head_queen_color /datum/sprite_accessory/hair/xeno_head_queen_color
name = "Queen dome" name = "Queen dome"
icon = 'icons/mob/human_face_alt.dmi' icon = 'modular_chomp/icons/mob/human_face_ch.dmi'//chompstation edit
icon_add = 'icons/mob/human_face_alt_add.dmi' icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi'//chompstation edit
icon_state = "cxeno_queen" icon_state = "cxeno_queen"
gender = NEUTER gender = NEUTER
/datum/sprite_accessory/hair/xeno_head_hunter_color /datum/sprite_accessory/hair/xeno_head_hunter_color
name = "Hunter dome" name = "Hunter dome"
icon = 'icons/mob/human_face_alt.dmi' icon = 'modular_chomp/icons/mob/human_face_ch.dmi'//chompstation edit
icon_add = 'icons/mob/human_face_alt_add.dmi' icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi'//chompstation edit
icon_state = "cxeno_hunter" icon_state = "cxeno_hunter"
gender = NEUTER gender = NEUTER
/datum/sprite_accessory/hair/xeno_head_praetorian_color /datum/sprite_accessory/hair/xeno_head_praetorian_color
name = "Praetorian dome" name = "Praetorian dome"
icon = 'icons/mob/human_face_alt.dmi' icon = 'modular_chomp/icons/mob/human_face_ch.dmi'//chompstation edit
icon_add = 'icons/mob/human_face_alt_add.dmi' icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi'//chompstation edit
icon_state = "cxeno_praetorian" icon_state = "cxeno_praetorian"
gender = NEUTER gender = NEUTER
@@ -1560,6 +1595,7 @@
/datum/sprite_accessory/hair/una/spines_short /datum/sprite_accessory/hair/una/spines_short
name = "Short Unathi Spines" name = "Short Unathi Spines"
icon_state = "soghun_shortspines"
/datum/sprite_accessory/hair/una/frills_long /datum/sprite_accessory/hair/una/frills_long
name = "Long Unathi Frills" name = "Long Unathi Frills"
@@ -1598,7 +1634,6 @@
/datum/sprite_accessory/hair/skr/tentacle_veryshort /datum/sprite_accessory/hair/skr/tentacle_veryshort
name = "Skrell Short Tentacles" name = "Skrell Short Tentacles"
icon_state = "skrell_hair_short" icon_state = "skrell_hair_short"
gender = MALE
/datum/sprite_accessory/hair/skr/tentacle_average /datum/sprite_accessory/hair/skr/tentacle_average
name = "Skrell Long Tentacles" name = "Skrell Long Tentacles"
@@ -1764,10 +1799,12 @@
/datum/sprite_accessory/hair/taj/bob /datum/sprite_accessory/hair/taj/bob
name = "Tajaran Bob" name = "Tajaran Bob"
icon_state = "hair_tbob" icon_state = "hair_tbob"
/datum/sprite_accessory/hair/taj/fingercurl
/datum/sprite_accessory/hair/taj_ears_fingercurl
name = "Tajaran Finger Curls" name = "Tajaran Finger Curls"
icon_state = "hair_fingerwave" icon_state = "hair_fingerwave"
//Teshari things //Teshari things
/datum/sprite_accessory/hair/teshari /datum/sprite_accessory/hair/teshari
name = "Teshari Default" name = "Teshari Default"
@@ -1867,3 +1904,70 @@
/datum/sprite_accessory/hair/vox/quills_mohawk /datum/sprite_accessory/hair/vox/quills_mohawk
name = "Quill Mohawk" name = "Quill Mohawk"
icon_state = "vox_mohawk" icon_state = "vox_mohawk"
/* CHOMPRemve Start
/datum/sprite_accessory/hair/shadekin_hair_rivyr
name = "Rivyr Hair"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "shadekin_rivyr"
ckeys_allowed = list("verysoft")
species_allowed = list(SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW)
gender = NEUTER
*/// CHOMPRemove End
/datum/sprite_accessory/hair/slicker
name = "Slicker"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hair_slicker"
/datum/sprite_accessory/facial_hair
icon = 'icons/mob/human_face_or_vr.dmi'
color_blend_mode = ICON_MULTIPLY
/datum/sprite_accessory/facial_hair/vulp_ruff
name = "Ruff"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_ruff"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_kita
name = "Kita"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_kita"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_swift
name = "Swift"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_swift"
gender = NEUTER
/*
////////////////////////////
/ =--------------------= /
/ == Misc Definitions == /
/ =--------------------= /
////////////////////////////
*/
// Yes, I have to add all of this just to make some glowy hair.
// No, this isn't a character creation option, but... I guess in the future it could be, if anyone wants that?
/datum/sprite_accessory/hair_accessory
name = DEVELOPER_WARNING_NAME
icon = 'icons/mob/vore/hair_accessories_vr.dmi'
do_colouration = 0 // Set to 1 to blend (ICON_ADD) hair color
var/ignores_lighting = 0 // Whether or not this hair accessory will ignore lighting and glow in the dark.
color_blend_mode = ICON_ADD // Only appliciable if do_coloration = 1
var/desc = DEVELOPER_WARNING_NAME
/datum/sprite_accessory/hair_accessory/verie_hair_glow
name = "veries hair glow"
desc = ""
icon_state = "verie_hair_glow"
ignores_lighting = 1
//ckeys_allowed = list("vitoras") // This probably won't come into play EVER but better safe than sorry

View File

@@ -1,514 +0,0 @@
////////////////////////
// For sergals and stuff
////////////////////////
// Note: Creating a sub-datum to group all vore stuff together
// would require us to exclude that datum from the global list.
/datum/sprite_accessory/hair/astolfo
name = "Astolfo"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hair_astolfo"
/* //Chomp REMOVE - No ckeys_allowed allowed
/datum/sprite_accessory/hair/awoohair
name = "Shoulder-length Messy"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "momijihair"
/datum/sprite_accessory/hair/citheronia
name = "Citheronia Hair (Kira72)"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "citheronia_hair"
ckeys_allowed = list("Kira72")
do_colouration = 0
/datum/sprite_accessory/hair/taramaw
name = "Hairmaw (Liquidfirefly)"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "maw_hair"
ckeys_allowed = list("liquidfirefly")
do_colouration = 0
*/ //Chomp REMOVE END
/datum/sprite_accessory/hair/citheronia_colorable
name = "Citheronia Hair"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "citheronia_hair_c"
do_colouration = 1
/datum/sprite_accessory/hair/sergal_plain
name = "Sergal Plain"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "serg_plain"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //CHOMPEdit
/datum/sprite_accessory/hair/sergal_medicore
name = "Sergal Medicore"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "serg_medicore"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //CHOMPEdit
/datum/sprite_accessory/hair/sergal_tapered
name = "Sergal Tapered"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "serg_tapered"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //CHOMPEdit
/datum/sprite_accessory/hair/sergal_fairytail
name = "Sergal Fairytail"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "serg_fairytail"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //CHOMPEdit
/datum/sprite_accessory/hair/braid
name = "Floorlength Braid"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hair_braid"
/datum/sprite_accessory/hair/twindrills
name = "Twin Drills"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hair_twincurl"
/datum/sprite_accessory/hair/twindrillslong
name = "Twin Drills Long"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hair_twincurllong"
/datum/sprite_accessory/hair/crescent_moon
name = "Crescent-Moon"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "crescent_moon"
/datum/sprite_accessory/hair/bald
name = "Bald"
icon_state = "bald"
gender = MALE
/datum/sprite_accessory/hair/ponytail6_fixed
name = "Ponytail 6 but fixed"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hair_ponytail6"
/datum/sprite_accessory/hair/una_hood
name = "Cobra Hood"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "soghun_hood"
/datum/sprite_accessory/hair/una_spines_long
name = "Long Unathi Spines"
icon_state = "soghun_longspines"
/datum/sprite_accessory/hair/una_spines_short
name = "Short Unathi Spines"
icon_state = "soghun_shortspines"
/datum/sprite_accessory/hair/una_frills_long
name = "Long Unathi Frills"
icon_state = "soghun_longfrills"
/datum/sprite_accessory/hair/una_frills_short
name = "Short Unathi Frills"
icon_state = "soghun_shortfrills"
/datum/sprite_accessory/hair/una_horns
name = "Unathi Horns"
icon_state = "soghun_horns"
/datum/sprite_accessory/hair/una_bighorns
name = "Unathi Big Horns"
icon_state = "unathi_bighorn"
/datum/sprite_accessory/hair/una_smallhorns
name = "Unathi Small Horns"
icon_state = "unathi_smallhorn"
/datum/sprite_accessory/hair/una_ramhorns
name = "Unathi Ram Horns"
icon_state = "unathi_ramhorn"
/datum/sprite_accessory/hair/una_sidefrills
name = "Unathi Side Frills"
icon_state = "unathi_sidefrills"
/datum/sprite_accessory/hair/una_doublehorns
name = "Double Unathi Horns"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "soghun_dubhorns"
/datum/sprite_accessory/hair/una_quinthorns
name = "Quintiple Unathi Horns"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "unathi_quintiple_horns"
/datum/sprite_accessory/hair/taj_ears
name = "Tajaran Ears"
icon_state = "ears_plain"
/datum/sprite_accessory/hair/taj_ears_clean
name = "Tajara Clean"
icon_state = "hair_clean"
/datum/sprite_accessory/hair/taj_ears_bangs
name = "Tajara Bangs"
icon_state = "hair_bangs"
/datum/sprite_accessory/hair/taj_ears_braid
name = "Tajara Braid"
icon_state = "hair_tbraid"
/datum/sprite_accessory/hair/taj_ears_shaggy
name = "Tajara Shaggy"
icon_state = "hair_shaggy"
/datum/sprite_accessory/hair/taj_ears_mohawk
name = "Tajaran Mohawk"
icon_state = "hair_mohawk"
/datum/sprite_accessory/hair/taj_ears_plait
name = "Tajara Plait"
icon_state = "hair_plait"
/datum/sprite_accessory/hair/taj_ears_straight
name = "Tajara Straight"
icon_state = "hair_straight"
/datum/sprite_accessory/hair/taj_ears_long
name = "Tajara Long"
icon_state = "hair_long"
/datum/sprite_accessory/hair/taj_ears_rattail
name = "Tajara Rat Tail"
icon_state = "hair_rattail"
/datum/sprite_accessory/hair/taj_ears_spiky
name = "Tajara Spiky"
icon_state = "hair_tajspiky"
/datum/sprite_accessory/hair/taj_ears_messy
name = "Tajara Messy"
icon_state = "hair_messy"
/datum/sprite_accessory/hair/taj_ears_curls
name = "Tajaran Curly"
icon_state = "hair_curly"
/datum/sprite_accessory/hair/taj_ears_wife
name = "Tajaran Housewife"
icon_state = "hair_wife"
/datum/sprite_accessory/hair/taj_ears_victory
name = "Tajaran Victory Curls"
icon_state = "hair_victory"
/datum/sprite_accessory/hair/taj_ears_bob
name = "Tajaran Bob"
icon_state = "hair_tbob"
/datum/sprite_accessory/hair/taj_ears_fingercurl
name = "Tajaran Finger Curls"
icon_state = "hair_fingerwave"
//Skrell 'hairstyles' - these were requested for a chimera and screw it, if one wants to eat seafood, go nuts
/datum/sprite_accessory/hair/skr_tentacle_veryshort
name = "Skrell Very Short Tentacles"
icon_state = "skrell_hair_veryshort"
/datum/sprite_accessory/hair/skr_tentacle_short
name = "Skrell Short Tentacles"
icon_state = "skrell_hair_short"
/datum/sprite_accessory/hair/skr_tentacle_average
name = "Skrell Average Tentacles"
icon_state = "skrell_hair_average"
/datum/sprite_accessory/hair/skr_tentacle_verylong
name = "Skrell Long Tentacles"
icon_state = "skrell_hair_verylong"
// Vulpa stuffs
/datum/sprite_accessory/hair/vulp_hair_kajam
name = "Kajam"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "kajam"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_keid
name = "Keid"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "keid"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_adhara
name = "Adhara"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "adhara"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_kleeia
name = "Kleeia"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "kleeia"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_mizar
name = "Mizar"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "mizar"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_apollo
name = "Apollo"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "apollo"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_belle
name = "Belle"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "belle"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_bun
name = "Vulp Bun"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "bun"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_jagged
name = "Jagged"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "jagged"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_curl
name = "Curl"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "curl"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_hawk
name = "Hawk"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hawk"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_anita
name = "Anita"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "anita"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_short
name = "Short"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "short"
gender = NEUTER
/datum/sprite_accessory/hair/vulp_hair_spike
name = "Spike"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "spike"
gender = NEUTER
//xeno stuffs
/datum/sprite_accessory/hair/xeno_head_drone_color
name = "Drone dome"
icon = 'modular_chomp/icons/mob/human_face_ch.dmi' //chompstation edit
icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi' //chompstation edit
icon_state = "cxeno_drone"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //ChompEDIT: allow for all
gender = NEUTER
// figure this one out for better coloring
/datum/sprite_accessory/hair/xeno_head_sentinel_color
name = "Sentinal dome"
icon = 'modular_chomp/icons/mob/human_face_ch.dmi'//chompstation edit
icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi'//chompstation edit
icon_state = "cxeno_sentinel"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //ChompEDIT: allow for all
gender = NEUTER
/datum/sprite_accessory/hair/xeno_head_queen_color
name = "Queen dome"
icon = 'modular_chomp/icons/mob/human_face_ch.dmi'//chompstation edit
icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi'//chompstation edit
icon_state = "cxeno_queen"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //ChompEDIT: allow for all
gender = NEUTER
/datum/sprite_accessory/hair/xeno_head_hunter_color
name = "Hunter dome"
icon = 'modular_chomp/icons/mob/human_face_ch.dmi'//chompstation edit
icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi'//chompstation edit
icon_state = "cxeno_hunter"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //ChompEDIT: allow for all
gender = NEUTER
/datum/sprite_accessory/hair/xeno_head_praetorian_color
name = "Praetorian dome"
icon = 'modular_chomp/icons/mob/human_face_ch.dmi'//chompstation edit
icon_add = 'modular_chomp/icons/mob/human_face_ch_add.dmi'//chompstation edit
icon_state = "cxeno_praetorian"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //ChompEDIT: allow for all
gender = NEUTER
// Shadekin stuffs
/datum/sprite_accessory/hair/shadekin_hair_short
name = "Shadekin Short Hair"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "shadekin_short"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //ChompEDIT: allow for all
gender = NEUTER
/datum/sprite_accessory/hair/shadekin_hair_poofy
name = "Shadekin Poofy Hair"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "shadekin_poofy"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //ChompEDIT: allow for all
gender = NEUTER
/datum/sprite_accessory/hair/shadekin_hair_long
name = "Shadekin Long Hair"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "shadekin_long"
species_allowed = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_TESHARI, SPECIES_NEVREAN, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_FENNEC, SPECIES_ZORREN_HIGH, SPECIES_VULPKANIN, SPECIES_XENOCHIMERA, SPECIES_XENOHYBRID, SPECIES_VASILISSAN, SPECIES_RAPALA, SPECIES_PROTEAN, SPECIES_ALRAUNE, SPECIES_WEREBEAST, SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW, SPECIES_SHADEKIN_YW, SPECIES_ALTEVIAN) //ChompEDIT: allow for all
gender = NEUTER
/* /datum/sprite_accessory/hair/shadekin_hair_rivyr //Chomp REMOVE START
name = "Rivyr Hair"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "shadekin_rivyr"
ckeys_allowed = list("verysoft")
species_allowed = list(SPECIES_SHADEKIN, SPECIES_SHADEKIN_CREW)
gender = NEUTER */ //Chomp REMOVE END
/datum/sprite_accessory/hair/slicker
name = "Slicker"
icon = 'icons/mob/human_face_vr.dmi'
icon_add = 'icons/mob/human_face_vr_add.dmi'
icon_state = "hair_slicker"
/datum/sprite_accessory/facial_hair
icon = 'icons/mob/human_face_or_vr.dmi'
color_blend_mode = ICON_MULTIPLY
/datum/sprite_accessory/facial_hair/shaved
name = "Shaved"
icon_state = "bald"
gender = NEUTER
/datum/sprite_accessory/facial_hair/neck_fluff
name = "Neck Fluff"
icon = 'icons/mob/human_face_or_vr.dmi'
icon_state = "facial_neckfluff"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_blaze
name = "Blaze"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_blaze"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_vulpine
name = "Vulpine"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_vulpine"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_earfluff
name = "Earfluff"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_earfluff"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_mask
name = "Mask"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_mask"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_patch
name = "Patch"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_patch"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_ruff
name = "Ruff"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_ruff"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_kita
name = "Kita"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_kita"
gender = NEUTER
/datum/sprite_accessory/facial_hair/vulp_swift
name = "Swift"
icon = 'icons/mob/human_face_vr.dmi'
icon_state = "vulp_facial_swift"
gender = NEUTER
/*
////////////////////////////
/ =--------------------= /
/ == Misc Definitions == /
/ =--------------------= /
////////////////////////////
*/
// Yes, I have to add all of this just to make some glowy hair.
// No, this isn't a character creation option, but... I guess in the future it could be, if anyone wants that?
/datum/sprite_accessory/hair_accessory
name = DEVELOPER_WARNING_NAME
icon = 'icons/mob/vore/hair_accessories_vr.dmi'
do_colouration = 0 // Set to 1 to blend (ICON_ADD) hair color
var/ignores_lighting = 0 // Whether or not this hair accessory will ignore lighting and glow in the dark.
color_blend_mode = ICON_ADD // Only appliciable if do_coloration = 1
var/desc = DEVELOPER_WARNING_NAME
/* //Chomp REMOVE - No ckeys_allowed allowed
/datum/sprite_accessory/hair_accessory/verie_hair_glow
name = "veries hair glow"
desc = ""
icon_state = "verie_hair_glow"
ignores_lighting = 1
//ckeys_allowed = list("vitoras") // This probably won't come into play EVER but better safe than sorry
*/ //Chomp REMOVE END

View File

@@ -8,6 +8,7 @@
includes scars and tattoos includes scars and tattoos
*/ */
/datum/sprite_accessory/marking /datum/sprite_accessory/marking
name = DEVELOPER_WARNING_NAME
icon = 'icons/mob/human_races/markings.dmi' icon = 'icons/mob/human_races/markings.dmi'
do_colouration = 1 //Almost all of them have it, COLOR_ADD do_colouration = 1 //Almost all of them have it, COLOR_ADD
@@ -203,7 +204,7 @@ includes scars and tattoos
body_parts = list(BP_HEAD) body_parts = list(BP_HEAD)
/datum/sprite_accessory/marking/bandsface_human /datum/sprite_accessory/marking/bandsface_human
name = "Color Bands (Face)" name = "Color Bands (Face) (Human)"
icon_state = "bandshumanface" icon_state = "bandshumanface"
body_parts = list(BP_HEAD) body_parts = list(BP_HEAD)
@@ -859,7 +860,7 @@ includes scars and tattoos
/datum/sprite_accessory/marking/diona_leaves /datum/sprite_accessory/marking/diona_leaves
name = "Leaves (Diona)" name = "Leaves (Diona)"
icon_state = "diona_leaves" icon_state = "diona_leaves"
body_parts = list(BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_TORSO, BP_GROIN, BP_HEAD) body_parts = list(BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM, BP_TORSO, BP_GROIN, BP_HEAD)
/datum/sprite_accessory/marking/diona_thorns /datum/sprite_accessory/marking/diona_thorns
name = "Thorns (Diona)" name = "Thorns (Diona)"
@@ -991,10 +992,14 @@ includes scars and tattoos
/datum/sprite_accessory/marking/aug/backside_left /datum/sprite_accessory/marking/aug/backside_left
name = "Augment (Backside Left, Head)" name = "Augment (Backside Left, Head)"
icon_state = "aug_backside_l" icon_state = "aug_backside_l"
body_parts = list(BP_HEAD)
/datum/sprite_accessory/marking/aug/backside_left/side_diode /datum/sprite_accessory/marking/aug/backside_left/side_diode
name = "Augment (Backside Left Diode, Head)" name = "Augment (Backside Left Diode, Head)"
icon_state = "aug_sidediode_l" icon_state = "aug_sidediode_l"
body_parts = list(BP_HEAD)
/datum/sprite_accessory/marking/aug/backside_right /datum/sprite_accessory/marking/aug/backside_right
name = "Augment (Backside Right, Head)" name = "Augment (Backside Right, Head)"
@@ -1127,7 +1132,7 @@ includes scars and tattoos
/datum/sprite_accessory/marking/bandage/torso/torso3 /datum/sprite_accessory/marking/bandage/torso/torso3
name = "Bandage, Torso 3" name = "Bandage, Torso 3"
icon_state = "bandage3" icon_state = "bandage3" //someone needs to make a proper torso sprite
/datum/sprite_accessory/marking/bandage/torso/torso3/teshari /datum/sprite_accessory/marking/bandage/torso/torso3/teshari
name = "Bandage, Torso 3 (Teshari)" name = "Bandage, Torso 3 (Teshari)"
@@ -1200,7 +1205,7 @@ includes scars and tattoos
icon_state = "bandage1_tesh" icon_state = "bandage1_tesh"
species_allowed = list(SPECIES_TESHARI) species_allowed = list(SPECIES_TESHARI)
/datum/sprite_accessory/marking/bandage/l_hand/l_hand2 /datum/sprite_accessory/marking/bandage/l_hand/l_hand_2
name = "Bandage, Left Hand 2" name = "Bandage, Left Hand 2"
icon_state = "bandage2" icon_state = "bandage2"
@@ -1302,7 +1307,7 @@ includes scars and tattoos
icon_state = "bandage1_tesh" icon_state = "bandage1_tesh"
species_allowed = list(SPECIES_TESHARI) species_allowed = list(SPECIES_TESHARI)
/datum/sprite_accessory/marking/bandage/l_foot/l_foot2 /datum/sprite_accessory/marking/bandage/l_foot/l_foot_2
name = "Bandage, Left Foot 2" name = "Bandage, Left Foot 2"
icon_state = "bandage2" icon_state = "bandage2"
@@ -1311,7 +1316,7 @@ includes scars and tattoos
icon_state = "bandage2_tesh" icon_state = "bandage2_tesh"
species_allowed = list(SPECIES_TESHARI) species_allowed = list(SPECIES_TESHARI)
/datum/sprite_accessory/marking/bandage/l_foot/l_foot3 /datum/sprite_accessory/marking/bandage/l_foot/l_foot_3
name = "Bandage, Left Foot 3" name = "Bandage, Left Foot 3"
icon_state = "bandage3" icon_state = "bandage3"
@@ -2064,7 +2069,7 @@ includes scars and tattoos
name = "Wrist Fluff" name = "Wrist Fluff"
icon_state = "fluffy_cuffs" icon_state = "fluffy_cuffs"
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND) body_parts = list(BP_L_ARM,BP_R_ARM)
/datum/sprite_accessory/marking/vr_chubby_belly /datum/sprite_accessory/marking/vr_chubby_belly
name = "Chubby Belly" name = "Chubby Belly"
@@ -2497,6 +2502,9 @@ includes scars and tattoos
//Replikant-specific markings //Replikant-specific markings
/datum/sprite_accessory/marking/replikant
name = DEVELOPER_WARNING_NAME
/datum/sprite_accessory/marking/replikant/replika_r_thigh /datum/sprite_accessory/marking/replikant/replika_r_thigh
name = "Replikant Stripe - Right Thigh" name = "Replikant Stripe - Right Thigh"
icon_state = "replika" icon_state = "replika"
@@ -2523,7 +2531,7 @@ includes scars and tattoos
/datum/sprite_accessory/marking/replikant/replika_panels_body /datum/sprite_accessory/marking/replikant/replika_panels_body
name = "Replikant Paneling - SynthFlesh (body)" name = "Replikant Paneling - SynthFlesh (body)"
icon_state = "replikao" icon_state = "replika"
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_TORSO) body_parts = list(BP_TORSO)
@@ -2535,7 +2543,7 @@ includes scars and tattoos
//Digitigrade markings //Digitigrade markings
/datum/sprite_accessory/marking/digi /datum/sprite_accessory/marking/digi
name = "Digitigrate Marking Subcat, Please Ignore" name = DEVELOPER_WARNING_NAME
icon = 'icons/mob/human_races/markings_digi.dmi' icon = 'icons/mob/human_races/markings_digi.dmi'
digitigrade_acceptance = MARKING_DIGITIGRADE_ONLY digitigrade_acceptance = MARKING_DIGITIGRADE_ONLY

View File

@@ -606,7 +606,7 @@
extra_overlay = "teshpattern_fem_tail" extra_overlay = "teshpattern_fem_tail"
/datum/sprite_accessory/tail/tesh_pattern_fem_alt /datum/sprite_accessory/tail/tesh_pattern_fem_alt
name = "Teshari male tail alt. pattern" name = "Teshari fem tail alt. pattern"
desc = "" desc = ""
icon_state = "teshtail_s" icon_state = "teshtail_s"
do_colouration = 1 do_colouration = 1
@@ -622,7 +622,7 @@
//For all species tails. Includes haircolored tails. //For all species tails. Includes haircolored tails.
/datum/sprite_accessory/tail/special /datum/sprite_accessory/tail/special
name = "Blank tail. Do not select." name = DEVELOPER_WARNING_NAME
icon = 'icons/effects/species_tails.dmi' icon = 'icons/effects/species_tails.dmi'
/datum/sprite_accessory/tail/special/unathi /datum/sprite_accessory/tail/special/unathi

View File

@@ -1312,7 +1312,9 @@
icon_loaf = 'icons/mob/vore/taurs_loaf.dmi' //This file needs to be nuked during the removal of 'taurs_ch_loaf.dmi' into the normal loaf file. icon_loaf = 'icons/mob/vore/taurs_loaf.dmi' //This file needs to be nuked during the removal of 'taurs_ch_loaf.dmi' into the normal loaf file.
loaf_offset = 5 loaf_offset = 5
/datum/sprite_accessory/tail/taur/lizard/fat/spotty
/datum/sprite_accessory/tail/taur/lizard/spotty_fat
name = "Fat Spotted Lizard (Taur, Tricolor)" name = "Fat Spotted Lizard (Taur, Tricolor)"
icon_state = "fatspottedlizard_s" icon_state = "fatspottedlizard_s"
extra_overlay = "fatspottedlizard_markings" extra_overlay = "fatspottedlizard_markings"

View File

@@ -58,23 +58,3 @@
icon_state = "preg_tummy_teshari" icon_state = "preg_tummy_teshari"
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_TORSO,BP_GROIN,BP_L_HAND,BP_R_HAND,BP_L_LEG,BP_R_LEG) body_parts = list(BP_TORSO,BP_GROIN,BP_L_HAND,BP_R_HAND,BP_L_LEG,BP_R_LEG)
/datum/sprite_accessory/marking/yw/teshari_pattern_female
name = "Teshari female pattern"
icon_state = "tesh-pattern-fem"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN,BP_HEAD)
/datum/sprite_accessory/marking/yw/teshari_pattern_male
name = "Teshari male pattern"
icon_state = "tesh-pattern-male"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN,BP_HEAD)
/datum/sprite_accessory/marking/yw/teshari_large_eyes
name = "Teshari large eyes"
icon_state = "teshlarge_eyes"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_HEAD)
/datum/sprite_accessory/marking/yw/teshari_coat
name = "Teshari coat"
icon_state = "tesh_coat"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_TORSO,BP_HEAD)

View File

@@ -1,6 +1,4 @@
// Little define makes it cleaner to read the tripple color values out of mobs. // Little define makes it cleaner to read the tripple color values out of mobs.
#define MOB_HEX_COLOR(M, V) "#[num2hex(M.r_##V, 2)][num2hex(M.g_##V, 2)][num2hex(M.b_##V, 2)]"
#define MENU_MAIN "Main" #define MENU_MAIN "Main"
#define MENU_BODYRECORDS "Body Records" #define MENU_BODYRECORDS "Body Records"
#define MENU_STOCKRECORDS "Stock Records" #define MENU_STOCKRECORDS "Stock Records"
@@ -16,18 +14,9 @@
light_color = "#315ab4" light_color = "#315ab4"
circuit = /obj/item/circuitboard/body_designer circuit = /obj/item/circuitboard/body_designer
req_access = list(access_medical) // Used for loading people's designs req_access = list(access_medical) // Used for loading people's designs
var/temp = "" var/datum/tgui_module/appearance_changer/body_designer/designer_gui
var/menu = MENU_MAIN //Which menu screen to display
var/datum/transhuman/body_record/active_br = null
//Mob preview
var/map_name
var/obj/screen/south_preview = null
var/obj/screen/east_preview = null
var/obj/screen/west_preview = null
var/obj/screen/north_preview = null
// Mannequins are somewhat expensive to create, so cache it
var/mob/living/carbon/human/dummy/mannequin/mannequin = null
var/obj/item/disk/body_record/disk = null var/obj/item/disk/body_record/disk = null
var/selected_record = FALSE
// Resleeving database this machine interacts with. Blank for default database // Resleeving database this machine interacts with. Blank for default database
// Needs a matching /datum/transcore_db with key defined in code // Needs a matching /datum/transcore_db with key defined in code
@@ -36,45 +25,19 @@
/obj/machinery/computer/transhuman/designer/Initialize() /obj/machinery/computer/transhuman/designer/Initialize()
. = ..() . = ..()
map_name = "transhuman_designer_[REF(src)]_map"
south_preview = new
south_preview.name = ""
south_preview.assigned_map = map_name
south_preview.del_on_map_removal = FALSE
south_preview.screen_loc = "[map_name]:2,1"
east_preview = new
east_preview.name = ""
east_preview.assigned_map = map_name
east_preview.del_on_map_removal = FALSE
east_preview.screen_loc = "[map_name]:4,1"
west_preview = new
west_preview.name = ""
west_preview.assigned_map = map_name
west_preview.del_on_map_removal = FALSE
west_preview.screen_loc = "[map_name]:0,1"
north_preview = new
north_preview.name = ""
north_preview.assigned_map = map_name
north_preview.del_on_map_removal = FALSE
north_preview.screen_loc = "[map_name]:6,1"
our_db = SStranscore.db_by_key(db_key) our_db = SStranscore.db_by_key(db_key)
/obj/machinery/computer/transhuman/designer/Destroy() /obj/machinery/computer/transhuman/designer/Destroy()
active_br = null if(disk)
mannequin = null disk.forceMove(get_turf(src))
disk = null disk = null
return ..() . = ..()
/obj/machinery/computer/transhuman/designer/dismantle() /obj/machinery/computer/transhuman/designer/dismantle()
if(disk) if(disk)
disk.forceMove(get_turf(src)) disk.forceMove(get_turf(src))
disk = null disk = null
..() . = ..()
/obj/machinery/computer/transhuman/designer/attackby(obj/item/W as obj, mob/user as mob) /obj/machinery/computer/transhuman/designer/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/disk/body_record)) if(istype(W, /obj/item/disk/body_record))
@@ -82,482 +45,24 @@
disk = W disk = W
disk.forceMove(src) disk.forceMove(src)
to_chat(user, span_notice("You insert \the [W] into \the [src].")) to_chat(user, span_notice("You insert \the [W] into \the [src]."))
updateUsrDialog() SStgui.update_uis(src)
else else
..() . = ..()
return
/obj/machinery/computer/transhuman/designer/attack_ai(mob/user as mob) /obj/machinery/computer/transhuman/designer/attack_ai(mob/user as mob)
return attack_hand(user) attack_hand(user)
/obj/machinery/computer/transhuman/designer/attack_hand(mob/user as mob) /obj/machinery/computer/transhuman/designer/attack_hand(mob/user as mob)
add_fingerprint(user) add_fingerprint(user)
if(inoperable()) if(inoperable())
return return
tgui_interact(user) if(!designer_gui)
designer_gui = new(src, null)
/obj/machinery/computer/transhuman/designer/tgui_interact(mob/user, datum/tgui/ui) designer_gui.linked_body_design_console = WEAKREF(src)
ui = SStgui.try_update_ui(user, src, ui) if(!designer_gui.owner)
if(!ui) designer_gui.make_fake_owner()
give_client_previews(user.client) selected_record = FALSE
ui = new(user, src, "BodyDesigner", name) designer_gui.tgui_interact(user)
ui.open()
/obj/machinery/computer/transhuman/designer/tgui_static_data(mob/user)
var/list/data = ..()
data["mapRef"] = map_name
return data
/obj/machinery/computer/transhuman/designer/tgui_data(mob/user)
var/list/data = list()
if(menu == MENU_BODYRECORDS)
var/bodyrecords_list_ui[0]
for(var/N in our_db.body_scans)
var/datum/transhuman/body_record/BR = our_db.body_scans[N]
bodyrecords_list_ui[++bodyrecords_list_ui.len] = list("name" = N, "recref" = "\ref[BR]")
if(bodyrecords_list_ui.len)
data["bodyrecords"] = bodyrecords_list_ui
if(menu == MENU_STOCKRECORDS)
var/stock_bodyrecords_list_ui[0]
for (var/N in GLOB.all_species)
var/datum/species/S = GLOB.all_species[N]
if((S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) != SPECIES_CAN_JOIN) continue
stock_bodyrecords_list_ui += N
if(stock_bodyrecords_list_ui.len)
data["stock_bodyrecords"] = stock_bodyrecords_list_ui
if(active_br)
data["activeBodyRecord"] = list(
"real_name" = active_br.mydna.name,
"speciesname" = active_br.speciesname ? active_br.speciesname : active_br.mydna.dna.species,
"blood_type" = active_br.mydna.dna.b_type,
"blood_color" = active_br.mydna.dna.blood_color,
"blood_reagents" = active_br.mydna.dna.blood_reagents,
"weight" = !isnull(active_br.weight) ? active_br.weight : 137, // 137 id default in code\modules\client\preference_setup\vore\02_size.dm
"flavors" = list(),
"scale_appearance" = active_br.mydna.dna.scale_appearance ? "Fuzzy" : "Sharp",
"offset_override" = active_br.mydna.dna.offset_override ? "Odd" : "Even",
"species_sound" = active_br.mydna.dna.species_sounds,
"gender" = active_br.bodygender,
"synthetic" = active_br.synthetic ? "Yes" : "No",
"locked" = active_br.locked,
"scale" = player_size_name(active_br.sizemult),
"booc" = active_br.body_oocnotes,
"styles" = list()
)
var/list/flavors = data["activeBodyRecord"]["flavors"]
flavors += active_br.mydna.flavor.Copy()
var/list/styles = data["activeBodyRecord"]["styles"]
var/list/temp
if (mannequin.species && mannequin.species.selects_bodytype)
if (!mannequin.species.base_species)
mannequin.species.base_species = mannequin.species.name
styles["Bodytype"] = list("styleHref" = "custom_base", "style" = mannequin.species.base_species)
temp = list("styleHref" = "ear_style", "style" = "Normal")
if(mannequin.ear_style)
temp["style"] = mannequin.ear_style.name
if(mannequin.ear_style.do_colouration)
temp["color"] = MOB_HEX_COLOR(mannequin, ears)
temp["colorHref"] = "ear_color"
if(mannequin.ear_style.extra_overlay)
temp["color2"] = MOB_HEX_COLOR(mannequin, ears2)
temp["colorHref2"] = "ear_color2"
if(mannequin.ear_style.extra_overlay2)
temp["color3"] = MOB_HEX_COLOR(mannequin, ears3)
temp["colorHref3"] = "ear_color3"
styles["Ears"] = temp
temp = list("styleHref" = "ear_style", "style" = "Normal")
if(mannequin.ear_secondary_style)
temp["style"] = mannequin.ear_secondary_style.name
if(length(mannequin.ear_secondary_colors) >= 1)
temp["color"] = mannequin.ear_secondary_colors[1]
temp["colorHref"] = list("act" = "ear_secondary_color", "channel" = 1)
if(length(mannequin.ear_secondary_colors) >= 2)
temp["color"] = mannequin.ear_secondary_colors[2]
temp["colorHref"] = list("act" = "ear_secondary_color", "channel" = 2)
styles["Horns"] = temp
temp = list("styleHref" = "tail_style", "style" = "Normal")
if(mannequin.tail_style)
temp["style"] = mannequin.tail_style.name
if(mannequin.tail_style.do_colouration)
temp["color"] = MOB_HEX_COLOR(mannequin, tail)
temp["colorHref"] = "tail_color"
if(mannequin.tail_style.extra_overlay)
temp["color2"] = MOB_HEX_COLOR(mannequin, tail2)
temp["colorHref2"] = "tail_color2"
if(mannequin.tail_style.extra_overlay2)
temp["color3"] = MOB_HEX_COLOR(mannequin, tail3)
temp["colorHref3"] = "tail_color3"
styles["Tail"] = temp
temp = list("styleHref" = "wing_style", "style" = "Normal")
if(mannequin.wing_style)
temp["style"] = mannequin.wing_style.name
if(mannequin.wing_style.do_colouration)
temp["color"] = MOB_HEX_COLOR(mannequin, wing)
temp["colorHref"] = "wing_color"
if(mannequin.wing_style.extra_overlay)
temp["color2"] = MOB_HEX_COLOR(mannequin, wing2)
temp["colorHref2"] = "wing_color2"
if(mannequin.wing_style.extra_overlay2)
temp["color3"] = MOB_HEX_COLOR(mannequin, wing3)
temp["colorHref3"] = "wing_color3"
styles["Wing"] = temp
temp = list("styleHref" = "hair_style", "style" = mannequin.h_style)
if(mannequin.species && (mannequin.species.appearance_flags & HAS_HAIR_COLOR))
temp["color"] = MOB_HEX_COLOR(mannequin, hair)
temp["colorHref"] = "hair_color"
styles["Hair"] = temp
temp = list("styleHref" = "facial_style", "style" = mannequin.f_style)
if(mannequin.species && (mannequin.species.appearance_flags & HAS_HAIR_COLOR))
temp["color"] = MOB_HEX_COLOR(mannequin, facial)
temp["colorHref"] = "facial_color"
styles["Facial"] = temp
if(mannequin.species && (mannequin.species.appearance_flags & HAS_EYE_COLOR))
styles["Eyes"] = list("colorHref" = "eye_color", "color" = MOB_HEX_COLOR(mannequin, eyes))
if(mannequin.species && (mannequin.species.appearance_flags & HAS_SKIN_COLOR))
styles["Body Color"] = list("colorHref" = "skin_color", "color" = MOB_HEX_COLOR(mannequin, skin))
var/datum/preferences/designer/P = new()
apply_markings_to_prefs(mannequin, P)
data["activeBodyRecord"]["markings"] = P.body_markings
data["activeBodyRecord"]["digitigrade"] = mannequin.digitigrade
data["menu"] = menu
data["temp"] = temp
data["disk"] = disk ? 1 : 0
data["diskStored"] = disk && disk.stored ? 1 : 0
return data
/obj/machinery/computer/transhuman/designer/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
switch(action)
if("debug_load_my_body")
active_br = new /datum/transhuman/body_record(ui.user, FALSE, FALSE)
update_preview_icon()
menu = MENU_SPECIFICRECORD
if("view_brec")
var/datum/transhuman/body_record/BR = locate(params["view_brec"])
if(BR && istype(BR.mydna))
if(allowed(ui.user) || BR.ckey == ui.user.ckey)
active_br = new /datum/transhuman/body_record(BR) // Load a COPY!
update_preview_icon()
menu = MENU_SPECIFICRECORD
else
active_br = null
temp = "Access denied: Body records are confidential."
else
active_br = null
temp = "ERROR: Record missing."
if("view_stock_brec")
var/datum/species/S = GLOB.all_species[params["view_stock_brec"]]
if(S && (S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) == SPECIES_CAN_JOIN)
// Generate body record from species!
mannequin = new(null, S.name)
mannequin.real_name = "Stock [S.name] Body"
mannequin.name = mannequin.real_name
mannequin.dna.real_name = mannequin.real_name
mannequin.dna.base_species = mannequin.species.base_species
active_br = new(mannequin, FALSE, FALSE)
active_br.speciesname = "Custom Sleeve"
update_preview_icon()
menu = MENU_SPECIFICRECORD
else
active_br = null
temp = "ERROR: Stock Record missing."
if("boocnotes")
menu = MENU_OOCNOTES
if("loadfromdisk")
if(disk && disk.stored)
active_br = new /datum/transhuman/body_record(disk.stored) // Loads a COPY!
update_preview_icon()
menu = MENU_SPECIFICRECORD
if("savetodisk")
if(active_br.locked)
var/answer = tgui_alert(ui.user,"This body record will be written to a disk and allow any mind to inhabit it. This is against the current body owner's configured OOC preferences for body impersonation. Please confirm that you have permission to do this, and are sure! Admins will be notified.","Mind Compatability",list("No","Yes"))
if(!answer)
return
if(answer == "No")
to_chat(ui.user, span_warning("ERROR: This body record is restricted."))
return
else
message_admins("[ui.user] wrote an unlocked version of [active_br.mydna.name]'s bodyrecord to a disk. Their preferences do not allow body impersonation, but may be allowed with OOC consent.")
if(disk && active_br)
active_br.locked = FALSE // remove lock
disk.stored = new /datum/transhuman/body_record(active_br) // Saves a COPY!
disk.name = "[initial(disk.name)] ([active_br.mydna.name])"
if("ejectdisk")
disk.forceMove(get_turf(src))
disk = null
if("menu")
menu = params["menu"]
temp = ""
if("href_conversion")
PrefHrefMiddleware(params, ui.user)
add_fingerprint(ui.user)
return TRUE // Return 1 to refresh UI
//
// Code below is for generating preview icons based on a body_record
//
// Based on /datum/preferences/proc/update_preview_icon()
/obj/machinery/computer/transhuman/designer/proc/update_preview_icon()
if(!mannequin)
mannequin = new ()
mannequin.delete_inventory(TRUE)
update_preview_mob(mannequin)
mannequin.ImmediateOverlayUpdate()
var/mutable_appearance/MA = new(mannequin)
south_preview.appearance = MA
south_preview.dir = SOUTH
south_preview.screen_loc = "[map_name]:2,1"
south_preview.name = ""
east_preview.appearance = MA
east_preview.dir = EAST
east_preview.screen_loc = "[map_name]:4,1"
east_preview.name = ""
west_preview.appearance = MA
west_preview.dir = WEST
west_preview.screen_loc = "[map_name]:0,1"
west_preview.name = ""
north_preview.appearance = MA
north_preview.dir = NORTH
north_preview.screen_loc = "[map_name]:6,1"
north_preview.name = ""
/obj/machinery/computer/transhuman/designer/proc/give_client_previews(client/C)
C.register_map_obj(south_preview)
C.register_map_obj(east_preview)
C.register_map_obj(west_preview)
C.register_map_obj(north_preview)
/obj/machinery/computer/transhuman/designer/proc/update_preview_mob(var/mob/living/carbon/human/H)
ASSERT(!QDELETED(H))
ASSERT(!QDELETED(active_br))
//log_debug("designer.update_preview_mob([H]) active_br = \ref[active_br]")
//Get the DNA and generate a new mob
var/datum/dna2/record/R = active_br.mydna
H.set_species(R.dna.species) // This needs to happen before anything else becuase it sets some variables.
// Update the external organs
for(var/part in active_br.limb_data)
var/status = active_br.limb_data[part]
if(status == null) continue //Species doesn't have limb? Child of amputated limb?
var/obj/item/organ/external/O = H.organs_by_name[part]
if(!O) continue //Not an organ. Perhaps another amputation removed it already.
if(status == 1) //Normal limbs
continue
else if(status == 0) //Missing limbs
O.remove_rejuv()
else if(status) //Anything else is a manufacturer
if(active_br.synthetic)
O.robotize(status)
else
O.remove_rejuv()
// Then the internal organs. I think only O_EYES acutally counts, but lets do all just in case
for(var/part in active_br.organ_data)
var/status = active_br.organ_data[part]
if(status == null) continue //Species doesn't have organ? Child of missing part?
var/obj/item/organ/I = H.internal_organs_by_name[part]
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
if(status == 0) //Normal organ
continue
else if(status == 1) //Assisted organ
I.mechassist()
else if(status == 2) //Mechanical organ
I.robotize()
else if(status == 3) //Digital organ
I.digitize()
// Apply DNA
qdel_swap(H.dna, R.dna.Clone())
H.UpdateAppearance() // Update all appearance stuff from the DNA record
// H.sync_dna_traits(FALSE) // Traitgenes edit - Sync traits to genetics if needed // Currently not implemented
H.sync_organ_dna() // Do this because sprites depend on DNA-gender of organs (chest etc)
H.resize(active_br.sizemult, FALSE)
// Emissiive...
if(H.ear_style)
H.ear_style.em_block = FALSE
if(H.tail_style)
H.tail_style.em_block = FALSE
if(H.wing_style)
H.wing_style.em_block = FALSE
for(var/key in R.flavor)
H.flavor_texts[key] = R.flavor[key]
H.weight = active_br.weight
// stupid dupe vars
H.b_type = active_br.mydna.dna.b_type
H.blood_color = active_br.mydna.dna.blood_color
// And as for clothing...
// We don't actually dress them! This is a medical machine, handle the nakedness DOCTOR!
H.regenerate_icons()
return 0 // Success!
// HORROR SHOW BELOW
// In order to avoid duplicating the many lines of code in player_setup that handle customizing
// body setup, we acutally are invoking those methods in order to let people customize the body here.
// Problem is, those procs save their data to /datum/preferences, not a body_record.
// Luckily the procs to convert from body_record to /datum/preferences and back already exist.
// Its ugly, but I think its still better than duplicating and maintaining all that code.
/obj/machinery/computer/transhuman/designer/proc/PrefHrefMiddleware(list/params, var/mob/user)
if(!mannequin || !active_br)
return
if(params["target_href"] == "size_multiplier")
var/new_size = tgui_input_number(user, "Choose your character's size, ranging from 25% to 200%", "Character Preference", null, 200, 25)
if(new_size && ISINRANGE(new_size,25,200))
active_br.sizemult = (new_size/100)
update_preview_icon()
return 1
// The black magic horror show begins
var/datum/preferences/designer/P = new()
// We did DNA to mob, now mob to prefs!
P.species = mannequin.species.name
apply_coloration_to_prefs(mannequin, P)
apply_organs_to_prefs(mannequin, P)
apply_markings_to_prefs(mannequin, P)
apply_ears_to_prefs(mannequin, P)
for(var/key in active_br.mydna.flavor)
P.flavor_texts[key] = active_br.mydna.flavor[key]
P.fuzzy = active_br.mydna.dna.scale_appearance
P.offset_override = active_br.mydna.dna.offset_override
P.species_sound = active_br.mydna.dna.species_sounds // CHOMPEnable
// Now we start using the player_setup objects to do stuff!
var/datum/category_collection/CC = P.player_setup
var/datum/category_group/CG = CC.categories_by_name["General"]
var/datum/category_item/player_setup_item/general/body/B = CG.items_by_name["Body"]
ASSERT(istype(B))
var/datum/category_item/player_setup_item/general/basic/G = CG.items_by_name["Basic"]
ASSERT(istype(G))
var/datum/category_item/player_setup_item/general/flavor/F = CG.items_by_name["Flavor"]
ASSERT(istype(F))
var/datum/category_item/player_setup_item/vore/size/S = CC.categories_by_name["VORE"].items_by_name["Size"]
ASSERT(istype(S))
var/datum/category_item/player_setup_item/vore/traits/V = CC.categories_by_name["VORE"].items_by_name["Traits"]
ASSERT(istype(V))
var/list/use_different_category = list("rename" = G, "bio_gender" = G, "blood_reagents" = V, "custom_species" = V, "blood_color" = V, "custom_base" = V, "species_sound_options" = S, "toggle_fuzzy" = S, "toggle_offset_override" = S, "weight" = S, "flavor_text" = F) //add more here if needed
var/href_list = list()
href_list["src"] = "\ref[src]"
var/list/target_href_maybe = params["target_href"]
// convert list-form inputs as needed
if(islist(target_href_maybe))
href_list[target_href_maybe["act"]] = TRUE
for(var/key in target_href_maybe["params"])
var/val = target_href_maybe["params"][key]
href_list[key] = "[val]"
else
href_list[target_href_maybe] = params["target_value"]
var/datum/category_item/player_setup_item/to_use = (params["target_href"] in use_different_category) ? use_different_category[params["target_href"]] : B
var/action = 0
action = to_use.OnTopic(list2params(href_list), href_list, user)
if((action & TOPIC_UPDATE_PREVIEW || action & TOPIC_REFRESH_UPDATE_PREVIEW || action & TOPIC_HANDLED || action & TOPIC_REFRESH) && mannequin && active_br) // Outpost 21 edit - Handled and Refreshes also count for check!
switch(params["target_href"])
if("rename")
active_br.mydna.name = P.real_name
active_br.mydna.dna.real_name = P.real_name
update_preview_icon()
return TRUE
if("bio_gender")
active_br.bodygender = P.biological_gender
active_br.mydna.dna.SetUIState(DNA_UI_GENDER, P.biological_gender!=MALE, 1)
update_preview_icon()
return TRUE
if("custom_species")
active_br.mydna.dna.custom_species = P.custom_species
active_br.speciesname = P.custom_species
update_preview_icon()
return TRUE
if("blood_color")
active_br.mydna.dna.blood_color = P.blood_color
update_preview_icon()
return TRUE
if("blood_type")
active_br.mydna.dna.b_type = P.b_type
update_preview_icon()
return TRUE
if("blood_reagents")
active_br.mydna.dna.blood_reagents = P.blood_reagents
update_preview_icon()
return TRUE
if("weight")
active_br.weight = P.weight_vr
update_preview_icon()
return TRUE
if("flavor_text")
to_use.copy_to_mob(mannequin)
for(var/key in mannequin.flavor_texts) // Get the flavors from the mob, which we just got from pref!
active_br.mydna.flavor[key] = mannequin.flavor_texts[key]
update_preview_icon()
return TRUE
if("toggle_fuzzy")
active_br.mydna.dna.scale_appearance = P.fuzzy
update_preview_icon()
return TRUE
if("toggle_offset_override")
active_br.mydna.dna.offset_override = P.offset_override
update_preview_icon()
return TRUE
if("species_sound_options")
// CHOMPEnable Start
active_br.mydna.dna.species_sounds = P.species_sound
update_preview_icon()
// CHOMPEnable End
return TRUE
to_use.copy_to_mob(mannequin)
mannequin.species.blood_color = active_br.mydna.dna.blood_color
mannequin.species.blood_reagents = active_br.mydna.dna.blood_reagents
active_br.mydna.dna.ResetUIFrom(mannequin)
update_preview_icon()
return TRUE
// Fake subtype of preferences we can use to steal code from player_setup
/datum/preferences/designer/New()
player_setup = new(src)
// Do NOT call ..(), it expects real stuff
// Disk for manually moving body records between the designer and sleever console etc. // Disk for manually moving body records between the designer and sleever console etc.
/obj/item/disk/body_record /obj/item/disk/body_record
@@ -585,8 +90,6 @@
for(var/i = 0 to 7) for(var/i = 0 to 7)
new /obj/item/disk/body_record(src) new /obj/item/disk/body_record(src)
#undef MOB_HEX_COLOR
#undef MENU_MAIN #undef MENU_MAIN
#undef MENU_BODYRECORDS #undef MENU_BODYRECORDS
#undef MENU_STOCKRECORDS #undef MENU_STOCKRECORDS

View File

@@ -216,7 +216,7 @@
/** /**
* Make a deep copy of this record so it can be saved on a disk without mofidications * Make a deep copy of this record so it can be saved on a disk without modifications
* to the original affecting the copy. * to the original affecting the copy.
* Just to be clear, this has nothing to do do with acutal biological cloning, body printing, resleeving, * Just to be clear, this has nothing to do do with acutal biological cloning, body printing, resleeving,
* or anything like that! This is the computer science concept of "cloning" a data structure! * or anything like that! This is the computer science concept of "cloning" a data structure!
@@ -239,9 +239,13 @@
src.speciesname = orig.speciesname src.speciesname = orig.speciesname
src.bodygender = orig.bodygender src.bodygender = orig.bodygender
src.body_oocnotes = orig.body_oocnotes src.body_oocnotes = orig.body_oocnotes
src.body_ooclikes = orig.body_ooclikes
src.body_oocdislikes = orig.body_oocdislikes
src.limb_data = orig.limb_data.Copy() src.limb_data = orig.limb_data.Copy()
src.organ_data = orig.organ_data.Copy() src.organ_data = orig.organ_data.Copy()
src.genetic_modifiers = orig.genetic_modifiers.Copy() src.genetic_modifiers = orig.genetic_modifiers.Copy()
src.toocomplex = orig.toocomplex src.toocomplex = orig.toocomplex
src.sizemult = orig.sizemult src.sizemult = orig.sizemult
src.aflags = orig.aflags src.aflags = orig.aflags
src.breath_type = orig.breath_type
src.weight = orig.weight

View File

@@ -1,3 +1,20 @@
// *******************************************************
// Unified body transformation UI for inround TF or bodyrecord editing.
// Make a new subtype of this, and configure it for whatever changes
// that you will be allowing on the objects. This is a tgui UI and can
// be attached to any object.
//
// USE THIS instead of recoding tf/appearance editing for the forth time
// in this codebase. It should all be in one place, and extended for every
// new feature added to cosmetics. Be sure to update bodyrecords and their
// cloning/to/from mob procs as well.
//
// owner is the mob being transformed, ui.user is the mob using the interface
// if owner and user are the same, there is some special logic for self-tf.
// use can_change(owner, APPEARANCE_X) to validate if the owner is still in a
// valid state for the module to edit them.
// *******************************************************
/datum/tgui_module/appearance_changer /datum/tgui_module/appearance_changer
name = "Appearance Editor" name = "Appearance Editor"
tgui_id = "AppearanceChanger" tgui_id = "AppearanceChanger"
@@ -25,6 +42,7 @@
var/list/valid_earstyles = list() var/list/valid_earstyles = list()
var/list/valid_tailstyles = list() var/list/valid_tailstyles = list()
var/list/valid_wingstyles = list() var/list/valid_wingstyles = list()
var/list/valid_gradstyles = list()
var/list/markings = null var/list/markings = null
/datum/tgui_module/appearance_changer/New( /datum/tgui_module/appearance_changer/New(
@@ -84,6 +102,12 @@
if(..()) if(..())
return TRUE return TRUE
var/obj/machinery/computer/transhuman/designer/DC = null
var/datum/tgui_module/appearance_changer/body_designer/BD = null
if(istype(src,/datum/tgui_module/appearance_changer/body_designer))
BD = src
DC = BD.linked_body_design_console?.resolve()
switch(action) switch(action)
if("race") if("race")
if(can_change(owner, APPEARANCE_RACE) && (params["race"] in valid_species)) if(can_change(owner, APPEARANCE_RACE) && (params["race"] in valid_species))
@@ -110,14 +134,14 @@
if("skin_tone") if("skin_tone")
if(can_change_skin_tone(owner)) if(can_change_skin_tone(owner))
var/new_s_tone = tgui_input_number(ui.user, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", -owner.s_tone + 35, 220, 1) var/new_s_tone = tgui_input_number(ui.user, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", -owner.s_tone + 35, 220, 1)
if(isnum(new_s_tone) && can_still_topic(owner, state)) if(isnum(new_s_tone) && can_still_topic(ui.user, state))
new_s_tone = 35 - max(min( round(new_s_tone), 220),1) new_s_tone = 35 - max(min( round(new_s_tone), 220),1)
changed_hook(APPEARANCECHANGER_CHANGED_SKINTONE) changed_hook(APPEARANCECHANGER_CHANGED_SKINTONE)
return owner.change_skin_tone(new_s_tone) return owner.change_skin_tone(new_s_tone)
if("skin_color") if("skin_color")
if(can_change_skin_color(owner)) if(can_change_skin_color(owner))
var/new_skin = tgui_color_picker(ui.user, "Choose your character's skin colour: ", "Skin Color", rgb(owner.r_skin, owner.g_skin, owner.b_skin)) var/new_skin = tgui_color_picker(ui.user, "Choose your character's skin colour: ", "Skin Color", rgb(owner.r_skin, owner.g_skin, owner.b_skin))
if(new_skin && can_still_topic(owner, state)) if(new_skin && can_still_topic(ui.user, state))
var/r_skin = hex2num(copytext(new_skin, 2, 4)) var/r_skin = hex2num(copytext(new_skin, 2, 4))
var/g_skin = hex2num(copytext(new_skin, 4, 6)) var/g_skin = hex2num(copytext(new_skin, 4, 6))
var/b_skin = hex2num(copytext(new_skin, 6, 8)) var/b_skin = hex2num(copytext(new_skin, 6, 8))
@@ -126,15 +150,23 @@
changed_hook(APPEARANCECHANGER_CHANGED_SKINCOLOR) changed_hook(APPEARANCECHANGER_CHANGED_SKINCOLOR)
return 1 return 1
if("hair") if("hair")
if(can_change(owner, APPEARANCE_HAIR) && (params["hair"] in valid_hairstyles)) if(can_change(owner, APPEARANCE_HAIR) && (params["name"] in valid_hairstyles))
if(owner.change_hair(params["hair"])) if(owner.change_hair(params["name"]))
update_dna(owner) update_dna(owner)
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE) changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
return 1 return 1
if("hair_grad")
var/picked = params["picked"]
if(picked && can_change(owner, APPEARANCE_HAIR_COLOR))
owner.grad_style = picked[1] // returned as a list
update_dna(owner)
owner.regenerate_icons()
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
return 1
if("hair_color") if("hair_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair)) var/new_hair = tgui_color_picker(ui.user, "Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
var/r_hair = hex2num(copytext(new_hair, 2, 4)) var/r_hair = hex2num(copytext(new_hair, 2, 4))
var/g_hair = hex2num(copytext(new_hair, 4, 6)) var/g_hair = hex2num(copytext(new_hair, 4, 6))
var/b_hair = hex2num(copytext(new_hair, 6, 8)) var/b_hair = hex2num(copytext(new_hair, 6, 8))
@@ -142,16 +174,27 @@
update_dna(owner) update_dna(owner)
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR) changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
return 1 return 1
if("hair_color_grad")
if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_grad = tgui_color_picker(ui.user, "Please select hair gradiant color.", "Hair Color", rgb(owner.r_grad, owner.g_grad, owner.b_grad))
if(new_grad && can_still_topic(ui.user, state))
var/r_grad = hex2num(copytext(new_grad, 2, 4))
var/g_grad = hex2num(copytext(new_grad, 4, 6))
var/b_grad = hex2num(copytext(new_grad, 6, 8))
if(owner.change_grad_color(r_grad, g_grad, b_grad))
update_dna(owner)
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
return 1
if("facial_hair") if("facial_hair")
if(can_change(owner, APPEARANCE_FACIAL_HAIR) && (params["facial_hair"] in valid_facial_hairstyles)) if(can_change(owner, APPEARANCE_FACIAL_HAIR) && (params["name"] in valid_facial_hairstyles))
if(owner.change_facial_hair(params["facial_hair"])) if(owner.change_facial_hair(params["name"]))
update_dna(owner) update_dna(owner)
changed_hook(APPEARANCECHANGER_CHANGED_F_HAIRSTYLE) changed_hook(APPEARANCECHANGER_CHANGED_F_HAIRSTYLE)
return 1 return 1
if("facial_hair_color") if("facial_hair_color")
if(can_change(owner, APPEARANCE_FACIAL_HAIR_COLOR)) if(can_change(owner, APPEARANCE_FACIAL_HAIR_COLOR))
var/new_facial = tgui_color_picker(ui.user, "Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial)) var/new_facial = tgui_color_picker(ui.user, "Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial))
if(new_facial && can_still_topic(owner, state)) if(new_facial && can_still_topic(ui.user, state))
var/r_facial = hex2num(copytext(new_facial, 2, 4)) var/r_facial = hex2num(copytext(new_facial, 2, 4))
var/g_facial = hex2num(copytext(new_facial, 4, 6)) var/g_facial = hex2num(copytext(new_facial, 4, 6))
var/b_facial = hex2num(copytext(new_facial, 6, 8)) var/b_facial = hex2num(copytext(new_facial, 6, 8))
@@ -162,7 +205,7 @@
if("eye_color") if("eye_color")
if(can_change(owner, APPEARANCE_EYE_COLOR)) if(can_change(owner, APPEARANCE_EYE_COLOR))
var/new_eyes = tgui_color_picker(ui.user, "Please select eye color.", "Eye Color", rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes)) var/new_eyes = tgui_color_picker(ui.user, "Please select eye color.", "Eye Color", rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes))
if(new_eyes && can_still_topic(owner, state)) if(new_eyes && can_still_topic(ui.user, state))
var/r_eyes = hex2num(copytext(new_eyes, 2, 4)) var/r_eyes = hex2num(copytext(new_eyes, 2, 4))
var/g_eyes = hex2num(copytext(new_eyes, 4, 6)) var/g_eyes = hex2num(copytext(new_eyes, 4, 6))
var/b_eyes = hex2num(copytext(new_eyes, 6, 8)) var/b_eyes = hex2num(copytext(new_eyes, 6, 8))
@@ -170,7 +213,6 @@
update_dna(owner) update_dna(owner)
changed_hook(APPEARANCECHANGER_CHANGED_EYES) changed_hook(APPEARANCECHANGER_CHANGED_EYES)
return 1 return 1
// VOREStation Add - Ears/Tails/Wings/Markings
if("ear") if("ear")
if(can_change(owner, APPEARANCE_ALL_HAIR)) if(can_change(owner, APPEARANCE_ALL_HAIR))
var/datum/sprite_accessory/ears/instance = locate(params["ref"]) var/datum/sprite_accessory/ears/instance = locate(params["ref"])
@@ -202,7 +244,7 @@
if("ears_color") if("ears_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select ear color.", "Ear Color", rgb(owner.r_ears, owner.g_ears, owner.b_ears)) var/new_hair = tgui_color_picker(ui.user, "Please select ear color.", "Ear Color", rgb(owner.r_ears, owner.g_ears, owner.b_ears))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
owner.r_ears = hex2num(copytext(new_hair, 2, 4)) owner.r_ears = hex2num(copytext(new_hair, 2, 4))
owner.g_ears = hex2num(copytext(new_hair, 4, 6)) owner.g_ears = hex2num(copytext(new_hair, 4, 6))
owner.b_ears = hex2num(copytext(new_hair, 6, 8)) owner.b_ears = hex2num(copytext(new_hair, 6, 8))
@@ -213,7 +255,7 @@
if("ears2_color") if("ears2_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select secondary ear color.", "2nd Ear Color", rgb(owner.r_ears2, owner.g_ears2, owner.b_ears2)) var/new_hair = tgui_color_picker(ui.user, "Please select secondary ear color.", "2nd Ear Color", rgb(owner.r_ears2, owner.g_ears2, owner.b_ears2))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
owner.r_ears2 = hex2num(copytext(new_hair, 2, 4)) owner.r_ears2 = hex2num(copytext(new_hair, 2, 4))
owner.g_ears2 = hex2num(copytext(new_hair, 4, 6)) owner.g_ears2 = hex2num(copytext(new_hair, 4, 6))
owner.b_ears2 = hex2num(copytext(new_hair, 6, 8)) owner.b_ears2 = hex2num(copytext(new_hair, 6, 8))
@@ -228,7 +270,7 @@
return TRUE return TRUE
var/existing = LAZYACCESS(owner.ear_secondary_colors, channel) || "#ffffff" var/existing = LAZYACCESS(owner.ear_secondary_colors, channel) || "#ffffff"
var/new_color = tgui_color_picker(ui.user, "Please select ear color.", "2nd Ear Color", existing) var/new_color = tgui_color_picker(ui.user, "Please select ear color.", "2nd Ear Color", existing)
if(new_color && can_still_topic(owner, state)) if(new_color && can_still_topic(ui.user, state))
owner.ear_secondary_colors[channel] = new_color owner.ear_secondary_colors[channel] = new_color
update_dna(owner) update_dna(owner)
owner.update_hair() owner.update_hair()
@@ -249,7 +291,7 @@
if("tail_color") if("tail_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select tail color.", "Tail Color", rgb(owner.r_tail, owner.g_tail, owner.b_tail)) var/new_hair = tgui_color_picker(ui.user, "Please select tail color.", "Tail Color", rgb(owner.r_tail, owner.g_tail, owner.b_tail))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
owner.r_tail = hex2num(copytext(new_hair, 2, 4)) owner.r_tail = hex2num(copytext(new_hair, 2, 4))
owner.g_tail = hex2num(copytext(new_hair, 4, 6)) owner.g_tail = hex2num(copytext(new_hair, 4, 6))
owner.b_tail = hex2num(copytext(new_hair, 6, 8)) owner.b_tail = hex2num(copytext(new_hair, 6, 8))
@@ -260,7 +302,7 @@
if("tail2_color") if("tail2_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select secondary tail color.", "2nd Tail Color", rgb(owner.r_tail2, owner.g_tail2, owner.b_tail2)) var/new_hair = tgui_color_picker(ui.user, "Please select secondary tail color.", "2nd Tail Color", rgb(owner.r_tail2, owner.g_tail2, owner.b_tail2))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
owner.r_tail2 = hex2num(copytext(new_hair, 2, 4)) owner.r_tail2 = hex2num(copytext(new_hair, 2, 4))
owner.g_tail2 = hex2num(copytext(new_hair, 4, 6)) owner.g_tail2 = hex2num(copytext(new_hair, 4, 6))
owner.b_tail2 = hex2num(copytext(new_hair, 6, 8)) owner.b_tail2 = hex2num(copytext(new_hair, 6, 8))
@@ -271,7 +313,7 @@
if("tail3_color") if("tail3_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select tertiary tail color.", "3rd Tail Color", rgb(owner.r_tail3, owner.g_tail3, owner.b_tail3)) var/new_hair = tgui_color_picker(ui.user, "Please select tertiary tail color.", "3rd Tail Color", rgb(owner.r_tail3, owner.g_tail3, owner.b_tail3))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
owner.r_tail3 = hex2num(copytext(new_hair, 2, 4)) owner.r_tail3 = hex2num(copytext(new_hair, 2, 4))
owner.g_tail3 = hex2num(copytext(new_hair, 4, 6)) owner.g_tail3 = hex2num(copytext(new_hair, 4, 6))
owner.b_tail3 = hex2num(copytext(new_hair, 6, 8)) owner.b_tail3 = hex2num(copytext(new_hair, 6, 8))
@@ -294,7 +336,7 @@
if("wing_color") if("wing_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select wing color.", "Wing Color", rgb(owner.r_wing, owner.g_wing, owner.b_wing)) var/new_hair = tgui_color_picker(ui.user, "Please select wing color.", "Wing Color", rgb(owner.r_wing, owner.g_wing, owner.b_wing))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
owner.r_wing = hex2num(copytext(new_hair, 2, 4)) owner.r_wing = hex2num(copytext(new_hair, 2, 4))
owner.g_wing = hex2num(copytext(new_hair, 4, 6)) owner.g_wing = hex2num(copytext(new_hair, 4, 6))
owner.b_wing = hex2num(copytext(new_hair, 6, 8)) owner.b_wing = hex2num(copytext(new_hair, 6, 8))
@@ -305,7 +347,7 @@
if("wing2_color") if("wing2_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select secondary wing color.", "2nd Wing Color", rgb(owner.r_wing2, owner.g_wing2, owner.b_wing2)) var/new_hair = tgui_color_picker(ui.user, "Please select secondary wing color.", "2nd Wing Color", rgb(owner.r_wing2, owner.g_wing2, owner.b_wing2))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
owner.r_wing2 = hex2num(copytext(new_hair, 2, 4)) owner.r_wing2 = hex2num(copytext(new_hair, 2, 4))
owner.g_wing2 = hex2num(copytext(new_hair, 4, 6)) owner.g_wing2 = hex2num(copytext(new_hair, 4, 6))
owner.b_wing2 = hex2num(copytext(new_hair, 6, 8)) owner.b_wing2 = hex2num(copytext(new_hair, 6, 8))
@@ -316,7 +358,7 @@
if("wing3_color") if("wing3_color")
if(can_change(owner, APPEARANCE_HAIR_COLOR)) if(can_change(owner, APPEARANCE_HAIR_COLOR))
var/new_hair = tgui_color_picker(ui.user, "Please select tertiary wing color.", "3rd Wing Color", rgb(owner.r_wing3, owner.g_wing3, owner.b_wing3)) var/new_hair = tgui_color_picker(ui.user, "Please select tertiary wing color.", "3rd Wing Color", rgb(owner.r_wing3, owner.g_wing3, owner.b_wing3))
if(new_hair && can_still_topic(owner, state)) if(new_hair && can_still_topic(ui.user, state))
owner.r_wing3 = hex2num(copytext(new_hair, 2, 4)) owner.r_wing3 = hex2num(copytext(new_hair, 2, 4))
owner.g_wing3 = hex2num(copytext(new_hair, 4, 6)) owner.g_wing3 = hex2num(copytext(new_hair, 4, 6))
owner.b_wing3 = hex2num(copytext(new_hair, 6, 8)) owner.b_wing3 = hex2num(copytext(new_hair, 6, 8))
@@ -336,10 +378,8 @@
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE) changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
return TRUE return TRUE
if (1) //add if (1) //add
var/list/usable_markings = markings.Copy() ^ body_marking_styles_list.Copy() if(name_marking && can_still_topic(ui.user, state))
var/new_marking = tgui_input_list(ui.user, "Choose a body marking:", "New Body Marking", usable_markings) var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[name_marking]
if(new_marking && can_still_topic(owner, state))
var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[new_marking]
if (owner.add_marking(mark_datum)) if (owner.add_marking(mark_datum))
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE) changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
return TRUE return TRUE
@@ -352,13 +392,211 @@
if (owner.change_priority_of_marking(mark_datum, TRUE)) if (owner.change_priority_of_marking(mark_datum, TRUE))
return TRUE return TRUE
if (4) //color if (4) //color
var/current = markings[name_marking] ? markings[name_marking] : "#000000" var/current = markings[name_marking] ? markings[name_marking]["color"] : "#000000"
var/marking_color = tgui_color_picker(ui.user, "Please select marking color", "Marking color", current) var/marking_color = tgui_color_picker(ui.user, "Please select marking color", "Marking color", current)
if(marking_color && can_still_topic(owner, state)) if(marking_color && can_still_topic(ui.user, state))
var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[name_marking] var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[name_marking]
if (owner.change_marking_color(mark_datum, marking_color)) if (owner.change_marking_color(mark_datum, marking_color))
return TRUE return TRUE
// VOREStation Add End if("rotate_view")
if(can_change(owner, APPEARANCE_RACE))
owner.set_dir(turn(owner.dir, 90))
return TRUE
if("rename")
if(owner)
var/raw_name = tgui_input_text(ui.user, "Choose the a name:", "Sleeve Name")
if(!isnull(raw_name) && can_change(owner, APPEARANCE_RACE))
var/new_name = sanitize_name(raw_name, owner.species, FALSE) // can't edit synths
if(new_name)
owner.dna.real_name = new_name
owner.real_name = new_name
owner.name = new_name
return TRUE
else
to_chat(ui.user, span_warning("Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and ."))
return TRUE
if("char_name")
if(DC) // Only body designer does this. no hrefing
var/new_name = sanitize(tgui_input_text(ui.user, "Input character's name:", "Name", owner.name, MAX_NAME_LEN), MAX_NAME_LEN)
if(can_change(owner, APPEARANCE_RACE)) // new name can be empty, it uses base species if so
owner.name = new_name
owner.real_name = owner.name
owner.dna.real_name = owner.name
return TRUE
if("race_name")
var/new_name = sanitize(tgui_input_text(ui.user, "Input custom species name:", "Custom Species Name", owner.custom_species, MAX_NAME_LEN), MAX_NAME_LEN)
if(can_change(owner, APPEARANCE_RACE)) // new name can be empty, it uses base species if so
owner.custom_species = new_name
return TRUE
if("base_icon")
if(owner.species.selects_bodytype == SELECTS_BODYTYPE_FALSE)
var/datum/species/S = GLOB.all_species[owner.species.name]
owner.species.base_species = S.base_species // Return to original form
generate_data(ui.user, owner)
changed_hook(APPEARANCECHANGER_CHANGED_RACE)
return TRUE
var/list/choices
var/datum/species/S = GLOB.all_species[owner.species.name]
if(S.selects_bodytype == SELECTS_BODYTYPE_SHAPESHIFTER)
choices = S.get_valid_shapeshifter_forms()
else if(S.selects_bodytype == SELECTS_BODYTYPE_CUSTOM)
choices = GLOB.custom_species_bases
var/new_species = tgui_input_list(ui.user, "Please select basic shape.", "Body Shape", choices)
if(new_species && can_change(owner, APPEARANCE_RACE))
owner.species.base_species = new_species
owner.regenerate_icons()
generate_data(ui.user, owner)
changed_hook(APPEARANCECHANGER_CHANGED_RACE)
return TRUE
if("blood_reagent")
var/new_blood_reagents = tgui_input_list(ui.user, "Please select blood restoration reagent:", "Character Preference", valid_bloodreagents)
if(new_blood_reagents && can_change(owner, APPEARANCE_RACE))
owner.dna.blood_reagents = new_blood_reagents
changed_hook(APPEARANCECHANGER_CHANGED_RACE)
return TRUE
if("blood_color")
var/current = owner.species.blood_color ? owner.species.blood_color : "#A10808"
var/blood_col = tgui_color_picker(ui.user, "Please select marking color", "Marking color", current)
if(blood_col && can_change(owner, APPEARANCE_RACE))
owner.dna.blood_color = blood_col
changed_hook(APPEARANCECHANGER_CHANGED_RACE)
return TRUE
if("weight")
var/new_weight = tgui_input_number(ui.user, "Choose tbe character's relative body weight.\n\
This measurement should be set relative to a normal 5'10'' person's body and not the actual size of the character.\n\
([WEIGHT_MIN]-[WEIGHT_MAX])", "Character Preference", null, WEIGHT_MAX, WEIGHT_MIN, round_value=FALSE)
if(new_weight && can_change(owner, APPEARANCE_RACE))
var/unit_of_measurement = tgui_alert(ui.user, "Is that number in pounds (lb) or kilograms (kg)?", "Confirmation", list("Pounds", "Kilograms"))
if(unit_of_measurement && can_change(owner, APPEARANCE_RACE))
if(unit_of_measurement == "Pounds")
new_weight = round(text2num(new_weight),4)
if(unit_of_measurement == "Kilograms")
new_weight = round(2.20462*text2num(new_weight),4)
owner.weight = sanitize_integer(new_weight, WEIGHT_MIN, WEIGHT_MAX, owner.weight)
changed_hook(APPEARANCECHANGER_CHANGED_RACE)
return TRUE
if("size_scale")
var/new_size = tgui_input_number(ui.user, "Choose size, ranging from [RESIZE_MINIMUM * 100]% to [RESIZE_MAXIMUM * 100]%", "Set Size", null, RESIZE_MAXIMUM * 100, RESIZE_MINIMUM * 100)
if(new_size && ISINRANGE(new_size,RESIZE_MINIMUM * 100,RESIZE_MAXIMUM * 100) && can_change(owner, APPEARANCE_RACE))
owner.size_multiplier = new_size / 100
owner.update_transform(TRUE)
owner.regenerate_icons()
owner.set_dir(owner.dir) // Causes a visual update for fuzzy/offset
changed_hook(APPEARANCECHANGER_CHANGED_RACE)
return TRUE
if("scale_appearance")
if(can_change(owner, APPEARANCE_RACE))
owner.dna.scale_appearance = !owner.dna.scale_appearance
owner.fuzzy = owner.dna.scale_appearance
owner.regenerate_icons()
owner.set_dir(owner.dir) // Causes a visual update for fuzzy/offset
return TRUE
if("offset_override")
if(can_change(owner, APPEARANCE_RACE))
owner.dna.offset_override = !owner.dna.offset_override
owner.offset_override = owner.dna.offset_override
owner.regenerate_icons()
owner.set_dir(owner.dir) // Causes a visual update for fuzzy/offset
return TRUE
if("digitigrade")
if(can_change(owner, APPEARANCE_RACE))
owner.dna.digitigrade = !owner.dna.digitigrade
owner.digitigrade = owner.dna.digitigrade
owner.regenerate_icons()
generate_data(ui.user, owner)
changed_hook(APPEARANCECHANGER_CHANGED_RACE)
return TRUE
// CHOMPEnable Start
if("species_sound")
var/list/possible_species_sound_types = species_sound_map
var/choice = tgui_input_list(ui.user, "Which set of sounds would you like to use? (Cough, Sneeze, Scream, Pain, Gasp, Death)", "Species Sounds", possible_species_sound_types)
if(choice && can_change(owner, APPEARANCE_RACE))
owner.species.species_sounds = choice
return TRUE
// CHOMPEnable End
if("flavor_text")
var/select_key = params["target"]
if(select_key && can_change(owner, APPEARANCE_RACE))
if(select_key in owner.flavor_texts)
switch(select_key)
if("general")
var/msg = strip_html_simple(tgui_input_text(ui.user,"Give a general description of the character. This will be shown regardless of clothings. Put in a single space to make blank.","Flavor Text",html_decode(owner.flavor_texts[select_key]), multiline = TRUE, prevent_enter = TRUE))
if(can_change(owner, APPEARANCE_RACE)) // allows empty to wipe flavor
owner.flavor_texts[select_key] = msg
return TRUE
else
var/msg = strip_html_simple(tgui_input_text(ui.user,"Set the flavor text for their [select_key]. Put in a single space to make blank.","Flavor Text",html_decode(owner.flavor_texts[select_key]), multiline = TRUE, prevent_enter = TRUE))
if(can_change(owner, APPEARANCE_RACE)) // allows empty to wipe flavor
owner.flavor_texts[select_key] = msg
return TRUE
// ***********************************
// Body designer UI
// ***********************************
if("view_brec")
var/datum/transhuman/body_record/BR = locate(params["view_brec"])
if(BR && istype(BR.mydna))
if(DC.allowed(ui.user) || BR.ckey == ui.user.ckey)
BD.load_record_to_body(BR)
owner.resleeve_lock = BR.locked
DC.selected_record = TRUE
return TRUE
if("view_stock_brec")
var/datum/species/S = GLOB.all_species[params["view_stock_brec"]]
if(S && (S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) == SPECIES_CAN_JOIN)
// Generate body record from species!
owner = new(null, S.name)
owner.real_name = "Stock [S.name] Body"
owner.name = owner.real_name
owner.dna.real_name = owner.real_name
owner.dna.base_species = S.base_species
owner.resleeve_lock = FALSE
owner.custom_species = "Custom Sleeve" // Custom name
DC.selected_record = TRUE
return TRUE
if("loadfromdisk")
if(!DC.disk)
return FALSE
if(DC.disk.stored && can_change(owner, APPEARANCE_RACE))
BD.load_record_to_body(DC.disk.stored)
DC.selected_record = TRUE
to_chat(ui.user,span_notice("\The [owner]'s bodyrecord was loaded from the disk."))
return TRUE
if("savetodisk")
if(!DC.selected_record)
return FALSE
if(!DC.disk)
return FALSE
if(owner.resleeve_lock)
var/answer = tgui_alert(ui.user,"This body record will be written to a disk and allow any mind to inhabit it. This is against the current body owner's configured OOC preferences for body impersonation. Please confirm that you have permission to do this, and are sure! Admins will be notified.","Mind Compatability",list("No","Yes"))
if(!answer)
return
if(answer == "No")
to_chat(ui.user, span_warning("ERROR: This body record is restricted."))
else
message_admins("[ui.user] wrote an unlocked version of [owner.real_name]'s bodyrecord to a disk. Their preferences do not allow body impersonation, but may be allowed with OOC consent.")
owner.resleeve_lock = FALSE // unlock it, even though it's only temp, so you don't get the warning every time
if(!owner.resleeve_lock && can_change(owner, APPEARANCE_RACE))
// Create it from the mob
if(DC.disk.stored)
qdel_null(DC.disk.stored)
to_chat(ui.user,span_notice("\The [owner]'s bodyrecord was saved to the disk."))
DC.disk.stored = new /datum/transhuman/body_record(owner, FALSE, FALSE) // Saves a COPY!
DC.disk.stored.locked = FALSE // remove lock
DC.disk.name = "[initial(DC.disk.name)] ([owner.real_name])"
return TRUE
if("ejectdisk")
if(!DC.disk)
return FALSE
if(can_change(owner, APPEARANCE_RACE))
to_chat(ui.user,span_notice("You eject the disk."))
DC.disk.forceMove(get_turf(DC))
DC.disk = null
return TRUE
if("back_to_library")
if(can_change(owner, APPEARANCE_RACE))
BD.make_fake_owner()
DC.selected_record = FALSE
return TRUE
return FALSE 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) /datum/tgui_module/appearance_changer/tgui_interact(mob/user, datum/tgui/ui = null, datum/tgui/parent_ui = null, datum/tgui_state/custom_state)
@@ -373,7 +611,7 @@
ui = SStgui.try_update_ui(user, src, ui) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
owner.AddComponent(/datum/component/recursive_move) owner.AddComponent(/datum/component/recursive_move)
RegisterSignal(owner, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen)) RegisterSignal(owner, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen), TRUE)
// Register map objects // Register map objects
user.client.register_map_obj(cam_screen) user.client.register_map_obj(cam_screen)
for(var/plane in cam_plane_masters) for(var/plane in cam_plane_masters)
@@ -400,20 +638,34 @@
if(can_change(owner, APPEARANCE_HAIR)) if(can_change(owner, APPEARANCE_HAIR))
var/hair_styles[0] var/hair_styles[0]
for(var/hair_style in valid_hairstyles) for(var/hair_style in valid_hairstyles)
hair_styles[++hair_styles.len] = list("hairstyle" = hair_style) var/datum/sprite_accessory/hair/S = hair_styles_list[hair_style]
hair_styles[++hair_styles.len] = list("name" = hair_style, "icon" = S.icon, "icon_state" = "[S.icon_state]_s")
data["hair_styles"] = hair_styles data["hair_styles"] = hair_styles
// VOREStation Add - Ears/Tails/Wings
data["ear_styles"] = valid_earstyles data["ear_styles"] = valid_earstyles
data["tail_styles"] = valid_tailstyles data["tail_styles"] = valid_tailstyles
data["wing_styles"] = valid_wingstyles data["wing_styles"] = valid_wingstyles
// VOREStation Add End
markings = owner.get_prioritised_markings()
var/list/usable_markings = markings.Copy() ^ body_marking_styles_list.Copy()
var/marking_styles[0]
for(var/marking_style in usable_markings)
var/datum/sprite_accessory/marking/S = body_marking_styles_list[marking_style]
var/our_iconstate = S.icon_state
if(LAZYLEN(S.body_parts))
our_iconstate += "-[S.body_parts[1]]"
marking_styles[++marking_styles.len] = list("name" = marking_style, "icon" = S.icon, "icon_state" = "[our_iconstate]")
data["marking_styles"] = marking_styles
if(can_change(owner, APPEARANCE_FACIAL_HAIR)) if(can_change(owner, APPEARANCE_FACIAL_HAIR))
var/facial_hair_styles[0] var/facial_hair_styles[0]
for(var/facial_hair_style in valid_facial_hairstyles) for(var/facial_hair_style in valid_facial_hairstyles)
facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_style) var/datum/sprite_accessory/facial_hair/S = facial_hair_styles_list[facial_hair_style]
facial_hair_styles[++facial_hair_styles.len] = list("name" = facial_hair_style, "icon" = S.icon, "icon_state" = "[S.icon_state]_s")
data["facial_hair_styles"] = facial_hair_styles data["facial_hair_styles"] = facial_hair_styles
if(can_change(owner, APPEARANCE_HAIR_COLOR))
data["hair_grads"] = valid_gradstyles
return data return data
/datum/tgui_module/appearance_changer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) /datum/tgui_module/appearance_changer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
@@ -421,10 +673,82 @@
generate_data(user, owner) generate_data(user, owner)
data["is_design_console"] = FALSE
data["disk"] = FALSE
data["selected_a_record"] = FALSE
data["character_records"] = list()
data["stock_records"] = list()
// Handle some unique stuff to the body design console
var/obj/machinery/computer/transhuman/designer/DC = null
if(istype(src,/datum/tgui_module/appearance_changer/body_designer))
var/datum/tgui_module/appearance_changer/body_designer/BD = src
DC = BD.linked_body_design_console?.resolve()
if(DC)
data["is_design_console"] = TRUE
data["disk"] = !isnull(DC.disk)
// Monkey is a placeholder, because I am not hackcoding the appearance changer to accept a null owner - Willbird
data["selected_a_record"] = DC.selected_record
if(!DC.selected_record)
// Load all records on station that can be printed
var/list/bodyrecords_list_ui = list()
for(var/N in DC.our_db.body_scans)
var/datum/transhuman/body_record/BR = DC.our_db.body_scans[N]
var/datum/species/S = GLOB.all_species[BR.mydna.dna.species]
if((S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) != SPECIES_CAN_JOIN || BR.synthetic) continue
bodyrecords_list_ui[++bodyrecords_list_ui.len] = list("name" = N, "recref" = "\ref[BR]")
data["character_records"] = bodyrecords_list_ui
// Load all stock records printable
var/list/stock_bodyrecords_list_ui = list()
for (var/N in GLOB.all_species)
var/datum/species/S = GLOB.all_species[N]
if((S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) != SPECIES_CAN_JOIN) continue
stock_bodyrecords_list_ui += N
data["stock_records"] = stock_bodyrecords_list_ui
data["change_race"] = can_change(owner, APPEARANCE_RACE)
data["gender_id"] = can_change(owner, APPEARANCE_GENDER)
data["change_gender"] = can_change(owner, APPEARANCE_GENDER)
data["change_hair"] = can_change(owner, APPEARANCE_HAIR)
data["change_eye_color"] = can_change(owner, APPEARANCE_EYE_COLOR)
data["change_hair_color"] = can_change(owner, APPEARANCE_HAIR_COLOR)
data["change_facial_hair_color"] = can_change(owner, APPEARANCE_FACIAL_HAIR_COLOR)
// Drop out early, as we have nothing to edit, and are on the BR menu for the designer
return data
// species/body
data["species_name"] = owner.custom_species
data["use_custom_icon"] = (owner.species.selects_bodytype >= SELECTS_BODYTYPE_CUSTOM)
data["base_icon"] = owner.species.base_species
data["synthetic"] = owner.synthetic ? "Yes" : "No"
data["size_scale"] = player_size_name(owner.size_multiplier)
data["scale_appearance"] = owner.dna.scale_appearance ? "Fuzzy" : "Sharp"
data["offset_override"] = owner.dna.offset_override ? "Odd" : "Even"
data["weight"] = owner.weight
data["digitigrade"] = owner.digitigrade
data["blood_reagent"] = owner.dna.blood_reagents
data["blood_color"] = owner.dna.blood_color
// CHOMPEnable Start
data["species_sound"] = owner.species.species_sounds //TODO: RAISE UP FROM CHOMP
// CHOMPEnable End
// Are these needed? It seems to be only used if above is unset??
//data["species_sounds_gendered"] = owner.species.gender_specific_species_sounds
//data["species_sounds_female"] = owner.species.species_sounds_female
//data["species_sounds_male"] = owner.species.species_sounds_male
// flavor
if(!owner.flavor_texts.len)
owner.flavor_texts["general"] = ""
owner.flavor_texts["head"] = ""
owner.flavor_texts["face"] = ""
owner.flavor_texts["eyes"] = ""
owner.flavor_texts["torso"] = ""
owner.flavor_texts["arms"] = ""
owner.flavor_texts["hands"] = ""
owner.flavor_texts["legs"] = ""
owner.flavor_texts["feet"] = ""
data["flavor_text"] = owner.flavor_texts.Copy()
data["name"] = owner.name data["name"] = owner.name
data["specimen"] = owner.species.name data["specimen"] = owner.species.name
data["gender"] = owner.gender data["gender"] = owner.gender
data["gender_id"] = owner.identifying_gender data["gender_id"] = owner.identifying_gender //This is saved to your MIND.
data["change_race"] = can_change(owner, APPEARANCE_RACE) data["change_race"] = can_change(owner, APPEARANCE_RACE)
data["change_gender"] = can_change(owner, APPEARANCE_GENDER) data["change_gender"] = can_change(owner, APPEARANCE_GENDER)
@@ -442,7 +766,6 @@
if(data["change_hair"]) if(data["change_hair"])
data["hair_style"] = owner.h_style data["hair_style"] = owner.h_style
// VOREStation Add - Ears/Tails/Wings
data["ear_style"] = owner.ear_style data["ear_style"] = owner.ear_style
data["ear_secondary_style"] = owner.ear_secondary_style?.name data["ear_secondary_style"] = owner.ear_secondary_style?.name
data["tail_style"] = owner.tail_style data["tail_style"] = owner.tail_style
@@ -452,7 +775,6 @@
for (var/marking in markings) for (var/marking in markings)
markings_data[++markings_data.len] = list("marking_name" = marking, "marking_color" = markings[marking]["color"] ? markings[marking]["color"] : "#000000") //too tired to add in another submenu for bodyparts here markings_data[++markings_data.len] = list("marking_name" = marking, "marking_color" = markings[marking]["color"] ? markings[marking]["color"] : "#000000") //too tired to add in another submenu for bodyparts here
data["markings"] = markings_data data["markings"] = markings_data
// VOREStation Add End
data["change_facial_hair"] = can_change(owner, APPEARANCE_FACIAL_HAIR) data["change_facial_hair"] = can_change(owner, APPEARANCE_FACIAL_HAIR)
if(data["change_facial_hair"]) if(data["change_facial_hair"])
@@ -470,10 +792,13 @@
data["change_hair_color"] = can_change(owner, APPEARANCE_HAIR_COLOR) data["change_hair_color"] = can_change(owner, APPEARANCE_HAIR_COLOR)
if(data["change_hair_color"]) if(data["change_hair_color"])
data["hair_color"] = rgb(owner.r_hair, owner.g_hair, owner.b_hair) data["hair_color"] = rgb(owner.r_hair, owner.g_hair, owner.b_hair)
// VOREStation Add - Ears/Tails/Wings data["hair_color_grad"] = rgb(owner.r_grad, owner.g_grad, owner.b_grad)
data["ears_color"] = rgb(owner.r_ears, owner.g_ears, owner.b_ears) data["ears_color"] = rgb(owner.r_ears, owner.g_ears, owner.b_ears)
data["ears2_color"] = rgb(owner.r_ears2, owner.g_ears2, owner.b_ears2) data["ears2_color"] = rgb(owner.r_ears2, owner.g_ears2, owner.b_ears2)
// not a color, but it basically is
data["hair_grad"] = owner.grad_style
// secondary ear colors // secondary ear colors
var/list/ear_secondary_color_channels = owner.ear_secondary_colors || list() var/list/ear_secondary_color_channels = owner.ear_secondary_colors || list()
ear_secondary_color_channels.len = owner.ear_secondary_style?.get_color_channel_count() || 0 ear_secondary_color_channels.len = owner.ear_secondary_style?.get_color_channel_count() || 0
@@ -485,7 +810,6 @@
data["wing_color"] = rgb(owner.r_wing, owner.g_wing, owner.b_wing) data["wing_color"] = rgb(owner.r_wing, owner.g_wing, owner.b_wing)
data["wing2_color"] = rgb(owner.r_wing2, owner.g_wing2, owner.b_wing2) data["wing2_color"] = rgb(owner.r_wing2, owner.g_wing2, owner.b_wing2)
data["wing3_color"] = rgb(owner.r_wing3, owner.g_wing3, owner.b_wing3) data["wing3_color"] = rgb(owner.r_wing3, owner.g_wing3, owner.b_wing3)
// VOREStation Add End
data["change_facial_hair_color"] = can_change(owner, APPEARANCE_FACIAL_HAIR_COLOR) data["change_facial_hair_color"] = can_change(owner, APPEARANCE_FACIAL_HAIR_COLOR)
if(data["change_facial_hair_color"]) if(data["change_facial_hair_color"])
@@ -502,26 +826,6 @@
cam_background.icon_state = "clear" cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, 1, 1) cam_background.fill_rect(1, 1, 1, 1)
local_skybox.cut_overlays() local_skybox.cut_overlays()
/*
var/turf/newturf = get_turf(customize_usr ? tgui_host() : owner)
if(newturf == last_camera_turf)
return
last_camera_turf = newturf
var/list/visible_turfs = list()
for(var/turf/T in range(1, newturf))
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(newturf)))
local_skybox.scale_to_view(3)
local_skybox.set_position("CENTER", "CENTER", (world.maxx>>1) - newturf.x, (world.maxy>>1) - newturf.y)
*/
/datum/tgui_module/appearance_changer/proc/update_dna(mob/living/carbon/human/target) /datum/tgui_module/appearance_changer/proc/update_dna(mob/living/carbon/human/target)
if(target && (flags & APPEARANCE_UPDATE_DNA)) if(target && (flags & APPEARANCE_UPDATE_DNA))
@@ -540,11 +844,10 @@
// Making the assumption that the available species remain constant // Making the assumption that the available species remain constant
valid_hairstyles.Cut() valid_hairstyles.Cut()
valid_facial_hairstyles.Cut() valid_facial_hairstyles.Cut()
// VOREStation Add - Ears/Tails/Wings
valid_earstyles.Cut() valid_earstyles.Cut()
valid_tailstyles.Cut() valid_tailstyles.Cut()
valid_wingstyles.Cut() valid_wingstyles.Cut()
// VOREStation Add End valid_gradstyles.Cut()
/datum/tgui_module/appearance_changer/proc/generate_data(mob/user, mob/living/carbon/human/target) /datum/tgui_module/appearance_changer/proc/generate_data(mob/user, mob/living/carbon/human/target)
if(!ishuman(target)) if(!ishuman(target))
@@ -557,7 +860,6 @@
valid_hairstyles = target.generate_valid_hairstyles(check_gender = 0) valid_hairstyles = target.generate_valid_hairstyles(check_gender = 0)
valid_facial_hairstyles = target.generate_valid_facial_hairstyles() valid_facial_hairstyles = target.generate_valid_facial_hairstyles()
// VOREStation Add - Ears/Tails/Wings
if(!LAZYLEN(valid_earstyles)) if(!LAZYLEN(valid_earstyles))
for(var/path in ear_styles_list) for(var/path in ear_styles_list)
var/datum/sprite_accessory/ears/instance = ear_styles_list[path] var/datum/sprite_accessory/ears/instance = ear_styles_list[path]
@@ -567,6 +869,8 @@
"instance" = REF(instance), "instance" = REF(instance),
"color" = !!instance.do_colouration, "color" = !!instance.do_colouration,
"second_color" = !!instance.extra_overlay, "second_color" = !!instance.extra_overlay,
"icon" = instance.icon,
"icon_state" = instance.icon_state
))) )))
if(!LAZYLEN(valid_tailstyles)) if(!LAZYLEN(valid_tailstyles))
@@ -578,6 +882,8 @@
"instance" = REF(instance), "instance" = REF(instance),
"color" = !!instance.do_colouration, "color" = !!instance.do_colouration,
"second_color" = !!instance.extra_overlay, "second_color" = !!instance.extra_overlay,
"icon" = instance.icon,
"icon_state" = instance.icon_state
))) )))
if(!LAZYLEN(valid_wingstyles)) if(!LAZYLEN(valid_wingstyles))
@@ -589,8 +895,13 @@
"instance" = REF(instance), "instance" = REF(instance),
"color" = !!instance.do_colouration, "color" = !!instance.do_colouration,
"second_color" = !!instance.extra_overlay, "second_color" = !!instance.extra_overlay,
"icon" = instance.icon,
"icon_state" = instance.icon_state
))) )))
// VOREStation Add End
if(!LAZYLEN(valid_gradstyles))
for(var/key in GLOB.hair_gradients)
valid_gradstyles.Add(list(list(key)))
/datum/tgui_module/appearance_changer/proc/get_genders(mob/living/carbon/human/target) /datum/tgui_module/appearance_changer/proc/get_genders(mob/living/carbon/human/target)
var/datum/species/S = target.species var/datum/species/S = target.species
@@ -605,7 +916,6 @@
/datum/tgui_module/appearance_changer/proc/changed_hook(flag) /datum/tgui_module/appearance_changer/proc/changed_hook(flag)
return return
// VOREStation Add - Ears/Tails/Wings
/datum/tgui_module/appearance_changer/proc/can_use_sprite(datum/sprite_accessory/X, mob/living/carbon/human/target, mob/user) /datum/tgui_module/appearance_changer/proc/can_use_sprite(datum/sprite_accessory/X, mob/living/carbon/human/target, mob/user)
if(X.name == DEVELOPER_WARNING_NAME) if(X.name == DEVELOPER_WARNING_NAME)
return FALSE return FALSE
@@ -616,8 +926,11 @@
return FALSE return FALSE
return TRUE return TRUE
// VOREStation Add End
// Subtypes for specific items or machines:
// *******************************************************
// Salon Pro
// *******************************************************
/datum/tgui_module/appearance_changer/mirror /datum/tgui_module/appearance_changer/mirror
name = "SalonPro Nano-Mirror&trade;" name = "SalonPro Nano-Mirror&trade;"
flags = APPEARANCE_ALL_HAIR flags = APPEARANCE_ALL_HAIR
@@ -625,3 +938,158 @@
/datum/tgui_module/appearance_changer/mirror/coskit /datum/tgui_module/appearance_changer/mirror/coskit
name = "SalonPro Porta-Makeover Deluxe&trade;" name = "SalonPro Porta-Makeover Deluxe&trade;"
// *******************************************************
// Vore TF
// *******************************************************
/datum/tgui_module/appearance_changer/vore
name = "Appearance Editor (Vore)"
flags = APPEARANCE_ALL
/datum/tgui_module/appearance_changer/vore/tgui_state(mob/user)
return GLOB.tgui_conscious_state
/datum/tgui_module/appearance_changer/vore/tgui_status(mob/user, datum/tgui_state/state)
if(!isbelly(owner.loc))
return STATUS_CLOSE
return ..()
/datum/tgui_module/appearance_changer/vore/update_active_camera_screen()
cam_screen.vis_contents = list(owner)
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, 1, 1)
local_skybox.cut_overlays()
/datum/tgui_module/appearance_changer/vore/tgui_close(mob/user)
. = ..()
QDEL_IN(src, 1)
/datum/tgui_module/appearance_changer/vore/changed_hook(flag)
var/mob/living/carbon/human/M = owner
var/mob/living/O = usr
switch(flag)
if(APPEARANCECHANGER_CHANGED_RACE)
to_chat(M, span_notice("You lose sensation of your body, feeling only the warmth of everything around you... "))
to_chat(O, span_notice("Your body shifts as you make dramatic changes to your captive's body."))
if(APPEARANCECHANGER_CHANGED_GENDER)
to_chat(M, span_notice("Your body feels very strange..."))
to_chat(O, span_notice("You feel strange as you alter your captive's gender."))
if(APPEARANCECHANGER_CHANGED_GENDER_ID)
to_chat(M, span_notice("You start to feel... [capitalize(M.gender)]?"))
to_chat(O, span_notice("You feel strange as you alter your captive's gender identity."))
if(APPEARANCECHANGER_CHANGED_SKINTONE, APPEARANCECHANGER_CHANGED_SKINCOLOR)
to_chat(M, span_notice("Your body tingles all over..."))
to_chat(O, span_notice("You tingle as you make noticeable changes to your captive's body."))
if(APPEARANCECHANGER_CHANGED_HAIRSTYLE, APPEARANCECHANGER_CHANGED_HAIRCOLOR, APPEARANCECHANGER_CHANGED_F_HAIRSTYLE, APPEARANCECHANGER_CHANGED_F_HAIRCOLOR)
to_chat(M, span_notice("Your body tingles all over..."))
to_chat(O, span_notice("You tingle as you make noticeable changes to your captive's body."))
if(APPEARANCECHANGER_CHANGED_EYES)
to_chat(M, span_notice("You feel lightheaded and drowsy..."))
to_chat(O, span_notice("You feel warm as you make subtle changes to your captive's body."))
// *******************************************************
// Weaver Cocoon
// *******************************************************
/datum/tgui_module/appearance_changer/cocoon
name ="Appearance Editor (Cocoon)"
flags = APPEARANCE_ALL_HAIR
customize_usr = TRUE
/datum/tgui_module/appearance_changer/cocoon/tgui_status(mob/user, datum/tgui_state/state)
//if(!istype(owner.loc, /obj/item/storage/vore_egg/bugcocoon))
if(!owner.transforming)
return STATUS_CLOSE
return ..()
// *******************************************************
// Body design console
// *******************************************************
/datum/tgui_module/appearance_changer/body_designer
name ="Appearance Editor (Body Designer)"
flags = APPEARANCE_ALL
var/datum/weakref/linked_body_design_console = null
/datum/tgui_module/appearance_changer/body_designer/tgui_status(mob/user, datum/tgui_state/state)
if(!istype(host,/obj/machinery/computer/transhuman/designer))
return STATUS_CLOSE
return ..()
/datum/tgui_module/appearance_changer/body_designer/Destroy()
var/obj/machinery/computer/transhuman/designer/DC = linked_body_design_console?.resolve()
if(DC)
DC.selected_record = FALSE
DC.designer_gui = null // no hardrefs
. = ..()
/datum/tgui_module/appearance_changer/body_designer/proc/make_fake_owner()
// checks for monkey to tell if on the menu
if(owner)
UnregisterSignal(owner, COMSIG_OBSERVER_MOVED)
qdel_null(owner)
owner = new(src)
owner.set_species(SPECIES_LLEILL)
owner.species.produceCopy(owner.species.traits.Copy(),owner,null,FALSE)
owner.invisibility = 101
// Add listeners back
owner.AddComponent(/datum/component/recursive_move)
RegisterSignal(owner, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen), TRUE)
/datum/tgui_module/appearance_changer/body_designer/proc/load_record_to_body(var/datum/transhuman/body_record/current_project)
if(owner)
UnregisterSignal(owner, COMSIG_OBSERVER_MOVED)
qdel_null(owner)
//Get the DNA and generate a new mob
var/datum/dna2/record/R = current_project.mydna
owner = new /mob/living/carbon/human(src, R.dna.species)
//Fix the external organs
for(var/part in current_project.limb_data)
var/status = current_project.limb_data[part]
if(status == null) continue //Species doesn't have limb? Child of amputated limb?
var/obj/item/organ/external/O = owner.organs_by_name[part]
if(!O) continue //Not an organ. Perhaps another amputation removed it already.
if(status == 1) //Normal limbs
continue
else if(status == 0) //Missing limbs
O.remove_rejuv()
else if(status) //Anything else is a manufacturer
O.remove_rejuv() //Don't robotize them, leave them removed so robotics can attach a part.
for(var/part in current_project.organ_data)
var/status = current_project.organ_data[part]
if(status == null) continue //Species doesn't have organ? Child of missing part?
var/obj/item/organ/I = owner.internal_organs_by_name[part]
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
if(status == 0) //Normal organ
continue
else if(status == 1) //Assisted organ
I.mechassist()
else if(status == 2) //Mechanical organ
I.robotize()
else if(status == 3) //Digital organ
I.digitize()
//Set the name or generate one
owner.real_name = R.dna.real_name
owner.name = owner.real_name
//Apply DNA
owner.dna = R.dna.Clone()
owner.original_player = current_project.ckey
//Apply legs
owner.digitigrade = R.dna.digitigrade // ensure clone mob has digitigrade var set appropriately
if(owner.dna.digitigrade <> R.dna.digitigrade)
owner.dna.digitigrade = R.dna.digitigrade // ensure cloned DNA is set appropriately from record??? for some reason it doesn't get set right despite the override to datum/dna/Clone()
//Update appearance, remake icons
owner.UpdateAppearance()
//owner.sync_dna_traits(FALSE) //Needs trait genetics first
owner.sync_organ_dna()
owner.dna.blood_reagents = R.dna.blood_reagents
owner.dna.blood_color = R.dna.blood_color
owner.regenerate_icons()
owner.flavor_texts = current_project.mydna.flavor.Copy()
owner.resize(current_project.sizemult, FALSE)
owner.appearance_flags = current_project.aflags
owner.weight = current_project.weight
if(current_project.speciesname)
owner.custom_species = current_project.speciesname
// Add listeners back
owner.AddComponent(/datum/component/recursive_move)
RegisterSignal(owner, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen), TRUE)

View File

@@ -1,57 +0,0 @@
/datum/tgui_module/appearance_changer/vore
name = "Appearance Editor (Vore)"
flags = APPEARANCE_ALL
/datum/tgui_module/appearance_changer/vore/tgui_state(mob/user)
return GLOB.tgui_conscious_state
/datum/tgui_module/appearance_changer/vore/tgui_status(mob/user, datum/tgui_state/state)
if(!isbelly(owner.loc))
return STATUS_CLOSE
return ..()
/datum/tgui_module/appearance_changer/vore/update_active_camera_screen()
cam_screen.vis_contents = list(owner)
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, 1, 1)
local_skybox.cut_overlays()
/datum/tgui_module/appearance_changer/vore/tgui_close(mob/user)
. = ..()
QDEL_IN(src, 1)
/datum/tgui_module/appearance_changer/vore/changed_hook(flag)
var/mob/living/carbon/human/M = owner
var/mob/living/O = usr
switch(flag)
if(APPEARANCECHANGER_CHANGED_RACE)
to_chat(M, span_notice("You lose sensation of your body, feeling only the warmth of everything around you... "))
to_chat(O, span_notice("Your body shifts as you make dramatic changes to your captive's body."))
if(APPEARANCECHANGER_CHANGED_GENDER)
to_chat(M, span_notice("Your body feels very strange..."))
to_chat(O, span_notice("You feel strange as you alter your captive's gender."))
if(APPEARANCECHANGER_CHANGED_GENDER_ID)
to_chat(M, span_notice("You start to feel... [capitalize(M.gender)]?"))
to_chat(O, span_notice("You feel strange as you alter your captive's gender identity."))
if(APPEARANCECHANGER_CHANGED_SKINTONE, APPEARANCECHANGER_CHANGED_SKINCOLOR)
to_chat(M, span_notice("Your body tingles all over..."))
to_chat(O, span_notice("You tingle as you make noticeable changes to your captive's body."))
if(APPEARANCECHANGER_CHANGED_HAIRSTYLE, APPEARANCECHANGER_CHANGED_HAIRCOLOR, APPEARANCECHANGER_CHANGED_F_HAIRSTYLE, APPEARANCECHANGER_CHANGED_F_HAIRCOLOR)
to_chat(M, span_notice("Your body tingles all over..."))
to_chat(O, span_notice("You tingle as you make noticeable changes to your captive's body."))
if(APPEARANCECHANGER_CHANGED_EYES)
to_chat(M, span_notice("You feel lightheaded and drowsy..."))
to_chat(O, span_notice("You feel warm as you make subtle changes to your captive's body."))
// Cocoon Stuff
/datum/tgui_module/appearance_changer/cocoon
name ="Appearance Editor (Cocoon)"
flags = APPEARANCE_ALL_HAIR
customize_usr = TRUE
/datum/tgui_module/appearance_changer/cocoon/tgui_status(mob/user, datum/tgui_state/state)
//if(!istype(owner.loc, /obj/item/storage/vore_egg/bugcocoon))
if(!owner.transforming)
return STATUS_CLOSE
return ..()

View File

@@ -21,11 +21,6 @@
name = "WolfTG (Taur)" name = "WolfTG (Taur)"
icon_state = "wolf2_s" icon_state = "wolf2_s"
/datum/sprite_accessory/tail/taur/wolf/wolf_2fat
icon = 'icons/mob/vore/taurs_yw.dmi' //CHOMP Fix
name = "Fat Wolf (Taur)"
icon_state = "wolf2f_s"
/datum/sprite_accessory/tail/taur/long_lizard /datum/sprite_accessory/tail/taur/long_lizard
name = "Large Dragon Tail" name = "Large Dragon Tail"
icon_state = "big_liz" icon_state = "big_liz"

View File

@@ -0,0 +1,87 @@
/datum/unit_test/sprite_accessories_shall_be_unique
name = "COSMETICS: Entries shall have unique name."
/datum/unit_test/sprite_accessories_shall_be_unique/start_test()
var/failed = 0
failed += validate_accessory_list( /datum/sprite_accessory/ears)
failed += validate_accessory_list( /datum/sprite_accessory/facial_hair)
failed += validate_accessory_list( /datum/sprite_accessory/hair)
failed += validate_accessory_list( /datum/sprite_accessory/hair_accessory)
failed += validate_accessory_list( /datum/sprite_accessory/marking)
failed += validate_accessory_list( /datum/sprite_accessory/tail)
failed += validate_accessory_list( /datum/sprite_accessory/wing)
if(failed)
fail("One or more /datum/sprite_accessory definitions had invalid names, icon_states, or names were reused definitions")
else
pass("All /datum/sprite_accessory definitions had correct settings.")
return 1
/datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_accessory_list(var/path)
var/failed = 0
var/total_good = 0
var/total_all = 0
var/list/collection = list()
for(var/SP in subtypesof(path))
total_all++
var/datum/sprite_accessory/A = new SP()
if(!A)
log_unit_test("[SP]: Cosmetic - Path resolved to null in list.")
continue
if(!A.name)
log_unit_test("[A] - [A.type]: Cosmetic - Missing name.")
failed = 1
if(A.name == DEVELOPER_WARNING_NAME)
continue
if(collection[A.name])
log_unit_test("[A] - [A.type]: Cosmetic - Name defined twice. Original def [collection[A.name]]")
failed = 1
else
collection[A.name] = A.type
if(istype(A,text2path("[path]/invisible")))
if(A.icon_state)
log_unit_test("[A] - [A.type]: Cosmetic - Invisible subtype has icon_state.")
failed = 1
else if(!A.icon_state)
log_unit_test("[A] - [A.type]: Cosmetic - Has no icon_state.")
failed = 1
else
// Check if valid icon
failed += validate_icons(A)
total_good++
qdel(A)
log_unit_test("[path]: Cosmetic - Total valid count: [total_good]/[total_all].")
return failed
/datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_icons(var/datum/sprite_accessory/A)
var/failed = 0
var/actual_icon_state = A.icon_state
if(istype(A,/datum/sprite_accessory/hair))
actual_icon_state = "[A.icon_state]_s"
if(!(actual_icon_state in cached_icon_states(A.icon)))
log_unit_test("[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].")
failed = 1
if(istype(A,/datum/sprite_accessory/facial_hair))
actual_icon_state = "[A.icon_state]_s"
if(!(actual_icon_state in cached_icon_states(A.icon)))
log_unit_test("[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].")
failed = 1
if(istype(A,/datum/sprite_accessory/marking))
var/datum/sprite_accessory/marking/MA = A
for(var/BP in MA.body_parts)
actual_icon_state = "[A.icon_state]-[BP]"
if(!(actual_icon_state in cached_icon_states(A.icon)))
log_unit_test("[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].")
failed = 1
return failed

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -136,7 +136,7 @@
/datum/sprite_accessory/hair/shyold /datum/sprite_accessory/hair/shyold
name = "Shy old" name = "Shy old"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "hair_shy_old" icon_state = "hair_shy_old"
flags = HAIR_TIEABLE flags = HAIR_TIEABLE
@@ -175,7 +175,7 @@
/datum/sprite_accessory/hair/emoleft /datum/sprite_accessory/hair/emoleft
name = "Emo Left" name = "Emo Left"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "hair_emoleft" icon_state = "hair_emoleft"
flags = HAIR_TIEABLE flags = HAIR_TIEABLE
@@ -205,7 +205,7 @@
/datum/sprite_accessory/hair/doll /datum/sprite_accessory/hair/doll
name = "Doll" name = "Doll"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "hair_doll" icon_state = "hair_doll"
flags = HAIR_TIEABLE flags = HAIR_TIEABLE
@@ -356,12 +356,12 @@
/datum/sprite_accessory/hair/teshari/tallmohawk /datum/sprite_accessory/hair/teshari/tallmohawk
name = "Teshari Tall Mohawk" name = "Teshari Tall Mohawk"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_tallmohawk" icon_state = "teshari_tallmohawk"
/datum/sprite_accessory/hair/teshari/aerodynamic /datum/sprite_accessory/hair/teshari/aerodynamic
name = "Teshari Aerodynamic" name = "Teshari Aerodynamic"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_aerodynamic" icon_state = "teshari_aerodynamic"
/datum/sprite_accessory/hair/teshari/pointy /datum/sprite_accessory/hair/teshari/pointy
@@ -369,7 +369,7 @@
/datum/sprite_accessory/hair/teshari/crowned /datum/sprite_accessory/hair/teshari/crowned
name = "Teshari Crowned" name = "Teshari Crowned"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_crowned" icon_state = "teshari_crowned"
/datum/sprite_accessory/hair/teshari/tight /datum/sprite_accessory/hair/teshari/tight
@@ -377,7 +377,7 @@
/datum/sprite_accessory/hair/teshari/bun /datum/sprite_accessory/hair/teshari/bun
name = "Teshari Bun" name = "Teshari Bun"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_bun" icon_state = "teshari_bun"
/datum/sprite_accessory/hair/teshari/droopy /datum/sprite_accessory/hair/teshari/droopy
@@ -402,7 +402,7 @@
/datum/sprite_accessory/hair/teshari/peel /datum/sprite_accessory/hair/teshari/peel
name = "Teshari Peel" name = "Teshari Peel"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_peel" icon_state = "teshari_peel"
/datum/sprite_accessory/hair/teshari/altdefault /datum/sprite_accessory/hair/teshari/altdefault
@@ -410,17 +410,17 @@
/datum/sprite_accessory/hair/teshari/sleek /datum/sprite_accessory/hair/teshari/sleek
name = "Teshari Sleek" name = "Teshari Sleek"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_sleek" icon_state = "teshari_sleek"
/datum/sprite_accessory/hair/teshari/ponytail /datum/sprite_accessory/hair/teshari/ponytail
name = "Teshari Ponytail" name = "Teshari Ponytail"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_ponytail" icon_state = "teshari_ponytail"
/datum/sprite_accessory/hair/teshari/sweep /datum/sprite_accessory/hair/teshari/sweep
name = "Teshari Sweep" name = "Teshari Sweep"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_sweep" icon_state = "teshari_sweep"
/datum/sprite_accessory/hair/teshari/spike /datum/sprite_accessory/hair/teshari/spike
@@ -431,7 +431,7 @@
/datum/sprite_accessory/hair/teshari/spiky2 /datum/sprite_accessory/hair/teshari/spiky2
name = "Teshari Alt. Spiky" name = "Teshari Alt. Spiky"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_spiky2" icon_state = "teshari_spiky2"
/datum/sprite_accessory/hair/teshari/mane /datum/sprite_accessory/hair/teshari/mane
@@ -454,12 +454,12 @@
/datum/sprite_accessory/hair/teshari/crest /datum/sprite_accessory/hair/teshari/crest
name = "Teshari Crest" name = "Teshari Crest"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon= 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_crest" icon_state = "teshari_crest"
/datum/sprite_accessory/hair/teshari/soap /datum/sprite_accessory/hair/teshari/soap
name = "Teshari Soap" name = "Teshari Soap"
icon_add = 'modular_chomp/icons/mob/human_face.dmi' icon = 'modular_chomp/icons/mob/human_face.dmi'
icon_state = "teshari_soap" icon_state = "teshari_soap"
//screll hair override //screll hair override
@@ -529,8 +529,6 @@
/datum/sprite_accessory/hair/una/Chomp /datum/sprite_accessory/hair/una/Chomp
name = "Long Unathi Spines Ch." name = "Long Unathi Spines Ch."
icon_state = "soghun_longspines" icon_state = "soghun_longspines"
name = "Long Unathi Spines"
icon_state = "soghun_longspines"
icon = 'modular_chomp/icons/mob/hair_unathi.dmi' icon = 'modular_chomp/icons/mob/hair_unathi.dmi'
icon_add = 'modular_chomp/icons/mob/hair_unathi_add.dmi' icon_add = 'modular_chomp/icons/mob/hair_unathi_add.dmi'
@@ -606,24 +604,12 @@
name = "Curled Unathi Horns" name = "Curled Unathi Horns"
icon_state = "unathi_horns_curled" icon_state = "unathi_horns_curled"
/datum/sprite_accessory/hair/una/ram_horns
icon = 'modular_chomp/icons/mob/hair_unathi.dmi'
icon_add = 'modular_chomp/icons/mob/hair_unathi_add.dmi'
name = "Unathi Ram Horns"
icon_state = "unathi_horns_ram"
/datum/sprite_accessory/hair/una/thick_ram_horns /datum/sprite_accessory/hair/una/thick_ram_horns
icon = 'modular_chomp/icons/mob/hair_unathi.dmi' icon = 'modular_chomp/icons/mob/hair_unathi.dmi'
icon_add = 'modular_chomp/icons/mob/hair_unathi_add.dmi' icon_add = 'modular_chomp/icons/mob/hair_unathi_add.dmi'
name = "Thick Unathi Ram Horns" name = "Thick Unathi Ram Horns"
icon_state = "unathi_horns_ram_thick" icon_state = "unathi_horns_ram_thick"
/datum/sprite_accessory/hair/una/double_horns
icon = 'modular_chomp/icons/mob/hair_unathi.dmi'
icon_add = 'modular_chomp/icons/mob/hair_unathi_add.dmi'
name = "Double Unathi Horns"
icon_state = "unathi_horns_double"
/datum/sprite_accessory/hair/una/swept_horns /datum/sprite_accessory/hair/una/swept_horns
icon = 'modular_chomp/icons/mob/hair_unathi.dmi' icon = 'modular_chomp/icons/mob/hair_unathi.dmi'
icon_add = 'modular_chomp/icons/mob/hair_unathi_add.dmi' icon_add = 'modular_chomp/icons/mob/hair_unathi_add.dmi'

View File

@@ -145,19 +145,6 @@
hide_body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG) hide_body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG)
body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_GROIN) body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_GROIN)
/datum/sprite_accessory/marking/ch/sect_drone
name = "Sect Drone Bodytype"
icon_state = "sectdrone"
color_blend_mode = ICON_MULTIPLY
hide_body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_TORSO,BP_HEAD)
body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_TORSO,BP_HEAD)
/datum/sprite_accessory/marking/ch/sect_drone_eyes
name = "Sect Drone Eyes"
icon_state = "sectdrone_eyes"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_HEAD)
/datum/sprite_accessory/marking/ch/thickneck /datum/sprite_accessory/marking/ch/thickneck
name = "Thick Neck" name = "Thick Neck"
icon_state = "thickneck" icon_state = "thickneck"
@@ -231,7 +218,7 @@
name = "Scaled Belly" name = "Scaled Belly"
icon_state = "scaled_belly" icon_state = "scaled_belly"
hide_body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND,BP_L_LEG,BP_R_LEG,BP_GROIN) hide_body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND,BP_L_LEG,BP_R_LEG,BP_GROIN)
body_parts = list(BP_TORSO,BP_GROIN,BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND) body_parts = list(BP_TORSO)
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
@@ -306,7 +293,7 @@
name = "Chubby Belly, Small" name = "Chubby Belly, Small"
icon_state = "smallchubbybelly" icon_state = "smallchubbybelly"
hide_body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND,BP_L_LEG,BP_R_LEG,BP_GROIN) hide_body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND,BP_L_LEG,BP_R_LEG,BP_GROIN)
body_parts = list(BP_TORSO,BP_GROIN,BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND) body_parts = list(BP_TORSO,BP_GROIN,BP_L_HAND,BP_R_HAND)
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
/datum/sprite_accessory/marking/ch/six_pack /datum/sprite_accessory/marking/ch/six_pack
@@ -332,7 +319,7 @@
/datum/sprite_accessory/marking/ch/sloog_head /datum/sprite_accessory/marking/ch/sloog_head
name = "sloog head" name = "sloog head"
icon = 'modular_chomp/icons/mob/human_races/sprite_accessories/sloog.dmi' icon = 'modular_chomp/icons/mob/human_races/sprite_accessories/sloog.dmi'
icon_state = "slooghead" icon_state = "sloog"
body_parts = list(BP_HEAD) body_parts = list(BP_HEAD)
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
// placed in seperate dmi till normal one is functional. // placed in seperate dmi till normal one is functional.
@@ -379,36 +366,13 @@
// DIGI LEGS // // DIGI LEGS //
/datum/sprite_accessory/marking/ch/xenomorph/digi_r_leg /datum/sprite_accessory/marking/ch/xenomorph/digi_legs
name = "Xenomorph right leg (digitigrade)" name = "Xenomorph legs (digitigrade)"
icon = 'icons/mob/human_races/markings_digi.dmi' icon = 'icons/mob/human_races/markings_digi.dmi'
icon_state = "xeno_digi" icon_state = "xeno_digi"
digitigrade_acceptance = MARKING_DIGITIGRADE_ONLY digitigrade_acceptance = MARKING_DIGITIGRADE_ONLY
body_parts = list(BP_R_LEG, BP_R_FOOT) body_parts = list(BP_R_LEG, BP_L_LEG) //This needs BP_L_FOOT AND BP_R_FOOT added to it but the sprite has to be split for that. And it's an upstream .dmi. So you will have to fix it upstream.
hide_body_parts = list(BP_L_LEG, BP_L_FOOT, BP_R_LEG, BP_R_FOOT)
/datum/sprite_accessory/marking/ch/xenomorph/digi_r_leg_hidden
name = "Xenomorph right leg (digitigrade, hide)"
icon = 'icons/mob/human_races/markings_digi.dmi'
icon_state = "xeno_digi"
digitigrade_acceptance = MARKING_DIGITIGRADE_ONLY
body_parts = list(BP_R_LEG, BP_R_FOOT)
hide_body_parts = list(BP_R_LEG, BP_R_FOOT)
/datum/sprite_accessory/marking/ch/xenomorph/digi_l_leg
name = "Xenomorph left leg (digitigrade)"
icon = 'icons/mob/human_races/markings_digi.dmi'
icon_state = "xeno_digi"
digitigrade_acceptance = MARKING_DIGITIGRADE_ONLY
body_parts = list(BP_L_LEG, BP_L_FOOT)
/datum/sprite_accessory/marking/ch/xenomorph/digi_l_leg_hidden
name = "Xenomorph left leg (digitigrade, hide)"
icon = 'icons/mob/human_races/markings_digi.dmi'
icon_state = "xeno_digi"
digitigrade_acceptance = MARKING_DIGITIGRADE_ONLY
body_parts = list(BP_L_LEG, BP_L_FOOT)
hide_body_parts = list(BP_L_LEG, BP_L_FOOT)
// TORSOS // // TORSOS //

View File

@@ -1,11 +1,3 @@
/datum/sprite_accessory/wing/sect_drone //We should some day make a variable to make some wings not be able to fly
name = "Sect drone wings (To use with bodytype marking)"
desc = ""
icon = 'modular_chomp/icons/mob/human_races/sprite_accessories/wings.dmi'
icon_state = "sectdrone_wing"
do_colouration = 1
color_blend_mode = ICON_MULTIPLY
/datum/sprite_accessory/wing/snagc /datum/sprite_accessory/wing/snagc
name = "xenomorph backplate, colorable" name = "xenomorph backplate, colorable"
desc = "" desc = ""

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 B

After

Width:  |  Height:  |  Size: 676 B

View File

@@ -1,5 +1,5 @@
import { useBackend } from 'tgui/backend'; import { useBackend } from 'tgui/backend';
import { Button, LabeledList, Section, Stack } from 'tgui-core/components'; import { Button, ColorBox, LabeledList, Section } from 'tgui-core/components';
import { Data, species } from './types'; import { Data, species } from './types';
@@ -12,16 +12,88 @@ export const AppearanceChangerSpecies = (props) => {
); );
return ( return (
<Section title="Species" fill scrollable> <Section title="Unique Identifiers" fill scrollable>
{sortedSpecies.map((spec) => ( <Section title="Species">
<Button {sortedSpecies.map((spec) => (
key={spec.specimen} <Button
selected={specimen === spec.specimen} key={spec.specimen}
onClick={() => act('race', { race: spec.specimen })} selected={specimen === spec.specimen}
> onClick={() => act('race', { race: spec.specimen })}
{spec.specimen} >
</Button> {spec.specimen}
))} </Button>
))}
</Section>
<Section title="DNA">
<LabeledList>
{data.is_design_console ? (
<LabeledList.Item label="Character Name">
<Button icon="pen" onClick={() => act('char_name')}>
{data.name}
</Button>
</LabeledList.Item>
) : (
''
)}
<LabeledList.Item label="Custom Species Name">
<Button icon="pen" onClick={() => act('race_name')}>
{data.species_name ? data.species_name : specimen}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Species Appearance">
<Button
icon="pen"
disabled={!data.use_custom_icon}
onClick={() => act('base_icon')}
>
{data.base_icon ? data.base_icon : specimen}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Blood Reagent">
<Button icon="pen" onClick={() => act('blood_reagent')}>
{data.blood_reagent}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Blood Color">
<Button icon="pen" onClick={() => act('blood_color')}>
{data.blood_color}
</Button>
<ColorBox color={data.blood_color} mr={1} />
</LabeledList.Item>
<LabeledList.Item label="Digitigrade">
<Button icon="pen" onClick={() => act('digitigrade')}>
{data.digitigrade ? 'Yes' : 'No'}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Species Sound">
<Button icon="pen" onClick={() => act('species_sound')}>
{data.species_sound}
</Button>
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Sizing">
<LabeledList.Item label="Scale">
<Button icon="pen" onClick={() => act('size_scale')}>
{data.size_scale}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Scale Appearance">
<Button icon="pen" onClick={() => act('scale_appearance')}>
{data.scale_appearance}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Scale Offset">
<Button icon="pen" onClick={() => act('offset_override')}>
{data.offset_override}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Weight">
<Button icon="pen" onClick={() => act('weight')}>
{data.weight}
</Button>
</LabeledList.Item>
</Section>
</Section> </Section>
); );
}; };
@@ -49,6 +121,7 @@ export const AppearanceChangerGender = (props) => {
{id_genders.map((g) => ( {id_genders.map((g) => (
<Button <Button
key={g.gender_key} key={g.gender_key}
disabled={data.is_design_console}
selected={g.gender_key === gender_id} selected={g.gender_key === gender_id}
onClick={() => act('gender_id', { gender_id: g.gender_key })} onClick={() => act('gender_id', { gender_id: g.gender_key })}
> >
@@ -60,115 +133,3 @@ export const AppearanceChangerGender = (props) => {
</Section> </Section>
); );
}; };
export const AppearanceChangerEars = (props) => {
const { act, data } = useBackend<Data>();
const { ear_style, ear_styles } = data;
ear_styles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
return (
<Stack vertical fill>
<Stack.Item grow>
<Section title="Ears" fill scrollable>
<Button
onClick={() => act('ear', { clear: true })}
selected={ear_style === null}
>
-- Not Set --
</Button>
{ear_styles.map((ear) => (
<Button
key={ear.instance}
onClick={() => act('ear', { ref: ear.instance })}
selected={ear.name === ear_style}
>
{ear.name}
</Button>
))}
</Section>
</Stack.Item>
<Stack.Item grow>
<Section title="Ears - Secondary" fill scrollable>
<Button
onClick={() => act('ear_secondary', { clear: true })}
selected={data.ear_secondary_style === null}
>
-- Not Set --
</Button>
{ear_styles.map((ear) => (
<Button
key={ear.instance}
onClick={() => act('ear_secondary', { ref: ear.instance })}
selected={ear.name === ear_style}
>
{ear.name}
</Button>
))}
</Section>
</Stack.Item>
</Stack>
);
};
export const AppearanceChangerTails = (props) => {
const { act, data } = useBackend<Data>();
const { tail_style, tail_styles } = data;
tail_styles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
return (
<Section title="Tails" fill scrollable>
<Button
onClick={() => act('tail', { clear: true })}
selected={tail_style === null}
>
-- Not Set --
</Button>
{tail_styles.map((tail) => (
<Button
key={tail.instance}
onClick={() => act('tail', { ref: tail.instance })}
selected={tail.name === tail_style}
>
{tail.name}
</Button>
))}
</Section>
);
};
export const AppearanceChangerWings = (props) => {
const { act, data } = useBackend<Data>();
const { wing_style, wing_styles } = data;
wing_styles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
return (
<Section title="Wings" fill scrollable>
<Button
onClick={() => act('wing', { clear: true })}
selected={wing_style === null}
>
-- Not Set --
</Button>
{wing_styles.map((wing) => (
<Button
key={wing.instance}
onClick={() => act('wing', { ref: wing.instance })}
selected={wing.name === wing_style}
>
{wing.name}
</Button>
))}
</Section>
);
};

View File

@@ -0,0 +1,41 @@
import { useBackend } from 'tgui/backend';
import { Button, Section } from 'tgui-core/components';
import { Data } from './types';
export const AppearanceChangerBodyRecords = () => {
const { act, data } = useBackend<Data>();
const { character_records, stock_records } = data;
return (
<Section title="Bodyrecord Database">
<Section title="Stock Records">
{stock_records
? stock_records.map((record) => (
<Button
icon="eye"
key={record}
onClick={() =>
act('view_stock_brec', { view_stock_brec: record })
}
>
{record}
</Button>
))
: ''}
</Section>
<Section title="Crew Records">
{character_records
? character_records.map((record) => (
<Button
icon="eye"
key={record.name}
onClick={() => act('view_brec', { view_brec: record.recref })}
>
{record.name}
</Button>
))
: ''}
</Section>
</Section>
);
};

View File

@@ -1,13 +1,21 @@
import { useState } from 'react';
import { useBackend } from 'tgui/backend'; import { useBackend } from 'tgui/backend';
import { import {
Box, Box,
Button, Button,
ColorBox, ColorBox,
Dropdown,
ImageButton,
Input,
LabeledList, LabeledList,
Section, Section,
Stack,
Tabs,
} from 'tgui-core/components'; } from 'tgui-core/components';
import { createSearch } from 'tgui-core/string';
import { Data, SPRITE_ACCESSORY_COLOR_CHANNEL_NAMES } from './types'; import { MARKINGS_PER_PAGE } from './constants';
import { bodyStyle, Data, SPRITE_ACCESSORY_COLOR_CHANNEL_NAMES } from './types';
export const AppearanceChangerColors = (props) => { export const AppearanceChangerColors = (props) => {
const { act, data } = useBackend<Data>(); const { act, data } = useBackend<Data>();
@@ -21,6 +29,8 @@ export const AppearanceChangerColors = (props) => {
eye_color, eye_color,
skin_color, skin_color,
hair_color, hair_color,
hair_grad,
hair_color_grad,
facial_hair_color, facial_hair_color,
ears_color, ears_color,
ears2_color, ears2_color,
@@ -31,6 +41,7 @@ export const AppearanceChangerColors = (props) => {
wing2_color, wing2_color,
wing3_color, wing3_color,
ear_secondary_colors, ear_secondary_colors,
hair_grads,
} = data; } = data;
return ( return (
@@ -64,6 +75,24 @@ export const AppearanceChangerColors = (props) => {
<ColorBox color={hair_color} mr={1} /> <ColorBox color={hair_color} mr={1} />
<Button onClick={() => act('hair_color')}>Change Hair Color</Button> <Button onClick={() => act('hair_color')}>Change Hair Color</Button>
</Box> </Box>
<Box>
<ColorBox color={hair_color_grad} mr={1} />
<Button onClick={() => act('hair_color_grad')}>
Change Hair gradiant Color
</Button>
<Dropdown
autoScroll={false}
width="30%"
selected={hair_grad || 'None'}
options={hair_grads.map((key: string) => {
return {
displayText: key,
value: key,
};
})}
onSelected={(val: string) => act('hair_grad', { picked: val })}
/>
</Box>
<Box> <Box>
<ColorBox color={ears_color} mr={1} /> <ColorBox color={ears_color} mr={1} />
<Button onClick={() => act('ears_color')}> <Button onClick={() => act('ears_color')}>
@@ -76,7 +105,7 @@ export const AppearanceChangerColors = (props) => {
Change Ears Color (Secondary) Change Ears Color (Secondary)
</Button> </Button>
</Box> </Box>
{data.ear_secondary_colors.map((color, index) => ( {ear_secondary_colors.map((color, index) => (
<Box key={index}> <Box key={index}>
<ColorBox color={color} mr={1} /> <ColorBox color={color} mr={1} />
<Button <Button
@@ -138,42 +167,124 @@ export const AppearanceChangerColors = (props) => {
export const AppearanceChangerMarkings = (props) => { export const AppearanceChangerMarkings = (props) => {
const { act, data } = useBackend<Data>(); const { act, data } = useBackend<Data>();
const { markings } = data; const { markings, marking_styles } = data;
const [searchText, setSearchText] = useState<string>('');
const [tabIndex, setTabIndex] = useState(0);
const searcher = createSearch(searchText, (style: bodyStyle) => {
return style.name;
});
const filteredStyles = marking_styles.filter(searcher);
filteredStyles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
const styleTabCount = Math.ceil(filteredStyles.length / MARKINGS_PER_PAGE);
const shownStyles: bodyStyle[][] = [];
for (let i = 0; i < styleTabCount; i++) {
shownStyles[i] = filteredStyles.slice(
i * MARKINGS_PER_PAGE,
i * MARKINGS_PER_PAGE + MARKINGS_PER_PAGE,
);
}
return ( return (
<Section title="Markings" fill scrollable> <Section title="Markings" fill scrollable>
<Box> <Stack vertical>
<Button onClick={() => act('marking', { todo: 1, name: 'na' })}> <Stack.Item>
Add Marking <LabeledList>
</Button> {markings.map((m) => (
</Box> <LabeledList.Item key={m.marking_name} label={m.marking_name}>
<LabeledList> <Stack>
{markings.map((m) => ( <Stack.Item grow />
<LabeledList.Item key={m.marking_name} label={m.marking_name}> <Stack.Item>
<ColorBox color={m.marking_color} mr={1} /> <ColorBox color={m.marking_color} mr={1} />
<Button </Stack.Item>
onClick={() => act('marking', { todo: 4, name: m.marking_name })} <Stack.Item>
<Button
onClick={() =>
act('marking', { todo: 4, name: m.marking_name })
}
>
Change Color
</Button>
</Stack.Item>
<Stack.Item>
<Button
onClick={() =>
act('marking', { todo: 0, name: m.marking_name })
}
>
-
</Button>
</Stack.Item>
<Stack.Item>
<Button
onClick={() =>
act('marking', { todo: 3, name: m.marking_name })
}
>
Move down
</Button>
</Stack.Item>
<Stack.Item>
<Button
onClick={() =>
act('marking', { todo: 2, name: m.marking_name })
}
>
Move up
</Button>
</Stack.Item>
</Stack>
</LabeledList.Item>
))}
</LabeledList>
</Stack.Item>
<Stack.Item>
<Input
fluid
placeholder={'Search for markings...'}
value={searchText}
onInput={(e, val) => setSearchText(val)}
/>
</Stack.Item>
<Stack.Item>
<Tabs>
<Stack wrap="wrap" justify="center">
{shownStyles.map((_, i) => (
<Stack.Item key={i}>
<Tabs.Tab
selected={tabIndex === i}
onClick={() => setTabIndex(i)}
>
Page {i + 1}
</Tabs.Tab>
</Stack.Item>
))}
</Stack>
</Tabs>
</Stack.Item>
<Stack.Item>
{shownStyles[tabIndex]?.map((style) => (
<ImageButton
key={style.name}
tooltip={style.name}
dmIcon={style.icon}
dmIconState={style.icon_state}
onClick={() => {
act('marking', { todo: 1, name: style.name });
}}
> >
Change Color {style.name}
</Button> </ImageButton>
<Button ))}
onClick={() => act('marking', { todo: 0, name: m.marking_name })} </Stack.Item>
> </Stack>
-
</Button>
<Button
onClick={() => act('marking', { todo: 3, name: m.marking_name })}
>
Move down
</Button>
<Button
onClick={() => act('marking', { todo: 2, name: m.marking_name })}
>
Move up
</Button>
</LabeledList.Item>
))}
</LabeledList>
</Section> </Section>
); );
}; };

View File

@@ -0,0 +1,35 @@
import { useBackend } from 'tgui/backend';
import { Box, Button, LabeledList, Section } from 'tgui-core/components';
import { capitalize } from 'tgui-core/string';
import { Data } from './types';
export const AppearanceChangerFlavor = (props) => {
const { act, data } = useBackend<Data>();
const { flavor_text } = data;
return (
<Section title="Flavor Text" fill scrollable>
<LabeledList>
{Object.keys(flavor_text).map((key) => (
<LabeledList.Item key={key} label={capitalize(key)}>
<Button
icon="pen"
onClick={() =>
act('flavor_text', {
target: key,
})
}
>
Edit
</Button>
<br />
<Box preserveWhitespace style={{ wordBreak: 'break-all' }}>
{flavor_text[key]}
</Box>
</LabeledList.Item>
))}
</LabeledList>
</Section>
);
};

View File

@@ -1,46 +0,0 @@
import { useBackend } from 'tgui/backend';
import { Button, Section } from 'tgui-core/components';
import { Data } from './types';
export const AppearanceChangerHair = (props) => {
const { act, data } = useBackend<Data>();
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}
>
{hair.hairstyle}
</Button>
))}
</Section>
);
};
export const AppearanceChangerFacialHair = (props) => {
const { act, data } = useBackend<Data>();
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}
>
{hair.facialhairstyle}
</Button>
))}
</Section>
);
};

View File

@@ -0,0 +1,33 @@
import { useBackend } from 'tgui/backend';
import { Button, Section } from 'tgui-core/components';
import { Data } from './types';
export const AppearanceChangerHeader = (props) => {
const { act, data } = useBackend<Data>();
const { disk, selected_a_record } = data;
return (
<Section>
<Button
icon="arrow-left"
disabled={!selected_a_record}
onClick={() => act('back_to_library')}
>
Back
</Button>
<Button
icon="save"
onClick={() => act('savetodisk')}
disabled={!disk || !selected_a_record}
>
Save To Disk
</Button>
<Button icon="save" onClick={() => act('loadfromdisk')} disabled={!disk}>
Load From Disk
</Button>
<Button icon="eject" onClick={() => act('ejectdisk')} disabled={!disk}>
Eject
</Button>
</Section>
);
};

View File

@@ -0,0 +1,135 @@
import { Fragment, useState } from 'react';
import { useBackend } from 'tgui/backend';
import { ImageButton, Input, Section, Stack } from 'tgui-core/components';
import { createSearch } from 'tgui-core/string';
import { bodyStyle, Data, styles } from './types';
export const AppearanceChangerParts = (props: {
sectionNames: string[];
possibleStyles: styles[][];
currentStyle: string[];
actions: string[];
canClear?: boolean;
}) => {
const { act } = useBackend<Data>();
const { sectionNames, possibleStyles, currentStyle, actions, canClear } =
props;
const [searchText, setSearchText] = useState<string>('');
const selectableStyles = possibleStyles.map((styles: styles[]) => {
const searcher = createSearch(searchText, (style: styles) => {
return style.name;
});
const filteredStyles = styles.filter(searcher);
return filteredStyles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
});
return (
<Stack vertical fill>
{sectionNames.map((section, i) => (
<Fragment key={section}>
<Stack.Item>
{i === 0 && (
<Input
fluid
placeholder={'Search for ' + section.toLowerCase() + '...'}
value={searchText}
onInput={(e, val) => setSearchText(val)}
/>
)}
</Stack.Item>
<Stack.Item grow>
<Section title={section} fill scrollable>
{canClear && (
<ImageButton
tooltip="-- Not Set --"
onClick={() => act(actions[i], { clear: true })}
selected={currentStyle[i] === null}
>
-- Not Set --
</ImageButton>
)}
{selectableStyles[i].map((style) => (
<ImageButton
tooltip={style.name}
dmIcon={style.icon}
dmIconState={style.icon_state}
key={style.name}
onClick={() => {
act(actions[i], { ref: style.instance });
}}
selected={style.name === currentStyle[i]}
>
{style.name}
</ImageButton>
))}
</Section>
</Stack.Item>
</Fragment>
))}
</Stack>
);
};
export const AppearanceChangerHair = (props: {
sectionNames: string[];
possibleStyles: bodyStyle[][];
currentStyle: string[];
actions: string[];
}) => {
const { act } = useBackend<Data>();
const { sectionNames, possibleStyles, currentStyle, actions } = props;
const [searchText, setSearchText] = useState<string>('');
const selectableStyles = possibleStyles.map((styles: bodyStyle[]) => {
const searcher = createSearch(searchText, (style: styles) => {
return style.name;
});
const filteredStyles = styles.filter(searcher);
return filteredStyles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
});
return (
<Stack vertical fill>
{sectionNames.map((section, i) => (
<Fragment key={section}>
<Stack.Item key={section}>
<Input
fluid
placeholder={'Search for ' + section.toLowerCase() + '...'}
value={searchText}
onInput={(e, val) => setSearchText(val)}
/>
</Stack.Item>
<Stack.Item grow>
<Section title={section} fill scrollable>
{selectableStyles[i].map((style) => (
<ImageButton
tooltip={style.name}
dmIcon={style.icon}
dmIconState={style.icon_state}
key={style.name}
onClick={() => {
act(actions[i], { name: style.name });
}}
selected={style.name === currentStyle[i]}
>
{style.name}
</ImageButton>
))}
</Section>
</Stack.Item>
</Fragment>
))}
</Stack>
);
};

View File

@@ -0,0 +1,12 @@
export const TAB_RACE = 0;
export const TAB_FLAVOR = 1;
export const TAB_GENDER = 2;
export const TAB_COLORS = 3;
export const TAB_HAIR = 4;
export const TAB_FACIAL_HAIR = 5;
export const TAB_EARS = 6;
export const TAB_EARS2 = 7;
export const TAB_TAIL = 8;
export const TAB_WINGS = 9;
export const TAB_MARKINGS = 10;
export const MARKINGS_PER_PAGE = 30;

View File

@@ -3,6 +3,7 @@ import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts'; import { Window } from 'tgui/layouts';
import { import {
Box, Box,
Button,
ByondUi, ByondUi,
LabeledList, LabeledList,
Section, Section,
@@ -12,20 +13,33 @@ import {
import { capitalize, decodeHtmlEntities } from 'tgui-core/string'; import { capitalize, decodeHtmlEntities } from 'tgui-core/string';
import { import {
AppearanceChangerEars,
AppearanceChangerGender, AppearanceChangerGender,
AppearanceChangerSpecies, AppearanceChangerSpecies,
AppearanceChangerTails,
AppearanceChangerWings,
} from './AppearanceChangerBody'; } from './AppearanceChangerBody';
import { AppearanceChangerBodyRecords } from './AppearanceChangerBodyRecords';
import { import {
AppearanceChangerColors, AppearanceChangerColors,
AppearanceChangerMarkings, AppearanceChangerMarkings,
} from './AppearanceChangerDetails'; } from './AppearanceChangerDetails';
import { AppearanceChangerFlavor } from './AppearanceChangerFlavor';
import { AppearanceChangerHeader } from './AppearanceChangerHeader';
import { import {
AppearanceChangerFacialHair,
AppearanceChangerHair, AppearanceChangerHair,
} from './AppearanceChangerHairs'; AppearanceChangerParts,
} from './AppearanceChangerParts';
import {
TAB_COLORS,
TAB_EARS,
TAB_EARS2,
TAB_FACIAL_HAIR,
TAB_FLAVOR,
TAB_GENDER,
TAB_HAIR,
TAB_MARKINGS,
TAB_RACE,
TAB_TAIL,
TAB_WINGS,
} from './constants';
import { Data } from './types'; import { Data } from './types';
export const AppearanceChanger = (props) => { export const AppearanceChanger = (props) => {
@@ -37,10 +51,16 @@ export const AppearanceChanger = (props) => {
gender, gender,
gender_id, gender_id,
hair_style, hair_style,
hair_styles,
facial_hair_style, facial_hair_style,
facial_hair_styles,
ear_style, ear_style,
ear_styles,
ear_secondary_style,
tail_style, tail_style,
tail_styles,
wing_style, wing_style,
wing_styles,
change_race, change_race,
change_gender, change_gender,
change_eye_color, change_eye_color,
@@ -51,6 +71,8 @@ export const AppearanceChanger = (props) => {
change_hair, change_hair,
change_facial_hair, change_facial_hair,
mapRef, mapRef,
is_design_console,
selected_a_record,
} = data; } = data;
const { title } = config; const { title } = config;
@@ -64,50 +86,98 @@ export const AppearanceChanger = (props) => {
change_hair_color || change_hair_color ||
change_facial_hair_color; change_facial_hair_color;
const disabled = <Box />;
tab[-1] = <AppearanceChangerDefaultError />; tab[-1] = <AppearanceChangerDefaultError />;
tab[0] = change_race ? ( tab[TAB_RACE] = change_race ? (
<AppearanceChangerSpecies /> <AppearanceChangerSpecies />
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
); );
tab[1] = change_gender ? ( tab[TAB_FLAVOR] = change_race ? (
<AppearanceChangerFlavor />
) : (
<AppearanceChangerDefaultError />
);
tab[TAB_GENDER] = change_gender ? (
<AppearanceChangerGender /> <AppearanceChangerGender />
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
); );
tab[2] = change_color ? ( tab[TAB_COLORS] = change_color ? (
<AppearanceChangerColors /> <AppearanceChangerColors />
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
); );
tab[3] = change_hair ? ( tab[TAB_HAIR] = change_hair ? (
<AppearanceChangerHair /> <AppearanceChangerHair
key={TAB_HAIR}
sectionNames={['Hair']}
possibleStyles={[hair_styles]}
currentStyle={[hair_style]}
actions={['hair']}
/>
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
); );
tab[4] = change_facial_hair ? ( tab[TAB_FACIAL_HAIR] = change_facial_hair ? (
<AppearanceChangerFacialHair /> <AppearanceChangerHair
key={TAB_FACIAL_HAIR}
sectionNames={['Facial Hair']}
possibleStyles={[facial_hair_styles]}
currentStyle={[facial_hair_style]}
actions={['facial_hair']}
/>
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
); );
tab[5] = change_hair ? ( tab[TAB_EARS] = change_hair ? (
<AppearanceChangerEars /> <AppearanceChangerParts
key={TAB_EARS}
sectionNames={['Ears']}
possibleStyles={[ear_styles]}
currentStyle={[ear_style]}
actions={['ear']}
canClear
/>
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
); );
tab[6] = change_hair ? ( tab[TAB_EARS2] = change_hair ? (
<AppearanceChangerTails /> <AppearanceChangerParts
key={TAB_EARS2}
sectionNames={['Ears - Secondary']}
possibleStyles={[ear_styles]}
currentStyle={[ear_secondary_style]}
actions={['ear_secondary']}
canClear
/>
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
); );
tab[7] = change_hair ? ( tab[TAB_TAIL] = change_hair ? (
<AppearanceChangerWings /> <AppearanceChangerParts
key={TAB_TAIL}
sectionNames={['Tail']}
possibleStyles={[tail_styles]}
currentStyle={[tail_style]}
actions={['tail']}
canClear
/>
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
); );
tab[8] = change_hair ? ( tab[TAB_WINGS] = change_hair ? (
<AppearanceChangerParts
key={TAB_WINGS}
sectionNames={['Wings']}
possibleStyles={[wing_styles]}
currentStyle={[wing_style]}
actions={['wing']}
canClear
/>
) : (
<AppearanceChangerDefaultError />
);
tab[TAB_MARKINGS] = change_hair ? (
<AppearanceChangerMarkings /> <AppearanceChangerMarkings />
) : ( ) : (
<AppearanceChangerDefaultError /> <AppearanceChangerDefaultError />
@@ -115,151 +185,207 @@ export const AppearanceChanger = (props) => {
let firstAccesibleTab = -1; let firstAccesibleTab = -1;
if (change_race) { if (change_race) {
firstAccesibleTab = 0; firstAccesibleTab = TAB_RACE;
} else if (change_gender) { } else if (change_gender) {
firstAccesibleTab = 1; firstAccesibleTab = TAB_GENDER;
} else if (change_color) { } else if (change_color) {
firstAccesibleTab = 2; firstAccesibleTab = TAB_COLORS;
} else if (change_hair) { } else if (change_hair) {
firstAccesibleTab = 4; firstAccesibleTab = TAB_HAIR;
} else if (change_facial_hair) { } else if (change_facial_hair) {
firstAccesibleTab = 5; firstAccesibleTab = TAB_FACIAL_HAIR;
} }
const [tabIndex, setTabIndex] = useState(firstAccesibleTab); const [tabIndex, setTabIndex] = useState(firstAccesibleTab);
return ( return (
<Window width={700} height={650} title={decodeHtmlEntities(title)}> <Window width={700} height={850} title={decodeHtmlEntities(title)}>
<Window.Content> {is_design_console && !selected_a_record ? (
<Section title="Reflection"> <Window.Content>
<Stack> <AppearanceChangerHeader />
<Stack.Item grow> <AppearanceChangerBodyRecords />
<LabeledList> </Window.Content>
<LabeledList.Item label="Name">{name}</LabeledList.Item> ) : (
<LabeledList.Item <Window.Content>
label="Species" <Stack vertical fill>
color={!change_race ? 'grey' : undefined}
>
{specimen}
</LabeledList.Item>
<LabeledList.Item
label="Biological Sex"
color={!change_gender ? 'grey' : undefined}
>
{gender ? capitalize(gender) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Gender Identity"
color={!change_color ? 'grey' : undefined}
>
{gender_id ? capitalize(gender_id) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Hair Style"
color={!change_hair ? 'grey' : undefined}
>
{hair_style ? capitalize(hair_style) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Facial Hair Style"
color={!change_facial_hair ? 'grey' : undefined}
>
{facial_hair_style
? capitalize(facial_hair_style)
: 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Ear Style"
color={!change_hair ? 'grey' : undefined}
>
{ear_style ? capitalize(ear_style) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Tail Style"
color={!change_hair ? 'grey' : undefined}
>
{tail_style ? capitalize(tail_style) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Wing Style"
color={!change_hair ? 'grey' : undefined}
>
{wing_style ? capitalize(wing_style) : 'Not Set'}
</LabeledList.Item>
</LabeledList>
</Stack.Item>
<Stack.Item> <Stack.Item>
<ByondUi {is_design_console ? <AppearanceChangerHeader /> : ''}
style={{ <Section title="Reflection">
width: '256px', <Stack fill>
height: '256px', <Stack.Item grow>
}} <Stack fill vertical>
params={{ <Stack.Item grow>
id: mapRef, <LabeledList>
type: 'map', <LabeledList.Item label="Name">
}} {name}
/> </LabeledList.Item>
<LabeledList.Item
label="Species"
color={!change_race ? 'grey' : undefined}
>
{specimen}
</LabeledList.Item>
<LabeledList.Item
label="Biological Sex"
color={!change_gender ? 'grey' : undefined}
>
{gender ? capitalize(gender) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Gender Identity"
color={!change_color ? 'grey' : undefined}
>
{gender_id ? capitalize(gender_id) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Hair Style"
color={!change_hair ? 'grey' : undefined}
>
{hair_style ? capitalize(hair_style) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Facial Hair Style"
color={!change_facial_hair ? 'grey' : undefined}
>
{facial_hair_style
? capitalize(facial_hair_style)
: 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Ear Style"
color={!change_hair ? 'grey' : undefined}
>
{ear_style ? capitalize(ear_style) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Tail Style"
color={!change_hair ? 'grey' : undefined}
>
{tail_style ? capitalize(tail_style) : 'Not Set'}
</LabeledList.Item>
<LabeledList.Item
label="Wing Style"
color={!change_hair ? 'grey' : undefined}
>
{wing_style ? capitalize(wing_style) : 'Not Set'}
</LabeledList.Item>
</LabeledList>
</Stack.Item>
<Stack.Item>
<Stack fill>
<Stack.Item grow />
<Stack.Item>
<Button onClick={() => act('rotate_view')}>
Rotate Preview
</Button>
</Stack.Item>
</Stack>
</Stack.Item>
</Stack>
</Stack.Item>
<Stack.Item>
<ByondUi
style={{
width: '256px',
height: '256px',
}}
params={{
id: mapRef,
type: 'map',
}}
/>
</Stack.Item>
</Stack>
</Section>
<Tabs>
{change_race ? (
<Tabs.Tab
selected={tabIndex === TAB_RACE}
onClick={() => setTabIndex(TAB_RACE)}
>
Race
</Tabs.Tab>
) : null}
{change_race ? (
<Tabs.Tab
selected={tabIndex === TAB_FLAVOR}
onClick={() => setTabIndex(TAB_FLAVOR)}
>
Flavor
</Tabs.Tab>
) : null}
{change_gender ? (
<Tabs.Tab
selected={tabIndex === TAB_GENDER}
onClick={() => setTabIndex(TAB_GENDER)}
>
Gender & Sex
</Tabs.Tab>
) : null}
{change_color ? (
<Tabs.Tab
selected={tabIndex === TAB_COLORS}
onClick={() => setTabIndex(TAB_COLORS)}
>
Colors
</Tabs.Tab>
) : null}
{change_hair ? (
<Tabs.Tab
selected={tabIndex === TAB_HAIR}
onClick={() => setTabIndex(TAB_HAIR)}
>
Hair
</Tabs.Tab>
) : null}
{change_facial_hair ? (
<Tabs.Tab
selected={tabIndex === TAB_FACIAL_HAIR}
onClick={() => setTabIndex(TAB_FACIAL_HAIR)}
>
Facial Hair
</Tabs.Tab>
) : null}
{change_hair ? (
<>
<Tabs.Tab
selected={tabIndex === TAB_EARS}
onClick={() => setTabIndex(TAB_EARS)}
>
Ears
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === TAB_EARS2}
onClick={() => setTabIndex(TAB_EARS2)}
>
Ears Secondary
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === TAB_TAIL}
onClick={() => setTabIndex(TAB_TAIL)}
>
Tail
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === TAB_WINGS}
onClick={() => setTabIndex(TAB_WINGS)}
>
Wings
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === TAB_MARKINGS}
onClick={() => setTabIndex(TAB_MARKINGS)}
>
Markings
</Tabs.Tab>
</>
) : null}
</Tabs>
</Stack.Item> </Stack.Item>
<Stack.Item grow>{tab[tabIndex]}</Stack.Item>
</Stack> </Stack>
</Section> </Window.Content>
<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>
<Tabs.Tab
selected={tabIndex === 5}
onClick={() => setTabIndex(5)}
>
Ear
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === 6}
onClick={() => setTabIndex(6)}
>
Tail
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === 7}
onClick={() => setTabIndex(7)}
>
Wing
</Tabs.Tab>
<Tabs.Tab
selected={tabIndex === 8}
onClick={() => setTabIndex(8)}
>
Markings
</Tabs.Tab>
</>
) : null}
{change_facial_hair ? (
<Tabs.Tab selected={tabIndex === 4} onClick={() => setTabIndex(4)}>
Facial Hair
</Tabs.Tab>
) : null}
</Tabs>
<Box height="43%">{tab[tabIndex]}</Box>
</Window.Content>
</Window> </Window>
); );
}; };

View File

@@ -14,6 +14,7 @@ export type Data = {
gender: string; gender: string;
gender_id: string; gender_id: string;
hair_style: string; hair_style: string;
hair_grad: string;
facial_hair_style: string; facial_hair_style: string;
ear_style: string; ear_style: string;
ear_styles: styles[]; ear_styles: styles[];
@@ -37,6 +38,7 @@ export type Data = {
eye_color: string; eye_color: string;
skin_color: string; skin_color: string;
hair_color: string; hair_color: string;
hair_color_grad: string;
facial_hair_color: string; facial_hair_color: string;
ears_color: string; ears_color: string;
ears2_color: string; ears2_color: string;
@@ -46,10 +48,35 @@ export type Data = {
wing_color: string; wing_color: string;
wing2_color: string; wing2_color: string;
wing3_color: string; wing3_color: string;
facial_hair_styles: { facialhairstyle: string }[]; facial_hair_styles: bodyStyle[];
hair_styles: { hairstyle: string }[]; hair_styles: bodyStyle[];
hair_grads: string[];
marking_styles: bodyStyle[];
ear_secondary_style: string; ear_secondary_style: string;
ear_secondary_colors: string[]; ear_secondary_colors: string[];
is_design_console: BooleanLike; // If we have disk access
selected_a_record: BooleanLike; // If we're past record selection
character_records: bodyrecord[];
stock_records: string[];
disk: BooleanLike;
stock_bodyrecords: string[];
bodyrecords: string[];
species_name: string;
use_custom_icon: BooleanLike;
base_icon: string;
size_scale: number;
synthetic: BooleanLike;
scale_appearance: BooleanLike;
offset_override: BooleanLike;
weight: number;
digitigrade: BooleanLike;
blood_reagent: string;
blood_color: string;
species_sound: string;
// species_sounds_gendered: BooleanLike;
// species_sounds_female: string;
// species_sounds_male: string;
flavor_text: flavors;
}; };
type genders = { gender_name: string; gender_key: string }[]; type genders = { gender_name: string; gender_key: string }[];
@@ -59,6 +86,28 @@ export type styles = {
instance: string; instance: string;
color: boolean; color: boolean;
second_color: boolean; second_color: boolean;
icon: string;
icon_state: string;
};
export type bodyStyle = {
name: string;
icon: string;
icon_state: string;
}; };
export type species = { specimen: string }; export type species = { specimen: string };
export type bodyrecord = { name: string; recref: string };
export type flavors = {
general: string;
head: string;
face: string;
eyes: string;
torso: string;
arms: string;
hands: string;
legs: string;
feet: string;
};

View File

@@ -1,33 +0,0 @@
import { useBackend } from 'tgui/backend';
import { Button, Section } from 'tgui-core/components';
import { bodyrecord } from './types';
export const BodyDesignerBodyRecords = (props: {
bodyrecords: bodyrecord[];
}) => {
const { act } = useBackend();
const { bodyrecords } = props;
return (
<Section
title="Body Records"
buttons={
<Button icon="arrow-left" onClick={() => act('menu', { menu: 'Main' })}>
Back
</Button>
}
>
{bodyrecords
? bodyrecords.map((record) => (
<Button
icon="eye"
key={record.name}
onClick={() => act('view_brec', { view_brec: record.recref })}
>
{record.name}
</Button>
))
: ''}
</Section>
);
};

View File

@@ -1,16 +0,0 @@
import { useBackend } from 'tgui/backend';
import { Button, Section } from 'tgui-core/components';
export const BodyDesignerMain = (props) => {
const { act } = useBackend();
return (
<Section title="Database Functions">
<Button icon="eye" onClick={() => act('menu', { menu: 'Body Records' })}>
View Individual Body Records
</Button>
<Button icon="eye" onClick={() => act('menu', { menu: 'Stock Records' })}>
View Stock Body Records
</Button>
</Section>
);
};

View File

@@ -1,30 +0,0 @@
import { useBackend } from 'tgui/backend';
import { Button, Section } from 'tgui-core/components';
import { activeBodyRecord } from './types';
export const BodyDesignerOOCNotes = (props: {
activeBodyRecord: activeBodyRecord;
}) => {
const { act } = useBackend();
const { activeBodyRecord } = props;
return (
<Section
title="Body OOC Notes (This is OOC!)"
height="100%"
scrollable
buttons={
<Button
icon="arrow-left"
onClick={() => act('menu', { menu: 'Specific Record' })}
>
Back
</Button>
}
style={{ wordBreak: 'break-all' }}
>
{(activeBodyRecord && activeBodyRecord.booc) ||
'ERROR: Body record not found!'}
</Section>
);
};

View File

@@ -1,440 +0,0 @@
import { useBackend } from 'tgui/backend';
import {
Box,
Button,
ByondUi,
ColorBox,
LabeledList,
Section,
Stack,
} from 'tgui-core/components';
import { capitalize } from 'tgui-core/string';
import { activeBodyRecord } from './types';
export const BodyDesignerSpecificRecord = (props: {
activeBodyRecord: activeBodyRecord;
mapRef: string;
}) => {
const { act } = useBackend();
const { activeBodyRecord, mapRef } = props;
return activeBodyRecord ? (
<Stack vertical>
<Section
title="Specific Record"
buttons={
<Button
icon="arrow-left"
onClick={() => act('menu', { menu: 'Main' })}
>
Back
</Button>
}
>
<Stack.Item basis="175px">
<Stack.Item basis="130px">
<ByondUi
style={{
width: '100%',
height: '128px',
}}
params={{
id: mapRef,
type: 'map',
}}
/>
</Stack.Item>
</Stack.Item>
</Section>
<Stack.Item>
<Stack>
<Stack.Item basis="48%">
<Section title="General">
<LabeledList>
<LabeledList.Item label="Name">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'rename',
target_value: 1,
})
}
>
{activeBodyRecord.real_name}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Species">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'custom_species',
target_value: 1,
})
}
>
{activeBodyRecord.speciesname}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Bio. Sex">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'bio_gender',
target_value: 1,
})
}
>
{capitalize(activeBodyRecord.gender)}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Synthetic">
{activeBodyRecord.synthetic}
</LabeledList.Item>
<LabeledList.Item label="Weight">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'weight',
target_value: 1,
})
}
>
{activeBodyRecord.weight}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Blood">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'blood_type',
target_value: 1,
})
}
>
{capitalize(activeBodyRecord.blood_type)}
</Button>
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'blood_reagents',
target_value: 1,
})
}
>
{activeBodyRecord.blood_reagents}
</Button>
<Button
icon="pen"
backgroundColor={activeBodyRecord.blood_color}
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'blood_color',
target_value: 1,
})
}
>
Color
</Button>
</LabeledList.Item>
<LabeledList.Item label="Species Sound">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'species_sound_options',
target_value: 1,
})
}
>
{activeBodyRecord.species_sound}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Mind Compat">
{activeBodyRecord.locked ? 'Low' : 'High'}
<Button
ml={1}
icon="eye"
disabled={!activeBodyRecord.booc}
onClick={() => act('boocnotes')}
>
View OOC Notes
</Button>
</LabeledList.Item>
</LabeledList>
</Section>
<Section
title="Flavor Text"
width="400px"
fill
height="57%"
scrollable
>
<LabeledList>
{Object.keys(activeBodyRecord.flavors).map((key) => {
return (
<LabeledList.Item key={key} label={capitalize(key)}>
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'flavor_text',
target_value: key,
})
}
>
Edit
</Button>
<br />
<Box
preserveWhitespace
style={{ wordBreak: 'break-all' }}
>
{activeBodyRecord.flavors[key]}
</Box>
</LabeledList.Item>
);
})}
</LabeledList>
</Section>
</Stack.Item>
<Stack.Item basis="50%">
<Section title="Unique Identifiers" scrollable fill height="600px">
<LabeledList.Item label="Scale">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'size_multiplier',
target_value: 1,
})
}
>
{activeBodyRecord.scale}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Scaled Appearance">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'toggle_fuzzy',
target_value: 1,
})
}
>
{activeBodyRecord.scale_appearance}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Scaling Center">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'toggle_offset_override',
target_value: 1,
})
}
>
{activeBodyRecord.offset_override}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Digitigrade">
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'digitigrade',
target_value: 1,
})
}
>
{activeBodyRecord.digitigrade ? 'Yes' : 'No'}
</Button>
</LabeledList.Item>
{Object.keys(activeBodyRecord.styles).map((key) => {
const style = activeBodyRecord.styles[key];
return (
<LabeledList.Item key={key} label={key}>
{style.styleHref ? (
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: style.styleHref,
target_value: 1,
})
}
>
{style.style}
</Button>
) : (
''
)}
{style.colorHref ? (
<Box>
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: style.colorHref,
target_value: 1,
})
}
>
{style.color}
</Button>
<ColorBox
verticalAlign="top"
width="32px"
height="20px"
color={style.color}
style={{
border: '1px solid #fff',
}}
/>
</Box>
) : (
''
)}
{style.colorHref2 ? (
<Box>
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: style.colorHref2,
target_value: 1,
})
}
>
{style.color2}
</Button>
<ColorBox
verticalAlign="top"
width="32px"
height="20px"
color={style.color2}
style={{
border: '1px solid #fff',
}}
/>
</Box>
) : (
''
)}
{style.colorHref3 ? (
<Box>
<Button
icon="pen"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: style.colorHref3,
target_value: 1,
})
}
>
{style.color3}
</Button>
<ColorBox
verticalAlign="top"
width="32px"
height="20px"
color={style.color3}
style={{
border: '1px solid #fff',
}}
/>
</Box>
) : (
''
)}
</LabeledList.Item>
);
})}
<LabeledList.Item label="Body Markings">
<Button
icon="plus"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'marking_style',
target_value: 1,
})
}
>
Add Marking
</Button>
<Stack wrap="wrap" justify="center" align="center">
{Object.keys(activeBodyRecord.markings).map((key) => {
const marking = activeBodyRecord.markings[key];
return (
<Stack.Item basis="100%" key={key}>
<Stack>
<Stack.Item>
<Button
mr={0.2}
fluid
icon="times"
color="red"
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'marking_remove',
target_value: key,
})
}
/>
</Stack.Item>
<Stack.Item grow>
<Button
fluid
backgroundColor={marking}
disabled={activeBodyRecord.locked === 1}
onClick={() =>
act('href_conversion', {
target_href: 'marking_color',
target_value: key,
})
}
>
{key}
</Button>
</Stack.Item>
</Stack>
</Stack.Item>
);
})}
</Stack>
</LabeledList.Item>
</Section>
</Stack.Item>
</Stack>
</Stack.Item>
</Stack>
) : (
<Box color="bad">ERROR: Record Not Found!</Box>
);
};

View File

@@ -1,29 +0,0 @@
import { useBackend } from 'tgui/backend';
import { Button, Section } from 'tgui-core/components';
export const BodyDesignerStockRecords = (props: {
stock_bodyrecords: string[];
}) => {
const { act } = useBackend();
const { stock_bodyrecords } = props;
return (
<Section
title="Stock Records"
buttons={
<Button icon="arrow-left" onClick={() => act('menu', { menu: 'Main' })}>
Back
</Button>
}
>
{stock_bodyrecords.map((record) => (
<Button
icon="eye"
key={record}
onClick={() => act('view_stock_brec', { view_stock_brec: record })}
>
{record}
</Button>
))}
</Section>
);
};

View File

@@ -1,72 +0,0 @@
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Box, Button } from 'tgui-core/components';
import { BodyDesignerBodyRecords } from './BodyDesignerBodyRecords';
import { BodyDesignerMain } from './BodyDesignerMain';
import { BodyDesignerOOCNotes } from './BodyDesignerOOCNotes';
import { BodyDesignerSpecificRecord } from './BodyDesignerSpecificRecord';
import { BodyDesignerStockRecords } from './BodyDesignerStockRecords';
import { Data } from './types';
export const BodyDesigner = (props) => {
const { act, data } = useBackend<Data>();
const {
menu,
disk,
diskStored,
activeBodyRecord,
stock_bodyrecords,
bodyrecords,
mapRef,
} = data;
const MenuToTemplate = {
Main: <BodyDesignerMain />,
'Body Records': <BodyDesignerBodyRecords bodyrecords={bodyrecords} />,
'Stock Records': (
<BodyDesignerStockRecords stock_bodyrecords={stock_bodyrecords} />
),
'Specific Record': (
<BodyDesignerSpecificRecord
activeBodyRecord={activeBodyRecord}
mapRef={mapRef}
/>
),
'OOC Notes': <BodyDesignerOOCNotes activeBodyRecord={activeBodyRecord} />,
};
let body = MenuToTemplate[menu];
return (
<Window width={750} height={850}>
<Window.Content>
<Box>
<Button
icon="save"
onClick={() => act('savetodisk')}
disabled={!disk || !activeBodyRecord}
>
Save To Disk
</Button>
<Button
icon="save"
onClick={() => act('loadfromdisk')}
disabled={!disk || !diskStored}
>
Load From Disk
</Button>
<Button
icon="eject"
onClick={() => act('ejectdisk')}
disabled={!disk}
>
Eject
</Button>
</Box>
{body}
</Window.Content>
</Window>
);
};

View File

@@ -1,82 +0,0 @@
import { BooleanLike } from 'tgui-core/react';
export type Data = {
mapRef: string;
bodyrecords: bodyrecord[];
stock_bodyrecords: string[];
activeBodyRecord: activeBodyRecord;
menu: string;
temp: {
styleHref: string;
style: string;
color: string | undefined;
colorHref: string | undefined | { act: string; params: Object };
color2?: string | undefined;
colorHref2?: string | undefined | { act: string; params: Object };
};
disk: BooleanLike;
diskStored: BooleanLike;
};
export type bodyrecord = { name: string; recref: string };
export type activeBodyRecord = {
real_name: string;
speciesname: string;
gender: string;
synthetic: string;
locked: BooleanLike;
scale: string;
booc: string;
digitigrade: BooleanLike;
styles: {
Ears: colourableStyle;
Horns: colourableStyle;
Tail: colourableStyle;
Wing: colourableStyle;
Hair: simpleStyle;
Facial: simpleStyle;
Eyes: colourStyle;
'Body Color': colourStyle;
Bodytype: { styleHref: string; style: string };
};
markings: { name: Record<string, { on: BooleanLike; color: string }> }; // Record entries match BP regions
scale_appearance: string;
offset_override: string;
species_sound: string;
weight: string;
blood_type: string;
blood_color: string;
blood_reagents: string;
flavors: {
general: string;
head: string;
face: string;
eyes: string;
arms: string;
hands: string;
legs: string;
feet: string;
};
};
type colourableStyle = {
styleHref: string;
style: string;
color: string | undefined;
colorHref: string | undefined;
color2: string | undefined;
colorHref2: string | undefined;
};
type simpleStyle = {
styleHref: string;
style: string;
colorHref: string;
color: string;
};
type colourStyle = {
colorHref: string;
color: string;
};

View File

@@ -3747,7 +3747,6 @@
#include "code\modules\mob\new_player\sprite_accessories_ear_ch.dm" #include "code\modules\mob\new_player\sprite_accessories_ear_ch.dm"
#include "code\modules\mob\new_player\sprite_accessories_extra_ch.dm" #include "code\modules\mob\new_player\sprite_accessories_extra_ch.dm"
#include "code\modules\mob\new_player\sprite_accessories_hair.dm" #include "code\modules\mob\new_player\sprite_accessories_hair.dm"
#include "code\modules\mob\new_player\sprite_accessories_hair_extra.dm"
#include "code\modules\mob\new_player\sprite_accessories_markings.dm" #include "code\modules\mob\new_player\sprite_accessories_markings.dm"
#include "code\modules\mob\new_player\sprite_accessories_tail.dm" #include "code\modules\mob\new_player\sprite_accessories_tail.dm"
#include "code\modules\mob\new_player\sprite_accessories_tail_ch.dm" #include "code\modules\mob\new_player\sprite_accessories_tail_ch.dm"
@@ -4498,7 +4497,6 @@
#include "code\modules\tgui\modules\agentcard.dm" #include "code\modules\tgui\modules\agentcard.dm"
#include "code\modules\tgui\modules\alarm.dm" #include "code\modules\tgui\modules\alarm.dm"
#include "code\modules\tgui\modules\appearance_changer.dm" #include "code\modules\tgui\modules\appearance_changer.dm"
#include "code\modules\tgui\modules\appearance_changer_vr.dm"
#include "code\modules\tgui\modules\atmos_control.dm" #include "code\modules\tgui\modules\atmos_control.dm"
#include "code\modules\tgui\modules\camera.dm" #include "code\modules\tgui\modules\camera.dm"
#include "code\modules\tgui\modules\communications.dm" #include "code\modules\tgui\modules\communications.dm"
@@ -4719,6 +4717,7 @@
#include "code\modules\xenobio\machinery\processor.dm" #include "code\modules\xenobio\machinery\processor.dm"
#include "code\modules\xgm\xgm_gas_data.dm" #include "code\modules\xgm\xgm_gas_data.dm"
#include "code\modules\xgm\xgm_gas_mixture.dm" #include "code\modules\xgm\xgm_gas_mixture.dm"
#include "code\unit_tests\cosmetic_tests.dm"
#include "code\unit_tests\decl_tests.dm" #include "code\unit_tests\decl_tests.dm"
#include "code\unit_tests\language_tests.dm" #include "code\unit_tests\language_tests.dm"
#include "code\unit_tests\loadout_tests.dm" #include "code\unit_tests\loadout_tests.dm"