diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index 6604811d34..14d9de4faf 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -71,6 +71,11 @@
#define MUT_EXTRA 2
#define MUT_OTHER 3
+//species use_skintones defines
+#define NO_SKINTONES 0
+#define USE_SKINTONES 1
+#define USE_SKINTONES_GRAYSCALE_CUSTOM 2 //adds a "_g" suffix to limb overlays icon states if the skin_tone is a custom one.
+
//DNA - Because fuck you and your magic numbers being all over the codebase.
#define DNA_BLOCK_SIZE 3
@@ -131,9 +136,10 @@
#define NOAROUSAL 20 //Stops all arousal effects
#define NOGENITALS 21 //Cannot create, use, or otherwise have genitals
#define MATRIXED 22 //if icon is color matrix'd
-#define SKINTONE 23 //uses skin tones
-#define HORNCOLOR 24
-#define WINGCOLOR 25
+#define SKINTONE 23
+#define CUSTOM_SKINTONE 24 //adds a "_g" suffix to bodypart overlays icon states
+#define HORNCOLOR 25
+#define WINGCOLOR 26
//organ slots
#define ORGAN_SLOT_BRAIN "brain"
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index e022c10007..38831fd5eb 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -262,24 +262,30 @@
if(!findname(.))
break
-/proc/random_skin_tone()
- return pick(GLOB.skin_tones)
+#define SKINTONE2HEX(skin_tone) GLOB.skin_tones[skin_tone] || skin_tone
+/proc/random_skin_tone()
+ return pick(GLOB.skin_tones - GLOB.nonstandard_skin_tones)
+
+//ordered by amount of tan. Keep the nonstandard skin tones last.
GLOBAL_LIST_INIT(skin_tones, list(
- "albino",
- "caucasian1",
- "caucasian2",
- "caucasian3",
- "latino",
- "mediterranean",
- "asian1",
- "asian2",
- "arab",
- "indian",
- "african1",
- "african2"
+ "albino" = "#fff4e6",
+ "caucasian1" = "#ffe0d1",
+ "caucasian2" = "#fcccb3",
+ "caucasian3" = "#e8b59b",
+ "latino" = "#d9ae96",
+ "mediterranean" = "#c79b8b",
+ "asian1" = "#ffdeb3",
+ "asian2" = "#e3ba84",
+ "arab" = "#c4915e",
+ "indian" = "#b87840",
+ "african1" = "#754523",
+ "african2" = "#471c18",
+ "orange" = "#ffc905", //Spray tan overdose.
))
+GLOBAL_LIST_INIT(nonstandard_skin_tones, list("orange"))
+
GLOBAL_LIST_EMPTY(species_list)
/proc/age2agedescription(age)
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 1c866ea535..e08d5c509c 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -17,6 +17,7 @@
var/mutation_index[DNA_MUTATION_BLOCKS] //List of which mutations this carbon has and its assigned block
var/stability = 100
var/scrambled = FALSE //Did we take something like mutagen? In that case we cant get our genes scanned to instantly cheese all the powers.
+ var/skin_tone_override //because custom skin tones are not found in the skin_tones global list.
/datum/dna/New(mob/living/new_holder)
if(istype(new_holder))
@@ -45,6 +46,7 @@
destination.dna.unique_enzymes = unique_enzymes
destination.dna.uni_identity = uni_identity
destination.dna.blood_type = blood_type
+ destination.dna.skin_tone_override = skin_tone_override
destination.set_species(species.type, icon_update=0)
destination.dna.features = features.Copy()
destination.dna.real_name = real_name
@@ -66,6 +68,7 @@
new_dna.mutation_index = mutation_index
new_dna.uni_identity = uni_identity
new_dna.blood_type = blood_type
+ new_dna.skin_tone_override = skin_tone_override
new_dna.features = features.Copy()
new_dna.species = new species.type
new_dna.real_name = real_name
@@ -262,10 +265,11 @@
return
/datum/dna/proc/is_same_as(datum/dna/D)
- if(uni_identity == D.uni_identity && mutation_index == D.mutation_index && real_name == D.real_name && nameless == D.nameless && custom_species == D.custom_species)
- if(species.type == D.species.type && features == D.features && blood_type == D.blood_type)
- return 1
- return 0
+ if(uni_identity != D.uni_identity || mutation_index != D.mutation_index || real_name != D.real_name || nameless != D.nameless || custom_species != D.custom_species)
+ return FALSE
+ if(species.type != D.species.type || features != D.features || blood_type != D.blood_type || skin_tone_override != D.skin_tone_override)
+ return FALSE
+ return TRUE
/datum/dna/proc/update_instability(alert=TRUE)
stability = 100
@@ -430,7 +434,7 @@
var/structure = dna.uni_identity
hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK))
facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK))
- skin_tone = GLOB.skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)]
+ skin_tone = dna.skin_tone_override || GLOB.skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)]
eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK))
facial_hair_style = GLOB.facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), GLOB.facial_hair_styles_list.len)]
hair_style = GLOB.hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)]
diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm
index c135458873..231c1465cd 100644
--- a/code/game/objects/effects/spawners/gibspawner.dm
+++ b/code/game/objects/effects/spawners/gibspawner.dm
@@ -37,7 +37,7 @@
if(ishuman(source_mob))
var/mob/living/carbon/human/H = source_mob
if(H.dna.species.use_skintones)
- body_coloring = "#[skintone2hex(H.skin_tone)]"
+ body_coloring = SKINTONE2HEX(H.skin_tone)
else
body_coloring = "#[H.dna.features["mcolor"]]"
@@ -49,7 +49,7 @@
H.set_species(gib_mob_species)
dna_to_add = temp_mob.get_blood_dna_list()
if(H.dna.species.use_skintones)
- body_coloring = "#[skintone2hex(H.skin_tone)]"
+ body_coloring = SKINTONE2HEX(H.skin_tone)
else
body_coloring = "#[H.dna.features["mcolor"]]"
else
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index e5ca09c7b8..5892574711 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -158,11 +158,21 @@
H.set_species(newrace, icon_update=0)
if(H.dna.species.use_skintones)
- var/new_s_tone = input(user, "Choose your skin tone:", "Race change") as null|anything in GLOB.skin_tones
-
+ var/new_s_tone = input(H, "Choose your skin tone:", "Race change") as null|anything in GLOB.skin_tones + "custom"
if(new_s_tone)
- H.skin_tone = new_s_tone
- H.dna.update_ui_block(DNA_SKIN_TONE_BLOCK)
+ if(new_s_tone == "custom")
+ var/default = H.dna.skin_tone_override || null
+ var/custom_tone = input(user, "Choose your custom skin tone:", "Race change", default) as color|null
+ if(custom_tone)
+ var/temp_hsv = RGBtoHSV(new_s_tone)
+ if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
+ to_chat(H,"Invalid color. Your color is not bright enough.")
+ else
+ H.skin_tone = custom_tone
+ H.dna.skin_tone_override = custom_tone
+ else
+ H.skin_tone = new_s_tone
+ H.dna.update_ui_block(DNA_SKIN_TONE_BLOCK)
if(MUTCOLORS in H.dna.species.species_traits)
var/new_mutantcolor = input(user, "Choose your skin color:", "Race change","#"+H.dna.features["mcolor"]) as color|null
diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm
index 3e604856c5..59651b17d5 100644
--- a/code/modules/admin/create_mob.dm
+++ b/code/modules/admin/create_mob.dm
@@ -18,6 +18,7 @@
H.undie_color = random_short_color()
H.undershirt = random_undershirt(H.gender)
H.shirt_color = random_short_color()
+ H.dna.skin_tone_override = null
H.skin_tone = random_skin_tone()
H.hair_style = random_hair_style(H.gender)
H.facial_hair_style = random_facial_hair_style(H.gender)
diff --git a/code/modules/antagonists/bloodsucker/powers/veil.dm b/code/modules/antagonists/bloodsucker/powers/veil.dm
index ecb0611940..671f88f2c1 100644
--- a/code/modules/antagonists/bloodsucker/powers/veil.dm
+++ b/code/modules/antagonists/bloodsucker/powers/veil.dm
@@ -82,6 +82,7 @@
// Change Appearance, not randomizing clothes colour, itll just be janky
H.gender = pick(MALE, FEMALE)
+ H.dna.skin_tone_override = null
H.skin_tone = random_skin_tone()
H.hair_style = random_hair_style(H.gender)
H.facial_hair_style = pick(random_facial_hair_style(H.gender),"Shaved")
@@ -124,6 +125,8 @@
// Revert Appearance
H.gender = prev_gender
H.skin_tone = prev_skin_tone
+ if(!GLOB.skin_tones[H.skin_tone])
+ H.dna.skin_tone_override = H.skin_tone
H.hair_style = prev_hair_style
H.facial_hair_style = prev_facial_hair_style
H.hair_color = prev_hair_color
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index 50dd1e5608..5dc11ed100 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -205,6 +205,8 @@
H.facial_hair_style = random_facial_hair_style(gender)
if(skin_tone)
H.skin_tone = skin_tone
+ if(!GLOB.skin_tones[H.skin_tone])
+ H.dna.skin_tone_override = H.skin_tone
else
H.skin_tone = random_skin_tone()
H.update_hair()
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index f7d251f32d..719d77118e 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -89,11 +89,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/facial_hair_style = "Shaved" //Face hair type
var/facial_hair_color = "000" //Facial hair color
var/skin_tone = "caucasian1" //Skin color
+ var/use_custom_skin_tone = FALSE
var/eye_color = "000" //Eye color
var/horn_color = "85615a" //Horn color
var/wing_color = "fff" //Wing color
var/datum/species/pref_species = new /datum/species/human() //Mutant race
var/list/features = list("mcolor" = "FFF",
+ "mcolor2" = "FFF",
+ "mcolor3" = "FFF",
"tail_lizard" = "Smooth",
"tail_human" = "None",
"snout" = "Round",
@@ -108,8 +111,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"insect_wings" = "Plain",
"insect_fluff" = "None",
"insect_markings" = "None",
- "mcolor2" = "FFF",
- "mcolor3" = "FFF",
"mam_body_markings" = "Plain",
"mam_ears" = "None",
"mam_snouts" = "None",
@@ -361,7 +362,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "
Skin Tone
"
- dat += "[skin_tone]
"
+ dat += "[use_custom_skin_tone ? "custom: " : skin_tone]
"
var/mutant_colors
if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits))
@@ -763,7 +764,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(features["has_cock"])
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
dat += "Penis Color:
"
- dat += " (Skin tone overriding)
"
+ dat += " (Skin tone overriding)
"
else
dat += "Penis Color:
"
dat += " Change
"
@@ -781,7 +782,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(features["has_balls"])
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
dat += "Testicles Color:
"
- dat += " (Skin tone overriding)
"
+ dat += " (Skin tone overriding)
"
else
dat += "Testicles Color:
"
dat += " Change
"
@@ -793,7 +794,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Vagina Type: [features["vag_shape"]]"
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
dat += "Vagina Color:
"
- dat += " (Skin tone overriding)
"
+ dat += " (Skin tone overriding)
"
else
dat += "Vagina Color:
"
dat += " Change
"
@@ -806,7 +807,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(features["has_breasts"])
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
dat += "Color:
"
- dat += " (Skin tone overriding)
"
+ dat += " (Skin tone overriding)
"
else
dat += "Color:
"
dat += " Change
"
@@ -1438,6 +1439,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
eye_color = random_eye_color()
if("s_tone")
skin_tone = random_skin_tone()
+ use_custom_skin_tone = null
if("bag")
backbag = pick(GLOB.backbaglist)
if("suit")
@@ -1834,9 +1836,22 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["insect_markings"] = new_insect_markings
if("s_tone")
- var/new_s_tone = input(user, "Choose your character's skin-tone:", "Character Preference") as null|anything in GLOB.skin_tones
+ var/list/choices = GLOB.skin_tones - GLOB.nonstandard_skin_tones + "custom"
+ var/new_s_tone = input(user, "Choose your character's skin tone:", "Character Preference") as null|anything in choices
if(new_s_tone)
- skin_tone = new_s_tone
+ if(new_s_tone == "custom")
+ var/default = use_custom_skin_tone ? skin_tone : null
+ var/custom_tone = input(user, "Choose your custom skin tone:", "Character Preference", default) as color|null
+ if(custom_tone)
+ var/temp_hsv = RGBtoHSV(new_s_tone)
+ if(ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3])
+ to_chat(user,"Invalid color. Your color is not bright enough.")
+ else
+ use_custom_skin_tone = TRUE
+ skin_tone = custom_tone
+ else
+ use_custom_skin_tone = FALSE
+ skin_tone = new_s_tone
if("taur")
var/list/snowflake_taur_list = list()
@@ -2430,6 +2445,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.wing_color = wing_color
character.skin_tone = skin_tone
+ character.dna.skin_tone_override = use_custom_skin_tone ? skin_tone : null
character.hair_style = hair_style
character.facial_hair_style = facial_hair_style
character.underwear = underwear
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 7da9d5a1dc..06f2559722 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -400,6 +400,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["hair_color"] >> hair_color
S["facial_hair_color"] >> facial_hair_color
S["eye_color"] >> eye_color
+ S["use_custom_skin_tone"] >> use_custom_skin_tone
S["skin_tone"] >> skin_tone
S["hair_style_name"] >> hair_style
S["facial_style_name"] >> facial_hair_style
@@ -548,7 +549,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
hair_color = sanitize_hexcolor(hair_color, 3, 0)
facial_hair_color = sanitize_hexcolor(facial_hair_color, 3, 0)
eye_color = sanitize_hexcolor(eye_color, 3, 0)
- skin_tone = sanitize_inlist(skin_tone, GLOB.skin_tones)
+ use_custom_skin_tone = sanitize_integer(use_custom_skin_tone, FALSE, TRUE, initial(use_custom_skin_tone))
+ if(use_custom_skin_tone)
+ skin_tone = sanitize_hexcolor(skin_tone, 6, TRUE, "#FFFFFF")
+ else
+ skin_tone = sanitize_inlist(skin_tone, GLOB.skin_tones - GLOB.nonstandard_skin_tones, initial(skin_tone))
horn_color = sanitize_hexcolor(horn_color, 3, FALSE)
wing_color = sanitize_hexcolor(wing_color, 3, FALSE, "#FFFFFF")
backbag = sanitize_inlist(backbag, GLOB.backbaglist, initial(backbag))
@@ -657,6 +662,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["hair_color"] , hair_color)
WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
WRITE_FILE(S["eye_color"] , eye_color)
+ WRITE_FILE(S["use_custom_skin_tone"] , use_custom_skin_tone)
WRITE_FILE(S["skin_tone"] , skin_tone)
WRITE_FILE(S["hair_style_name"] , hair_style)
WRITE_FILE(S["facial_style_name"] , facial_hair_style)
diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm
index a7fdf2d914..b669e30a06 100644
--- a/code/modules/mob/dead/new_player/preferences_setup.dm
+++ b/code/modules/mob/dead/new_player/preferences_setup.dm
@@ -11,6 +11,7 @@
shirt_color = random_short_color()
socks = random_socks()
socks_color = random_short_color()
+ use_custom_skin_tone = FALSE
skin_tone = random_skin_tone()
hair_style = random_hair_style(gender)
facial_hair_style = random_facial_hair_style(gender)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index e39ce7d488..f7450979c2 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -39,7 +39,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/horn_color //specific horn colors, because why not?
var/wing_color
- var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans)
+ var/use_skintones = NO_SKINTONES // does it use skintones or not? (spoiler alert this is only used by humans)
var/exotic_blood = "" // If your race wants to bleed something other than bog standard blood, change this to reagent id.
var/exotic_bloodtype = "" //If your race uses a non standard bloodtype (A+, O-, AB-, etc)
var/meat = /obj/item/reagent_containers/food/snacks/meat/slab/human //What the species drops on gibbing
@@ -853,7 +853,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!forced_colour)
switch(S.color_src)
if(SKINTONE)
- accessory_overlay.color = "#[skintone2hex(H.skin_tone)]"
+ accessory_overlay.color = SKINTONE2HEX(H.skin_tone)
if(MUTCOLORS)
if(fixed_mut_color)
accessory_overlay.color = "#[fixed_mut_color]"
@@ -1456,12 +1456,12 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(target.check_martial_melee_block())
target.visible_message("[target] blocks [user]'s attack!")
return FALSE
-
+
if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount
user.adjustStaminaLossBuffered(1.5)
else
user.adjustStaminaLossBuffered(3.5)
-
+
if(attacker_style && attacker_style.harm_act(user,target))
return TRUE
else
@@ -1526,7 +1526,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(user.limb_destroyer)
target.dismembering_strike(user, affecting.body_zone)
-
+
if(atk_verb == ATTACK_EFFECT_KICK)//kicks deal 1.5x raw damage + 0.5x stamina damage
target.apply_damage(damage*1.5, BRUTE, affecting, armor_block)
target.apply_damage(damage*0.5, STAMINA, affecting, armor_block)
@@ -1538,21 +1538,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if((target.stat != DEAD) && damage >= user.dna.species.punchstunthreshold)
if((punchedstam > 50) && prob(punchedstam*0.5)) //If our punch victim has been hit above the threshold, and they have more than 50 stamina damage, roll for stun, probability of 1% per 2 stamina damage
-
+
target.visible_message("[user] knocks [target] down!", \
"You're knocked down by [user]!", "You hear aggressive shuffling followed by a loud thud!", COMBAT_MESSAGE_RANGE, user)
to_chat(user, "You knock [target] down!")
-
+
var/knockdown_duration = 40 + (punchedstam + (punchedbrute*0.5))*0.8 - armor_block
target.DefaultCombatKnockdown(knockdown_duration)
target.forcesay(GLOB.hit_appends)
log_combat(user, target, "got a stun punch with their previous punch")
-
+
if(HAS_TRAIT(user, TRAIT_KI_VAMPIRE) && !HAS_TRAIT(target, TRAIT_NOBREATH) && (punchedbrute < 100)) //If we're a ki vampire we also sap them of lifeforce, but only if they're not too beat up. Also living organics only.
user.adjustBruteLoss(-5)
user.adjustFireLoss(-5)
user.adjustStaminaLoss(-20)
-
+
target.adjustCloneLoss(10)
target.adjustBruteLoss(10)
diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm
index 5474adcf88..1a92da3b0a 100644
--- a/code/modules/mob/living/carbon/human/species_types/angel.dm
+++ b/code/modules/mob/living/carbon/human/species_types/angel.dm
@@ -4,7 +4,7 @@
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "wings" = "Angel")
- use_skintones = 1
+ use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
no_equip = list(SLOT_BACK)
blacklisted = 1
limbs_id = "human"
diff --git a/code/modules/mob/living/carbon/human/species_types/corporate.dm b/code/modules/mob/living/carbon/human/species_types/corporate.dm
index 3de530ff5b..e062e1cbf7 100644
--- a/code/modules/mob/living/carbon/human/species_types/corporate.dm
+++ b/code/modules/mob/living/carbon/human/species_types/corporate.dm
@@ -13,8 +13,7 @@
punchstunthreshold = 25
attack_verb = "smash"
attack_sound = 'sound/weapons/resonator_blast.ogg'
- blacklisted = 1
- use_skintones = 0
+ blacklisted = TRUE
species_traits = list(NOBLOOD,EYECOLOR,NOGENITALS)
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER)
sexes = 0
diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
index a41cc8c55a..ef730da219 100644
--- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
@@ -5,7 +5,7 @@
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "deco_wings" = "None")
- use_skintones = TRUE
+ use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
mutant_brain = /obj/item/organ/brain/dullahan
mutanteyes = /obj/item/organ/eyes/dullahan
mutanttongue = /obj/item/organ/tongue/dullahan
diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
index bb2c08aa9b..235dacc70a 100644
--- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
@@ -9,7 +9,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NO_UNDERWEAR)
inherent_traits = list()
limbs_id = "human"
- use_skintones = 1
+ use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
say_mod = "bellows" //high energy, EXTRA BIOLOGICAL FUEL
damage_overlay_type = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm
index 02cff6d924..606b7a8bfd 100644
--- a/code/modules/mob/living/carbon/human/species_types/humans.dm
+++ b/code/modules/mob/living/carbon/human/species_types/humans.dm
@@ -5,7 +5,7 @@
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR)
mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None")
- use_skintones = 1
+ use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
skinned_type = /obj/item/stack/sheet/animalhide/human
disliked_food = GROSS | RAW
liked_food = JUNKFOOD | FRIED
diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
index cb8fdbf101..5390d9e7f4 100644
--- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
@@ -22,7 +22,6 @@
heatmod = 1.5
mutanteyes = /obj/item/organ/eyes/night_vision/mushroom
- use_skintones = FALSE
var/datum/martial_art/mushpunch/mush
/datum/species/mush/after_equip_job(datum/job/J, mob/living/carbon/human/H)
diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm
index 6c42e622fe..deab31dec3 100644
--- a/code/modules/mob/living/carbon/human/species_types/synths.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synths.dm
@@ -80,7 +80,7 @@
fake_species = null
meat = initial(meat)
limbs_id = "synth"
- use_skintones = 0
+ use_skintones = FALSE
sexes = 0
fixed_mut_color = ""
hair_color = ""
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index 415cd9889c..f37e718462 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -7,7 +7,7 @@
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutant_bodyparts = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
exotic_bloodtype = "U"
- use_skintones = TRUE
+ use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
mutant_heart = /obj/item/organ/heart/vampire
mutanttongue = /obj/item/organ/tongue/vampire
blacklisted = TRUE
@@ -23,7 +23,8 @@
/datum/species/vampire/on_species_gain(mob/living/carbon/human/C, datum/species/old_species)
. = ..()
to_chat(C, "[info_text]")
- C.skin_tone = "albino"
+ if(!C.dna.skin_tone_override)
+ C.skin_tone = "albino"
C.update_body(0)
var/obj/effect/proc_holder/spell/targeted/shapeshift/bat/B = new
C.AddSpell(B)
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index c2f14e69ec..e66ebc5f20 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -507,93 +507,83 @@
/datum/reagent/spraytan/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(ishuman(M))
if(method == PATCH || method == VAPOR)
- var/mob/living/carbon/human/N = M
- if(N.dna.species.id == "human")
- switch(N.skin_tone)
- if("african1")
- N.skin_tone = "african2"
- if("indian")
- N.skin_tone = "african1"
- if("arab")
- N.skin_tone = "indian"
- if("asian2")
- N.skin_tone = "arab"
- if("asian1")
- N.skin_tone = "asian2"
- if("mediterranean")
- N.skin_tone = "african1"
- if("latino")
- N.skin_tone = "mediterranean"
- if("caucasian3")
- N.skin_tone = "mediterranean"
- if("caucasian2")
- N.skin_tone = pick("caucasian3", "latino")
- if("caucasian1")
- N.skin_tone = "caucasian2"
- if ("albino")
- N.skin_tone = "caucasian1"
+ var/mob/living/carbon/human/H = M
+ if(H.dna.species.use_skintones)
+ if(!H.dna.skin_tone_override)
+ var/diff_len = length(GLOB.skin_tones - GLOB.nonstandard_skin_tones)
+ H.skin_tone = GLOB.skin_tones[min(diff_len, GLOB.skin_tones.Find(H.skin_tone) + 1)]
+ else
+ H.skin_tone = H.dna.skin_tone_override = tan_mutant_color(H.dna.skin_tone_override, "#202020")
+ if(MUTCOLORS in H.dna.species.species_traits) //take current alien color and darken it slightly
+ H.dna.features["mcolor"] = tan_mutant_color(H.dna.features["mcolor"])
+ H.update_body()
- if(MUTCOLORS in N.dna.species.species_traits) //take current alien color and darken it slightly
- var/newcolor = ""
- var/string = N.dna.features["mcolor"]
- var/len = length(string)
- var/char = ""
- var/ascii = 0
- for(var/i=1, i<=len, i += length(char))
- char = string[i]
- ascii = text2ascii(char)
- switch(ascii)
- if(48)
- newcolor += "0"
- if(49 to 57)
- newcolor += ascii2text(ascii-1) //numbers 1 to 9
- if(97)
- newcolor += "9"
- if(98 to 102)
- newcolor += ascii2text(ascii-1) //letters b to f lowercase
- if(65)
- newcolor += "9"
- if(66 to 70)
- newcolor += ascii2text(ascii+31) //letters B to F - translates to lowercase
- else
- break
- if(ReadHSV(newcolor)[3] >= ReadHSV("#7F7F7F")[3])
- N.dna.features["mcolor"] = newcolor
- N.regenerate_icons()
+ if(method == INGEST)
+ if(show_message)
+ to_chat(M, "That tasted horrible.")
+ return ..()
+/datum/reagent/spraytan/proc/tan_mutant_color(color, limit = "#7F7F7F")
+ var/newcolor = ""
+ var/len = length(color)
+ var/char = ""
+ var/ascii = 0
+ for(var/i=1, i<=len, i += length(char))
+ char = color[i]
+ ascii = text2ascii(char)
+ switch(ascii)
+ if(35)
+ newcolor += "#"
+ if(48)
+ newcolor += "0"
+ if(49 to 57)
+ newcolor += ascii2text(ascii-1) //numbers 1 to 9
+ if(97)
+ newcolor += "9"
+ if(98 to 102)
+ newcolor += ascii2text(ascii-1) //letters b to f lowercase
+ if(65)
+ newcolor += "9"
+ if(66 to 70)
+ newcolor += ascii2text(ascii+31) //letters B to F - translates to lowercase
+ else
+ break
+ if(ReadHSV(newcolor)[3] >= ReadHSV(limit)[3])
+ return newcolor
+ return color
- if(method == INGEST)
- if(show_message)
- to_chat(M, "That tasted horrible.")
- ..()
-
+/datum/reagent/spraytan/overdose_start(mob/living/M)
+ . = ..()
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.hair_style = "Spiky"
+ H.facial_hair_style = "Shaved"
+ H.facial_hair_color = "000"
+ H.hair_color = "000"
+ if(!(HAIR in H.dna.species.species_traits)) //No hair? No problem!
+ H.dna.species.species_traits += HAIR
+ if(H.dna.species.use_skintones)
+ if(H.dna.skin_tone_override)
+ H.skin_tone = H.dna.skin_tone_override = "#FF8800"
+ else
+ H.skin_tone = "orange"
+ else if(MUTCOLORS in H.dna.species.species_traits) //Aliens with custom colors simply get turned orange
+ H.dna.features["mcolor"] = "f80"
+ H.update_body()
/datum/reagent/spraytan/overdose_process(mob/living/M)
metabolization_rate = 1 * REAGENTS_METABOLISM
-
if(ishuman(M))
- var/mob/living/carbon/human/N = M
- N.hair_style = "Spiky"
- N.facial_hair_style = "Shaved"
- N.facial_hair_color = "000"
- N.hair_color = "000"
- if(!(HAIR in N.dna.species.species_traits)) //No hair? No problem!
- N.dna.species.species_traits += HAIR
- if(N.dna.species.use_skintones)
- N.skin_tone = "orange"
- else if(MUTCOLORS in N.dna.species.species_traits) //Aliens with custom colors simply get turned orange
- N.dna.features["mcolor"] = "f80"
- N.regenerate_icons()
+ var/mob/living/carbon/human/H = M
if(prob(7))
- if(N.w_uniform)
- M.visible_message(pick("[M]'s collar pops up without warning.", "[M] flexes [M.p_their()] arms."))
+ if(H.w_uniform)
+ H.visible_message(pick("[H]'s collar pops up without warning.", "[H] flexes [H.p_their()] arms."))
else
- M.visible_message("[M] flexes [M.p_their()] arms.")
+ H.visible_message("[H] flexes [H.p_their()] arms.")
if(prob(10))
M.say(pick("Shit was SO cash.", "You are everything bad in the world.", "What sports do you play, other than 'jack off to naked drawn Japanese people?'", "Don’t be a stranger. Just hit me with your best shot.", "My name is John and I hate every single one of you."), forced = "spraytan")
- ..()
- return
+ return ..()
/datum/reagent/mutationtoxin
name = "Stable Mutation Toxin"
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index 54f2aef10d..7a99d3ff29 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -350,7 +350,8 @@
body_gender = H.dna.features["body_model"]
should_draw_gender = S.sexes
- if(MUTCOLORS in S.species_traits)
+ var/mut_colors = (MUTCOLORS in S.species_traits)
+ if(mut_colors)
if(S.fixed_mut_color)
species_color = S.fixed_mut_color
else
@@ -360,7 +361,7 @@
species_color = ""
if(base_bp_icon != DEFAULT_BODYPART_ICON)
- color_src = MUTCOLORS //TODO - Add color matrix support to base limbs
+ color_src = mut_colors ? MUTCOLORS : (H.dna.skin_tone_override && S.use_skintones == USE_SKINTONES_GRAYSCALE_CUSTOM) ? CUSTOM_SKINTONE : SKINTONE
if(S.mutant_bodyparts["legs"])
if(body_zone == BODY_ZONE_L_LEG || body_zone == BODY_ZONE_R_LEG)
@@ -544,12 +545,20 @@
return
if(color_src) //TODO - add color matrix support for base species limbs
- var/draw_color = mutation_color || species_color || (skin_tone && skintone2hex(skin_tone))
+ var/draw_color = mutation_color || species_color || GLOB.skin_tones[skin_tone]
+ var/grayscale = FALSE
+ if(!draw_color) //check for custom skin tones.
+ draw_color = skin_tone
+ grayscale = color_src == CUSTOM_SKINTONE //Cause human (the species) parts states have a very pale pink hue.
if(draw_color)
+ if(grayscale)
+ limb.icon_state += "_g"
limb.color = "#[draw_color]"
if(aux_icons)
for(var/a in aux)
var/image/I = a
+ if(grayscale)
+ I.icon_state += "_g"
I.color = "#[draw_color]"
if(!isnull(aux_marking))
for(var/a in auxmarking)
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index aaca33685b..a1f1bd7daf 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -252,37 +252,6 @@
L.change_bodypart_status(BODYPART_ROBOTIC)
. = L
-
-/proc/skintone2hex(skin_tone)
- . = 0
- switch(skin_tone)
- if("caucasian1")
- . = "ffe0d1"
- if("caucasian2")
- . = "fcccb3"
- if("caucasian3")
- . = "e8b59b"
- if("latino")
- . = "d9ae96"
- if("mediterranean")
- . = "c79b8b"
- if("asian1")
- . = "ffdeb3"
- if("asian2")
- . = "e3ba84"
- if("arab")
- . = "c4915e"
- if("indian")
- . = "b87840"
- if("african1")
- . = "754523"
- if("african2")
- . = "471c18"
- if("albino")
- . = "fff4e6"
- if("orange")
- . = "ffc905"
-
/mob/living/carbon/proc/Digitigrade_Leg_Swap(swap_back)
for(var/X in bodyparts)
var/obj/item/bodypart/O = X
diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi
index 3ecfc7bb0c..989ec8049c 100644
Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ
diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm
index 8fda73b199..68e9259183 100644
--- a/modular_citadel/code/modules/arousal/genitals.dm
+++ b/modular_citadel/code/modules/arousal/genitals.dm
@@ -319,7 +319,7 @@
genital_overlay = center_image(genital_overlay, dim_x, dim_y)
if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
- genital_overlay.color = "#[skintone2hex(skin_tone)]"
+ genital_overlay.color = SKINTONE2HEX(skin_tone)
else
switch(S.color_src)
if("cock_color")
@@ -331,7 +331,7 @@
if("vag_color")
genital_overlay.color = "#[dna.features["vag_color"]]"
- genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size][dna.species.use_skintones ? "_s" : ""]_[aroused_state]_[layertext]"
+ genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size][(dna.species.use_skintones && !dna.skin_tone_override) ? "_s" : ""]_[aroused_state]_[layertext]"
if(layers_num[layer] == GENITALS_FRONT_LAYER && G.genital_flags & GENITAL_THROUGH_CLOTHES)
genital_overlay.layer = -GENITALS_EXPOSED_LAYER
@@ -361,9 +361,8 @@
var/willyCheck = getorganslot(ORGAN_SLOT_PENIS)
if(organCheck == FALSE)
- if(ishuman(src) && dna.species.id == "human")
+ if(ishuman(src) && dna.species.use_skintones)
dna.features["genitals_use_skintone"] = TRUE
- dna.species.use_skintones = TRUE
if(src.dna.species.fixed_mut_color)
dna.features["cock_color"] = "[dna.species.fixed_mut_color]"
dna.features["breasts_color"] = "[dna.species.fixed_mut_color]"
diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm
index 8183ba92bc..c936eb9dc4 100644
--- a/modular_citadel/code/modules/arousal/organs/breasts.dm
+++ b/modular_citadel/code/modules/arousal/organs/breasts.dm
@@ -55,13 +55,14 @@
var/datum/sprite_accessory/S = GLOB.breasts_shapes_list[shape]
var/icon_shape = S ? S.icon_state : "pair"
var/icon_size = CLAMP(breast_values[size], BREASTS_ICON_MIN_SIZE, BREASTS_ICON_MAX_SIZE)
- icon_state = "breasts_[icon_shape]_[breast_values[icon_size]]"
+ icon_state = "breasts_[icon_shape]_[icon_size]"
if(owner)
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
- color = "#[skintone2hex(H.skin_tone)]"
- icon_state += "_s"
+ color = SKINTONE2HEX(H.skin_tone)
+ if(!H.dna.skin_tone_override)
+ icon_state += "_s"
else
color = "#[owner.dna.features["breasts_color"]]"
@@ -117,7 +118,7 @@
/obj/item/organ/genital/breasts/get_features(mob/living/carbon/human/H)
var/datum/dna/D = H.dna
if(D.species.use_skintones && D.features["genitals_use_skintone"])
- color = "#[skintone2hex(H.skin_tone)]"
+ color = SKINTONE2HEX(H.skin_tone)
else
color = "#[D.features["breasts_color"]]"
size = D.features["breasts_size"]
diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm
index b3ca0062f8..c05549aaa0 100644
--- a/modular_citadel/code/modules/arousal/organs/penis.dm
+++ b/modular_citadel/code/modules/arousal/organs/penis.dm
@@ -84,8 +84,9 @@
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
- color = "#[skintone2hex(H.skin_tone)]"
- icon_state += "_s"
+ color = SKINTONE2HEX(H.skin_tone)
+ if(!H.dna.skin_tone_override)
+ icon_state += "_s"
else
color = "#[owner.dna.features["cock_color"]]"
if(genital_flags & GENITAL_CAN_TAUR && S?.taur_icon && (!S.feat_taur || owner.dna.features[S.feat_taur]) && owner.dna.species.mutant_bodyparts["taur"])
@@ -98,7 +99,7 @@
/obj/item/organ/genital/penis/get_features(mob/living/carbon/human/H)
var/datum/dna/D = H.dna
if(D.species.use_skintones && D.features["genitals_use_skintone"])
- color = "#[skintone2hex(H.skin_tone)]"
+ color = SKINTONE2HEX(H.skin_tone)
else
color = "#[D.features["cock_color"]]"
length = D.features["cock_length"]
diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm
index 4264cf5e48..a8946294b1 100644
--- a/modular_citadel/code/modules/arousal/organs/testicles.dm
+++ b/modular_citadel/code/modules/arousal/organs/testicles.dm
@@ -49,15 +49,16 @@
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
- color = "#[skintone2hex(H.skin_tone)]"
- icon_state += "_s"
+ color = SKINTONE2HEX(H.skin_tone)
+ if(!H.dna.skin_tone_override)
+ icon_state += "_s"
else
color = "#[owner.dna.features["balls_color"]]"
/obj/item/organ/genital/testicles/get_features(mob/living/carbon/human/H)
var/datum/dna/D = H.dna
if(D.species.use_skintones && D.features["genitals_use_skintone"])
- color = "#[skintone2hex(H.skin_tone)]"
+ color = SKINTONE2HEX(H.skin_tone)
else
color = "#[D.features["balls_color"]]"
shape = D.features["balls_shape"]
diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/modular_citadel/code/modules/arousal/organs/vagina.dm
index f7e8eddcbd..cdc7dc4927 100644
--- a/modular_citadel/code/modules/arousal/organs/vagina.dm
+++ b/modular_citadel/code/modules/arousal/organs/vagina.dm
@@ -55,8 +55,9 @@
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
- color = "#[skintone2hex(H.skin_tone)]"
- icon_state += "_s"
+ color = SKINTONE2HEX(H.skin_tone)
+ if(!H.dna.skin_tone_override)
+ icon_state += "_s"
else
color = "#[owner.dna.features["vag_color"]]"
if(ishuman(owner))
@@ -66,7 +67,7 @@
/obj/item/organ/genital/vagina/get_features(mob/living/carbon/human/H)
var/datum/dna/D = H.dna
if(D.species.use_skintones && D.features["genitals_use_skintone"])
- color = "#[skintone2hex(H.skin_tone)]"
+ color = SKINTONE2HEX(H.skin_tone)
else
color = "[D.features["vag_color"]]"
shape = "[D.features["vag_shape"]]"
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
index 198e6c5c24..97261e07f2 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
@@ -68,11 +68,11 @@
B = new
if(H.dna.species.use_skintones && H.dna.features["genitals_use_skintone"])
- B.color = skintone2hex(H.skin_tone)
+ B.color = SKINTONE2HEX(H.skin_tone)
else if(M.dna.features["breasts_color"])
B.color = "#[M.dna.features["breasts_color"]]"
else
- B.color = skintone2hex(H.skin_tone)
+ B.color = SKINTONE2HEX(H.skin_tone)
B.size = "flat"
B.cached_size = 0
B.prev_size = 0