diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 0a17f0d1df..19aac1aee0 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -78,6 +78,12 @@ var/datum/emote/E = new path() E.emote_list[E.key] = E + // Hair Gradients - Initialise all /datum/sprite_accessory/hair_gradient into an list indexed by gradient-style name + for(var/path in subtypesof(/datum/sprite_accessory/hair_gradient)) + var/datum/sprite_accessory/hair_gradient/H = new path() + GLOB.hair_gradients_list[H.name] = H + + // Keybindings init_keybindings() //Uplink Items diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 28f657828b..64c96cae3b 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -6,6 +6,7 @@ GLOBAL_LIST_EMPTY(hair_styles_female_list) //stores only hair names GLOBAL_LIST_EMPTY(facial_hair_styles_list) //stores /datum/sprite_accessory/facial_hair indexed by name GLOBAL_LIST_EMPTY(facial_hair_styles_male_list) //stores only hair names GLOBAL_LIST_EMPTY(facial_hair_styles_female_list) //stores only hair names +GLOBAL_LIST_EMPTY(hair_gradients_list) //stores /datum/sprite_accessory/hair_gradient indexed by name //Underwear GLOBAL_LIST_EMPTY_TYPED(underwear_list, /datum/sprite_accessory/underwear/bottom) //stores bottoms indexed by name GLOBAL_LIST_EMPTY(underwear_m) //stores only underwear name diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index 2f0667d942..36712ea6bb 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -162,3 +162,20 @@ gain_text = "You feel like munching on a can of soda." lose_text = "You no longer feel like you should be eating trash." mob_trait = TRAIT_TRASHCAN + +/datum/quirk/colorist + name = "Colorist" + desc = "You like carrying around a hair dye spray to quickly apply color patterns to your hair." + value = 0 + medical_record_text = "Patient enjoys dyeing their hair with pretty colors." + +/datum/quirk/colorist/on_spawn() + var/mob/living/carbon/human/H = quirk_holder + var/obj/item/dyespray/spraycan = new(get_turf(quirk_holder)) + H.equip_to_slot(spraycan, SLOT_IN_BACKPACK) + H.regenerate_icons() + +/datum/quirk/colorist/post_add() + var/mob/living/carbon/human/H = quirk_holder + SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H) + to_chat(quirk_holder, "You brought some extra dye with you! It's in your bag if you forgot.") diff --git a/code/game/objects/items/dyekit.dm b/code/game/objects/items/dyekit.dm new file mode 100644 index 0000000000..43a05c7939 --- /dev/null +++ b/code/game/objects/items/dyekit.dm @@ -0,0 +1,40 @@ +/obj/item/dyespray + name = "hair dye spray" + desc = "A spray to dye your hair any gradients you'd like." + icon = 'icons/obj/dyespray.dmi' + icon_state = "dyespray" + +/obj/item/dyespray/attack_self(mob/user) + dye(user) + +/obj/item/dyespray/pre_attack(atom/target, mob/living/user, params) + dye(target) + return ..() + +/** + * Applies a gradient and a gradient color to a mob. + * + * Arguments: + * * target - The mob who we will apply the gradient and gradient color to. + */ + +/obj/item/dyespray/proc/dye(mob/target) + if(!ishuman(target)) + return + var/mob/living/carbon/human/human_target = target + + var/new_grad_style = input(usr, "Choose a color pattern:", "Character Preference") as null|anything in GLOB.hair_gradients_list + if(!new_grad_style) + return + + var/new_grad_color = input(usr, "Choose a secondary hair color:", "Character Preference","#"+human_target.grad_color) as color|null + if(!new_grad_color) + return + + human_target.grad_style = new_grad_style + human_target.grad_color = sanitize_hexcolor(new_grad_color) + to_chat(human_target, "You start applying the hair dye...") + if(!do_after(usr, 30, target = human_target)) + return + playsound(src, 'sound/effects/spray.ogg', 5, TRUE, 5) + human_target.update_hair() diff --git a/code/modules/cargo/packs/goodies.dm b/code/modules/cargo/packs/goodies.dm index 5d4598fd58..5151845221 100644 --- a/code/modules/cargo/packs/goodies.dm +++ b/code/modules/cargo/packs/goodies.dm @@ -70,6 +70,12 @@ cost = 1500 contains = list(/obj/item/toy/plush/beeplushie) +/datum/supply_pack/goody/dyespray + name = "Hair Dye Spray" + desc = "A cool spray to dye your hair with awesome colors!" + cost = PAYCHECK_EASY * 2 + contains = list(/obj/item/dyespray) + /datum/supply_pack/goody/beach_ball name = "Beach Ball" desc = "The simple beach ball is one of Nanotrasen's most popular products. 'Why do we make beach balls? Because we can! (TM)' - Nanotrasen" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 8b214e85a4..cb262e57f3 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -119,6 +119,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/hair_color = "000000" //Hair color var/facial_hair_style = "Shaved" //Face hair type var/facial_hair_color = "000000" //Facial hair color + var/grad_style //Hair gradient style + var/grad_color = "FFFFFF" //Hair gradient color var/skin_tone = "caucasian1" //Skin color var/use_custom_skin_tone = FALSE var/left_eye_color = "000000" //Eye color @@ -505,6 +507,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "< >
" dat += "    Change
" + dat += "

Hair Gradient

" + + dat += "[grad_style]" + dat += "< >
" + dat += "    Change
" + dat += "" //Mutant stuff var/mutant_category = 0 @@ -1711,6 +1719,23 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("previous_facehair_style") facial_hair_style = previous_list_item(facial_hair_style, GLOB.facial_hair_styles_list) + if("grad_color") + var/new_grad_color = input(user, "Choose your character's gradient colour:", "Character Preference","#"+grad_color) as color|null + if(new_grad_color) + grad_color = sanitize_hexcolor(new_grad_color, 6) + + if("grad_style") + var/new_grad_style + new_grad_style = input(user, "Choose your character's hair gradient style:", "Character Preference") as null|anything in GLOB.hair_gradients_list + if(new_grad_style) + grad_style = new_grad_style + + if("next_grad_style") + grad_style = next_list_item(grad_style, GLOB.hair_gradients_list) + + if("previous_grad_style") + grad_style = previous_list_item(grad_style, GLOB.hair_gradients_list) + if("cycle_bg") bgstate = next_list_item(bgstate, bgstate_options) @@ -3016,6 +3041,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) 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.grad_style = grad_style + character.grad_color = grad_color character.underwear = underwear character.saved_underwear = underwear diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 4d62bb149d..c17bc16551 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -683,6 +683,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["skin_tone"] >> skin_tone S["hair_style_name"] >> hair_style S["facial_style_name"] >> facial_hair_style + S["grad_style"] >> grad_style + S["grad_color"] >> grad_color S["underwear"] >> underwear S["undie_color"] >> undie_color S["undershirt"] >> undershirt @@ -875,6 +877,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) hair_color = sanitize_hexcolor(hair_color, 6, FALSE) facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE) + grad_style = sanitize_inlist(grad_style, GLOB.hair_gradients_list) + grad_color = sanitize_hexcolor(grad_color, 6, FALSE) eye_type = sanitize_inlist(eye_type, GLOB.eye_types, DEFAULT_EYES_TYPE) left_eye_color = sanitize_hexcolor(left_eye_color, 6, FALSE) right_eye_color = sanitize_hexcolor(right_eye_color, 6, FALSE) @@ -1044,6 +1048,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["skin_tone"] , skin_tone) WRITE_FILE(S["hair_style_name"] , hair_style) WRITE_FILE(S["facial_style_name"] , facial_hair_style) + WRITE_FILE(S["grad_style"] , grad_style) + WRITE_FILE(S["grad_color"] , grad_color) WRITE_FILE(S["underwear"] , underwear) WRITE_FILE(S["undie_color"] , undie_color) WRITE_FILE(S["undershirt"] , undershirt) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm index 88dda923a0..e002fa369d 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm @@ -1058,3 +1058,58 @@ /datum/sprite_accessory/hair/zone name = "Zone" icon_state = "hair_zone" + +/datum/sprite_accessory/hair_gradient + icon = 'icons/mob/hair_gradients.dmi' + +/datum/sprite_accessory/hair_gradient/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/hair_gradient/fadeup + name = "Fade Up" + icon_state = "fadeup" + +/datum/sprite_accessory/hair_gradient/fadedown + name = "Fade Down" + icon_state = "fadedown" + +/datum/sprite_accessory/hair_gradient/vertical_split + name = "Vertical Split" + icon_state = "vsplit" + +/datum/sprite_accessory/hair_gradient/_split + name = "Horizontal Split" + icon_state = "bottomflat" + +/datum/sprite_accessory/hair_gradient/reflected + name = "Reflected" + icon_state = "reflected_high" + +/datum/sprite_accessory/hair_gradient/reflected_inverse + name = "Reflected Inverse" + icon_state = "reflected_inverse_high" + +/datum/sprite_accessory/hair_gradient/wavy + name = "Wavy" + icon_state = "wavy" + +/datum/sprite_accessory/hair_gradient/long_fade_up + name = "Long Fade Up" + icon_state = "long_fade_up" + +/datum/sprite_accessory/hair_gradient/long_fade_down + name = "Long Fade Down" + icon_state = "long_fade_down" + +/datum/sprite_accessory/hair_gradient/short_fade_up + name = "Short Fade Up" + icon_state = "short_fade_up" + +/datum/sprite_accessory/hair_gradient/short_fade_down + name = "Short Fade Down" + icon_state = "short_fade_down" + +/datum/sprite_accessory/hair_gradient/wavy_spike + name = "Spiked Wavy" + icon_state = "wavy_spiked" diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index e15f5b8be0..6723d2d4a6 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -20,6 +20,11 @@ var/hair_color = "000" var/hair_style = "Bald" + ///Colour used for the hair gradient. + var/grad_color = "000" + ///Style used for the hair gradient. + var/grad_style + //Facial hair colour and style var/facial_hair_color = "000" var/facial_hair_style = "Shaved" diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 6f94be2d41..80edd142b7 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -52,6 +52,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/hair_color ///The alpha used by the hair. 255 is completely solid, 0 is invisible. var/hair_alpha = 255 + ///The gradient style used for the mob's hair. + var/grad_style + ///The gradient color used to color the gradient. + var/grad_color ///Does the species use skintones or not? As of now only used by humans. var/use_skintones = FALSE @@ -678,6 +682,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(!hair_hidden || dynamic_hair_suffix) var/mutable_appearance/hair_overlay = mutable_appearance(layer = -HAIR_LAYER) + var/mutable_appearance/gradient_overlay = mutable_appearance(layer = -HAIR_LAYER) if(!hair_hidden && !H.getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain if(!(NOBLOOD in species_traits)) hair_overlay.icon = 'icons/mob/human_parts.dmi' @@ -713,8 +718,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) hair_overlay.color = "#" + hair_color else hair_overlay.color = "#" + H.hair_color + + //Gradients + grad_style = H.grad_style + grad_color = H.grad_color + if(grad_style) + var/datum/sprite_accessory/gradient = GLOB.hair_gradients_list[grad_style] + var/icon/temp = icon(gradient.icon, gradient.icon_state) + var/icon/temp_hair = icon(hair_file, hair_state) + temp.Blend(temp_hair, ICON_ADD) + gradient_overlay.icon = temp + gradient_overlay.color = "#" + grad_color + else hair_overlay.color = forced_colour + hair_overlay.alpha = hair_alpha if(OFFSET_HAIR in H.dna.species.offset_features) @@ -723,6 +741,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(hair_overlay.icon) standing += hair_overlay + standing += gradient_overlay if(standing.len) H.overlays_standing[HAIR_LAYER] = standing diff --git a/code/modules/vending/games.dm b/code/modules/vending/games.dm index cea9c5ae70..a1d9bc1691 100644 --- a/code/modules/vending/games.dm +++ b/code/modules/vending/games.dm @@ -9,6 +9,7 @@ /obj/item/toy/cards/deck/cas/black = 3, /obj/item/toy/cards/deck/unum = 3, /obj/item/cardpack/series_one = 10, + /obj/item/dyespray=3, /obj/item/tcgcard_binder = 5) contraband = list(/obj/item/dice/fudge = 9) premium = list(/obj/item/melee/skateboard/pro = 3, diff --git a/icons/mob/hair_gradients.dmi b/icons/mob/hair_gradients.dmi new file mode 100644 index 0000000000..ceb3b52eab Binary files /dev/null and b/icons/mob/hair_gradients.dmi differ diff --git a/icons/obj/dyespray.dmi b/icons/obj/dyespray.dmi new file mode 100644 index 0000000000..eb05603679 Binary files /dev/null and b/icons/obj/dyespray.dmi differ diff --git a/tgstation.dme b/tgstation.dme index c3a1e7087c..408ca3ae54 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1101,6 +1101,7 @@ #include "code\game\objects\items\dna_injector.dm" #include "code\game\objects\items\documents.dm" #include "code\game\objects\items\dualsaber.dm" +#include "code\game\objects\items\dyekit.dm" #include "code\game\objects\items\eightball.dm" #include "code\game\objects\items\electrostaff.dm" #include "code\game\objects\items\extinguisher.dm"