From ca78e5f31182993cb7001b076ccc5ceb14fa5bd1 Mon Sep 17 00:00:00 2001 From: mochi Date: Sun, 13 Jun 2021 10:55:21 +0200 Subject: [PATCH 1/4] Add hair gradient customization --- SQL/paradise_schema.sql | 4 + SQL/paradise_schema_prefixed.sql | 10 ++- SQL/updates/24-25.sql | 6 ++ code/__DEFINES/colors.dm | 4 + code/__DEFINES/misc.dm | 2 +- code/__HELPERS/global_lists.dm | 2 + code/_globalvars/lists/flavor_misc.dm | 2 +- code/modules/client/preference/preferences.dm | 45 +++++++++++ .../client/preference/preferences_mysql.dm | 29 ++++++- .../mob/living/carbon/human/update_icons.dm | 73 ++++++++++-------- .../sprite_accessories/sprite_accessories.dm | 45 +++++++++++ .../surgery/organs/subtypes/standard.dm | 5 ++ config/example/dbconfig.txt | 2 +- icons/mob/hair_gradients.dmi | Bin 0 -> 1663 bytes tools/ci/dbconfig.txt | 2 +- 15 files changed, 191 insertions(+), 40 deletions(-) create mode 100644 SQL/updates/24-25.sql create mode 100644 icons/mob/hair_gradients.dmi diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index f73134e6704..eaca618b7d3 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -75,6 +75,10 @@ CREATE TABLE `characters` ( `body_accessory` longtext COLLATE utf8mb4_unicode_ci NOT NULL, `gear` longtext COLLATE utf8mb4_unicode_ci NOT NULL, `autohiss` tinyint(1) NOT NULL, + `hair_gradient` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL, + `hair_gradient_offset` varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0,0', + `hair_gradient_colour` varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '#000000', + `hair_gradient_alpha` tinyint(3) UNSIGNED NOT NULL DEFAULT '255', PRIMARY KEY (`id`), KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=125467 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index 16ea512fb08..3c843251572 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -75,6 +75,10 @@ CREATE TABLE `SS13_characters` ( `body_accessory` longtext COLLATE utf8mb4_unicode_ci NOT NULL, `gear` longtext COLLATE utf8mb4_unicode_ci NOT NULL, `autohiss` tinyint(1) NOT NULL, + `hair_gradient` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL, + `hair_gradient_offset` varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0,0', + `hair_gradient_colour` varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '#000000', + `hair_gradient_alpha` tinyint(3) UNSIGNED NOT NULL DEFAULT '255', PRIMARY KEY (`id`), KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=125467 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; @@ -276,13 +280,13 @@ CREATE TABLE `SS13_player` ( `fupdate` smallint(4) DEFAULT '0', `parallax` tinyint(1) DEFAULT '8', `byond_date` DATE DEFAULT NULL, + `keybindings` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `keybindings` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL, `2fa_status` ENUM('DISABLED','ENABLED_IP','ENABLED_ALWAYS') NOT NULL DEFAULT 'DISABLED' COLLATE 'utf8mb4_general_ci', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`), KEY `lastseen` (`lastseen`), - KEY `computerid` (`computerid`), - KEY `ip` (`ip`), - KEY `fuid` (`fuid`), + KEY `co KEY `fupdate` (`fupdate`) ) ENGINE=InnoDB AUTO_INCREMENT=135298 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/SQL/updates/24-25.sql b/SQL/updates/24-25.sql new file mode 100644 index 00000000000..a9dc047f27a --- /dev/null +++ b/SQL/updates/24-25.sql @@ -0,0 +1,6 @@ +# Updates DB from 24 to 25 -dearmochi +# Adds support for hair gradient +ALTER TABLE `characters` ADD COLUMN `hair_gradient` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL; +ALTER TABLE `characters` ADD COLUMN `hair_gradient_offset` varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0,0'; +ALTER TABLE `characters` ADD COLUMN `hair_gradient_colour` varchar(7) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '#000000'; +ALTER TABLE `characters` ADD COLUMN `hair_gradient_alpha` tinyint(3) UNSIGNED NOT NULL DEFAULT '255' diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index fc67f448526..00789c063db 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -114,3 +114,7 @@ #define PIPE_COLOR_GREEN "#00ff00" #define PIPE_COLOR_YELLOW "#ffcc00" #define PIPE_COLOR_PURPLE "#5c1ec0" + +// Color matrix utilities +#define COLOR_MATRIX_ADD(C) list(COLOR_RED, COLOR_GREEN, COLOR_BLUE, C) +#define COLOR_MATRIX_OVERLAY(C) list(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK, C) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index ad182c9f9c4..4a7b6f9dfc9 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -363,7 +363,7 @@ #define INVESTIGATE_BOMB "bombs" // The SQL version required by this version of the code -#define SQL_VERSION 24 +#define SQL_VERSION 25 // Vending machine stuff #define CAT_NORMAL 1 diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 282ad53cd06..1193efeb4c0 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -10,6 +10,8 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/head_accessory, GLOB.head_accessory_styles_list) //hair init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, GLOB.hair_styles_public_list, GLOB.hair_styles_male_list, GLOB.hair_styles_female_list, GLOB.hair_styles_full_list) + //hair gradients + init_sprite_accessory_subtypes(/datum/sprite_accessory/hair_gradient, GLOB.hair_gradients_list) //facial hair init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hair_styles_list, GLOB.facial_hair_styles_male_list, GLOB.facial_hair_styles_female_list) //underwear diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index fc18f2d83cd..ad0f11f97f1 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -11,7 +11,7 @@ GLOBAL_LIST_INIT(hair_styles_full_list, list()) //fluff hair styles GLOBAL_LIST_INIT(facial_hair_styles_list, list()) //stores /datum/sprite_accessory/facial_hair indexed by name GLOBAL_LIST_INIT(facial_hair_styles_male_list, list()) GLOBAL_LIST_INIT(facial_hair_styles_female_list, list()) -GLOBAL_LIST_INIT(skin_styles_female_list, list()) //unused +GLOBAL_LIST_EMPTY(hair_gradients_list) //stores /datum/sprite_accessory/hair_gradient indexed by name //Underwear GLOBAL_LIST_INIT(underwear_list, list()) //stores /datum/sprite_accessory/underwear indexed by name GLOBAL_LIST_INIT(underwear_m, list()) //stores only underwear name diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 12d7bc62237..fcc8757be46 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -210,6 +210,13 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts /// Do we want to force our runechat colour to be white? var/force_white_runechat = FALSE + // Hair gradient + var/h_grad_style = "None" + var/h_grad_offset_x = 0 + var/h_grad_offset_y = 0 + var/h_grad_colour = "#000000" + var/h_grad_alpha = 255 + /datum/preferences/New(client/C) parent = C b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") @@ -333,9 +340,18 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts dat += "Hair: " dat += "[h_style]" dat += "Color [color_square(h_colour)]" + // Secondary hair color var/datum/sprite_accessory/temp_hair_style = GLOB.hair_styles_public_list[h_style] if(temp_hair_style && temp_hair_style.secondary_theme && !temp_hair_style.no_sec_colour) dat += " Color #2 [color_square(h_sec_colour)]" + // Hair gradient + dat += "
" + dat += "- Gradient:" + dat += " [h_grad_style]" + dat += " Color [color_square(h_grad_colour)]" + dat += " [h_grad_alpha]" + dat += "
" + dat += "- Gradient Offset: [h_grad_offset_x],[h_grad_offset_y]" dat += "
" dat += "Facial Hair: " @@ -1495,6 +1511,29 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts if(new_h_style) h_style = new_h_style + if("h_grad_style") + var/result = input(user, "Choose your character's hair gradient style:", "Character Preference") as null|anything in GLOB.hair_gradients_list + if(result) + h_grad_style = result + + if("h_grad_offset") + var/result = input(user, "Enter your character's hair gradient offset as a comma-separated value (x,y). Example:\n0,0 (no offset)\n5,0 (5 pixels to the right)", "Character Preference") as null|text + if(result) + var/list/expl = splittext(result, ",") + if(length(expl) == 2) + h_grad_offset_x = clamp(text2num(expl[1]) || 0, -16, 16) + h_grad_offset_y = clamp(text2num(expl[2]) || 0, -16, 16) + + if("h_grad_colour") + var/result = input(user, "Choose your character's hair gradient colour:", "Character Preference", h_grad_colour) as color|null + if(result) + h_grad_colour = result + + if("h_grad_alpha") + var/result = input(user, "Choose your character's hair gradient alpha:", "Character Preference", h_grad_alpha) as num|null + if(!isnull(result)) + h_grad_alpha = clamp(result, 0, 255) + if("headaccessory") if(S.bodyflags & HAS_HEAD_ACCESSORY) //Species with head accessories. var/input = "Choose the colour of your your character's head accessory:" @@ -2200,6 +2239,12 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts H.f_style = f_style H.alt_head = alt_head + + H.h_grad_style = h_grad_style + H.h_grad_offset_x = h_grad_offset_x + H.h_grad_offset_y = h_grad_offset_y + H.h_grad_colour = h_grad_colour + H.h_grad_alpha = h_grad_alpha //End of head-specific. character.skin_colour = s_colour diff --git a/code/modules/client/preference/preferences_mysql.dm b/code/modules/client/preference/preferences_mysql.dm index bcb5823af6a..72ad26ed70b 100644 --- a/code/modules/client/preference/preferences_mysql.dm +++ b/code/modules/client/preference/preferences_mysql.dm @@ -195,7 +195,11 @@ socks, body_accessory, gear, - autohiss + autohiss, + hair_gradient, + hair_gradient_offset, + hair_gradient_colour, + hair_gradient_alpha FROM [format_table_name("characters")] WHERE ckey=:ckey AND slot=:slot"}, list( "ckey" = C.ckey, "slot" = slot @@ -276,6 +280,11 @@ loadout_gear = params2list(query.item[51]) autohiss_mode = text2num(query.item[52]) + h_grad_style = query.item[53] + h_grad_offset_x = query.item[54] // parsed down below + h_grad_colour = query.item[55] + h_grad_alpha = query.item[56] + saved = TRUE qdel(query) @@ -331,6 +340,14 @@ socks = sanitize_text(socks, initial(socks)) body_accessory = sanitize_text(body_accessory, initial(body_accessory)) + // h_grad_style = + var/list/expl = splittext(h_grad_offset_x, ",") + if(length(expl) == 2) + h_grad_offset_x = text2num(expl[1]) || 0 + h_grad_offset_y = text2num(expl[2]) || 0 + h_grad_colour = sanitize_hexcolor(h_grad_colour) + h_grad_alpha = sanitize_integer(h_grad_alpha, 0, 255, initial(h_grad_alpha)) + // if(isnull(disabilities)) disabilities = 0 if(!player_alt_titles) player_alt_titles = new() if(!organ_data) src.organ_data = list() @@ -421,7 +438,11 @@ socks=:socks, body_accessory=:body_accessory, gear=:gearlist, - autohiss=:autohiss_mode + autohiss=:autohiss_mode, + hair_gradient=:h_grad_style, + hair_gradient_offset=:h_grad_offset, + hair_gradient_colour=:h_grad_colour, + hair_gradient_alpha=:h_grad_alpha WHERE ckey=:ckey AND slot=:slot"}, list( // OH GOD SO MANY PARAMETERS @@ -477,6 +498,10 @@ "body_accessory" = (body_accessory ? body_accessory : ""), "gearlist" = (gearlist ? gearlist : ""), "autohiss_mode" = autohiss_mode, + "h_grad_style" = h_grad_style, + "h_grad_offset" = "[h_grad_offset_x],[h_grad_offset_y]", + "h_grad_colour" = h_grad_colour, + "h_grad_alpha" = h_grad_alpha, "ckey" = C.ckey, "slot" = default_slot ) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index e3ef4648fa4..141c73a0a3c 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -354,49 +354,60 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) else //warning("Invalid ha_style for [species.name]: [ha_style]") - - -//HAIR OVERLAY +/** + * Generates overlays for the hair layer. + */ /mob/living/carbon/human/proc/update_hair() - //Reset our hair remove_overlay(HAIR_LAYER) - var/obj/item/organ/external/head/head_organ = get_organ("head") - if(!head_organ) + var/obj/item/organ/external/head/O = get_organ("head") + if(!O) return - //masks and helmets can obscure our hair, unless we're a synthetic - if((head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR))) + if((head?.flags & BLOCKHAIR) || (wear_mask?.flags & BLOCKHAIR)) return - //base icons - var/icon/hair_standing = new /icon('icons/mob/human_face.dmi',"bald_s") - if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(ismachineperson(src)))) - var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style] - if(hair_style && hair_style.species_allowed) - if((head_organ.dna.species.name in hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... - var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(istype(head_organ.dna.species, /datum/species/slime)) // I am el worstos - hair_s.Blend("[skin_colour]A0", ICON_AND) - else if(hair_style.do_colouration) - hair_s.Blend(head_organ.hair_colour, ICON_ADD) + var/mutable_appearance/MA = new() + MA.appearance_flags = KEEP_TOGETHER + MA.layer = -HAIR_LAYER + if(O.h_style && !(head?.flags & BLOCKHEADHAIR) && !ismachineperson(src)) + var/datum/sprite_accessory/hair/hair = GLOB.hair_styles_full_list[O.h_style] + if(hair?.species_allowed && ((O.dna.species.name in hair.species_allowed) || (O.dna.species.bodyflags & ALL_RPARTS))) + // Base hair + var/mutable_appearance/img_hair = new() + img_hair.icon = hair.icon + img_hair.icon_state = "[hair.icon_state]_s" + if(istype(O.dna.species, /datum/species/slime)) + img_hair.color = COLOR_MATRIX_OVERLAY("[skin_colour]A0") + else if(hair.do_colouration) + img_hair.color = COLOR_MATRIX_ADD(O.hair_colour) + MA.overlays += img_hair - if(hair_style.secondary_theme) - var/icon/hair_secondary_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_[hair_style.secondary_theme]_s") - if(!hair_style.no_sec_colour) - hair_secondary_s.Blend(head_organ.sec_hair_colour, ICON_ADD) - hair_s.Blend(hair_secondary_s, ICON_OVERLAY) + // Gradient + var/datum/sprite_accessory/hair_gradient/gradient = GLOB.hair_gradients_list[O.h_grad_style] + if(gradient) + var/mutable_appearance/img_gradient = new() + img_gradient.icon = gradient.icon + img_gradient.icon_state = gradient.icon_state + img_gradient.alpha = O.h_grad_alpha + img_gradient.color = COLOR_MATRIX_OVERLAY(O.h_grad_colour) + img_gradient.pixel_x = O.h_grad_offset_x + img_gradient.pixel_y = O.h_grad_offset_y + img_gradient.blend_mode = BLEND_INSET_OVERLAY + MA.overlays += img_gradient - hair_standing = hair_s //hair_standing.Blend(hair_s, ICON_OVERLAY) - //Having it this way preserves animations. Useful for IPC screens. - else - //warning("Invalid h_style for [species.name]: [h_style]") - //hair_standing.Blend(debrained_s, ICON_OVERLAY)//how does i overlay for fish? + // Secondary style + if(hair.secondary_theme) + var/mutable_appearance/img_secondary = new() + img_secondary.icon = hair.icon + img_secondary.icon_state = "[hair.icon_state]_[hair.secondary_theme]_s" + if(!hair.no_sec_colour) + img_secondary.color = COLOR_MATRIX_ADD(O.sec_hair_colour) + MA.overlays += img_secondary - overlays_standing[HAIR_LAYER] = mutable_appearance(hair_standing, layer = -HAIR_LAYER) + overlays_standing[HAIR_LAYER] = MA apply_overlay(HAIR_LAYER) - //FACIAL HAIR OVERLAY /mob/living/carbon/human/proc/update_fhair() //Reset our facial hair diff --git a/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm index 44fa9cfbd3b..96151e62274 100644 --- a/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm @@ -616,3 +616,48 @@ /datum/sprite_accessory/socks/black_fishnet name = "Black Fishnet" icon_state = "black_fishnet" + +/* HAIR GRADIENT */ + +/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" diff --git a/code/modules/surgery/organs/subtypes/standard.dm b/code/modules/surgery/organs/subtypes/standard.dm index 895bcbefd95..f992c31fd77 100644 --- a/code/modules/surgery/organs/subtypes/standard.dm +++ b/code/modules/surgery/organs/subtypes/standard.dm @@ -213,6 +213,11 @@ var/hair_colour = "#000000" var/sec_hair_colour = "#000000" var/h_style = "Bald" + var/h_grad_style = "None" + var/h_grad_offset_x = 0 + var/h_grad_offset_y = 0 + var/h_grad_colour = "#000000" + var/h_grad_alpha = 255 //Head accessory colour and style var/headacc_colour = "#000000" diff --git a/config/example/dbconfig.txt b/config/example/dbconfig.txt index ffceb33e7de..e39bec963c0 100644 --- a/config/example/dbconfig.txt +++ b/config/example/dbconfig.txt @@ -18,7 +18,7 @@ FEEDBACK_DATABASE feedback ## This value must be set to the version of the paradise schema in use. ## If this value does not match, the SQL database will not be loaded and an error will be generated. ## Roundstart will be delayed. -DB_VERSION 24 +DB_VERSION 25 ## Prefix to be added to the name of every table, older databases will require this be set to erro_ ## If left out defaults to erro_ for legacy reasons, if you want no table prefix, give a blank prefix rather then comment out diff --git a/icons/mob/hair_gradients.dmi b/icons/mob/hair_gradients.dmi new file mode 100644 index 0000000000000000000000000000000000000000..d457ebf7d143801a2d255d646a465a0db6d3f91f GIT binary patch literal 1663 zcmaKtdsNZ~6vuy<5Aba&m5($q=Bi1JO)*W-Vfai-m(H24Fv?U6Ez%79sVPjInng+T z{V2DVX;UIa{dsa(Noh78^U0w^na@ppFqFprXxkraf86^$=bn4d_nvb<=iILY50MRY zEp!0@F!1&w9Z@UzSHQK^`H|c4ZnZqT7#wSNA??7kClUsrWT_?zzoq^W`0qwjaN^HHfhg&bWMJ&S>F>Di$&mYlk;KyCsds zZOvOhHumL*0HBrTO>z%TDxNE8%|m;dWdQXso}EF&OfI^>}_)_vGeh zKZjZ3-qNkQ{qx#o3M?(5{-H7yplh!n!pV1=a$gH@qW&=SW{b~=x}RpRTr`x%9^?=cdaBDDzrxI)2=y0Wv}XQI|K-as<8lT;*C!D^~&nGmuyaA zwiovSwoiq3=!_Z4-maV;EMsW^;~k&)kvpUsdy0@gk$09L z4Sl#HIP3F^V@@uL`0>DdkTj^-2hOTWjQfQjj= z;|4dXe9sp0xzCeH@*(pNCF^W!S*^$&42q2jYFnez69msuZ-%c`ktfKU#+|JJZ=8TN z(^u(p`AiS%P5;`mQ>A=Px@l9`FL+4FrEt@AjWLQW)dp4WjN)F^@0Jn<bep*CA3wc_67!?J=&PP@qg6|_Hh zHPJwkR89F^AxG`$OSvp!MsXUGt3RVSXaKJqh4CpykMVh_Hv99#W;9-f5pq^+ir4@X zU+kYG{OB<~_wdu%@(UjNTl8%6w2ZqnI22fC10YfJv7Zm}O0$iY(%JZ6Fv% zq;2X~vz*1zGCl Date: Tue, 27 Jul 2021 18:15:28 +0200 Subject: [PATCH 2/4] Finish the damn PR --- SQL/paradise_schema_prefixed.sql | 6 ++--- code/game/objects/structures/mirror.dm | 4 +++ .../mob/living/carbon/human/appearance.dm | 25 +++++++++++++++++++ .../mob/new_player/preferences_setup.dm | 13 ++++++++++ .../tgui/modules/appearance_changer.dm | 25 +++++++++++++++++++ .../tgui/interfaces/AppearanceChanger.js | 9 +++++++ tgui/packages/tgui/public/tgui.bundle.js | 2 +- 7 files changed, 80 insertions(+), 4 deletions(-) diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index 3c843251572..9d38c9aacbd 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -280,13 +280,13 @@ CREATE TABLE `SS13_player` ( `fupdate` smallint(4) DEFAULT '0', `parallax` tinyint(1) DEFAULT '8', `byond_date` DATE DEFAULT NULL, - `keybindings` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `keybindings` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL, `2fa_status` ENUM('DISABLED','ENABLED_IP','ENABLED_ALWAYS') NOT NULL DEFAULT 'DISABLED' COLLATE 'utf8mb4_general_ci', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`), KEY `lastseen` (`lastseen`), - KEY `co + KEY `computerid` (`computerid`), + KEY `ip` (`ip`), + KEY `fuid` (`fuid`), KEY `fupdate` (`fupdate`) ) ENGINE=InnoDB AUTO_INCREMENT=135298 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index c56f4cb2603..6af22e2a79e 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -23,6 +23,10 @@ if(WEST) pixel_x = 32 +/obj/structure/mirror/Destroy() + QDEL_LIST_ASSOC_VAL(ui_users) + return ..() + /obj/structure/mirror/attack_hand(mob/user) if(broken) return diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index c6d224975e8..4892d5bb935 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -153,6 +153,12 @@ else //this shouldn't happen H.h_style = "Bald" + // Gradient + H.h_grad_style = "None" + H.h_grad_offset_x = 0 + H.h_grad_offset_y = 0 + H.h_grad_colour = "#000000" + H.h_grad_alpha = 255 update_hair() @@ -310,6 +316,25 @@ update_body() return 1 +/mob/living/carbon/human/proc/change_hair_gradient(style, offset_raw, color, alpha) + var/obj/item/organ/external/head/H = get_organ("head") + if(!H) + return + + if(!isnull(style)) + H.h_grad_style = style + if(!isnull(offset_raw)) + var/list/expl = splittext(offset_raw, ",") + if(length(expl) == 2) + H.h_grad_offset_x = clamp(text2num(expl[1]) || 0, -16, 16) + H.h_grad_offset_y = clamp(text2num(expl[2]) || 0, -16, 16) + if(!isnull(color)) + H.h_grad_colour = color + if(!isnull(alpha)) + H.h_grad_alpha = clamp(alpha, 0, 255) + + update_hair() + /mob/living/carbon/human/proc/update_dna() check_dna() dna.ready_dna(src) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 3fe022269da..2ba6941994f 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -346,6 +346,19 @@ else if(hair_style.do_colouration) hair_s.Blend(h_colour, ICON_ADD) + // mochi TODO: rewrite the mess that is this proc + var/datum/sprite_accessory/hair_gradient/gradient = GLOB.hair_gradients_list[h_grad_style] + if(gradient) + var/icon/grad_s = new/icon("icon" = gradient.icon, "icon_state" = gradient.icon_state) + if(h_grad_offset_x) + grad_s.Shift(EAST, h_grad_offset_x) + if(h_grad_offset_y) + grad_s.Shift(NORTH, h_grad_offset_y) + grad_s.Blend(hair_s, ICON_ADD) + grad_s.MapColors(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK, h_grad_colour) + grad_s.ChangeOpacity(h_grad_alpha / 255) + hair_s.Blend(grad_s, ICON_OVERLAY) + if(hair_style.secondary_theme) var/icon/hair_secondary_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_[hair_style.secondary_theme]_s") if(!hair_style.no_sec_colour && hair_style.do_colouration ) diff --git a/code/modules/tgui/modules/appearance_changer.dm b/code/modules/tgui/modules/appearance_changer.dm index 6af513e1d08..1e07b1508f1 100644 --- a/code/modules/tgui/modules/appearance_changer.dm +++ b/code/modules/tgui/modules/appearance_changer.dm @@ -93,6 +93,30 @@ if(new_hair && (!..()) && owner.change_hair_color(new_hair, 1)) update_dna() + if("hair_gradient") + if(can_change(APPEARANCE_HAIR) && length(valid_hairstyles)) + var/new_style = input("Please select gradient style.", "Hair Gradient", head_organ.h_grad_style) as null|anything in GLOB.hair_gradients_list + if(new_style) + owner.change_hair_gradient(style = new_style) + + if("hair_gradient_offset") + if(can_change(APPEARANCE_HAIR) && length(valid_hairstyles)) + var/new_offset = input("Please enter gradient offset as a comma-separated value (x,y). Example:\n0,0 (no offset)\n5,0 (5 pixels to the right)", "Hair Gradient", "[head_organ.h_grad_offset_x],[head_organ.h_grad_offset_y]") as null|text + if(new_offset) + owner.change_hair_gradient(offset_raw = new_offset) + + if("hair_gradient_colour") + if(can_change(APPEARANCE_HAIR) && length(valid_hairstyles)) + var/new_color = input("Please select gradient color.", "Hair Gradient", head_organ.h_grad_colour) as null|color + if(new_color) + owner.change_hair_gradient(color = new_color) + + if("hair_gradient_alpha") + if(can_change(APPEARANCE_HAIR) && length(valid_hairstyles)) + var/new_alpha = input("Please enter gradient alpha.", "Hair Gradient", head_organ.h_grad_alpha) as null|num + if(!isnull(new_alpha)) + owner.change_hair_gradient(alpha = new_alpha) + if("facial_hair") if(can_change(APPEARANCE_FACIAL_HAIR) && (params["facial_hair"] in valid_facial_hairstyles)) if(owner.change_facial_hair(params["facial_hair"])) @@ -274,6 +298,7 @@ data["change_head_marking_color"] = can_change_markings("head") data["change_body_marking_color"] = can_change_markings("body") data["change_tail_marking_color"] = can_change_markings("tail") + data["change_hair_gradient"] = can_change(APPEARANCE_HAIR) && length(valid_hairstyles) return data diff --git a/tgui/packages/tgui/interfaces/AppearanceChanger.js b/tgui/packages/tgui/interfaces/AppearanceChanger.js index 56c318bd774..3146a47f4a8 100644 --- a/tgui/packages/tgui/interfaces/AppearanceChanger.js +++ b/tgui/packages/tgui/interfaces/AppearanceChanger.js @@ -28,6 +28,7 @@ export const AppearanceChanger = (props, context) => { change_hair, hair_styles, hair_style, + change_hair_gradient, change_facial_hair, facial_hair_styles, facial_hair_style, @@ -130,6 +131,14 @@ export const AppearanceChanger = (props, context) => { ))} )} + {!!change_hair_gradient && ( + +