diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index c782a63ed7..019739030b 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -154,6 +154,11 @@ proc/get_id_photo(var/mob/living/carbon/human/H)
else
preview_icon.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT)
+ // Skin color
+ if(H.species.flags & HAS_SKIN_TONE)
+ if(!H.species || H.species.flags & HAS_SKIN_COLOR)
+ preview_icon.Blend(rgb(H.r_skin, H.g_skin, H.b_skin), ICON_ADD)
+
var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = H.species ? H.species.eyes : "eyes_s")
eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD)
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index 28e297b710..32c7ef1dd6 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -24,13 +24,16 @@
#define DNA_UI_BEARD_G 5
#define DNA_UI_BEARD_B 6
#define DNA_UI_SKIN_TONE 7
-#define DNA_UI_EYES_R 8
-#define DNA_UI_EYES_G 9
-#define DNA_UI_EYES_B 10
-#define DNA_UI_GENDER 11
-#define DNA_UI_BEARD_STYLE 12
-#define DNA_UI_HAIR_STYLE 13
-#define DNA_UI_LENGTH 13 // Update this when you add something, or you WILL break shit.
+#define DNA_UI_SKIN_R 8
+#define DNA_UI_SKIN_G 9
+#define DNA_UI_SKIN_B 10
+#define DNA_UI_EYES_R 11
+#define DNA_UI_EYES_G 12
+#define DNA_UI_EYES_B 13
+#define DNA_UI_GENDER 14
+#define DNA_UI_BEARD_STYLE 15
+#define DNA_UI_HAIR_STYLE 16
+#define DNA_UI_LENGTH 16 // Update this when you add something, or you WILL break shit.
#define DNA_SE_LENGTH 27
// For later:
@@ -140,6 +143,10 @@ var/global/list/datum/dna/gene/dna_genes[0]
SetUIValueRange(DNA_UI_EYES_G, character.g_eyes, 255, 1)
SetUIValueRange(DNA_UI_EYES_B, character.b_eyes, 255, 1)
+ SetUIValueRange(DNA_UI_SKIN_R, character.r_skin, 255, 1)
+ SetUIValueRange(DNA_UI_SKIN_G, character.g_skin, 255, 1)
+ SetUIValueRange(DNA_UI_SKIN_B, character.b_skin, 255, 1)
+
SetUIValueRange(DNA_UI_SKIN_TONE, 35-character.s_tone, 220, 1) // Value can be negative.
SetUIState(DNA_UI_GENDER, character.gender!=MALE, 1)
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 4cdefb36ec..4ffa5ea512 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -139,6 +139,10 @@
H.g_facial = dna.GetUIValueRange(DNA_UI_BEARD_G, 255)
H.b_facial = dna.GetUIValueRange(DNA_UI_BEARD_B, 255)
+ H.r_skin = dna.GetUIValueRange(DNA_UI_SKIN_R, 255)
+ H.g_skin = dna.GetUIValueRange(DNA_UI_SKIN_G, 255)
+ H.b_skin = dna.GetUIValueRange(DNA_UI_SKIN_B, 255)
+
H.r_eyes = dna.GetUIValueRange(DNA_UI_EYES_R, 255)
H.g_eyes = dna.GetUIValueRange(DNA_UI_EYES_G, 255)
H.b_eyes = dna.GetUIValueRange(DNA_UI_EYES_B, 255)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 0258ddb50a..7bd3854017 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -668,6 +668,12 @@ var/list/admin_verbs_mod = list(
M.g_eyes = hex2num(copytext(new_eyes, 4, 6))
M.b_eyes = hex2num(copytext(new_eyes, 6, 8))
+ var/new_skin = input("Please select body color. This is for Tajaran, Unathi, and Skrell only!", "Character Generation") as color
+ if(new_skin)
+ M.r_skin = hex2num(copytext(new_skin, 2, 4))
+ M.g_skin = hex2num(copytext(new_skin, 4, 6))
+ M.b_skin = hex2num(copytext(new_skin, 6, 8))
+
var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text
if (new_tone)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 462f825400..af8d75edb6 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -64,7 +64,10 @@ datum/preferences
var/r_facial = 0 //Face hair color
var/g_facial = 0 //Face hair color
var/b_facial = 0 //Face hair color
- var/s_tone = 0 //Skin color
+ var/s_tone = 0 //Skin tone
+ var/r_skin = 0 //Skin color
+ var/g_skin = 0 //Skin color
+ var/b_skin = 0 //Skin color
var/r_eyes = 0 //Eye color
var/g_eyes = 0 //Eye color
var/b_eyes = 0 //Eye color
@@ -377,7 +380,10 @@ datum/preferences
dat += " Style: [f_style]
"
dat += "
Eyes
"
- dat += "Change Color "
+ dat += "Change Color
"
+
+ dat += "
Body Color
"
+ dat += "Change Color "
dat += "
"
if(jobban_isbanned(user, "Syndicate"))
@@ -855,6 +861,10 @@ datum/preferences
b_eyes = rand(0,255)
if("s_tone")
s_tone = random_skin_tone()
+ if("s_color")
+ r_skin = rand(0,255)
+ g_skin = rand(0,255)
+ b_skin = rand(0,255)
if("bag")
backbag = rand(1,4)
/*if("skin_style")
@@ -969,7 +979,7 @@ datum/preferences
b_type = new_b_type
if("hair")
- if(species == "Human" || species == "Unathi")
+ if(species == "Human" || species == "Unathi" || species == "Tajaran" || species == "Skrell")
var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference") as color|null
if(new_hair)
r_hair = hex2num(copytext(new_hair, 2, 4))
@@ -1048,6 +1058,14 @@ datum/preferences
if(new_s_tone)
s_tone = 35 - max(min( round(new_s_tone), 220),1)
+ if("skin")
+ if(species == "Unathi" || species == "Tajaran" || species == "Skrell")
+ var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference") as color|null
+ if(new_skin)
+ r_skin = hex2num(copytext(new_skin, 2, 4))
+ g_skin = hex2num(copytext(new_skin, 4, 6))
+ b_skin = hex2num(copytext(new_skin, 6, 8))
+
if("ooccolor")
var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference") as color|null
if(new_ooccolor)
@@ -1278,6 +1296,10 @@ datum/preferences
character.g_facial = g_facial
character.b_facial = b_facial
+ character.r_skin = r_skin
+ character.g_skin = g_skin
+ character.b_skin = b_skin
+
character.s_tone = s_tone
character.h_style = h_style
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 86adc65265..e27be7dd90 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -117,6 +117,9 @@
S["facial_green"] >> g_facial
S["facial_blue"] >> b_facial
S["skin_tone"] >> s_tone
+ S["skin_red"] >> r_skin
+ S["skin_green"] >> g_skin
+ S["skin_blue"] >> b_skin
S["hair_style_name"] >> h_style
S["facial_style_name"] >> f_style
S["eyes_red"] >> r_eyes
@@ -177,6 +180,9 @@
g_facial = sanitize_integer(g_facial, 0, 255, initial(g_facial))
b_facial = sanitize_integer(b_facial, 0, 255, initial(b_facial))
s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone))
+ r_skin = sanitize_integer(r_facial, 0, 255, initial(r_skin))
+ g_skin = sanitize_integer(r_facial, 0, 255, initial(g_skin))
+ b_skin = sanitize_integer(r_facial, 0, 255, initial(b_skin))
h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style))
f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style))
r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes))
@@ -227,7 +233,10 @@
S["facial_red"] << r_facial
S["facial_green"] << g_facial
S["facial_blue"] << b_facial
- S["skin_tone"] << s_tone
+ S["skin_tone"] >> s_tone
+ S["skin_red"] << r_skin
+ S["skin_green"] << g_skin
+ S["skin_blue"] << b_skin
S["hair_style_name"] << h_style
S["facial_style_name"] << f_style
S["eyes_red"] << r_eyes
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index f22eb0db41..edc21f439f 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -18,6 +18,11 @@
var/s_tone = 0 //Skin tone
+ //Skin colour
+ var/r_skin = 0
+ var/g_skin = 0
+ var/b_skin = 0
+
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
var/age = 30 //Player's age (pure fluff)
@@ -48,7 +53,7 @@
var/icon/stand_icon = null
var/icon/lying_icon = null
-
+
var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life()
var/speech_problem_flag = 0
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 0c7d03781c..09395c8d02 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -287,6 +287,10 @@ proc/get_damage_icon_part(damage_state, body_part)
else
stand_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT)
+ //Skin color
+ if(!skeleton && !husk && !hulk && (species.flags & HAS_SKIN_COLOR))
+ stand_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
+
if(husk)
var/icon/mask = new(stand_icon)
var/icon/husk_over = new(race_icon,"overlay_husk")
@@ -735,7 +739,11 @@ proc/get_damage_icon_part(damage_state, body_part)
if(species.tail && species.flags & HAS_TAIL)
if(!wear_suit || !(wear_suit.flags_inv & HIDEJUMPSUIT) && !istype(wear_suit, /obj/item/clothing/suit/space))
- overlays_standing[TAIL_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s")
+ var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s")
+ tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
+
+ stand_icon.Blend(tail_s, ICON_OVERLAY)
+ overlays_standing[TAIL_LAYER] = image(stand_icon)
if(update_icons)
update_icons()
diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm
index a8d595c710..2c65f88090 100644
--- a/code/modules/mob/living/carbon/species.dm
+++ b/code/modules/mob/living/carbon/species.dm
@@ -122,7 +122,7 @@
heat_level_2 = 480 //Default 400
heat_level_3 = 1100 //Default 1000
- flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL
+ flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR
flesh_color = "#34AF10"
@@ -146,7 +146,7 @@
primitive = /mob/living/carbon/monkey/tajara
- flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL
+ flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR
flesh_color = "#AFA59E"
@@ -157,7 +157,7 @@
language = "Skrellian"
primitive = /mob/living/carbon/monkey/skrell
- flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR
+ flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR
flesh_color = "#8CD7A3"
diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm
index f5c78684ba..108e6e5ca9 100644
--- a/code/modules/mob/new_player/preferences_setup.dm
+++ b/code/modules/mob/new_player/preferences_setup.dm
@@ -12,6 +12,7 @@ datum/preferences
randomize_hair_color("hair")
randomize_hair_color("facial")
randomize_eyes_color()
+ randomize_skin_color()
underwear = rand(1,underwear_m.len)
undershirt = rand(1,undershirt_t.len)
backbag = 2
@@ -128,6 +129,54 @@ datum/preferences
g_eyes = green
b_eyes = blue
+ proc/randomize_skin_color()
+ var/red
+ var/green
+ var/blue
+
+ var/col = pick ("black", "grey", "brown", "chestnut", "blue", "lightblue", "green", "albino")
+ switch(col)
+ if("black")
+ red = 0
+ green = 0
+ blue = 0
+ if("grey")
+ red = rand (100, 200)
+ green = red
+ blue = red
+ if("brown")
+ red = 102
+ green = 51
+ blue = 0
+ if("chestnut")
+ red = 153
+ green = 102
+ blue = 0
+ if("blue")
+ red = 51
+ green = 102
+ blue = 204
+ if("lightblue")
+ red = 102
+ green = 204
+ blue = 255
+ if("green")
+ red = 0
+ green = 102
+ blue = 0
+ if("albino")
+ red = rand (200, 255)
+ green = rand (0, 150)
+ blue = rand (0, 150)
+
+ red = max(min(red + rand (-25, 25), 255), 0)
+ green = max(min(green + rand (-25, 25), 255), 0)
+ blue = max(min(blue + rand (-25, 25), 255), 0)
+
+ r_skin = red
+ g_skin = green
+ b_skin = blue
+
proc/update_preview_icon() //seriously. This is horrendous.
del(preview_icon_front)
@@ -163,6 +212,10 @@ datum/preferences
preview_icon.Blend(temp, ICON_OVERLAY)
+ // Skin color
+ if(current_species && (current_species.flags & HAS_SKIN_COLOR))
+ preview_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
+
// Skin tone
if(current_species && (current_species.flags & HAS_SKIN_TONE))
if (s_tone >= 0)
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index 5648f7be1c..471bb71762 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -859,6 +859,11 @@ obj/item/weapon/organ/New(loc, mob/living/carbon/human/H)
else
base.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT)
+ if(base)
+ //Changing limb's skin color to match owner
+ if(!H.species || H.species.flags & HAS_SKIN_COLOR)
+ base.Blend(rgb(H.r_skin, H.g_skin, H.b_skin), ICON_ADD)
+
icon = base
dir = SOUTH
src.transform = turn(src.transform, rand(70,130))
diff --git a/code/setup.dm b/code/setup.dm
index 93c0be5539..8bf2d9eb08 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -731,18 +731,19 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse
#define NO_PAIN 8
#define HAS_SKIN_TONE 16
-#define HAS_LIPS 32
-#define HAS_UNDERWEAR 64
-#define HAS_TAIL 128
+#define HAS_SKIN_COLOR 32
+#define HAS_LIPS 64
+#define HAS_UNDERWEAR 128
+#define HAS_TAIL 256
-#define IS_SLOW 256
-#define IS_PLANT 512
-#define IS_WHITELISTED 1024
+#define IS_SLOW 512
+#define IS_PLANT 1024
+#define IS_WHITELISTED 2048
-#define RAD_ABSORB 2048
-#define REQUIRE_LIGHT 4096
+#define RAD_ABSORB 4096
+#define REQUIRE_LIGHT 8192
-#define IS_SYNTHETIC 8192
+#define IS_SYNTHETIC 16384
//Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.