diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 906a3b4de87c..36da4792dbaf 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -60,6 +60,7 @@ #define UI_CHANGED "ui changed" #define UE_CHANGED "ue changed" +#define UF_CHANGED "uf changed" #define CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY 255 #define CHAMELEON_MUTATION_MINIMUM_TRANSPARENCY 30 @@ -81,6 +82,8 @@ //DNA - Because fuck you and your magic numbers being all over the codebase. #define DNA_BLOCK_SIZE 3 +#define DNA_BLOCK_SIZE_COLOR DEFAULT_HEX_COLOR_LEN + #define DNA_UNI_IDENTITY_BLOCKS 7 #define DNA_HAIR_COLOR_BLOCK 1 #define DNA_FACIAL_HAIR_COLOR_BLOCK 2 @@ -90,6 +93,30 @@ #define DNA_FACIAL_HAIR_STYLE_BLOCK 6 #define DNA_HAIR_STYLE_BLOCK 7 +/// This number needs to equal the total number of DNA blocks +#define DNA_FEATURE_BLOCKS 19 + +#define DNA_MUTANT_COLOR_BLOCK 1 +#define DNA_ETHEREAL_COLOR_BLOCK 2 +#define DNA_LIZARD_MARKINGS_BLOCK 3 +#define DNA_LIZARD_TAIL_BLOCK 4 +#define DNA_SNOUT_BLOCK 5 +#define DNA_HORNS_BLOCK 6 +#define DNA_FRILLS_BLOCK 7 +#define DNA_SPINES_BLOCK 8 +#define DNA_HUMAN_TAIL_BLOCK 9 +#define DNA_EARS_BLOCK 10 +#define DNA_MOTH_WINGS_BLOCK 11 +#define DNA_MUSHROOM_CAPS_BLOCK 12 +#define DNA_POD_HAIR_BLOCK 13 +//Yog specific DNA Blocks +#define DNA_POD_FLOWER_BLOCK 14 +#define DNA_POLY_TAIL_BLOCK 15 +#define DNA_POLY_TEETH_BLOCK 16 +#define DNA_POLY_DOME_BLOCK 17 +#define DNA_POLY_DORSAL_BLOCK 18 +#define DNA_ETHEREAL_MARK_BLOCK 19 + #define DNA_SEQUENCE_LENGTH 4 #define DNA_MUTATION_BLOCKS 8 #define DNA_UNIQUE_ENZYMES_LEN 32 diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 91ff62653b06..ef64e821a051 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -1,7 +1,16 @@ // This is eventually for wjohn to add more color standardization stuff like I keep asking him >:( -#define COLOR_INPUT_DISABLED "#F0F0F0" -#define COLOR_INPUT_ENABLED "#D3B5B5" +//different types of atom colorations +/// Only used by rare effects like greentext coloring mobs and when admins varedit color +#define ADMIN_COLOUR_PRIORITY 1 +/// e.g. purple effect of the revenant on a mob, black effect when mob electrocuted +#define TEMPORARY_COLOUR_PRIORITY 2 +/// Color splashed onto an atom (e.g. paint on turf) +#define WASHABLE_COLOUR_PRIORITY 3 +/// Color inherent to the atom (e.g. blob color) +#define FIXED_COLOUR_PRIORITY 4 +///how many colour priority levels there are. +#define COLOUR_PRIORITY_AMOUNT 4 #define COLOR_DARKMODE_BACKGROUND "#202020" #define COLOR_DARKMODE_DARKBACKGROUND "#171717" @@ -122,31 +131,37 @@ #define COLOR_PURPLE_GRAY "#AE8CA8" //Color defines used by the assembly detailer. -#define COLOR_ASSEMBLY_BLACK "#545454" -#define COLOR_ASSEMBLY_BGRAY "#9497AB" -#define COLOR_ASSEMBLY_WHITE "#E2E2E2" -#define COLOR_ASSEMBLY_RED "#CC4242" -#define COLOR_ASSEMBLY_ORANGE "#E39751" -#define COLOR_ASSEMBLY_BEIGE "#AF9366" -#define COLOR_ASSEMBLY_BROWN "#97670E" -#define COLOR_ASSEMBLY_GOLD "#AA9100" -#define COLOR_ASSEMBLY_YELLOW "#CECA2B" -#define COLOR_ASSEMBLY_GURKHA "#999875" -#define COLOR_ASSEMBLY_LGREEN "#789876" -#define COLOR_ASSEMBLY_GREEN "#44843C" -#define COLOR_ASSEMBLY_LBLUE "#5D99BE" -#define COLOR_ASSEMBLY_BLUE "#38559E" -#define COLOR_ASSEMBLY_PURPLE "#6F6192" +#define COLOR_ASSEMBLY_BLACK "#545454" +#define COLOR_ASSEMBLY_BGRAY "#9497AB" +#define COLOR_ASSEMBLY_WHITE "#E2E2E2" +#define COLOR_ASSEMBLY_RED "#CC4242" +#define COLOR_ASSEMBLY_ORANGE "#E39751" +#define COLOR_ASSEMBLY_BEIGE "#AF9366" +#define COLOR_ASSEMBLY_BROWN "#97670E" +#define COLOR_ASSEMBLY_GOLD "#AA9100" +#define COLOR_ASSEMBLY_YELLOW "#CECA2B" +#define COLOR_ASSEMBLY_GURKHA "#999875" +#define COLOR_ASSEMBLY_LGREEN "#789876" +#define COLOR_ASSEMBLY_GREEN "#44843C" +#define COLOR_ASSEMBLY_LBLUE "#5D99BE" +#define COLOR_ASSEMBLY_BLUE "#38559E" +#define COLOR_ASSEMBLY_PURPLE "#6F6192" -/// The default color for admin say, used as a fallback when the preference is not enabled -#define DEFAULT_ASAY_COLOR "#996600" +///Colors for grayscale tools +#define COLOR_TOOL_BLUE "#1861d5" +#define COLOR_TOOL_RED "#951710" +#define COLOR_TOOL_PINK "#d5188d" +#define COLOR_TOOL_BROWN "#a05212" +#define COLOR_TOOL_GREEN "#0e7f1b" +#define COLOR_TOOL_CYAN "#18a2d5" +#define COLOR_TOOL_YELLOW "#d58c18" -/* - * Antag Specific Colors -*/ - -#define COLOR_CHANGELING_CHEMICALS "#DD66DD" -#define COLOR_DARKSPAWN_PSI "#7264FF" +///Colors for xenobiology vatgrowing +#define COLOR_SAMPLE_YELLOW "#c0b823" +#define COLOR_SAMPLE_PURPLE "#342941" +#define COLOR_SAMPLE_GREEN "#98b944" +#define COLOR_SAMPLE_BROWN "#91542d" +#define COLOR_SAMPLE_GRAY "#5e5856" ///Main colors for UI themes #define COLOR_THEME_MIDNIGHT "#6086A0" @@ -157,8 +172,15 @@ #define COLOR_THEME_GLASS "#75A4C4" #define COLOR_THEME_CLOCKWORK "#CFBA47" #define COLOR_THEME_TRASENKNOX "#3ce375" + +///yog UI colors #define COLOR_THEME_DETECTIVE "#c7b08b" +///Colors for eigenstates +#define COLOR_PERIWINKLEE "#9999FF" + +/// Starlight! +#define COLOR_STARLIGHT "#8589fa" /** * Some defines to generalise colours used in lighting. * @@ -168,68 +190,145 @@ /// Warm but extremely diluted red. rgb(250, 130, 130) #define LIGHT_COLOR_RED "#FA8282" /// Bright but quickly dissipating neon green. rgb(100, 200, 100) -#define LIGHT_COLOR_GREEN "#64C864" +#define LIGHT_COLOR_GREEN "#64C864" +/// Electric green. rgb(0, 255, 0) +#define LIGHT_COLOR_ELECTRIC_GREEN "#00FF00" /// Cold, diluted blue. rgb(100, 150, 250) -#define LIGHT_COLOR_BLUE "#6496FA" +#define LIGHT_COLOR_BLUE "#6496FA" /// Light blueish green. rgb(125, 225, 175) -#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" +#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" /// Diluted cyan. rgb(125, 225, 225) -#define LIGHT_COLOR_CYAN "#7DE1E1" +#define LIGHT_COLOR_CYAN "#7DE1E1" +/// Electric cyan rgb(0, 255, 255) +#define LIGHT_COLOR_ELECTRIC_CYAN "#00FFFF" /// More-saturated cyan. rgb(64, 206, 255) #define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" /// Saturated blue. rgb(51, 117, 248) -#define LIGHT_COLOR_DARK_BLUE "#6496FA" +#define LIGHT_COLOR_DARK_BLUE "#6496FA" /// Diluted, mid-warmth pink. rgb(225, 125, 225) -#define LIGHT_COLOR_PINK "#E17DE1" +#define LIGHT_COLOR_PINK "#E17DE1" /// Dimmed yellow, leaning kaki. rgb(225, 225, 125) -#define LIGHT_COLOR_YELLOW "#E1E17D" +#define LIGHT_COLOR_YELLOW "#E1E17D" /// Clear brown, mostly dim. rgb(150, 100, 50) -#define LIGHT_COLOR_BROWN "#966432" +#define LIGHT_COLOR_BROWN "#966432" /// Mostly pure orange. rgb(250, 150, 50) -#define LIGHT_COLOR_ORANGE "#FA9632" +#define LIGHT_COLOR_ORANGE "#FA9632" /// Light Purple. rgb(149, 44, 244) -#define LIGHT_COLOR_PURPLE "#952CF4" +#define LIGHT_COLOR_PURPLE "#952CF4" /// Less-saturated light purple. rgb(155, 81, 255) -#define LIGHT_COLOR_LAVENDER "#9B51FF" - -///slightly desaturated bright yellow. -#define LIGHT_COLOR_HOLY_MAGIC "#FFF743" +#define LIGHT_COLOR_LAVENDER "#9B51FF" +/// slightly desaturated bright yellow. +#define LIGHT_COLOR_HOLY_MAGIC "#FFF743" /// deep crimson -#define LIGHT_COLOR_BLOOD_MAGIC "#D00000" +#define LIGHT_COLOR_BLOOD_MAGIC "#D00000" +/// yog clockies color #define LIGHT_COLOR_CLOCKWORK "#BE8700" -//These ones aren't a direct colour like the ones above, because nothing would fit +/* These ones aren't a direct colour like the ones above, because nothing would fit */ /// Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25) -#define LIGHT_COLOR_FIRE "#FAA019" +#define LIGHT_COLOR_FIRE "#FAA019" /// Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24) -#define LIGHT_COLOR_LAVA "#C48A18" +#define LIGHT_COLOR_LAVA "#C48A18" /// Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75) -#define LIGHT_COLOR_FLARE "#FA644B" +#define LIGHT_COLOR_FLARE "#FA644B" /// Weird color, between yellow and green, very slimy. rgb(175, 200, 75) #define LIGHT_COLOR_SLIME_LAMP "#AFC84B" /// Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175) -#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" +#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" /// Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250) -#define LIGHT_COLOR_HALOGEN "#F0FAFA" - -#define CABLE_COLOR_BLUE "blue" - #define CABLE_HEX_COLOR_BLUE COLOR_STRONG_BLUE -#define CABLE_COLOR_BROWN "brown" - #define CABLE_HEX_COLOR_BROWN COLOR_ORANGE_BROWN -#define CABLE_COLOR_CYAN "cyan" - #define CABLE_HEX_COLOR_CYAN COLOR_CYAN -#define CABLE_COLOR_GREEN "green" - #define CABLE_HEX_COLOR_GREEN COLOR_DARK_LIME -#define CABLE_COLOR_ORANGE "orange" - #define CABLE_HEX_COLOR_ORANGE COLOR_MOSTLY_PURE_ORANGE -#define CABLE_COLOR_PINK "pink" - #define CABLE_HEX_COLOR_PINK COLOR_LIGHT_PINK -#define CABLE_COLOR_RED "red" - #define CABLE_HEX_COLOR_RED COLOR_RED -#define CABLE_COLOR_WHITE "white" - #define CABLE_HEX_COLOR_WHITE COLOR_WHITE -#define CABLE_COLOR_YELLOW "yellow" - #define CABLE_HEX_COLOR_YELLOW COLOR_YELLOW +#define LIGHT_COLOR_HALOGEN "#F0FAFA" + +//The GAGS greyscale_colors for each department's computer/machine circuits +#define CIRCUIT_COLOR_GENERIC "#1A7A13" +#define CIRCUIT_COLOR_COMMAND "#1B4594" +#define CIRCUIT_COLOR_SECURITY "#9A151E" +#define CIRCUIT_COLOR_SCIENCE "#BC4A9B" +#define CIRCUIT_COLOR_SERVICE "#92DCBA" +#define CIRCUIT_COLOR_MEDICAL "#00CCFF" +#define CIRCUIT_COLOR_ENGINEERING "#F8D700" +#define CIRCUIT_COLOR_SUPPLY "#C47749" + +/// Colors for pride week +#define COLOR_PRIDE_RED "#FF6666" +#define COLOR_PRIDE_ORANGE "#FC9F3C" +#define COLOR_PRIDE_YELLOW "#EAFF51" +#define COLOR_PRIDE_GREEN "#41FC66" +#define COLOR_PRIDE_BLUE "#42FFF2" +#define COLOR_PRIDE_PURPLE "#5D5DFC" + +/// The default color for admin say, used as a fallback when the preference is not enabled +#define DEFAULT_ASAY_COLOR COLOR_MOSTLY_PURE_RED + +#define DEFAULT_HEX_COLOR_LEN 6 + +// Color filters +/// Icon filter that creates ambient occlusion +#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, color="#04080FAA") +/// Icon filter that creates gaussian blur +#define GAUSSIAN_BLUR(filter_size) filter(type="blur", size=filter_size) + +/* + * Antag Specific Colors +*/ + +#define COLOR_CHANGELING_CHEMICALS "#DD66DD" +#define COLOR_DARKSPAWN_PSI "#7264FF" + +#define CABLE_COLOR_BLUE "blue" + #define CABLE_HEX_COLOR_BLUE COLOR_STRONG_BLUE +#define CABLE_COLOR_BROWN "brown" + #define CABLE_HEX_COLOR_BROWN COLOR_ORANGE_BROWN +#define CABLE_COLOR_CYAN "cyan" + #define CABLE_HEX_COLOR_CYAN COLOR_CYAN +#define CABLE_COLOR_GREEN "green" + #define CABLE_HEX_COLOR_GREEN COLOR_DARK_LIME +#define CABLE_COLOR_ORANGE "orange" + #define CABLE_HEX_COLOR_ORANGE COLOR_MOSTLY_PURE_ORANGE +#define CABLE_COLOR_PINK "pink" + #define CABLE_HEX_COLOR_PINK COLOR_LIGHT_PINK +#define CABLE_COLOR_RED "red" + #define CABLE_HEX_COLOR_RED COLOR_RED +#define CABLE_COLOR_WHITE "white" + #define CABLE_HEX_COLOR_WHITE COLOR_WHITE +#define CABLE_COLOR_YELLOW "yellow" + #define CABLE_HEX_COLOR_YELLOW COLOR_YELLOW + +#define COLOR_CARP_PURPLE "#aba2ff" +#define COLOR_CARP_PINK "#da77a8" +#define COLOR_CARP_GREEN "#70ff25" +#define COLOR_CARP_GRAPE "#df0afb" +#define COLOR_CARP_SWAMP "#e5e75a" +#define COLOR_CARP_TURQUOISE "#04e1ed" +#define COLOR_CARP_BROWN "#ca805a" +#define COLOR_CARP_TEAL "#20e28e" +#define COLOR_CARP_LIGHT_BLUE "#4d88cc" +#define COLOR_CARP_RUSTY "#dd5f34" +#define COLOR_CARP_RED "#fd6767" +#define COLOR_CARP_YELLOW "#f3ca4a" +#define COLOR_CARP_BLUE "#09bae1" +#define COLOR_CARP_PALE_GREEN "#7ef099" +#define COLOR_CARP_SILVER "#fdfbf3" +#define COLOR_CARP_DARK_BLUE "#3a384d" + +#define COLOR_GNOME_RED_ONE "#f10b0b" +#define COLOR_GNOME_RED_TWO "#bc5347" +#define COLOR_GNOME_RED_THREE "#b40f1a" +#define COLOR_GNOME_BLUE_ONE "#2e8ff7" +#define COLOR_GNOME_BLUE_TWO "#312bd6" +#define COLOR_GNOME_BLUE_THREE "#4e409a" +#define COLOR_GNOME_GREEN_ONE "#28da1c" +#define COLOR_GNOME_GREEN_TWO "#50a954" +#define COLOR_GNOME_YELLOW "#f6da3c" +#define COLOR_GNOME_ORANGE "#d56f2f" +#define COLOR_GNOME_BROWN_ONE "#874e2a" +#define COLOR_GNOME_BROWN_TWO "#543d2e" +#define COLOR_GNOME_PURPLE "#ac1dd7" +#define COLOR_GNOME_WHITE "#e8e8e8" +#define COLOR_GNOME_GREY "#a9a9a9" +#define COLOR_GNOME_BLACK "#303030" + +#define SOFA_BROWN "#a75400" +#define SOFA_MAROON "#830000" GLOBAL_LIST_INIT(cable_colors, list( CABLE_COLOR_BLUE = CABLE_HEX_COLOR_BLUE, @@ -242,3 +341,8 @@ GLOBAL_LIST_INIT(cable_colors, list( CABLE_COLOR_YELLOW = CABLE_HEX_COLOR_YELLOW, CABLE_COLOR_BROWN = CABLE_HEX_COLOR_BROWN )) + +// Yog Colors + +#define COLOR_INPUT_DISABLED "#F0F0F0" +#define COLOR_INPUT_ENABLED "#D3B5B5" diff --git a/code/__DEFINES/cult.dm b/code/__DEFINES/cult.dm index 871c6c5d00e2..b3b7a131be0a 100644 --- a/code/__DEFINES/cult.dm +++ b/code/__DEFINES/cult.dm @@ -26,7 +26,7 @@ #define DEFAULT_TOOLTIP "6:-29,5:-2" //misc #define SOULS_TO_REVIVE 3 -#define BLOODCULT_EYE "f00" +#define BLOODCULT_EYE "#FF0000" //soulstone & construct themes #define THEME_CULT "cult" #define THEME_WIZARD "wizard" diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index c1a99d61b24b..9629ab27ed0b 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -307,13 +307,6 @@ GLOBAL_LIST_INIT(donor_pdas, list(PDA_COLOR_NORMAL, PDA_COLOR_TRANSPARENT, PDA_C #define LUMA_G 0.715 #define LUMA_B 0.072 -//different types of atom colorations -#define ADMIN_COLOUR_PRIORITY 1 //only used by rare effects like greentext coloring mobs and when admins varedit color -#define TEMPORARY_COLOUR_PRIORITY 2 //e.g. purple effect of the revenant on a mob, black effect when mob electrocuted -#define WASHABLE_COLOUR_PRIORITY 3 //color splashed onto an atom (e.g. paint on turf) -#define FIXED_COLOUR_PRIORITY 4 //color inherent to the atom (e.g. blob color) -#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are. - //Endgame Results #define NUKE_NEAR_MISS 1 #define NUKE_MISS_STATION 2 @@ -442,10 +435,6 @@ GLOBAL_LIST_INIT(donor_pdas, list(PDA_COLOR_NORMAL, PDA_COLOR_TRANSPARENT, PDA_C // Used by PDA and cartridge code to reduce repetitiveness of spritesheets #define PDAIMG(what) {""} -//Filters -#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, color="#04080FAA") -#define GAUSSIAN_BLUR(filter_size) filter(type="blur", size=filter_size) - #define STANDARD_GRAVITY 1 //Anything above this is high gravity, anything below no grav #define GRAVITY_DAMAGE_TRESHOLD 3 //Starting with this value gravity will start to damage mobs diff --git a/code/__HELPERS/dna.dm b/code/__HELPERS/dna.dm index 5ec66923ea54..0ec3e7ee8d49 100644 --- a/code/__HELPERS/dna.dm +++ b/code/__HELPERS/dna.dm @@ -10,4 +10,9 @@ #define GET_MUTATION_STABILIZER(A) ((A.stabilizer_coeff < 0) ? 1 : A.stabilizer_coeff) #define GET_MUTATION_SYNCHRONIZER(A) ((A.synchronizer_coeff < 0) ? 1 : A.synchronizer_coeff) #define GET_MUTATION_POWER(A) ((A.power_coeff < 0) ? 1 : A.power_coeff) -#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff) \ No newline at end of file +#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff) + +///Getter macro used to get the length of a identity block +#define GET_UI_BLOCK_LEN(blocknum) (GLOB.identity_block_lengths["[blocknum]"] || DNA_BLOCK_SIZE) +///Ditto, but for a feature. +#define GET_UF_BLOCK_LEN(blocknum) (GLOB.features_block_lengths["[blocknum]"] || DNA_BLOCK_SIZE) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 8e48ce3c35b9..ee4100adfe31 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -710,207 +710,185 @@ world ((hi3 >= 65 ? hi3-55 : hi3-48)<<4) | (lo3 >= 65 ? lo3-55 : lo3-48), ((hi4 >= 65 ? hi4-55 : hi4-48)<<4) | (lo4 >= 65 ? lo4-55 : lo4-48)) -// Creates a single icon from a given /atom or /image. Only the first argument is required. -/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE) - //Define... defines. - var/static/icon/flat_template = icon('icons/effects/effects.dmi', "nothing") - - #define BLANK icon(flat_template) - #define SET_SELF(SETVAR) do { \ - var/icon/SELF_ICON=icon(icon(curicon, curstate, base_icon_dir),"",SOUTH,no_anim?1:null); \ - if(A.alpha<255) { \ - SELF_ICON.Blend(rgb(255,255,255,A.alpha),ICON_MULTIPLY);\ - } \ - if(A.color) { \ - if(islist(A.color)){ \ - SELF_ICON.MapColors(arglist(A.color))} \ - else{ \ - SELF_ICON.Blend(A.color,ICON_MULTIPLY)} \ - } \ - ##SETVAR=SELF_ICON;\ - } while (0) - #define INDEX_X_LOW 1 - #define INDEX_X_HIGH 2 - #define INDEX_Y_LOW 3 - #define INDEX_Y_HIGH 4 - - #define flatX1 flat_size[INDEX_X_LOW] - #define flatX2 flat_size[INDEX_X_HIGH] - #define flatY1 flat_size[INDEX_Y_LOW] - #define flatY2 flat_size[INDEX_Y_HIGH] - #define addX1 add_size[INDEX_X_LOW] - #define addX2 add_size[INDEX_X_HIGH] - #define addY1 add_size[INDEX_Y_LOW] - #define addY2 add_size[INDEX_Y_HIGH] - - if(!A || A.alpha <= 0) - return BLANK - - var/noIcon = FALSE +/// Create a single [/icon] from a given [/atom] or [/image]. +/// +/// Very low-performance. Should usually only be used for HTML, where BYOND's +/// appearance system (overlays/underlays, etc.) is not available. +/// +/// Only the first argument is required. +/proc/getFlatIcon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE) + // Loop through the underlays, then overlays, sorting them into the layers list + #define PROCESS_OVERLAYS_OR_UNDERLAYS(flat, process, base_layer) \ + for (var/i in 1 to process.len) { \ + var/image/current = process[i]; \ + if (!current) { \ + continue; \ + } \ + if (current.plane != FLOAT_PLANE && current.plane != appearance.plane) { \ + continue; \ + } \ + var/current_layer = current.layer; \ + if (current_layer < 0) { \ + if (current_layer <= -1000) { \ + return flat; \ + } \ + current_layer = base_layer + appearance.layer + current_layer / 1000; \ + } \ + for (var/index_to_compare_to in 1 to layers.len) { \ + var/compare_to = layers[index_to_compare_to]; \ + if (current_layer < layers[compare_to]) { \ + layers.Insert(index_to_compare_to, current); \ + break; \ + } \ + } \ + layers[current] = current_layer; \ + } + + var/static/icon/flat_template = icon('icons/blanks/32x32.dmi', "nothing") + + if(!appearance || appearance.alpha <= 0) + return icon(flat_template) + if(start) if(!defdir) - defdir = A.dir + defdir = appearance.dir if(!deficon) - deficon = A.icon + deficon = appearance.icon if(!defstate) - defstate = A.icon_state + defstate = appearance.icon_state if(!defblend) - defblend = A.blend_mode + defblend = appearance.blend_mode + + var/curicon = appearance.icon || deficon + var/curstate = appearance.icon_state || defstate + var/curdir = (!appearance.dir || appearance.dir == SOUTH) ? defdir : appearance.dir - var/curicon = A.icon || deficon - var/curstate = A.icon_state || defstate + var/render_icon = curicon - if(!((noIcon = (!curicon)))) + if (render_icon) var/curstates = icon_states(curicon) if(!(curstate in curstates)) - if("" in curstates) + if ("" in curstates) curstate = "" else - noIcon = TRUE // Do not render this object. + render_icon = FALSE - var/curdir - var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have - - //These should use the parent's direction (most likely) - if(!A.dir || A.dir == SOUTH) - curdir = defdir - else - curdir = A.dir + var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have //Try to remove/optimize this section ASAP, CPU hog. //Determines if there's directionals. - if(!noIcon && curdir != SOUTH) - var/exist = FALSE - var/static/list/checkdirs = list(NORTH, EAST, WEST) - for(var/i in checkdirs) //Not using GLOB for a reason. - if(length(icon_states(icon(curicon, curstate, i)))) - exist = TRUE - break - if(!exist) + if(render_icon && curdir != SOUTH) + if ( + !length(icon_states(icon(curicon, curstate, NORTH))) \ + && !length(icon_states(icon(curicon, curstate, EAST))) \ + && !length(icon_states(icon(curicon, curstate, WEST))) \ + ) base_icon_dir = SOUTH - // if(!base_icon_dir) base_icon_dir = curdir - ASSERT(!BLEND_DEFAULT) //I might just be stupid but lets make sure this define is 0. + var/curblend = appearance.blend_mode || defblend - var/curblend = A.blend_mode || defblend - - if(A.overlays.len || A.underlays.len) - var/icon/flat = BLANK + if(appearance.overlays.len || appearance.underlays.len) + var/icon/flat = icon(flat_template) // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed var/list/layers = list() var/image/copy // Add the atom's icon itself, without pixel_x/y offsets. - if(!noIcon) - copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=base_icon_dir) - copy.color = A.color - copy.alpha = A.alpha + if(render_icon) + copy = image(icon=curicon, icon_state=curstate, layer=appearance.layer, dir=base_icon_dir) + copy.color = appearance.color + copy.alpha = appearance.alpha copy.blend_mode = curblend - layers[copy] = A.layer - - // Loop through the underlays, then overlays, sorting them into the layers list - for(var/process_set in 0 to 1) - var/list/process = process_set? A.overlays : A.underlays - for(var/i in 1 to process.len) - var/image/current = process[i] - if(!current) - continue - if(current.plane != FLOAT_PLANE && current.plane != A.plane) - continue - var/current_layer = current.layer - if(current_layer < 0) - if(current_layer <= -1000) - return flat - current_layer = process_set + A.layer + current_layer / 1000 - - for(var/p in 1 to layers.len) - var/image/cmp = layers[p] - if(current_layer < layers[cmp]) - layers.Insert(p, current) - break - layers[current] = current_layer - - //sortTim(layers, /proc/cmp_image_layer_asc) + layers[copy] = appearance.layer + + PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.underlays, 0) + PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.overlays, 1) var/icon/add // Icon of overlay being added - // Current dimensions of flattened icon - var/list/flat_size = list(1, flat.Width(), 1, flat.Height()) - // Dimensions of overlay being added - var/list/add_size[4] + var/flatX1 = 1 + var/flatX2 = flat.Width() + var/flatY1 = 1 + var/flatY2 = flat.Height() - for(var/V in layers) - var/image/I = V - if(I.alpha == 0) + var/addX1 = 0 + var/addX2 = 0 + var/addY1 = 0 + var/addY2 = 0 + + for(var/image/layer_image as anything in layers) + if(layer_image.alpha == 0) continue - if(I == copy) // 'I' is an /image based on the object being flattened. + if(layer_image == copy) // 'layer_image' is an /image based on the object being flattened. curblend = BLEND_OVERLAY - add = icon(I.icon, I.icon_state, base_icon_dir) + add = icon(layer_image.icon, layer_image.icon_state, base_icon_dir) else // 'I' is an appearance object. - add = getFlatIcon(image(I), curdir, curicon, curstate, curblend, FALSE, no_anim) + add = getFlatIcon(image(layer_image), curdir, curicon, curstate, curblend, FALSE, no_anim) if(!add) continue + // Find the new dimensions of the flat icon to fit the added overlay - add_size = list( - min(flatX1, I.pixel_x+1), - max(flatX2, I.pixel_x+add.Width()), - min(flatY1, I.pixel_y+1), - max(flatY2, I.pixel_y+add.Height()) + addX1 = min(flatX1, layer_image.pixel_x + 1) + addX2 = max(flatX2, layer_image.pixel_x + add.Width()) + addY1 = min(flatY1, layer_image.pixel_y + 1) + addY2 = max(flatY2, layer_image.pixel_y + add.Height()) + + if ( + addX1 != flatX1 \ + && addX2 != flatX2 \ + && addY1 != flatY1 \ + && addY2 != flatY2 \ ) - - if(flat_size ~! add_size) // Resize the flattened icon so the new icon fits flat.Crop( - addX1 - flatX1 + 1, - addY1 - flatY1 + 1, - addX2 - flatX1 + 1, - addY2 - flatY1 + 1 + addX1 - flatX1 + 1, + addY1 - flatY1 + 1, + addX2 - flatX1 + 1, + addY2 - flatY1 + 1 ) - flat_size = add_size.Copy() + + flatX1 = addX1 + flatX2 = addY1 + flatY1 = addX2 + flatY2 = addY2 // Blend the overlay into the flattened icon - flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1) + flat.Blend(add, blendMode2iconMode(curblend), layer_image.pixel_x + 2 - flatX1, layer_image.pixel_y + 2 - flatY1) - if(A.color) - if(islist(A.color)) - flat.MapColors(arglist(A.color)) + if(appearance.color) + if(islist(appearance.color)) + flat.MapColors(arglist(appearance.color)) else - flat.Blend(A.color, ICON_MULTIPLY) + flat.Blend(appearance.color, ICON_MULTIPLY) - if(A.alpha < 255) - flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) + if(appearance.alpha < 255) + flat.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY) if(no_anim) //Clean up repeated frames var/icon/cleaned = new /icon() cleaned.Insert(flat, "", SOUTH, 1, 0) - . = cleaned + return cleaned else - . = icon(flat, "", SOUTH) - else //There's no overlays. - if(!noIcon) - SET_SELF(.) - - //Clear defines - #undef flatX1 - #undef flatX2 - #undef flatY1 - #undef flatY2 - #undef addX1 - #undef addX2 - #undef addY1 - #undef addY2 - - #undef INDEX_X_LOW - #undef INDEX_X_HIGH - #undef INDEX_Y_LOW - #undef INDEX_Y_HIGH - - #undef BLANK - #undef SET_SELF + return icon(flat, "", SOUTH) + else if (render_icon) // There's no overlays. + var/icon/final_icon = icon(icon(curicon, curstate, base_icon_dir), "", SOUTH, no_anim ? TRUE : null) + + if (appearance.alpha < 255) + final_icon.Blend(rgb(255,255,255, appearance.alpha), ICON_MULTIPLY) + + if (appearance.color) + if (islist(appearance.color)) + final_icon.MapColors(arglist(appearance.color)) + else + final_icon.Blend(appearance.color, ICON_MULTIPLY) + + return final_icon + + #undef PROCESS_OVERLAYS_OR_UNDERLAYS /proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A. diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 62d6f348e67a..6fbf5760e179 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -4,21 +4,21 @@ /proc/random_eye_color() switch(pick(20;"brown",20;"hazel",20;"grey",15;"blue",15;"green",1;"amber",1;"albino")) if("brown") - return "630" + return "#663300" if("hazel") - return "542" + return "#554422" if("grey") - return pick("666","777","888","999","aaa","bbb","ccc") + return pick("#666666","#777777","#888888","#999999","#aaaaaa","#bbbbbb","#cccccc") if("blue") - return "36c" + return "#3366cc" if("green") - return "060" + return "#006600" if("amber") - return "fc0" + return "#ffcc00" if("albino") - return pick("c","d","e","f") + pick("0","1","2","3","4","5","6","7","8","9") + pick("0","1","2","3","4","5","6","7","8","9") + return "#" + pick("cc","dd","ee","ff") + pick("00","11","22","33","44","55","66","77","88","99") + pick("00","11","22","33","44","55","66","77","88","99") else - return "000" + return "#000000" /proc/random_underwear(gender) if(!GLOB.underwear_list.len) @@ -93,9 +93,9 @@ //For now we will always return none for tail_human and ears. this shit was unreadable if you do somethign like this make it at least readable return(list( - "mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "mcolor" = "#[pick("7F","FF")][pick("7F","FF")][pick("7F","FF")]", "gradientstyle" = random_hair_gradient_style(10), - "gradientcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "gradientcolor" = "#[pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F")]", "ethcolor" = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)], "pretcolor" = GLOB.color_list_preternis[pick(GLOB.color_list_preternis)], "tail_lizard" = pick(GLOB.tails_list_lizard), @@ -110,7 +110,7 @@ "legs" = "Normal Legs", "caps" = pick(GLOB.caps_list), "moth_wings" = pick(GLOB.moth_wings_list), - "tail_polysmorph" = "Polys", + "tail_polysmorph" = pick(GLOB.tails_list_polysmorph), "teeth" = pick(GLOB.teeth_list), "dome" = pick(GLOB.dome_list), "dorsal_tubes" = pick(GLOB.dorsal_tubes_list), diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index e3403250baa5..6b76a5c20bfa 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -29,7 +29,7 @@ return value if(default) return default - if(List && List.len) + if(List?.len) return pick(List) @@ -51,40 +51,64 @@ return default return default -/proc/sanitize_hexcolor(color, desired_format=3, include_crunch=0, default) +/** + * Sanitize_Hexcolor takes in a color in hexcode as a string, be it shorthand hex as 3 characters, or full-sized 6 digit hex, with or without a leading # + * you can pass it a full hexcode with leading #, such as "#FFFFFF", and with the default arguments you will get exactly that color back, because it accounts for + * leading # signs and ignores them, then later in the function will either readd one, or won't depending on what you want. + * + * Full hexcolors will just be validated, shorthand hex of 3 characters can be cleanly converted up to full hex with a leading # no problem. + * + * With default arguments: + * * "FFF" -> "#FFFFFF" + * * "#FFFFFF" -> "#FFFFFF" + * + * converting down to short, with or without the # is doable by setting the desired format to the length you want and specifying the crunch to true for adding a # or false to not + */ +/proc/sanitize_hexcolor(color, desired_format = DEFAULT_HEX_COLOR_LEN, include_crunch = TRUE, default) var/crunch = include_crunch ? "#" : "" if(!istext(color)) color = "" + //start checks for a leading "#", and if there is it skips past it before doing the color logic. + //this means you can pass something like "#FFFFFF" into sanitize_hexcolor without arguments, and it will automatically cut the leading #, and readd it at the end + //there is no risk of accidentally creating a malformed color like ##FFFFFF var/start = 1 + (text2ascii(color, 1) == 35) var/len = length(color) var/char = "" - // RRGGBB -> RGB but awful - var/convert_to_shorthand = desired_format == 3 && length_char(color) > 3 + // Used for conversion between RGBA hex formats. + var/format_input_ratio = "[desired_format]:[length_char(color)-(start-1)]" . = "" var/i = start while(i <= len) char = color[i] + i += length(char) switch(text2ascii(char)) - if(48 to 57) //numbers 0 to 9 + if(48 to 57) //numbers 0 to 9 + . += char + if(97 to 102) //letters a to f . += char - if(97 to 102) //letters a to f + if(65 to 70) //letters A to F + char = lowertext(char) . += char - if(65 to 70) //letters A to F - . += lowertext(char) else break - i += length(char) - if(convert_to_shorthand && i <= len) //skip next one - i += length(color[i]) - - if(length_char(.) != desired_format) - if(default) - return default - return crunch + repeat_string(desired_format, "0") + switch(format_input_ratio) + //if you're trying to convert up from short hex (3 characters) to a full hex 6, that's what these switch statements are doing, adding and removing to meet the desired format + if("3:8", "4:8", "3:6", "4:6") //skip next one. RRGGBB(AA) -> RGB(A) + i += length(color[i]) + if("6:4", "6:3", "8:4", "8:3") //add current char again. RGB(A) -> RRGGBB(AA) + . += char - return crunch + . + if(length_char(.) == desired_format) + return crunch + . + switch(format_input_ratio) //add or remove alpha channel depending on desired format. + if("3:8", "3:4", "6:4") + return crunch + copytext(., 1, desired_format+1) + if("4:6", "4:3", "8:3") + return crunch + . + ((desired_format == 4) ? "f" : "ff") + else //not a supported hex color format. + return default ? default : crunch + repeat_string(desired_format, "0") /proc/sanitize_color(color) if(length(color) != length_char(color)) diff --git a/code/_globalvars/_regexes.dm b/code/_globalvars/_regexes.dm deleted file mode 100644 index 59f468dcf022..000000000000 --- a/code/_globalvars/_regexes.dm +++ /dev/null @@ -1,3 +0,0 @@ -//These are a bunch of regex datums for use /((any|every|no|some|head|foot)where(wolf)?\sand\s)+(\.[\.\s]+\s?where\?)?/i - -GLOBAL_DATUM_INIT(is_color, /regex, regex("^#\[0-9a-fA-F]{6}$")) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index c8fa54349e0f..e71e647eb487 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -57,12 +57,30 @@ GLOBAL_LIST_INIT(plasmaman_helmet_list, list( "Low" = "low")) //for icon making -> use "enviro" before this GLOBAL_LIST_EMPTY(ethereal_mark_list) //ethereal face marks -GLOBAL_LIST_INIT(color_list_ethereal,\ - list("O Class (Dark Green)" = "37833F", "O2 Class(Green)" = "97ee63", "O3 Class (Light Green)" = "00ff00",\ - "B Class (Blue)" = "3399ff", "A Class (Cyan)" = "00ffff", "F Class (White)" = "ffffff", "K Class (Yellow)" = "ffff00",\ - "M Class (Orange)" = "ff8700", "L Class (Red)" = "ff0000", "L2 Class (Dark Red)" = "9c3030", "T Class (Light Purple)" = "ff00ff",\ - "T2 Class (Dark Purple)" = "ee82ee")) -GLOBAL_LIST_INIT(color_list_preternis, list("Factory Default" = "FFFFFF", "Rust" = "B7410E", "Chrome" = "B0C4DE", "Overgrown" = "b2ee69", "Gunmetal Gray" = "8D918D", "Gold" = "D4AF37")) +GLOBAL_LIST_INIT(color_list_ethereal,list( + "O Class (Dark Green)" = "#37833F", + "O2 Class(Green)" = "#97ee63", + "O3 Class (Light Green)" = "#00ff00", + "B Class (Blue)" = "#3399ff", + "B1 Class (Dark Blue)" = "#6666ff", + "B2 Class (Faint Blue)" = "#b3d9ff", + "A Class (Cyan)" = "#00ffff", + "F Class (White)" = "#ffffff", + "K Class (Yellow)" = "#ffff00", + "M Class (Orange)" = "#ff8700", + "L Class (Red)" = "#ff0000", + "L1 Class (Faint Red)" = "#ff4d4d", + "L2 Class (Dark Red)" = "#9c3030", + "T Class (Light Purple)" = "#ff00ff", + "T2 Class (Dark Purple)" = "#ee82ee", + "White Dwarf" = "#f2f2f2",)) +GLOBAL_LIST_INIT(color_list_preternis, list( + "Factory Default" = "#FFFFFF", + "Rust" = "#B7410E", + "Chrome" = "#B0C4DE", + "Overgrown" = "#b2ee69", + "Gunmetal Gray" = "#8D918D", + "Gold" = "#D4AF37")) GLOBAL_LIST_EMPTY(pod_hair_list) //ethereal face marks GLOBAL_LIST_EMPTY(pod_flower_list) //ethereal face marks diff --git a/code/_globalvars/regexes.dm b/code/_globalvars/regexes.dm index bd252b68ce43..86c41cc7ab69 100644 --- a/code/_globalvars/regexes.dm +++ b/code/_globalvars/regexes.dm @@ -5,3 +5,4 @@ GLOBAL_DATUM_INIT(is_website, /regex, regex("http|www.|\[a-z0-9_-]+.(com|org|net GLOBAL_DATUM_INIT(is_email, /regex, regex("\[a-z0-9_-]+@\[a-z0-9_-]+.\[a-z0-9_-]+", "i")) GLOBAL_DATUM_INIT(is_alphanumeric, /regex, regex("\[a-z0-9]+", "i")) GLOBAL_DATUM_INIT(is_punctuation, /regex, regex("\[.!?]+", "i")) +GLOBAL_DATUM_INIT(is_color, /regex, regex("^#\[0-9a-fA-F]{6}$")) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index bd9ed1f4a8f9..c6d23ad8b245 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -654,7 +654,7 @@ screen_loc = ui_mood /atom/movable/screen/splash - icon = 'icons/blank_title.png' + icon = 'icons/blanks/blank_title.png' icon_state = "" screen_loc = "1,1" layer = SPLASHSCREEN_LAYER diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm index 9775303802c4..b9d618d4092d 100644 --- a/code/datums/components/forensics.dm +++ b/code/datums/components/forensics.dm @@ -99,7 +99,7 @@ if(!ignoregloves) H.gloves.add_fingerprint(H, TRUE) //ignoregloves = 1 to avoid infinite loop. return - var/full_print = md5(H.dna.uni_identity) + var/full_print = md5(H.dna.unique_identity) LAZYSET(fingerprints, full_print, full_print) return TRUE @@ -212,9 +212,9 @@ if(!iscarbon(M)) return var/mob/living/carbon/smelly = M - if(!smelly?.dna?.uni_identity) + if(!smelly?.dna?.unique_identity) return - var/smell_print = md5(smelly.dna.uni_identity) + var/smell_print = md5(smelly.dna.unique_identity) LAZYSET(scents, smell_print, smelly) return TRUE diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 252be124c5cf..3691cdd0c14f 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -326,7 +326,7 @@ G.fields["rank"] = assignment G.fields["age"] = H.age G.fields["species"] = H.dna.species.name - G.fields["fingerprint"] = md5(H.dna.uni_identity) + G.fields["fingerprint"] = md5(H.dna.unique_identity) G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" G.fields["gender"] = H.gender @@ -383,7 +383,7 @@ G.fields["gender"] = "Other" L.fields["blood_type"] = H.dna.blood_type L.fields["b_dna"] = H.dna.unique_enzymes - L.fields["identity"] = H.dna.uni_identity + L.fields["identity"] = H.dna.unique_identity L.fields["species"] = H.dna.species.type L.fields["features"] = H.dna.features L.fields["image"] = image diff --git a/code/datums/diseases/advance/symptoms/skin.dm b/code/datums/diseases/advance/symptoms/skin.dm index 22972ce9e44d..c9beaeb322cb 100644 --- a/code/datums/diseases/advance/symptoms/skin.dm +++ b/code/datums/diseases/advance/symptoms/skin.dm @@ -43,14 +43,14 @@ BONUS var/mob/living/carbon/human/H = M if(H.skin_tone == "albino") return - if(H.dna.features["mcolor"] == "EEE") + if(H.dna.features["mcolor"] == "#EEEEEE") return switch(A.stage) if(5) if(H.dna.species.use_skintones) H.skin_tone = "albino" else if(MUTCOLORS in H.dna.species.species_traits) - H.dna.features["mcolor"] = "EEE" //pure white. + H.dna.features["mcolor"] = "#EEEEEE" //pure white. H.regenerate_icons() else H.visible_message(span_warning("[H] looks a bit pale..."), span_notice("Your skin suddenly appears lighter...")) @@ -110,14 +110,14 @@ BONUS var/mob/living/carbon/human/H = M if(H.skin_tone == "african2") return - if(H.dna.features["mcolor"] == "000") + if(H.dna.features["mcolor"] == "#000000") return switch(A.stage) if(5) if(H.dna.species.use_skintones) H.skin_tone = "african2" else if(MUTCOLORS in H.dna.species.species_traits) - H.dna.features["mcolor"] = "000" //pure black. + H.dna.features["mcolor"] = "#000000" //pure black. H.regenerate_icons() else H.visible_message(span_warning("[H] looks a bit dark..."), span_notice("Your skin suddenly appears darker...")) diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index 81cb105cda5e..c54724705a37 100644 --- a/code/datums/diseases/retrovirus.dm +++ b/code/datums/diseases/retrovirus.dm @@ -66,10 +66,13 @@ to_chat(affected_mob, span_danger("Your entire body vibrates.")) if (prob(35)) - if(prob(50)) - scramble_dna(affected_mob, 1, 0, rand(15,45)) - else - scramble_dna(affected_mob, 0, 1, rand(15,45)) + switch(rand(1,3)) + if(1) + scramble_dna(affected_mob, 1, 0, 0, rand(15,45)) + if(2) + scramble_dna(affected_mob, 0, 1, 0, rand(15,45)) + if(3) + scramble_dna(affected_mob, 0, 0, 1, rand(15,45)) if(4) if(restcure) @@ -78,7 +81,10 @@ cure() return if (prob(60)) - if(prob(50)) - scramble_dna(affected_mob, 1, 0, rand(50,75)) - else - scramble_dna(affected_mob, 0, 1, rand(50,75)) \ No newline at end of file + switch(rand(1,3)) + if(1) + scramble_dna(affected_mob, 1, 0, 0, rand(50,75)) + if(2) + scramble_dna(affected_mob, 0, 1, 0, rand(50,75)) + if(3) + scramble_dna(affected_mob, 0, 0, 1, rand(50,75)) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 5e2f92b663ac..698a9cafc52c 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -1,21 +1,82 @@ +/** + * Some identity blocks (basically pieces of the unique_identity string variable of the dna datum, commonly abbreviated with ui) + * may have a length that differ from standard length of 3 ASCII characters. This list is necessary + * for these non-standard blocks to work, as well as the entire unique identity string. + * Should you add a new ui block which size differ from the standard (again, 3 ASCII characters), like for example, a color, + * please do not forget to also include it in this list in the following format: + * "[dna block number]" = dna block size, + * Failure to do that may result in bugs. Thanks. + */ +GLOBAL_LIST_INIT(identity_block_lengths, list( + "[DNA_HAIR_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, + "[DNA_FACIAL_HAIR_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, + "[DNA_EYE_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, + )) + +/** + * The same rules of the above also apply here, with the exception that this is for the unique_features string variable + * (commonly abbreviated with uf) and its blocks. Both ui and uf have a standard block length of 3 ASCII characters. + */ +GLOBAL_LIST_INIT(features_block_lengths, list( + "[DNA_MUTANT_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, + "[DNA_ETHEREAL_COLOR_BLOCK]" = DNA_BLOCK_SIZE_COLOR, + )) + +/** + * A list of numbers that keeps track of where ui blocks start in the unique_identity string variable of the dna datum. + * Commonly used by the datum/dna/set_uni_identity_block and datum/dna/get_uni_identity_block procs. + */ +GLOBAL_LIST_INIT(total_ui_len_by_block, populate_total_ui_len_by_block()) + +/proc/populate_total_ui_len_by_block() + . = list() + var/total_block_len = 1 + for(var/blocknumber in 1 to DNA_UNI_IDENTITY_BLOCKS) + . += total_block_len + total_block_len += GET_UI_BLOCK_LEN(blocknumber) + +///Ditto but for unique features. Used by the datum/dna/set_uni_feature_block and datum/dna/get_uni_feature_block procs. +GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) + +/proc/populate_total_uf_len_by_block() + . = list() + var/total_block_len = 1 + for(var/blocknumber in 1 to DNA_FEATURE_BLOCKS) + . += total_block_len + total_block_len += GET_UF_BLOCK_LEN(blocknumber) + /////////////////////////// DNA DATUM /datum/dna + ///An md5 hash of the dna holder's real name var/unique_enzymes - var/uni_identity + ///Stores the hashed values of traits such as skin tones, hair style, and gender + var/unique_identity var/blood_type - var/datum/species/species = new /datum/species/human //The type of mutant race the player is if applicable (i.e. potato-man) - var/list/features = list("FFF") //first value is mutant color - var/real_name //Stores the real name of the person who originally got this dna datum. Used primarely for changelings, - var/list/mutations = list() //All mutations are from now on here - var/list/temporary_mutations = list() //Temporary changes to the UE - var/list/previous = list() //For temporary name/ui/ue/blood_type modifications + ///The type of mutant race the player is if applicable (i.e. potato-man) + var/datum/species/species = new /datum/species/human + ///first value is mutant color + var/list/features = list("FFF") + ///Stores the hashed values of the person's non-human features + var/unique_features + ///Stores the real name of the person who originally got this dna datum. Used primarely for changelings, + var/real_name + ///All mutations are from now on here + var/list/mutations = list() + ///Temporary changes to the UE + var/list/temporary_mutations = list() + ///For temporary name/ui/ue/blood_type modifications + var/list/previous = list() var/mob/living/holder - var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875 - var/mutation_index[DNA_MUTATION_BLOCKS] //List of which mutations this carbon has and its assigned block - var/default_mutation_genes[DNA_MUTATION_BLOCKS] //List of the default genes from this mutation to allow DNA Scanner highlighting + ///List of which mutations this carbon has and its assigned block + var/mutation_index[DNA_MUTATION_BLOCKS] + ///List of the default genes from this mutation to allow DNA Scanner highlighting + var/default_mutation_genes[DNA_MUTATION_BLOCKS] 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. + ///Did we take something like mutagen? In that case we cant get our genes scanned to instantly cheese all the powers. + var/scrambled = FALSE + + var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875 /datum/dna/New(mob/living/new_holder) if(istype(new_holder)) @@ -41,9 +102,10 @@ if(!istype(destination)) return destination.dna.unique_enzymes = unique_enzymes - destination.dna.uni_identity = uni_identity + destination.dna.unique_identity = unique_identity destination.dna.blood_type = blood_type destination.set_species(species.type, icon_update=0) + destination.dna.unique_features = unique_features destination.dna.features = features.Copy() destination.dna.real_name = real_name destination.dna.temporary_mutations = temporary_mutations.Copy() @@ -56,7 +118,8 @@ new_dna.unique_enzymes = unique_enzymes new_dna.mutation_index = mutation_index new_dna.default_mutation_genes = default_mutation_genes - new_dna.uni_identity = uni_identity + new_dna.unique_identity = unique_identity + new_dna.unique_features = unique_features new_dna.blood_type = blood_type new_dna.features = features.Copy() new_dna.species = new species.type @@ -71,9 +134,11 @@ mutation_type = HM.type if(get_mutation(mutation_type)) return + SEND_SIGNAL(holder, COMSIG_CARBON_GAIN_MUTATION, mutation_type, class) return force_give(new mutation_type (class, time, copymut = mutation)) /datum/dna/proc/remove_mutation(mutation_type) + SEND_SIGNAL(holder, COMSIG_CARBON_LOSE_MUTATION, mutation_type) return force_lose(get_mutation(mutation_type)) /datum/dna/proc/check_mutation(mutation_type) @@ -90,7 +155,7 @@ if((HM.class in classes) && !(HM.mutadone_proof && mutadone)) force_lose(HM) -/datum/dna/proc/generate_uni_identity() +/datum/dna/proc/generate_unique_identity() . = "" var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS) @@ -106,20 +171,63 @@ if(!GLOB.hair_styles_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/hair,GLOB.hair_styles_list, GLOB.hair_styles_male_list, GLOB.hair_styles_female_list) L[DNA_HAIR_STYLE_BLOCK] = construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len) - L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color) + L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color, include_crunch = FALSE) if(!GLOB.facial_hair_styles_list.len) 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) L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len) - L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color) + L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color, include_crunch = FALSE) L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len) - L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color) + L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color, include_crunch = FALSE) - for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) - if(L[i]) - . += L[i] - else - . += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) - return . + for(var/blocknum in 1 to DNA_UNI_IDENTITY_BLOCKS) + . += L[blocknum] || random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters) + +/datum/dna/proc/generate_unique_features() + . = "" + + var/list/L = new /list(DNA_FEATURE_BLOCKS) + + if(features["mcolor"]) + L[DNA_MUTANT_COLOR_BLOCK] = sanitize_hexcolor(features["mcolor"], include_crunch = FALSE) + if(features["ethcolor"]) + L[DNA_ETHEREAL_COLOR_BLOCK] = sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE) + if(features["body_markings"]) + L[DNA_LIZARD_MARKINGS_BLOCK] = construct_block(GLOB.body_markings_list.Find(features["body_markings"]), GLOB.body_markings_list.len) + if(features["tail_lizard"]) + L[DNA_LIZARD_TAIL_BLOCK] = construct_block(GLOB.tails_list_lizard.Find(features["tail_lizard"]), GLOB.tails_list_lizard.len) + if(features["snout"]) + L[DNA_SNOUT_BLOCK] = construct_block(GLOB.snouts_list.Find(features["snout"]), GLOB.snouts_list.len) + if(features["horns"]) + L[DNA_HORNS_BLOCK] = construct_block(GLOB.horns_list.Find(features["horns"]), GLOB.horns_list.len) + if(features["frills"]) + L[DNA_FRILLS_BLOCK] = construct_block(GLOB.frills_list.Find(features["frills"]), GLOB.frills_list.len) + if(features["spines"]) + L[DNA_SPINES_BLOCK] = construct_block(GLOB.spines_list.Find(features["spines"]), GLOB.spines_list.len) + if(features["tail_human"]) + L[DNA_HUMAN_TAIL_BLOCK] = construct_block(GLOB.tails_list_human.Find(features["tail_human"]), GLOB.tails_list_human.len) + if(features["ears"]) + L[DNA_EARS_BLOCK] = construct_block(GLOB.ears_list.Find(features["ears"]), GLOB.ears_list.len) + if(features["moth_wings"] != "Burnt Off") + L[DNA_MOTH_WINGS_BLOCK] = construct_block(GLOB.moth_wings_list.Find(features["moth_wings"]), GLOB.moth_wings_list.len) + if(features["caps"]) + L[DNA_MUSHROOM_CAPS_BLOCK] = construct_block(GLOB.caps_list.Find(features["caps"]), GLOB.caps_list.len) + if(features["tail_polysmorph"]) + L[DNA_POLY_TAIL_BLOCK] = construct_block(GLOB.tails_list_polysmorph.Find(features["tail_polysmorph"]), GLOB.tails_list_polysmorph.len) + if(features["teeth"]) + L[DNA_POLY_TEETH_BLOCK] = construct_block(GLOB.teeth_list.Find(features["teeth"]), GLOB.teeth_list.len) + if(features["dome"]) + L[DNA_POLY_DOME_BLOCK] = construct_block(GLOB.dome_list.Find(features["dome"]), GLOB.dome_list.len) + if(features["dorsal_tubes"]) + L[DNA_POLY_DORSAL_BLOCK] = construct_block(GLOB.dorsal_tubes_list.Find(features["dorsal_tubes"]), GLOB.dorsal_tubes_list.len) + if(features["ethereal_mark"]) + L[DNA_ETHEREAL_MARK_BLOCK] = construct_block(GLOB.ethereal_mark_list.Find(features["ethereal_mark"]), GLOB.ethereal_mark_list.len) + if(features["pod_hair"]) + L[DNA_POD_HAIR_BLOCK] = construct_block(GLOB.pod_hair_list.Find(features["pod_hair"]), GLOB.pod_hair_list.len) + if(features["pod_flower"]) + L[DNA_POD_FLOWER_BLOCK] = construct_block(GLOB.pod_flower_list.Find(features["pod_flower"]), GLOB.pod_flower_list.len) + + for(var/blocknum in 1 to DNA_FEATURE_BLOCKS) + . += L[blocknum] || random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters) /datum/dna/proc/generate_dna_blocks() var/bonus @@ -137,10 +245,17 @@ else mutation_index[RACEMUT] = create_sequence(RACEMUT, FALSE) default_mutation_genes[RACEMUT] = mutation_index[RACEMUT] - for(var/i in 2 to DNA_MUTATION_BLOCKS) - var/datum/mutation/human/M = mutations_temp[i] - mutation_index[M.type] = create_sequence(M.type, FALSE, M.difficulty) - default_mutation_genes[M.type] = mutation_index[M.type] + while(mutation_index.len < DNA_MUTATION_BLOCKS) + var/datum/mutation/human/mutation = mutations_temp[mutation_index.len] + var/conflict = FALSE + for(var/conflicting_mut in mutation.conflicts) + if(mutation_index.Find(conflicting_mut)) + conflict = TRUE //no more conflicting mutations in the same mob dna + mutations_temp.Cut(mutation_index.len, mutation_index.len+1) + if(conflict) + continue + mutation_index[mutation.type] = create_sequence(mutation.type, FALSE, mutation.difficulty) + default_mutation_genes[mutation.type] = mutation_index[mutation.type] shuffle_inplace(mutation_index) //Used to generate original gene sequences for every mutation @@ -163,8 +278,8 @@ if(active) return sequence while(difficulty) - var/randnum = rand(1, length_char(sequence)) - sequence = copytext_char(sequence, 1, randnum) + "X" + copytext_char(sequence, randnum + 1) + var/randnum = rand(1, length(sequence)) + sequence = copytext(sequence, 1, randnum) + "X" + copytext(sequence, randnum + 1) difficulty-- return sequence @@ -177,35 +292,90 @@ . += random_string(DNA_UNIQUE_ENZYMES_LEN, GLOB.hex_characters) return . +///Setter macro used to modify unique identity blocks. +/datum/dna/proc/set_uni_identity_block(blocknum, input) + var/precesing_blocks = copytext(unique_identity, 1, GLOB.total_ui_len_by_block[blocknum]) + var/succeeding_blocks = blocknum < GLOB.total_ui_len_by_block.len ? copytext(unique_identity, GLOB.total_ui_len_by_block[blocknum+1]) : "" + unique_identity = precesing_blocks + input + succeeding_blocks + +///Setter macro used to modify unique features blocks. +/datum/dna/proc/set_uni_feature_block(blocknum, input) + var/precesing_blocks = copytext(unique_features, 1, GLOB.total_uf_len_by_block[blocknum]) + var/succeeding_blocks = blocknum < GLOB.total_uf_len_by_block.len ? copytext(unique_features, GLOB.total_uf_len_by_block[blocknum+1]) : "" + unique_features = precesing_blocks + input + succeeding_blocks + /datum/dna/proc/update_ui_block(blocknumber) - if(!blocknumber || !ishuman(holder)) - return + if(!blocknumber) + CRASH("UI block index is null") + if(!ishuman(holder)) + CRASH("Non-human mobs shouldn't have DNA") var/mob/living/carbon/human/H = holder switch(blocknumber) if(DNA_HAIR_COLOR_BLOCK) - uni_identity = setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color)) + set_uni_identity_block(blocknumber, sanitize_hexcolor(H.hair_color, include_crunch = FALSE)) if(DNA_FACIAL_HAIR_COLOR_BLOCK) - uni_identity = setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color)) + set_uni_identity_block(blocknumber, sanitize_hexcolor(H.facial_hair_color, include_crunch = FALSE)) if(DNA_SKIN_TONE_BLOCK) - uni_identity = setblock(uni_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)) + set_uni_identity_block(blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)) if(DNA_EYE_COLOR_BLOCK) - uni_identity = setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color)) - var/obj/item/organ/eyes/eyes = H.getorgan(/obj/item/organ/eyes) - if(eyes) - eyes.old_eye_color = sanitize_hexcolor(H.eye_color) - eyes.eye_color = sanitize_hexcolor(H.eye_color) + set_uni_identity_block(blocknumber, sanitize_hexcolor(H.eye_color, include_crunch = FALSE)) if(DNA_GENDER_BLOCK) switch(H.gender) if(MALE) - uni_identity = setblock(uni_identity, blocknumber, construct_block(G_MALE, 3)) + set_uni_identity_block(blocknumber, construct_block(G_MALE, 3)) if(FEMALE) - uni_identity = setblock(uni_identity, blocknumber, construct_block(G_FEMALE, 3)) + set_uni_identity_block(blocknumber, construct_block(G_FEMALE, 3)) else - uni_identity = setblock(uni_identity, blocknumber, construct_block(G_PLURAL, 3)) + set_uni_identity_block(blocknumber, construct_block(G_PLURAL, 3)) if(DNA_FACIAL_HAIR_STYLE_BLOCK) - uni_identity = setblock(uni_identity, blocknumber, construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len)) + set_uni_identity_block(blocknumber, construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len)) if(DNA_HAIR_STYLE_BLOCK) - uni_identity = setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len)) + set_uni_identity_block(blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len)) + +/datum/dna/proc/update_uf_block(blocknumber) + if(!blocknumber) + CRASH("UF block index is null") + if(!ishuman(holder)) + CRASH("Non-human mobs shouldn't have DNA") + switch(blocknumber) + if(DNA_MUTANT_COLOR_BLOCK) + set_uni_feature_block(blocknumber, sanitize_hexcolor(features["mcolor"], include_crunch = FALSE)) + if(DNA_ETHEREAL_COLOR_BLOCK) + set_uni_feature_block(blocknumber, sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE)) + if(DNA_LIZARD_MARKINGS_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.body_markings_list.Find(features["body_markings"]), GLOB.body_markings_list.len)) + if(DNA_LIZARD_TAIL_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_lizard.Find(features["tail_lizard"]), GLOB.tails_list_lizard.len)) + if(DNA_SNOUT_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.snouts_list.Find(features["snout"]), GLOB.snouts_list.len)) + if(DNA_HORNS_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.horns_list.Find(features["horns"]), GLOB.horns_list.len)) + if(DNA_FRILLS_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.frills_list.Find(features["frills"]), GLOB.frills_list.len)) + if(DNA_SPINES_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.spines_list.Find(features["spines"]), GLOB.spines_list.len)) + if(DNA_HUMAN_TAIL_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_human.Find(features["tail_human"]), GLOB.tails_list_human.len)) + if(DNA_EARS_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.ears_list.Find(features["ears"]), GLOB.ears_list.len)) + if(DNA_MOTH_WINGS_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.moth_wings_list.Find(features["moth_wings"]), GLOB.moth_wings_list.len)) + if(DNA_MUSHROOM_CAPS_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.caps_list.Find(features["caps"]), GLOB.caps_list.len)) + if(DNA_POLY_TAIL_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_polysmorph.Find(features["tail_polysmorph"]), GLOB.tails_list_polysmorph.len)) + if(DNA_POLY_TEETH_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.teeth_list.Find(features["teeth"]), GLOB.teeth_list.len)) + if(DNA_POLY_DOME_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.dome_list.Find(features["dome"]), GLOB.dome_list.len)) + if(DNA_POLY_DORSAL_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.dorsal_tubes_list.Find(features["dorsal_tubes"]), GLOB.dorsal_tubes_list.len)) + if(DNA_ETHEREAL_MARK_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.ethereal_mark_list.Find(features["ethereal_mark"]), GLOB.ethereal_mark_list.len)) + if(DNA_POD_HAIR_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.pod_hair_list.Find(features["pod_hair"]), GLOB.pod_hair_list.len)) + if(DNA_POD_FLOWER_BLOCK) + set_uni_feature_block(blocknumber, construct_block(GLOB.pod_flower_list.Find(features["pod_flower"]), GLOB.pod_flower_list.len)) //Please use add_mutation or activate_mutation instead /datum/dna/proc/force_give(datum/mutation/human/HM) @@ -226,7 +396,7 @@ 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) + if(unique_identity == D.unique_identity && mutation_index == D.mutation_index && real_name == D.real_name) if(species.type == D.species.type && features == D.features && blood_type == D.blood_type) return 1 return 0 @@ -259,17 +429,19 @@ //used to update dna UI, UE, and dna.real_name. /datum/dna/proc/update_dna_identity() - uni_identity = generate_uni_identity() + unique_identity = generate_unique_identity() unique_enzymes = generate_unique_enzymes() + unique_features = generate_unique_features() /datum/dna/proc/initialize_dna(newblood_type, skip_index = FALSE) if(newblood_type) blood_type = newblood_type unique_enzymes = generate_unique_enzymes() - uni_identity = generate_uni_identity() + unique_identity = generate_unique_identity() if(!skip_index) //I hate this generate_dna_blocks() features = random_features() + unique_features = generate_unique_features() /datum/dna/stored //subtype used by brain mob's stored_dna @@ -342,6 +514,7 @@ //Do not use force_transfer_mutations for stuff like cloners without some precautions, otherwise some conditional mutations could break (timers, drill hat etc) if(newfeatures) dna.features = newfeatures + dna.generate_unique_features() if(mrace) var/datum/species/newrace = new mrace.type @@ -356,7 +529,7 @@ dna.blood_type = newblood_type if(ui) - dna.uni_identity = ui + dna.unique_identity = ui updateappearance(icon_update=0) if(LAZYLEN(mutation_index)) @@ -390,7 +563,7 @@ if(!has_dna()) return - switch(deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 3)) + switch(deconstruct_block(get_uni_identity_block(dna.unique_identity, DNA_GENDER_BLOCK), 3)) if(G_MALE) gender = MALE if(G_FEMALE) @@ -400,18 +573,61 @@ /mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) ..() - 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)] - 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)] + var/structure = dna.unique_identity + hair_color = sanitize_hexcolor(get_uni_identity_block(structure, DNA_HAIR_COLOR_BLOCK)) + facial_hair_color = sanitize_hexcolor(get_uni_identity_block(structure, DNA_FACIAL_HAIR_COLOR_BLOCK)) + skin_tone = GLOB.skin_tones[deconstruct_block(get_uni_identity_block(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)] + eye_color = sanitize_hexcolor(get_uni_identity_block(structure, DNA_EYE_COLOR_BLOCK)) + facial_hair_style = GLOB.facial_hair_styles_list[deconstruct_block(get_uni_identity_block(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), GLOB.facial_hair_styles_list.len)] if(HAS_TRAIT(src, TRAIT_BALD)) - hair_style = "Bald" + hair_style = "Bald" else - hair_style = GLOB.hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)] + hair_style = GLOB.hair_styles_list[deconstruct_block(get_uni_identity_block(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)] + var/features = dna.unique_features + if(dna.features["mcolor"]) + dna.features["mcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_MUTANT_COLOR_BLOCK)) + if(dna.features["ethcolor"]) + dna.features["ethcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_ETHEREAL_COLOR_BLOCK)) + if(dna.features["body_markings"]) + dna.features["body_markings"] = GLOB.body_markings_list[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_MARKINGS_BLOCK), GLOB.body_markings_list.len)] + if(dna.features["tail_lizard"]) + dna.features["tail_lizard"] = GLOB.tails_list_lizard[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_TAIL_BLOCK), GLOB.tails_list_lizard.len)] + if(dna.features["snout"]) + dna.features["snout"] = GLOB.snouts_list[deconstruct_block(get_uni_feature_block(features, DNA_SNOUT_BLOCK), GLOB.snouts_list.len)] + if(dna.features["horns"]) + dna.features["horns"] = GLOB.horns_list[deconstruct_block(get_uni_feature_block(features, DNA_HORNS_BLOCK), GLOB.horns_list.len)] + if(dna.features["frills"]) + dna.features["frills"] = GLOB.frills_list[deconstruct_block(get_uni_feature_block(features, DNA_FRILLS_BLOCK), GLOB.frills_list.len)] + if(dna.features["spines"]) + dna.features["spines"] = GLOB.spines_list[deconstruct_block(get_uni_feature_block(features, DNA_SPINES_BLOCK), GLOB.spines_list.len)] + if(dna.features["tail_human"]) + dna.features["tail_human"] = GLOB.tails_list_human[deconstruct_block(get_uni_feature_block(features, DNA_HUMAN_TAIL_BLOCK), GLOB.tails_list_human.len)] + if(dna.features["ears"]) + dna.features["ears"] = GLOB.ears_list[deconstruct_block(get_uni_feature_block(features, DNA_EARS_BLOCK), GLOB.ears_list.len)] + if(dna.features["moth_wings"]) + var/genetic_value = GLOB.moth_wings_list[deconstruct_block(get_uni_feature_block(features, DNA_MOTH_WINGS_BLOCK), GLOB.moth_wings_list.len)] + dna.features["original_moth_wings"] = genetic_value + if(dna.features["moth_wings"] != "Burnt Off") + dna.features["moth_wings"] = genetic_value + if(dna.features["caps"]) + dna.features["caps"] = GLOB.caps_list[deconstruct_block(get_uni_feature_block(features, DNA_MUSHROOM_CAPS_BLOCK), GLOB.caps_list.len)] + // if(features["tail_polysmorph"]) + // dna.features["tail_polysmorph"] = GLOB.tails_list_polysmorph[deconstruct_block(get_uni_feature_block(features, DNA_POLY_TAIL_BLOCK), GLOB.tails_list_polysmorph.len)] + if(dna.features["teeth"]) + dna.features["teeth"] = GLOB.teeth_list[deconstruct_block(get_uni_feature_block(features, DNA_POLY_TEETH_BLOCK), GLOB.teeth_list.len)] + if(dna.features["dome"]) + dna.features["dome"] = GLOB.dome_list[deconstruct_block(get_uni_feature_block(features, DNA_POLY_DOME_BLOCK), GLOB.dome_list.len)] + if(dna.features["dorsal_tubes"]) + dna.features["dorsal_tubes"] = GLOB.dorsal_tubes_list[deconstruct_block(get_uni_feature_block(features, DNA_POLY_DORSAL_BLOCK), GLOB.dorsal_tubes_list.len)] + if(dna.features["ethereal_mark"]) + dna.features["ethereal_mark"] = GLOB.ethereal_mark_list[deconstruct_block(get_uni_feature_block(features, DNA_ETHEREAL_MARK_BLOCK), GLOB.ethereal_mark_list.len)] + if(dna.features["pod_hair"]) + dna.features["pod_hair"] = GLOB.pod_hair_list[deconstruct_block(get_uni_feature_block(features, DNA_POD_HAIR_BLOCK), GLOB.pod_hair_list.len)] + if(dna.features["pod_flower"]) + dna.features["pod_flower"] = GLOB.pod_flower_list[deconstruct_block(get_uni_feature_block(features, DNA_POD_FLOWER_BLOCK), GLOB.pod_flower_list.len)] + if(icon_update) - update_body() + dna.species.handle_body(src) // We want 'update_body_parts()' to be called only if mutcolor_update is TRUE, so no 'update_body()' here. update_hair() if(mutcolor_update) update_body_parts() @@ -443,7 +659,7 @@ //Return the active mutation of a type if there is one /datum/dna/proc/get_mutation(A) for(var/datum/mutation/human/HM in mutations) - if(HM.type == A) + if(istype(HM, A)) return HM /datum/dna/proc/check_block_string(mutation) @@ -479,22 +695,6 @@ /////////////////////////// DNA HELPER-PROCS ////////////////////////////// -/proc/getleftblocks(input,blocknumber,blocksize) - if(blocknumber > 1) - return copytext_char(input,1,((blocksize*blocknumber)-(blocksize-1))) - -/proc/getrightblocks(input,blocknumber,blocksize) - if(blocknumber < (length(input)/blocksize)) - return copytext_char(input,blocksize*blocknumber+1,length(input)+1) - -/proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE) - return copytext_char(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) - -/proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE) - if(!istring || !blocknumber || !replacement || !blocksize) - return 0 - return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize) - /datum/dna/proc/mutation_in_sequence(mutation) if(!mutation) return @@ -506,15 +706,15 @@ return TRUE -/mob/living/carbon/proc/randmut(list/candidates, difficulty = 2) +/mob/living/carbon/proc/random_mutate(list/candidates, difficulty = 2) if(!has_dna()) - return + CRASH("[src] does not have DNA") var/mutation = pick(candidates) . = dna.add_mutation(mutation) -/mob/living/carbon/proc/easy_randmut(quality = POSITIVE + NEGATIVE + MINOR_NEGATIVE, scrambled = TRUE, sequence = TRUE, exclude_monkey = TRUE) +/mob/living/carbon/proc/easy_random_mutate(quality = POSITIVE + NEGATIVE + MINOR_NEGATIVE, scrambled = TRUE, sequence = TRUE, exclude_monkey = TRUE) if(!has_dna()) - return + CRASH("[src] does not have DNA") var/list/mutations = list() if(quality & POSITIVE) mutations += GLOB.good_mutations @@ -537,37 +737,47 @@ HM.scrambled = TRUE return TRUE -/mob/living/carbon/proc/randmuti() +/mob/living/carbon/proc/random_mutate_unique_identity() if(!has_dna()) - return + CRASH("[src] does not have DNA") var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS) - var/newdna = setblock(dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) - dna.uni_identity = newdna + dna.set_uni_feature_block(num, random_string(GET_UI_BLOCK_LEN(num), GLOB.hex_characters)) updateappearance(mutations_overlay_update=1) +/mob/living/carbon/proc/random_mutate_unique_features() + if(!has_dna()) + CRASH("[src] does not have DNA") + var/num = rand(1, DNA_FEATURE_BLOCKS) + dna.set_uni_feature_block(num, random_string(GET_UF_BLOCK_LEN(num), GLOB.hex_characters)) + updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE) + /mob/living/carbon/proc/clean_dna() if(!has_dna()) - return + CRASH("[src] does not have DNA") dna.remove_all_mutations() -/mob/living/carbon/proc/clean_randmut(list/candidates, difficulty = 2) +/mob/living/carbon/proc/clean_random_mutate(list/candidates, difficulty = 2) clean_dna() - randmut(candidates, difficulty) + random_mutate(candidates, difficulty) -/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability) +/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, uf=FALSE, probability) if(!M.has_dna()) - return 0 + CRASH("[M] does not have DNA") if(se) for(var/i=1, i<=DNA_MUTATION_BLOCKS, i++) if(prob(probability)) M.dna.generate_dna_blocks() M.domutcheck() if(ui) - for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) + for(var/blocknum in 1 to DNA_UNI_IDENTITY_BLOCKS) + if(prob(probability)) + M.dna.set_uni_feature_block(blocknum, random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters)) + if(uf) + for(var/blocknum in 1 to DNA_FEATURE_BLOCKS) if(prob(probability)) - M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) - M.updateappearance(mutations_overlay_update=1) - return 1 + M.dna.set_uni_feature_block(blocknum, random_string(GET_UF_BLOCK_LEN(blocknum), GLOB.hex_characters)) + if(ui || uf) + M.updateappearance(mutcolor_update=uf, mutations_overlay_update=1) //value in range 1 to values. values must be greater than 0 //all arguments assumed to be positive integers @@ -586,6 +796,12 @@ value = values return value +/proc/get_uni_identity_block(identity, blocknum) + return copytext(identity, GLOB.total_ui_len_by_block[blocknum], LAZYACCESS(GLOB.total_ui_len_by_block, blocknum+1)) + +/proc/get_uni_feature_block(features, blocknum) + return copytext(features, GLOB.total_uf_len_by_block[blocknum], LAZYACCESS(GLOB.total_uf_len_by_block, blocknum+1)) + /////////////////////////// DNA HELPER-PROCS /mob/living/carbon/human/proc/something_horrible(ignore_stability) diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index 1543df3d7b73..fea91f7f2b65 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -37,12 +37,15 @@ to_chat(owner, text_gain_indication) var/mob/new_mob if(prob(95)) - if(prob(50)) - new_mob = owner.easy_randmut(NEGATIVE + MINOR_NEGATIVE) - else - new_mob = owner.randmuti() + switch(rand(1,3)) + if(1) + new_mob = owner.easy_random_mutate(NEGATIVE + MINOR_NEGATIVE) + if(2) + new_mob = owner.random_mutate_unique_identity() + if(3) + new_mob = owner.random_mutate_unique_features() else - new_mob = owner.easy_randmut(POSITIVE) + new_mob = owner.easy_random_mutate(POSITIVE) if(new_mob && ismob(new_mob)) owner = new_mob . = owner @@ -195,6 +198,7 @@ var/obj/effect/dummy/luminescent_glow/glowth //shamelessly copied from luminescents var/glow = 3.5 var/range = 2.5 + var/glow_color var/current_nullify_timer // For veil yogstation\code\modules\antagonists\shadowling\shadowling_abilities.dm power_coeff = 1 conflicts = list(/datum/mutation/human/glow/anti) @@ -203,6 +207,7 @@ . = ..() if(.) return + glow_color = owner.dna.features["mcolor"] glowth = new(owner) modify() @@ -210,19 +215,8 @@ /datum/mutation/human/glow/modify() if(!glowth) return - - var/glow_color - - if(owner.dna.features["mcolor"][1] != "#") - //if it doesn't start with a pound, it needs that for the color - glow_color += "#" - if(length(owner.dna.features["mcolor"]) < 6) - //this atrocity converts shorthand hex rgb back into full hex that's required for light to be given a functional value - glow_color += owner.dna.features["mcolor"][1] + owner.dna.features["mcolor"][1] + owner.dna.features["mcolor"][2] + owner.dna.features["mcolor"][2] + owner.dna.features["mcolor"][3] + owner.dna.features["mcolor"][3] - else - glow_color += owner.dna.features["mcolor"] - - glowth.set_light_range_power_color(range * GET_MUTATION_POWER(src), glow, glow_color) + var/power = GET_MUTATION_POWER(src) + glowth.set_light_range_power_color(range * power, glow * power, glow_color) /datum/mutation/human/glow/on_losing(mob/living/carbon/human/owner) . = ..() diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index 1bf5b8e0c257..1bb19fd951ab 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -36,12 +36,13 @@ var/mob/living/carbon/human/H = L if(H.dna && !HAS_TRAIT(H, TRAIT_GENELESS)) if(prob(max(0,100-resist))) - H.randmuti() + H.random_mutate_unique_identity() + H.random_mutate_unique_features() if(prob(50)) if(prob(90)) - H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) + H.easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) else - H.easy_randmut(POSITIVE) + H.easy_random_mutate(POSITIVE) H.domutcheck() L.rad_act(20) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index bf8621f5ef17..298aac00fe45 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -237,9 +237,9 @@ GLOBAL_VAR_INIT(clones, 0) var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations) H.dna.remove_mutation_group(unclean_mutations) if(efficiency > 5 && prob(20)) - H.easy_randmut(POSITIVE) + H.easy_random_mutate(POSITIVE) if(efficiency < 3 && prob(50)) - var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) + var/mob/M = H.easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) if(ismob(M)) H = M if((AGENDER || MGENDER || FGENDER) in H.dna.species.species_traits) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index f2de6d295cd9..625f67c8aa5f 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -554,7 +554,7 @@ R.fields["name"] = mob_occupant.real_name R.fields["id"] = copytext_char(md5(mob_occupant.real_name), 2, 6) R.fields["UE"] = dna.unique_enzymes - R.fields["UI"] = dna.uni_identity + R.fields["UI"] = dna.unique_identity R.fields["SE"] = dna.mutation_index R.fields["blood_type"] = dna.blood_type R.fields["features"] = dna.features @@ -594,7 +594,7 @@ var/datum/data/record/old_record = find_record("mindref", REF(mob_occupant.mind), records) if(body_only) old_record = find_record("UE", dna.unique_enzymes, records) //Body-only records cannot be identified by mind, so we use the DNA - if(old_record && ((old_record.fields["UI"] != dna.uni_identity) || (!old_record.fields["body_only"]))) //Never overwrite a mind-and-body record if it exists + if(old_record && ((old_record.fields["UI"] != dna.unique_identity) || (!old_record.fields["body_only"]))) //Never overwrite a mind-and-body record if it exists old_record = null if(old_record) records -= old_record diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index ea57402f9c34..7de000c1102d 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -34,6 +34,11 @@ /// Flag for the mutation ref search system. Search will include advanced injector mutations #define SEARCH_ADV_INJ 8 +#define ENZYME_COPY_BASE_COOLDOWN (60 SECONDS) + +#define RAD_PULSE_UNIQUE_IDENTITY "ui" +#define RAD_PULSE_UNIQUE_FEATURES "uf" + /obj/machinery/computer/scan_consolenew name = "DNA Console" desc = "Scan DNA." @@ -90,7 +95,11 @@ var/rad_pulse_index = 0 /// World time when the enzyme pulse should complete var/rad_pulse_timer = 0 - + /// Which dna string to edit with the pulse + var/rad_pulse_type + /// Cooldown for the genetic makeup transfer actions. + COOLDOWN_DECLARE(enzyme_copy_timer) + /// Used for setting tgui data - Whether the connected DNA Scanner is usable var/can_use_scanner = FALSE /// Used for setting tgui data - Whether the current DNA Scanner occupant is viable for genetic modification @@ -139,7 +148,7 @@ // This is for pulsing the UI element with radiation as part of genetic makeup // If rad_pulse_index > 0 then it means we're attempting a rad pulse - if((rad_pulse_index > 0) && (rad_pulse_timer <= world.time)) + if(((rad_pulse_index > 0) && (rad_pulse_timer <= world.time) && (rad_pulse_type == RAD_PULSE_UNIQUE_IDENTITY || rad_pulse_type == RAD_PULSE_UNIQUE_FEATURES))) rad_pulse() return @@ -290,7 +299,8 @@ data["subjectRads"] = scanner_occupant.radiation/(RAD_MOB_SAFE/100) data["subjectEnzymes"] = scanner_occupant.dna.unique_enzymes data["isMonkey"] = ismonkey(scanner_occupant) - data["subjectUNI"] = scanner_occupant.dna.uni_identity + data["subjectUNI"] = scanner_occupant.dna.unique_identity + data["subjectUF"] = scanner_occupant.dna.unique_features data["storage"]["occupant"] = tgui_occupant_mutations //data["subjectMutations"] = tgui_occupant_mutations else @@ -490,12 +500,12 @@ // X to allow highlighting logic to work on the tgui interface. if(newgene == "X") var/defaultseq = scanner_occupant.dna.default_mutation_genes[path] - defaultseq = copytext_char(defaultseq, 1, genepos) + newgene + copytext_char(defaultseq, genepos + 1) + defaultseq = copytext(defaultseq, 1, genepos) + newgene + copytext(defaultseq, genepos + 1) scanner_occupant.dna.default_mutation_genes[path] = defaultseq // Copy genome to scanner occupant and do some basic mutation checks as // we've increased the occupant rads - sequence = copytext_char(sequence, 1, genepos) + newgene + copytext_char(sequence, genepos + 1) + sequence = copytext(sequence, 1, genepos) + newgene + copytext(sequence, genepos + 1) scanner_occupant.dna.mutation_index[path] = sequence scanner_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER/connected_scanner.damage_coeff scanner_occupant.domutcheck() @@ -1003,8 +1013,9 @@ // Set the new information genetic_makeup_buffer[buffer_index] = list( "label"="Slot [buffer_index]:[scanner_occupant.real_name]", - "UI"=scanner_occupant.dna.uni_identity, + "UI"=scanner_occupant.dna.unique_identity, "UE"=scanner_occupant.dna.unique_enzymes, + "UF"=scanner_occupant.dna.unique_features, "name"=scanner_occupant.real_name, "blood_type"=scanner_occupant.dna.blood_type) @@ -1051,6 +1062,7 @@ // Expected results: // "ue" - Unique Enzyme, changes name and blood type // "ui" - Unique Identity, changes looks + // "uf" - Unique Features, changes mutant bodyparts and mutcolors // "mixed" - Combination of both ue and ui if("makeup_injector") // Convert the index to a number and clamp within the array range, then @@ -1094,6 +1106,21 @@ I = new /obj/item/dnainjector/timed(loc) I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"]) + // If there is a connected scanner, we can use its upgrades to reduce + // the radiation generated by this injector + if(scanner_operational()) + I.damage_coeff = connected_scanner.damage_coeff + if("uf") + // GUARD CHECK - There's currently no way to save partial genetic data. + // However, if this is the case, we can't make a complete injector and + // this catches that edge case + if(!buffer_slot["name"] || !buffer_slot["UF"] || !buffer_slot["blood_type"]) + to_chat(usr,"Genetic data corrupted, unable to create injector.") + return + + I = new /obj/item/dnainjector/timed(loc) + I.fields = list("name"=buffer_slot["name"], "UF"=buffer_slot["UF"]) + // If there is a connected scanner, we can use its upgrades to reduce // the radiation generated by this injector if(scanner_operational()) @@ -1102,12 +1129,12 @@ // GUARD CHECK - There's currently no way to save partial genetic data. // However, if this is the case, we can't make a complete injector and // this catches that edge case - if(!buffer_slot["UI"] || !buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"]) + if(!buffer_slot["UI"] || !buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["UF"] || !buffer_slot["blood_type"]) to_chat(usr,span_warning("Genetic data corrupted, unable to create injector.")) return I = new /obj/item/dnainjector/timed(loc) - I.fields = list("UI"=buffer_slot["UI"],"name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"]) + I.fields = list("UI"=buffer_slot["UI"],"name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "UF"=buffer_slot["UF"], "blood_type"=buffer_slot["blood_type"]) // If there is a connected scanner, we can use its upgrades to reduce // the radiation generated by this injector @@ -1130,6 +1157,7 @@ // Expected results: // "ue" - Unique Enzyme, changes name and blood type // "ui" - Unique Identity, changes looks + // "uf" - Unique Features, changes mutant bodyparts and mutcolors // "mixed" - Combination of both ue and ui if("makeup_apply") // GUARD CHECK - Can we genetically modify the occupant? Includes scanner @@ -1167,6 +1195,7 @@ // Expected results: // "ue" - Unique Enzyme, changes name and blood type // "ui" - Unique Identity, changes looks + // "uf" - Unique Features, changes mutant bodyparts and mutcolors // "mixed" - Combination of both ue and ui if("makeup_delay") // Convert the index to a number and clamp within the array range, then @@ -1190,6 +1219,10 @@ // Attempts to modify the indexed element of the Unique Identity string // This is a time delayed action that is handled in process() // ---------------------------------------------------------------------- // + // params["type"] - Type of genetic makeup string to edit + // Expected results: + // "ui" - Unique Identity, changes looks + // "uf" - Unique Features, changes mutant bodyparts and mutcolors // params["index"] - The BYOND index of the Unique Identity string to // attempt to modify if("makeup_pulse") @@ -1198,9 +1231,16 @@ if(!can_modify_occupant()) return - // Set the appropriate timer and index to pulse. This is then managed + // Set the appropriate timer, string, and index to pulse. This is then managed // later on in process() - var/len = length_char(scanner_occupant.dna.uni_identity) + var/type = params["type"] + rad_pulse_type = type + var/len + switch(type) + if("ui") + len = length(scanner_occupant.dna.unique_identity) + if("uf") + len = length(scanner_occupant.dna.unique_features) rad_pulse_timer = world.time + (radduration*10) rad_pulse_index = WRAP(text2num(params["index"]), 1, len+1) begin_processing() @@ -1425,11 +1465,24 @@ if(!buffer_slot["UI"]) to_chat(usr,span_warning("Genetic data corrupted, unable to apply genetic data.")) return FALSE - scanner_occupant.dna.uni_identity = buffer_slot["UI"] + scanner_occupant.dna.unique_identity = buffer_slot["UI"] scanner_occupant.updateappearance(mutations_overlay_update=1) scanner_occupant.radiation += rad_increase scanner_occupant.domutcheck() return TRUE + if("uf") + // GUARD CHECK - There's currently no way to save partial genetic data. + // However, if this is the case, we can't make a complete injector and + // this catches that edge case + if(!buffer_slot["UF"]) + to_chat(usr,"Genetic data corrupted, unable to apply genetic data.") + return FALSE + COOLDOWN_START(src, enzyme_copy_timer, ENZYME_COPY_BASE_COOLDOWN) + scanner_occupant.dna.unique_features = buffer_slot["UF"] + scanner_occupant.updateappearance(mutcolor_update=1, mutations_overlay_update=1) + scanner_occupant.radiation += rad_increase + scanner_occupant.domutcheck() + return TRUE if("ue") // GUARD CHECK - There's currently no way to save partial genetic data. // However, if this is the case, we can't make a complete injector and @@ -1437,6 +1490,7 @@ if(!buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"]) to_chat(usr,span_warning("Genetic data corrupted, unable to apply genetic data.")) return FALSE + COOLDOWN_START(src, enzyme_copy_timer, ENZYME_COPY_BASE_COOLDOWN) scanner_occupant.real_name = buffer_slot["name"] scanner_occupant.name = buffer_slot["name"] scanner_occupant.dna.unique_enzymes = buffer_slot["UE"] @@ -1448,11 +1502,13 @@ // GUARD CHECK - There's currently no way to save partial genetic data. // However, if this is the case, we can't make a complete injector and // this catches that edge case - if(!buffer_slot["UI"] || !buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"]) + if(!buffer_slot["UI"] || !buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["UF"] || !buffer_slot["blood_type"]) to_chat(usr,span_warning("Genetic data corrupted, unable to apply genetic data.")) return FALSE - scanner_occupant.dna.uni_identity = buffer_slot["UI"] - scanner_occupant.updateappearance(mutations_overlay_update=1) + COOLDOWN_START(src, enzyme_copy_timer, ENZYME_COPY_BASE_COOLDOWN) + scanner_occupant.dna.unique_identity = buffer_slot["UI"] + scanner_occupant.dna.unique_features = buffer_slot["UF"] + scanner_occupant.updateappearance(mutcolor_update=1, mutations_overlay_update=1) scanner_occupant.real_name = buffer_slot["name"] scanner_occupant.name = buffer_slot["name"] scanner_occupant.dna.unique_enzymes = buffer_slot["UE"] @@ -1944,20 +2000,36 @@ // GUARD CHECK - Can we genetically modify the occupant? Includes scanner // operational guard checks. // If we can't, abort the procedure. - if(!can_modify_occupant()) + if(!can_modify_occupant()|| (rad_pulse_type != RAD_PULSE_UNIQUE_IDENTITY && rad_pulse_type != RAD_PULSE_UNIQUE_FEATURES)) rad_pulse_index = 0 end_processing() return - var/len = length_char(scanner_occupant.dna.uni_identity) + var/len + switch(rad_pulse_type) + if(RAD_PULSE_UNIQUE_IDENTITY) + len = length(scanner_occupant.dna.unique_identity) + if(RAD_PULSE_UNIQUE_FEATURES) + len = length(scanner_occupant.dna.unique_features) + var/num = randomize_radiation_accuracy(rad_pulse_index, radduration + (connected_scanner.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2 //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low - var/hex = copytext_char(scanner_occupant.dna.uni_identity, num, num+1) + var/hex + switch(rad_pulse_type) + if(RAD_PULSE_UNIQUE_IDENTITY) + hex = copytext(scanner_occupant.dna.unique_identity, num, num+1) + if(RAD_PULSE_UNIQUE_FEATURES) + hex = copytext(scanner_occupant.dna.unique_features, num, num+1) hex = scramble(hex, radstrength, radduration) - scanner_occupant.dna.uni_identity = copytext_char(scanner_occupant.dna.uni_identity, 1, num) + hex + copytext_char(scanner_occupant.dna.uni_identity, num + 1) - scanner_occupant.updateappearance(mutations_overlay_update=1) + switch(rad_pulse_type) + if(RAD_PULSE_UNIQUE_IDENTITY) + scanner_occupant.dna.unique_identity = copytext(scanner_occupant.dna.unique_identity, 1, num) + hex + copytext(scanner_occupant.dna.unique_identity, num + 1) + if(RAD_PULSE_UNIQUE_FEATURES) + scanner_occupant.dna.unique_features = copytext(scanner_occupant.dna.unique_features, 1, num) + hex + copytext(scanner_occupant.dna.unique_features, num + 1) + scanner_occupant.updateappearance(mutcolor_update=1, mutations_overlay_update=1) rad_pulse_index = 0 + rad_pulse_type = null end_processing() return diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm index 29d959fea8ae..00fe2a5bc253 100644 --- a/code/game/machinery/exp_cloner.dm +++ b/code/game/machinery/exp_cloner.dm @@ -26,9 +26,9 @@ var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations) H.dna.remove_mutation_group(unclean_mutations) if(efficiency > 5 && prob(20)) - H.easy_randmut(POSITIVE) + H.easy_random_mutate(POSITIVE) if(efficiency < 3 && prob(50)) - var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) + var/mob/M = H.easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) if(ismob(M)) H = M @@ -298,6 +298,6 @@ temp = "Cloning cycle already in progress." playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) else - pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, clone_species, dna.features, mob_occupant.faction) + pod.growclone(mob_occupant.real_name, dna.unique_identity, dna.mutation_index, null, null, clone_species, dna.features, mob_occupant.faction) temp = "[mob_occupant.real_name] => Cloning data sent to pod." playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm index 16f24abb5e66..575b113d92c6 100644 --- a/code/game/objects/items/cosmetics.dm +++ b/code/game/objects/items/cosmetics.dm @@ -262,7 +262,7 @@ 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 + 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 diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index 5b82cf6d7ef2..6bc297d91ea4 100644 --- a/code/game/objects/items/dna_injector.dm +++ b/code/game/objects/items/dna_injector.dm @@ -41,8 +41,11 @@ M.name = M.real_name M.dna.blood_type = fields["blood_type"] if(fields["UI"]) //UI+UE - M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"]) - M.updateappearance(mutations_overlay_update=1) + M.dna.unique_identity = merge_text(M.dna.unique_identity, fields["UI"]) + if(fields["UF"]) + M.dna.unique_features = merge_text(M.dna.unique_features, fields["UF"]) + if(fields["UI"] || fields["UF"]) + M.updateappearance(mutcolor_update=1, mutations_overlay_update=1) log_attack("[log_msg] [loc_name(user)]") return TRUE return FALSE @@ -505,10 +508,16 @@ M.dna.temporary_mutations[UE_CHANGED] = endtime if(fields["UI"]) //UI+UE if(!M.dna.previous["UI"]) - M.dna.previous["UI"] = M.dna.uni_identity - M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"]) - M.updateappearance(mutations_overlay_update=1) + M.dna.previous["UI"] = M.dna.unique_identity + M.dna.unique_identity = merge_text(M.dna.unique_identity, fields["UI"]) M.dna.temporary_mutations[UI_CHANGED] = endtime + if(fields["UF"]) //UI+UE + if(!M.dna.previous["UF"]) + M.dna.previous["UF"] = M.dna.unique_features + M.dna.unique_features = merge_text(M.dna.unique_features, fields["UF"]) + M.dna.temporary_mutations[UF_CHANGED] = endtime + if(fields["UI"] || fields["UF"]) + M.updateappearance(mutcolor_update=1, mutations_overlay_update=1) log_attack("[log_msg] [loc_name(user)]") return TRUE else diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 5dcb1d361bba..92c92d3ae602 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -39,7 +39,7 @@ /obj/structure/mirror/proc/preapply_choices(selectiontype, mob/living/carbon/human/H) switch(selectiontype) if(FACE_HAIR_COLOR) - var/new_hair_color = input(H, "Choose your face hair color", "Face Hair Color","#"+H.facial_hair_color) as color|null + var/new_hair_color = input(H, "Choose your face hair color", "Face Hair Color",H.facial_hair_color) as color|null if(!new_hair_color) return TRUE H.facial_hair_color = sanitize_hexcolor(new_hair_color) @@ -47,7 +47,7 @@ H.update_hair() return TRUE if(HAIR_COLOR) - var/new_hair_color = input(H, "Choose your hair color", "Hair Color","#"+H.hair_color) as color|null + var/new_hair_color = input(H, "Choose your hair color", "Hair Color",H.hair_color) as color|null if(!new_hair_color) return TRUE H.hair_color = sanitize_hexcolor(new_hair_color) @@ -185,7 +185,7 @@ . = ..() switch(selectiontype) if(EYE_COLOR) - var/new_eye_color = input(H, "Choose your eye color", "Eye Color","#"+H.eye_color) as color|null + var/new_eye_color = input(H, "Choose your eye color", "Eye Color",H.eye_color) as color|null if(!new_eye_color) return TRUE H.eye_color = sanitize_hexcolor(new_eye_color) @@ -204,12 +204,13 @@ H.mind.name = newname return TRUE if(MUTANT_COLOR) - var/new_mutantcolor = input(H, "Choose your skin color:", "Race change","#"+H.dna.features["mcolor"]) as color|null + var/new_mutantcolor = input(H, "Choose your skin color:", "Race change",H.dna.features["mcolor"]) as color|null if(!new_mutantcolor) return TRUE var/temp_hsv = RGBtoHSV(new_mutantcolor) - if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright + if(ReadHSV(temp_hsv)[3] >= ReadHSV("#3a3a3a")[3]) // mutantcolors must be bright H.dna.features["mcolor"] = sanitize_hexcolor(new_mutantcolor) + H.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) else to_chat(H, span_notice("Invalid color. Your color is not bright enough.")) H.update_body() diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index a2e6ba03b463..4aa999d19ab2 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -63,7 +63,7 @@ /turf/closed/indestructible/splashscreen name = "Space Station 13" - icon = 'icons/blank_title.png' + icon = 'icons/blanks/blank_title.png' icon_state = "" layer = FLY_LAYER bullet_bounce_sound = null diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index f1c69425f798..d75c7b3274eb 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -10,38 +10,38 @@ user << browse(create_panel_helper(create_mob_html), "window=create_mob;size=425x475") -/proc/randomize_human(mob/living/carbon/human/H) - H.gender = pick(MALE, FEMALE) - H.real_name = random_unique_name(H.gender) - H.name = H.real_name - H.underwear = random_underwear(H.gender) - H.skin_tone = random_skin_tone() - H.hair_style = random_hair_style(H.gender) - H.facial_hair_style = random_facial_hair_style(H.gender) - H.hair_color = random_short_color() - H.facial_hair_color = H.hair_color - H.eye_color = random_eye_color() - H.dna.blood_type = random_blood_type() +/proc/randomize_human(mob/living/carbon/human/human) + human.gender = pick(MALE, FEMALE) + human.real_name = human.dna?.species.random_name(human.gender) || random_unique_name(human.gender) + human.name = human.real_name + human.underwear = random_underwear(human.gender) + human.skin_tone = random_skin_tone() + human.hair_style = random_hair_style(human.gender) + human.facial_hair_style = random_facial_hair_style(human.gender) + human.hair_color = "#[random_color()]" + human.facial_hair_color = human.hair_color + human.eye_color = random_eye_color() + human.dna.blood_type = random_blood_type() // Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant. - H.dna.features["mcolor"] = random_short_color() - H.dna.features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] - H.dna.features["pretcolor"] = GLOB.color_list_preternis[pick(GLOB.color_list_preternis)] - H.dna.features["tail_lizard"] = pick(GLOB.tails_list_lizard) - H.dna.features["tail_polysmorph"] = pick(GLOB.tails_list_polysmorph) - H.dna.features["snout"] = pick(GLOB.snouts_list) - H.dna.features["horns"] = pick(GLOB.horns_list) - H.dna.features["frills"] = pick(GLOB.frills_list) - H.dna.features["spines"] = pick(GLOB.spines_list) - H.dna.features["body_markings"] = pick(GLOB.body_markings_list) - H.dna.features["moth_wings"] = pick(GLOB.moth_wings_list) - H.dna.features["teeth"] = pick(GLOB.teeth_list) - H.dna.features["dome"] = pick(GLOB.dome_list) - H.dna.features["dorsal_tubes"] = pick(GLOB.dorsal_tubes_list) - H.dna.features["ethereal_mark"] = pick(GLOB.ethereal_mark_list) - H.dna.features["pod_hair"] = pick(GLOB.pod_hair_list) - H.dna.features["pod_flower"] = GLOB.pod_flower_list[H.dna.features["pod_hair"]] + human.dna.features["mcolor"] = "#[random_color()]" + human.dna.features["ethcolor"] = GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)] + human.dna.features["pretcolor"] = GLOB.color_list_preternis[pick(GLOB.color_list_preternis)] + human.dna.features["tail_lizard"] = pick(GLOB.tails_list_lizard) + human.dna.features["tail_polysmorph"] = pick(GLOB.tails_list_polysmorph) + human.dna.features["snout"] = pick(GLOB.snouts_list) + human.dna.features["horns"] = pick(GLOB.horns_list) + human.dna.features["frills"] = pick(GLOB.frills_list) + human.dna.features["spines"] = pick(GLOB.spines_list) + human.dna.features["body_markings"] = pick(GLOB.body_markings_list) + human.dna.features["moth_wings"] = pick(GLOB.moth_wings_list) + human.dna.features["teeth"] = pick(GLOB.teeth_list) + human.dna.features["dome"] = pick(GLOB.dome_list) + human.dna.features["dorsal_tubes"] = pick(GLOB.dorsal_tubes_list) + human.dna.features["ethereal_mark"] = pick(GLOB.ethereal_mark_list) + human.dna.features["pod_hair"] = pick(GLOB.pod_hair_list) + human.dna.features["pod_flower"] = GLOB.pod_flower_list[human.dna.features["pod_hair"]] - H.update_body() - H.update_hair() - H.update_body_parts() + human.update_body() + human.update_hair() + human.update_body_parts() diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index a701a07d8372..6afba9e29fa4 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -248,7 +248,7 @@ dat += "" for(var/mob/living/carbon/human/H in GLOB.carbon_list) if(H.ckey) - dat += "" + dat += "" dat += "
NameFingerprints
[H][md5(H.dna.uni_identity)]
[H][md5(H.dna.unique_identity)]
" mob_user << browse(dat, "window=fingerprints;size=440x410") diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index fe1e488dfc13..a04e0abb7de1 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -251,6 +251,7 @@ randomize_human(owner) var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/gorilla, /datum/species/moth, /datum/species/fly)) // yogs -- gorilla people owner.set_species(species) + owner.dna.update_dna_identity() /obj/item/organ/heart/gland/ventcrawling true_name = "pliant cartilage enabler" diff --git a/code/modules/antagonists/bloodsuckers/powers/olfaction.dm b/code/modules/antagonists/bloodsuckers/powers/olfaction.dm index 066a975b56bf..1089d603dc9a 100644 --- a/code/modules/antagonists/bloodsuckers/powers/olfaction.dm +++ b/code/modules/antagonists/bloodsuckers/powers/olfaction.dm @@ -67,7 +67,7 @@ possible |= C if(IS_BLOODSUCKER(C)) // Bloodsuckers have no scent, and finding their lair with this during Sol would be OP continue - if(scents[md5(C.dna.uni_identity)] && !possible.Find(C)) + if(scents[md5(C.dna.unique_identity)] && !possible.Find(C)) var/datum/job/J = SSjob.GetJob(C.job) if(!J) J = new() diff --git a/code/modules/antagonists/bloodsuckers/powers/veil.dm b/code/modules/antagonists/bloodsuckers/powers/veil.dm index 6339c00ec4c9..00dc396f3817 100644 --- a/code/modules/antagonists/bloodsuckers/powers/veil.dm +++ b/code/modules/antagonists/bloodsuckers/powers/veil.dm @@ -68,7 +68,7 @@ user.skin_tone = random_skin_tone() user.hair_style = random_hair_style(user.gender) user.facial_hair_style = pick(random_facial_hair_style(user.gender), "Shaved") - user.hair_color = random_short_color() + user.hair_color = "#[random_color()]" user.facial_hair_color = user.hair_color user.underwear = random_underwear(user.gender) user.undershirt = random_undershirt(user.gender) diff --git a/code/modules/antagonists/creep/creep.dm b/code/modules/antagonists/creep/creep.dm index 910186ea92ee..dd2cb4b7c335 100644 --- a/code/modules/antagonists/creep/creep.dm +++ b/code/modules/antagonists/creep/creep.dm @@ -25,7 +25,7 @@ /datum/antagonist/obsessed/get_preview_icon() var/mob/living/carbon/human/dummy/consistent/victim_dummy = new - victim_dummy.hair_color = "b96" // Brown + victim_dummy.hair_color = "#bb9966" // Brown victim_dummy.hair_style = "Messy" victim_dummy.update_hair() diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm index e44f93d7628e..bc131a39933c 100644 --- a/code/modules/antagonists/devil/devil.dm +++ b/code/modules/antagonists/devil/devil.dm @@ -249,7 +249,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", H.underwear = "Nude" H.undershirt = "Nude" H.socks = "Nude" - H.dna.features["mcolor"] = "511" //A deep red + H.dna.features["mcolor"] = "#551111" //A deep red H.regenerate_icons() else //Did the devil get hit by a staff of transmutation? owner.current.color = "#501010" @@ -491,7 +491,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", H.underwear = "Nude" H.undershirt = "Nude" H.socks = "Nude" - H.dna.features["mcolor"] = "511" + H.dna.features["mcolor"] = "#551111" H.regenerate_icons() if(SOULVALUE >= TRUE_THRESHOLD) //Yes, BOTH this and the above if statement are to run if soulpower is high enough. var/mob/living/carbon/true_devil/A = new /mob/living/carbon/true_devil(targetturf) diff --git a/code/modules/antagonists/eldritch_cult/eldritch_transmutations.dm b/code/modules/antagonists/eldritch_cult/eldritch_transmutations.dm index 552a2b42a940..7c5f68a0130c 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_transmutations.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_transmutations.dm @@ -81,7 +81,7 @@ var/list/compiled_list = list() for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) - if(fingerprints[md5(H.dna.uni_identity)]) + if(fingerprints[md5(H.dna.unique_identity)]) compiled_list |= H if(compiled_list.len == 0) diff --git a/code/modules/antagonists/fugitive/fugitive_outfits.dm b/code/modules/antagonists/fugitive/fugitive_outfits.dm index 8219ad234158..b738c281a302 100644 --- a/code/modules/antagonists/fugitive/fugitive_outfits.dm +++ b/code/modules/antagonists/fugitive/fugitive_outfits.dm @@ -45,12 +45,12 @@ if(visualsOnly) return H.fully_replace_character_name(null,"Waldo") - H.eye_color = "000" + H.eye_color = "#000000" H.gender = MALE H.skin_tone = "caucasian3" H.hair_style = "Business Hair 3" H.facial_hair_style = "Shaved" - H.hair_color = "000" + H.hair_color = "#000000" H.facial_hair_color = H.hair_color var/list/no_drops = list() diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index fa3fdf8a3742..21f3fa748ce0 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -369,7 +369,7 @@ if(!length(prints)) return FALSE for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) - if(prints[md5(H.dna.uni_identity)]) + if(prints[md5(H.dna.unique_identity)]) possible |= H /obj/item/voodoo/proc/GiveHint(mob/victim,force=0) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 953e205b135d..8ba670c445a3 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -268,14 +268,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) if (isnull(requested_preference)) return FALSE - if (!istype(requested_preference, /datum/preference/color) \ - && !istype(requested_preference, /datum/preference/color_legacy) \ - ) + if (!istype(requested_preference, /datum/preference/color)) return FALSE var/default_value = read_preference(requested_preference.type) - if (istype(requested_preference, /datum/preference/color_legacy)) - default_value = expand_three_digit_color(default_value) + // Yielding var/new_color = input( diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index b90084afccc7..5184738932b2 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -440,32 +440,20 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) return data -/// A preference that represents an RGB color of something, crunched down to 3 hex numbers. -/// Was used heavily in the past, but doesn't provide as much range and only barely conserves space. -/datum/preference/color_legacy - abstract_type = /datum/preference/color_legacy - -/datum/preference/color_legacy/deserialize(input, datum/preferences/preferences) - return sanitize_hexcolor(input) - -/datum/preference/color_legacy/create_default_value() - return random_short_color() - -/datum/preference/color_legacy/is_valid(value) - var/static/regex/is_legacy_color = regex(@"^[0-9a-fA-F]{3}$") - return findtext(value, is_legacy_color) - /// A preference that represents an RGB color of something. /// Will give the value as 6 hex digits, without a hash. /datum/preference/color abstract_type = /datum/preference/color /datum/preference/color/deserialize(input, datum/preferences/preferences) - return sanitize_color(input) + return sanitize_hexcolor(input) /datum/preference/color/create_default_value() return random_color() +/datum/preference/color/serialize(input) + return sanitize_hexcolor(input) + /datum/preference/color/is_valid(value) return findtext(value, GLOB.is_color) diff --git a/code/modules/client/preferences/skin_tone.dm b/code/modules/client/preferences/skin_tone.dm index 70aebc3521ec..119fd6a86a31 100644 --- a/code/modules/client/preferences/skin_tone.dm +++ b/code/modules/client/preferences/skin_tone.dm @@ -14,7 +14,7 @@ var/list/to_hex = list() for (var/choice in get_choices()) var/hex_value = skintone2hex(choice) - var/list/hsl = rgb2num("#[hex_value]", COLORSPACE_HSL) + var/list/hsl = rgb2num(hex_value, COLORSPACE_HSL) to_hex[choice] = list( "lightness" = hsl[3], diff --git a/code/modules/client/preferences/species_features/basic.dm b/code/modules/client/preferences/species_features/basic.dm index 4eac89c6a6f3..5bd7f39ef2ca 100644 --- a/code/modules/client/preferences/species_features/basic.dm +++ b/code/modules/client/preferences/species_features/basic.dm @@ -2,7 +2,7 @@ var/list/values = possible_values_for_sprite_accessory_list(accessories) var/icon/head_icon = icon('icons/mob/human_parts_greyscale.dmi', "human_head_m") - head_icon.Blend("#[skintone2hex("caucasian1")]", ICON_MULTIPLY) + head_icon.Blend(skintone2hex("caucasian1"), ICON_MULTIPLY) for (var/name in values) var/datum/sprite_accessory/accessory = accessories[name] @@ -23,14 +23,14 @@ return values -/datum/preference/color_legacy/eye_color +/datum/preference/color/eye_color category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_key = "eye_color" savefile_identifier = PREFERENCE_CHARACTER relevant_species_trait = EYECOLOR unique = TRUE -/datum/preference/color_legacy/eye_color/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/eye_color/apply_to_human(mob/living/carbon/human/target, value) target.eye_color = value var/obj/item/organ/eyes/eyes_organ = target.getorgan(/obj/item/organ/eyes) @@ -39,7 +39,7 @@ eyes_organ.eye_color = value eyes_organ.old_eye_color = value -/datum/preference/color_legacy/eye_color/create_default_value() +/datum/preference/color/eye_color/create_default_value() return random_eye_color() @@ -58,13 +58,13 @@ target.hair_style = value -/datum/preference/color_legacy/hair_color +/datum/preference/color/hair_color category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_key = "hair_color" savefile_identifier = PREFERENCE_CHARACTER relevant_species_trait = HAIR -/datum/preference/color_legacy/hair_color/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/hair_color/apply_to_human(mob/living/carbon/human/target, value) target.hair_color = value @@ -83,13 +83,13 @@ target.facial_hair_style = value -/datum/preference/color_legacy/facial_hair_color +/datum/preference/color/facial_hair_color category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_key = "facial_hair_color" savefile_identifier = PREFERENCE_CHARACTER relevant_species_trait = FACEHAIR -/datum/preference/color_legacy/facial_hair_color/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/facial_hair_color/apply_to_human(mob/living/carbon/human/target, value) target.facial_hair_color = value @@ -109,11 +109,11 @@ return "None" -/datum/preference/color_legacy/hair_gradient +/datum/preference/color/hair_gradient category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_key = "feature_gradientcolor" savefile_identifier = PREFERENCE_CHARACTER relevant_species_trait = HAIR -/datum/preference/color_legacy/hair_gradient/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/hair_gradient/apply_to_human(mob/living/carbon/human/target, value) target.grad_color = value diff --git a/code/modules/client/preferences/species_features/ethereal.dm b/code/modules/client/preferences/species_features/ethereal.dm index cbdd949a8607..97af510186e9 100644 --- a/code/modules/client/preferences/species_features/ethereal.dm +++ b/code/modules/client/preferences/species_features/ethereal.dm @@ -24,7 +24,7 @@ var/color = GLOB.color_list_ethereal[name] var/icon/icon = new(ethereal_base) - icon.Blend("#[color]", ICON_MULTIPLY) + icon.Blend(color, ICON_MULTIPLY) values[name] = icon return values diff --git a/code/modules/client/preferences/species_features/ipc.dm b/code/modules/client/preferences/species_features/ipc.dm index 83119e191ca9..4cf06caed73b 100644 --- a/code/modules/client/preferences/species_features/ipc.dm +++ b/code/modules/client/preferences/species_features/ipc.dm @@ -12,14 +12,14 @@ target.dna.features["ipc_screen"] = value -/datum/preference/color_legacy/ipc_screen_color +/datum/preference/color/ipc_screen_color category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_key = "feature_ipc_screen_color" savefile_identifier = PREFERENCE_CHARACTER relevant_mutant_bodypart = "ipc_screen" unique = TRUE -/datum/preference/color_legacy/ipc_screen_color/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/ipc_screen_color/apply_to_human(mob/living/carbon/human/target, value) target.eye_color = value var/obj/item/organ/eyes/eyes_organ = target.getorgan(/obj/item/organ/eyes) @@ -43,14 +43,14 @@ target.dna.features["ipc_antenna"] = value -/datum/preference/color_legacy/ipc_antenna_color +/datum/preference/color/ipc_antenna_color category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_key = "feature_ipc_antenna_color" savefile_identifier = PREFERENCE_CHARACTER relevant_mutant_bodypart = "ipc_antenna" unique = TRUE -/datum/preference/color_legacy/ipc_antenna_color/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/ipc_antenna_color/apply_to_human(mob/living/carbon/human/target, value) target.hair_color = value diff --git a/code/modules/client/preferences/species_features/mutants.dm b/code/modules/client/preferences/species_features/mutants.dm index 0f8cfff73b68..eb6f1a8a045c 100644 --- a/code/modules/client/preferences/species_features/mutants.dm +++ b/code/modules/client/preferences/species_features/mutants.dm @@ -1,20 +1,20 @@ -/datum/preference/color_legacy/mutant_color +/datum/preference/color/mutant_color savefile_key = "feature_mcolor" savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_SECONDARY_FEATURES relevant_species_trait = MUTCOLORS -/datum/preference/color_legacy/mutant_color/create_default_value() +/datum/preference/color/mutant_color/create_default_value() return sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]") -/datum/preference/color_legacy/mutant_color/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/mutant_color/apply_to_human(mob/living/carbon/human/target, value) target.dna.features["mcolor"] = value -/datum/preference/color_legacy/mutant_color/is_valid(value) +/datum/preference/color/mutant_color/is_valid(value) if (!..(value)) return FALSE - if (is_color_dark(expand_three_digit_color(value), 22)) + if (is_color_dark(value, 22)) return FALSE return TRUE diff --git a/code/modules/client/preferences/species_features/pod.dm b/code/modules/client/preferences/species_features/pod.dm index 49459c63e791..e3fb89d54271 100644 --- a/code/modules/client/preferences/species_features/pod.dm +++ b/code/modules/client/preferences/species_features/pod.dm @@ -33,40 +33,40 @@ target.dna.features["pod_flower"] = value -/datum/preference/color_legacy/pod_hair_color +/datum/preference/color/pod_hair_color category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_key = "feature_pod_hair_color" savefile_identifier = PREFERENCE_CHARACTER relevant_mutant_bodypart = "pod_hair" unique = TRUE -/datum/preference/color_legacy/pod_hair_color/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/pod_hair_color/apply_to_human(mob/living/carbon/human/target, value) target.hair_color = value -/datum/preference/color_legacy/pod_hair_color/is_valid(value) +/datum/preference/color/pod_hair_color/is_valid(value) if (!..(value)) return FALSE - if (is_color_dark(expand_three_digit_color(value), 22)) + if (is_color_dark(value, 22)) return FALSE return TRUE -/datum/preference/color_legacy/pod_flower_color +/datum/preference/color/pod_flower_color category = PREFERENCE_CATEGORY_SECONDARY_FEATURES savefile_key = "feature_pod_flower_color" savefile_identifier = PREFERENCE_CHARACTER relevant_mutant_bodypart = "pod_flower" unique = TRUE -/datum/preference/color_legacy/pod_flower_color/apply_to_human(mob/living/carbon/human/target, value) +/datum/preference/color/pod_flower_color/apply_to_human(mob/living/carbon/human/target, value) target.facial_hair_color = value -/datum/preference/color_legacy/pod_flower_color/is_valid(value) +/datum/preference/color/pod_flower_color/is_valid(value) if (!..(value)) return FALSE - if (is_color_dark(expand_three_digit_color(value), 22)) + if (is_color_dark(value, 22)) return FALSE return TRUE diff --git a/code/modules/client/preferences/species_features/preternis.dm b/code/modules/client/preferences/species_features/preternis.dm index 8ad3c05a1400..a5af851c8855 100644 --- a/code/modules/client/preferences/species_features/preternis.dm +++ b/code/modules/client/preferences/species_features/preternis.dm @@ -24,7 +24,7 @@ var/color = GLOB.color_list_preternis[name] var/icon/icon = new(preternis_base) - icon.Blend("#[color]", ICON_MULTIPLY) + icon.Blend(color, ICON_MULTIPLY) values[name] = icon return values diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 0f9465fecbd8..dd07e425d30a 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -83,10 +83,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car migrate_character_to_tgui_prefs_menu() if (current_version < 41) - write_preference(GLOB.preference_entries[/datum/preference/color_legacy/pod_hair_color], read_preference(/datum/preference/color_legacy/hair_color)) - write_preference(GLOB.preference_entries[/datum/preference/color_legacy/ipc_antenna_color], read_preference(/datum/preference/color_legacy/hair_color)) - write_preference(GLOB.preference_entries[/datum/preference/color_legacy/pod_flower_color], read_preference(/datum/preference/color_legacy/facial_hair_color)) - write_preference(GLOB.preference_entries[/datum/preference/color_legacy/ipc_screen_color], read_preference(/datum/preference/color_legacy/eye_color)) + write_preference(GLOB.preference_entries[/datum/preference/color/pod_hair_color], read_preference(/datum/preference/color/hair_color)) + write_preference(GLOB.preference_entries[/datum/preference/color/ipc_antenna_color], read_preference(/datum/preference/color/hair_color)) + write_preference(GLOB.preference_entries[/datum/preference/color/pod_flower_color], read_preference(/datum/preference/color/facial_hair_color)) + write_preference(GLOB.preference_entries[/datum/preference/color/ipc_screen_color], read_preference(/datum/preference/color/eye_color)) + if(current_version < 42) + save_character() + to_chat(parent, span_userdanger(span_big("Color code has been reworked. Check all your character preferences, especially colors, before playing."))) /// checks through keybindings for outdated unbound keys and updates them /datum/preferences/proc/check_keybindings() diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 1967027f554d..7c433361c60d 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -347,7 +347,7 @@ return ..() var/mob/living/carbon/human/loc_human = loc if(!colored_before) - add_atom_colour("#[loc_human.eye_color]", FIXED_COLOUR_PRIORITY) + add_atom_colour(loc_human.eye_color, FIXED_COLOUR_PRIORITY) colored_before = TRUE return ..() @@ -357,7 +357,7 @@ var/mob/living/carbon/human/H = loc var/mutable_appearance/M = mutable_appearance('icons/mob/clothing/eyes/eyes.dmi', "blindfoldwhite") M.appearance_flags |= RESET_COLOR - M.color = "#[H.eye_color]" + M.color = H.eye_color . += M /obj/item/clothing/glasses/sunglasses/big diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm index ce4fb1278211..27ef90386171 100644 --- a/code/modules/clothing/head/collectable.dm +++ b/code/modules/clothing/head/collectable.dm @@ -114,7 +114,7 @@ if(!ishuman(loc)) return var/mob/living/carbon/human/loc_human = loc - add_atom_colour("#[loc_human.hair_color]", FIXED_COLOUR_PRIORITY) + add_atom_colour(loc_human.hair_color, FIXED_COLOUR_PRIORITY) /obj/item/clothing/head/collectable/rabbitears name = "collectable rabbit ears" diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 2a5b877123ee..93f3cac65d23 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -154,7 +154,7 @@ if(!ishuman(loc)) return var/mob/living/carbon/human/loc_human = loc - add_atom_colour("#[loc_human.hair_color]", FIXED_COLOUR_PRIORITY) + add_atom_colour(loc_human.hair_color, FIXED_COLOUR_PRIORITY) /obj/item/clothing/head/kitty/genuine desc = "A pair of kitty ears. A tag on the inside says \"Hand made from real cats.\"" @@ -271,7 +271,7 @@ /obj/item/clothing/head/wig/natural/equipped(mob/living/carbon/human/user, slot) . = ..() if(ishuman(user) && slot == ITEM_SLOT_HEAD) - hair_color = "#[user.hair_color]" + hair_color = user.hair_color update_appearance(UPDATE_ICON) user.update_inv_head() diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index ce806464ec2a..7e9e230f21fe 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -182,7 +182,7 @@ var/mob/living/carbon/human/H = A if(!H.gloves) - fingerprints += md5(H.dna.uni_identity) + fingerprints += md5(H.dna.unique_identity) else if(!ismob(A)) diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index ed31a3960fd5..036f976759cc 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -56,7 +56,7 @@ D = new virus_type() var/datum/disease/dnaspread/DS = D DS.strain_data["name"] = H.real_name - DS.strain_data["UI"] = H.dna.uni_identity + DS.strain_data["UI"] = H.dna.unique_identity DS.strain_data["SE"] = H.dna.mutation_index else D = new virus_type() diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index cacd4166a04f..5cba8e0e3f80 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -421,8 +421,8 @@ var/parentcolor = parent.atom_colours[FIXED_COLOUR_PRIORITY] SV.add_atom_colour(parentcolor, FIXED_COLOUR_PRIORITY) if(prob(mutativeness)) - var/datum/spacevine_mutation/randmut = pick(vine_mutations_list - SV.mutations) - randmut.add_mutation_to_vinepiece(SV) + var/datum/spacevine_mutation/random_mutate = pick(vine_mutations_list - SV.mutations) + random_mutate.add_mutation_to_vinepiece(SV) for(var/datum/spacevine_mutation/SM in SV.mutations) SM.on_birth(SV) diff --git a/code/modules/goals/station_goals/dna_vault.dm b/code/modules/goals/station_goals/dna_vault.dm index 4548ed43218e..903124d5e87a 100644 --- a/code/modules/goals/station_goals/dna_vault.dm +++ b/code/modules/goals/station_goals/dna_vault.dm @@ -112,10 +112,10 @@ //humans if(ishuman(target)) var/mob/living/carbon/human/H = target - if(dna[H.dna.uni_identity]) + if(dna[H.dna.unique_identity]) to_chat(user, span_notice("Humanoid data already present in local storage.")) return - dna[H.dna.uni_identity] = 1 + dna[H.dna.unique_identity] = 1 to_chat(user, span_notice("Humanoid data added to local storage.")) /obj/machinery/dna_vault diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index b7759d5de036..bc752d202c5b 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -1078,6 +1078,13 @@ GLOBAL_LIST_EMPTY(aide_list) switch(random) if(1) + to_chat(user, span_danger("Your appearance morphs to that of a very small humanoid ash dragon! You feel a little tougher, and fire now seems oddly comforting.")) + H.dna.features = list("mcolor" = "#A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Drake", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body", "legs" = "Digitigrade Legs") + H.set_species(/datum/species/lizard/draconid) + H.eye_color = "fee5a3" + H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK) + H.updateappearance() + if(2) to_chat(user, span_danger("Your flesh begins to melt! Miraculously, you seem fine otherwise.")) H.set_species(/datum/species/skeleton) if(2) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 12adf35f59db..9b751ea0fafa 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -229,7 +229,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) if(S) facial_hair_overlay = mutable_appearance(S.icon, "[S.icon_state]", -HAIR_LAYER) if(facial_hair_color) - facial_hair_overlay.color = "#" + facial_hair_color + facial_hair_overlay.color = facial_hair_color facial_hair_overlay.alpha = 200 add_overlay(facial_hair_overlay) if(hair_style) @@ -237,7 +237,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) if(S) hair_overlay = mutable_appearance(S.icon, "[S.icon_state]", -HAIR_LAYER) if(hair_color) - hair_overlay.color = "#" + hair_color + hair_overlay.color = hair_color hair_overlay.alpha = 200 add_overlay(hair_overlay) @@ -812,11 +812,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(HAIR in species.species_traits) hair_style = client.prefs.read_preference(/datum/preference/choiced/hairstyle) - hair_color = brighten_color(client.prefs.read_preference(/datum/preference/color_legacy/hair_color)) + hair_color = brighten_color(client.prefs.read_preference(/datum/preference/color/hair_color)) if(FACEHAIR in species.species_traits) facial_hair_style = client.prefs.read_preference(/datum/preference/choiced/facial_hairstyle) - facial_hair_color = brighten_color(client.prefs.read_preference(/datum/preference/color_legacy/facial_hair_color)) + facial_hair_color = brighten_color(client.prefs.read_preference(/datum/preference/color/facial_hair_color)) qdel(species) diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 7d9a68e290ac..214b9a49280a 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -77,7 +77,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) target.dna.initialize_dna(skip_index = TRUE) target.dna.features["body_markings"] = "None" target.dna.features["ears"] = "None" - target.dna.features["ethcolor"] = "EEEEEE" // white-ish + target.dna.features["ethcolor"] = COLOR_VERY_LIGHT_GRAY target.dna.features["frills"] = "None" target.dna.features["horns"] = "None" target.dna.features["mcolor"] = COLOR_VIBRANT_LIME diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 61777dccb0ca..cef26d570606 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -118,7 +118,7 @@ . += "Energy Charge: [round(SN.cell.charge/100)]%" . += "Smoke Bombs: \Roman [SN.s_bombs]" //Ninja status - . += "Fingerprints: [md5(dna.uni_identity)]" + . += "Fingerprints: [md5(dna.unique_identity)]" . += "Unique Identity: [dna.unique_enzymes]" . += "Overall Status: [stat > 1 ? "dead" : "[health]% healthy"]" . += "Nutrition Status: [nutrition]" diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index c470c772d655..78b8957a0e42 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -8,20 +8,20 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID blocks_emissive = EMISSIVE_BLOCK_UNIQUE //Hair colour and style - var/hair_color = "000" + var/hair_color = "#000000" var/hair_style = "Bald" ///Colour used for the hair gradient. - var/grad_color = "000" + var/grad_color = "#000000" ///Style used for the hair gradient. var/grad_style //Facial hair colour and style - var/facial_hair_color = "000" + var/facial_hair_color = "#000000" var/facial_hair_style = "Shaved" //Eye colour - var/eye_color = "000" + var/eye_color = "#000000" var/skin_tone = "caucasian1" //Skin tone diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 0638a4818837..da08336932d7 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -359,6 +359,20 @@ GLOBAL_LIST_EMPTY(features_by_species) new_lizard_tail.tail_type = C.dna.features["tail_lizard"] new_lizard_tail.spines = C.dna.features["spines"] + // if(tail && (!should_have_tail || replace_current)) + // tail.Remove(C,1) + // QDEL_NULL(tail) + // if(should_have_tail && !tail) + // tail = new mutanttail + // if(iscatperson(C)) + // tail.tail_type = C.dna.features["tail_human"] + // if(ispolysmorph(C)) + // tail.tail_type = C.dna.features["tail_polysmorph"] + // if(islizard(C)) + // var/obj/item/organ/tail/lizard/T = tail + // T.tail_type = C.dna.features["tail_lizard"] + // T.spines = C.dna.features["spines"] + // tail.Insert(C) used_neworgan = TRUE neworgan.Insert(C, TRUE, FALSE) @@ -562,13 +576,13 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!forced_colour) if(hair_color) if(hair_color == "mutcolor") - facial_overlay.color = "#" + H.dna.features["mcolor"] + facial_overlay.color = H.dna.features["mcolor"] else if(hair_color == "fixedmutcolor") - facial_overlay.color = "#[fixed_mut_color]" + facial_overlay.color = fixed_mut_color else - facial_overlay.color = "#" + hair_color + facial_overlay.color = hair_color else - facial_overlay.color = "#" + H.facial_hair_color + facial_overlay.color = H.facial_hair_color else facial_overlay.color = forced_colour @@ -625,13 +639,13 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!forced_colour) if(hair_color) if(hair_color == "mutcolor") - hair_overlay.color = "#" + H.dna.features["mcolor"] + hair_overlay.color = H.dna.features["mcolor"] else if(hair_color == "fixedmutcolor") - hair_overlay.color = "#[fixed_mut_color]" + hair_overlay.color = fixed_mut_color else - hair_overlay.color = "#" + hair_color + hair_overlay.color = hair_color else - hair_overlay.color = "#" + H.hair_color + hair_overlay.color = H.hair_color //Gradients grad_style = H.grad_style @@ -642,7 +656,7 @@ GLOBAL_LIST_EMPTY(features_by_species) var/icon/temp_hair = icon(hair_file, hair_state) temp.Blend(temp_hair, ICON_ADD) gradient_overlay.icon = temp - gradient_overlay.color = "#" + grad_color + gradient_overlay.color = grad_color else hair_overlay.color = forced_colour @@ -664,7 +678,7 @@ GLOBAL_LIST_EMPTY(features_by_species) //if you're working with sprite code i hope this helps because i wish i was dead now. S = GLOB.pod_hair_list[H.dna.features["pod_hair"]] if(S) - if(ReadHSV(RGBtoHSV(H.hair_color))[3] <= ReadHSV("#7F7F7F")[3]) + if(ReadHSV(RGBtoHSV(H.hair_color))[3] <= ReadHSV("#777777")[3]) H.hair_color = H.dna.species.default_color var/hair_state = S.icon_state var/hair_file = S.icon @@ -673,13 +687,13 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!forced_colour) if(hair_color) if(hair_color == "mutcolor") - hair_overlay.color = "#" + H.dna.features["mcolor"] + hair_overlay.color = H.dna.features["mcolor"] else if(hair_color == "fixedmutcolor") - hair_overlay.color = "#[fixed_mut_color]" + hair_overlay.color = fixed_mut_color else - hair_overlay.color = "#" + hair_color + hair_overlay.color = hair_color else - hair_overlay.color = "#" + H.hair_color + hair_overlay.color = H.hair_color hair_overlay.alpha = hair_alpha standing+=hair_overlay //var/mutable_appearance/pod_flower = mutable_appearance(GLOB.pod_flower_list[H.dna.features["pod_flower"]].icon, GLOB.pod_flower_list[H.dna.features["pod_flower"]].icon_state, -HAIR_LAYER) @@ -693,13 +707,13 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!forced_colour) if(hair_color) if(hair_color == "mutcolor") - flower_overlay.color = "#" + H.dna.features["mcolor"] + flower_overlay.color = H.dna.features["mcolor"] else if(hair_color == "fixedmutcolor") - flower_overlay.color = "#[fixed_mut_color]" + flower_overlay.color = fixed_mut_color else - flower_overlay.color = "#" + hair_color - else - flower_overlay.color = "#" + H.facial_hair_color + flower_overlay.color = hair_color + else + flower_overlay.color = H.facial_hair_color flower_overlay.alpha = hair_alpha standing += flower_overlay if(standing.len) @@ -1018,20 +1032,20 @@ GLOBAL_LIST_EMPTY(features_by_species) if(H.dna.check_mutation(HULK) || H.dna.check_mutation(ACTIVE_HULK)) //HULK GO FIRST accessory_overlay.color = "#00aa00" else if(fixed_mut_color) //Then fixed color if applicable - accessory_overlay.color = "#[fixed_mut_color]" + accessory_overlay.color = fixed_mut_color else //Then snowflake color - accessory_overlay.color = "#[H.dna.features["mcolor"]]" + accessory_overlay.color = H.dna.features["mcolor"] if(HAIR) if(hair_color == "mutcolor") - accessory_overlay.color = "#[H.dna.features["mcolor"]]" + accessory_overlay.color = H.dna.features["mcolor"] else if(hair_color == "fixedmutcolor") - accessory_overlay.color = "#[fixed_mut_color]" + accessory_overlay.color = fixed_mut_color else - accessory_overlay.color = "#[H.hair_color]" + accessory_overlay.color = H.hair_color if(FACEHAIR) - accessory_overlay.color = "#[H.facial_hair_color]" + accessory_overlay.color = H.facial_hair_color if(EYECOLOR) - accessory_overlay.color = "#[H.eye_color]" + accessory_overlay.color = H.eye_color else accessory_overlay.color = forced_colour standing += accessory_overlay @@ -1414,7 +1428,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(radiation > RAD_MOB_MUTATE) if(prob(1)) to_chat(H, span_danger("You mutate!")) - H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) + H.easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) H.emote("gasp") H.domutcheck() 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 44debbb969c5..efdd910521ab 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -4,7 +4,7 @@ default_color = "FFFFFF" species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH) - default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None") + default_features = list("mcolor" = "#FFFFFF", "tail_human" = "None", "ears" = "None", "wings" = "None") use_skintones = TRUE mutantbrain = /obj/item/organ/brain/dullahan mutanteyes = /obj/item/organ/eyes/dullahan diff --git a/code/modules/mob/living/carbon/human/species_types/eggpeople.dm b/code/modules/mob/living/carbon/human/species_types/eggpeople.dm index 04ef75465104..f31799f0ec0e 100644 --- a/code/modules/mob/living/carbon/human/species_types/eggpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/eggpeople.dm @@ -8,7 +8,7 @@ name = "Eggperson" id = "egg" say_mod = "blurbles" - fixed_mut_color = "FFE7C9" + fixed_mut_color = "#FFE7C9" offset_features = list(OFFSET_EARS = list(0,2), OFFSET_HEAD = list(0,2)) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID brutemod = EGG_MAXBRUTEMOD // not the toughest egg in the dozen (handled by the #defines above) diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index 3e5aae56dd8f..8db8f3ff3264 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -63,7 +63,7 @@ return var/mob/living/carbon/human/ethereal = C - default_color = "#[ethereal.dna.features["ethcolor"]]" + default_color = ethereal.dna.features["ethcolor"] r1 = GETREDPART(default_color) g1 = GETGREENPART(default_color) b1 = GETBLUEPART(default_color) @@ -83,22 +83,30 @@ return randname -/datum/species/ethereal/spec_updatehealth(mob/living/carbon/human/H) +/datum/species/ethereal/spec_updatehealth(mob/living/carbon/human/ethereal) . = ..() - if(H.stat != DEAD && !EMPeffect) - var/healthpercent = max(H.health, 0) / 100 + if(!ethereal_light) + return + if(default_color != ethereal.dna.features["ethcolor"]) + var/new_color = ethereal.dna.features["ethcolor"] + r1 = GETREDPART(new_color) + g1 = GETGREENPART(new_color) + b1 = GETBLUEPART(new_color) + if(ethereal.stat != DEAD && !EMPeffect) + var/healthpercent = max(ethereal.health, 0) / 100 var/light_range = 1 + (4 * healthpercent) + var/light_power = 1 + healthpercent if(!emageffect) current_color = rgb(r2 + ((r1-r2)*healthpercent), g2 + ((g1-g2)*healthpercent), b2 + ((b1-b2)*healthpercent)) - H.set_light(light_range + 1, 0.1, current_color)//this just controls actual view range, not the overlay - ethereal_light.set_light_range_power_color(light_range, healthpercent, current_color) + ethereal.set_light(light_range + 1, 0.1, current_color)//this just controls actual view range, not the overlay + ethereal_light.set_light_range_power_color(light_range, light_power, current_color) ethereal_light.set_light_on(TRUE) - fixed_mut_color = copytext_char(current_color, 2) + fixed_mut_color = current_color else - H.set_light(0) + ethereal.set_light(0) ethereal_light.set_light_on(FALSE) fixed_mut_color = rgb(128,128,128) - H.update_body() + ethereal.update_body() /datum/species/ethereal/spec_emp_act(mob/living/carbon/human/H, severity) .=..() diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index eee0b8b3acbc..26800f54fcf6 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -9,7 +9,7 @@ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE,HAS_TAIL) mutant_bodyparts = list("ears", "tail_human") - default_features = list("mcolor" = "FFF", "tail_human" = "Cat", "ears" = "Cat", "wings" = "None") + default_features = list("mcolor" = "#FFFFFF", "tail_human" = "Cat", "ears" = "Cat", "wings" = "None") rare_say_mod = list("meows"= 10) liked_food = SEAFOOD | DAIRY | MICE disliked_food = GROSS | RAW @@ -35,7 +35,7 @@ var/mob/living/carbon/human/H = C if(!pref_load) //Hah! They got forcefully purrbation'd. Force default felinid parts on them if they have no mutant parts in those areas! if(H.dna.features["tail_human"] == "None") - H.dna.features["tail_human"] = "Cat" + H.dna.features["tail_human"] = "Cat" if(H.dna.features["ears"] == "None") H.dna.features["ears"] = "Cat" if(H.dna.features["ears"] == "Cat") @@ -48,6 +48,8 @@ tail.Insert(H, drop_if_replaced = FALSE) else mutanttail = initial(old_species.mutanttail) + H.dna.update_uf_block(DNA_HUMAN_TAIL_BLOCK) + H.dna.update_uf_block(DNA_EARS_BLOCK) /datum/species/human/felinid/on_species_loss(mob/living/carbon/H, datum/species/new_species, pref_load) var/obj/item/organ/ears/cat/ears = H.getorgan(/obj/item/organ/ears/cat) @@ -64,7 +66,7 @@ // Go with default ears NE = new /obj/item/organ/ears NE.Insert(H, drop_if_replaced = FALSE) - + H.dna.update_uf_block(DNA_EARS_BLOCK) if(tail) var/obj/item/organ/tail/NT if(new_species && new_species.mutanttail) @@ -76,6 +78,8 @@ NT.Insert(H, drop_if_replaced = FALSE) else tail.Remove(H) + H.dna.update_uf_block(DNA_HUMAN_TAIL_BLOCK) + ///turn everyone into catgirls. Technically not girls specifically but you get the point. /proc/mass_purrbation() diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index c75df6cca1d5..b71a421c2f4b 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -21,7 +21,7 @@ // To prevent golem subtypes from overwhelming the odds when random species // changes, only the Random Golem type can be chosen limbs_id = "golem" - fixed_mut_color = "aaa" + fixed_mut_color = "#aaaaaa" swimming_component = /datum/component/swimming/golem var/info_text = "As an Iron Golem, you don't have any special traits." var/random_eligible = TRUE //If false, the golem subtype can't be made through golem mutation toxin @@ -82,7 +82,7 @@ id = "adamantine golem" meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine mutant_organs = list(/obj/item/organ/adamantine_resonator, /obj/item/organ/vocal_cords/adamantine) - fixed_mut_color = "4ed" + fixed_mut_color = "#44eedd" info_text = "As an Adamantine Golem, you possess special vocal cords allowing you to \"resonate\" messages to all golems. Your unique mineral makeup makes you immune to most types of magic." prefix = "Adamantine" special_names = null @@ -99,7 +99,7 @@ /datum/species/golem/plasma name = "Plasma Golem" id = "plasma golem" - fixed_mut_color = "a3d" + fixed_mut_color = "#aa33dd" meat = /obj/item/stack/ore/plasma //Can burn and takes damage from heat inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER) //no RESISTHEAT, NOFIRE @@ -159,7 +159,7 @@ name = "Diamond Golem" id = "diamond golem" limbs_id = "cr_golem" - fixed_mut_color = "0ff" + fixed_mut_color = "#00ffff" armor = 70 //up from 55 meat = /obj/item/stack/ore/diamond info_text = "As a Diamond Golem, you are more resistant than the average golem." @@ -170,7 +170,7 @@ /datum/species/golem/gold name = "Gold Golem" id = "gold golem" - fixed_mut_color = "cc0" + fixed_mut_color = "#cccc00" speedmod = 1 armor = 25 //down from 55 meat = /obj/item/stack/ore/gold @@ -182,7 +182,7 @@ /datum/species/golem/silver name = "Silver Golem" id = "silver golem" - fixed_mut_color = "ddd" + fixed_mut_color = "#dddddd" punchstunthreshold = 9 //60% chance, from 40% meat = /obj/item/stack/ore/silver info_text = "As a Silver Golem, your attacks have a higher chance of stunning. Being made of silver, your body is immune to most types of magic." @@ -201,7 +201,7 @@ /datum/species/golem/plasteel name = "Plasteel Golem" id = "plasteel golem" - fixed_mut_color = "bbb" + fixed_mut_color = "#bbbbbb" stunmod = 0.4 punchdamagelow = 12 punchdamagehigh = 21 @@ -229,7 +229,7 @@ /datum/species/golem/titanium name = "Titanium Golem" id = "titanium golem" - fixed_mut_color = "fff" + fixed_mut_color = "#ffffff" meat = /obj/item/stack/ore/titanium info_text = "As a Titanium Golem, you are immune to ash storms, and slightly more resistant to burn damage." burnmod = 0.9 @@ -248,7 +248,7 @@ /datum/species/golem/plastitanium name = "Plastitanium Golem" id = "plastitanium golem" - fixed_mut_color = "888" + fixed_mut_color = "#888888" meat = /obj/item/stack/ore/titanium info_text = "As a Plastitanium Golem, you are immune to both ash storms and lava, and slightly more resistant to burn damage." burnmod = 0.8 @@ -269,7 +269,7 @@ /datum/species/golem/alloy name = "Alien Alloy Golem" id = "alloy golem" - fixed_mut_color = "333" + fixed_mut_color = "#333333" meat = /obj/item/stack/sheet/mineral/abductor mutanttongue = /obj/item/organ/tongue/abductor speedmod = 1 //faster @@ -289,7 +289,7 @@ /datum/species/golem/wood name = "Wood Golem" id = "wood golem" - fixed_mut_color = "9E704B" + fixed_mut_color = "#9E704B" meat = /obj/item/stack/sheet/mineral/wood //Can burn and take damage from heat inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER) @@ -348,7 +348,7 @@ /datum/species/golem/uranium name = "Uranium Golem" id = "uranium golem" - fixed_mut_color = "7f0" + fixed_mut_color = "#77ff00" meat = /obj/item/stack/ore/uranium info_text = "As an Uranium Golem, your very touch burns and irradiates organic lifeforms. You don't hit as hard as most golems, though." attack_verb = "burn" @@ -395,7 +395,7 @@ /datum/species/golem/sand name = "Sand Golem" id = "sand golem" - fixed_mut_color = "ffdc8f" + fixed_mut_color = "#ffdc8f" meat = /obj/item/stack/ore/glass //this is sand armor = 0 burnmod = 3 //melts easily @@ -427,7 +427,7 @@ name = "Glass Golem" id = "glass golem" limbs_id = "cr_golem" - fixed_mut_color = "5a96b4aa" //transparent body + fixed_mut_color = "#5a96b4aa" //transparent body meat = /obj/item/shard armor = 0 brutemod = 3 //very fragile @@ -465,7 +465,7 @@ name = "Bluespace Golem" id = "bluespace golem" limbs_id = "cr_golem" - fixed_mut_color = "33f" + fixed_mut_color = "#3333ff" meat = /obj/item/stack/ore/bluespace_crystal info_text = "As a Bluespace Golem, you are spatially unstable: You will teleport when hit, and you can teleport manually at a long distance." attack_verb = "bluespace punch" @@ -558,7 +558,7 @@ /datum/species/golem/bananium name = "Bananium Golem" id = "bananium golem" - fixed_mut_color = "ff0" + fixed_mut_color = "#ffff00" say_mod = "honks" punchdamagelow = 0 punchdamagehigh = 1 @@ -876,7 +876,7 @@ id = "plastic golem" prefix = "Plastic" special_names = list("Sheet", "Bag", "Bottle") - fixed_mut_color = "fff" + fixed_mut_color = "#ffffff" info_text = "As a Plastic Golem, you are capable of ventcrawling and passing through plastic flaps as long as you are naked." /datum/species/golem/plastic/on_species_gain(mob/living/carbon/C, datum/species/old_species) @@ -892,7 +892,7 @@ id = "bronze golem" prefix = "Bronze" special_names = list("Bell") - fixed_mut_color = "cd7f32" + fixed_mut_color = "#cd7f32" info_text = "As a Bronze Golem, you are very resistant to loud noises, and make loud noises if something hard hits you, however this ability does hurt your hearing." special_step_sounds = list('sound/machines/clockcult/integration_cog_install.ogg', 'sound/magic/clockwork/fellowship_armory.ogg' ) mutantears = /obj/item/organ/ears/bronze @@ -1054,7 +1054,7 @@ special_names = list("Face", "Man", "Belt") //Ah dude 4 strength 4 stam leather belt AHHH inherent_traits = list(TRAIT_NOBREATH,TRAIT_NOHUNGER, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER, TRAIT_STRONG_GRABBER) prefix = "Leather" - fixed_mut_color = "624a2e" + fixed_mut_color = "#624a2e" info_text = "As a Leather Golem, you are flammable, but you can grab things with incredible ease, allowing all your grabs to start at a strong level." grab_sound = 'sound/weapons/whipgrab.ogg' attack_sound = 'sound/weapons/whip.ogg' @@ -1263,7 +1263,7 @@ /datum/species/golem/cheese name = "Cheese Golem" id = "cheese golem" - fixed_mut_color = "F1D127" + fixed_mut_color = "#F1D127" meat = /obj/item/stack/sheet/cheese inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER) armor = 10 @@ -1296,7 +1296,7 @@ /datum/species/golem/mhydrogen name = "Metallic Hydrogen Golem" id = "Metallic Hydrogen golem" - fixed_mut_color = "ddd" + fixed_mut_color = "#dddddd" info_text = "As a Metallic Hydrogen Golem, you were forged in the highest pressures and the highest heats. Your exotic makeup makes you tougher than diamond." prefix = "Hydrogen" stunmod = 0.6 //as opposed to plasteel's 0.4 @@ -1317,7 +1317,7 @@ name = "Telecrystal Golem" id = "telecrystal golem" limbs_id = "cr_golem" - fixed_mut_color = "e02828" + fixed_mut_color = "#e02828" speedmod = 1 //same as golden golem random_eligible = FALSE //too strong for a charged black extract info_text = "As a Telecrystal Golem, you are faster than an avarage golem. Being created out of telecrystal, a much stable but less powerful variation of bluespace, you possess the ability to make controlled short ranged phase jumps." 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 1ded8c94f9ad..f76826f86652 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -3,7 +3,7 @@ id = "human" default_color = "FFFFFF" species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) - default_features = list("mcolor" = "FFF", "wings" = "None") + default_features = list("mcolor" = "#FFFFFF", "wings" = "None") use_skintones = 1 skinned_type = /obj/item/stack/sheet/animalhide/human disliked_food = GROSS | RAW | MICE diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index b5ec23277559..fa28253d4d3b 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -258,7 +258,8 @@ spare.underwear = "Nude" H.dna.transfer_identity(spare, transfer_SE=1) - spare.dna.features["mcolor"] = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F") + spare.dna.features["mcolor"] = pick("#FFFFFF","#7F7F7F", "#7FFF7F", "#7F7FFF", "#FF7F7F", "#7FFFFF", "#FF7FFF", "#FFFF7F") + spare.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) spare.real_name = spare.dna.real_name spare.name = spare.dna.real_name spare.updateappearance(mutcolor_update=1) @@ -326,7 +327,7 @@ var/list/L = list() // HTML colors need a # prefix - L["htmlcolor"] = "#[body.dna.features["mcolor"]]" + L["htmlcolor"] = body.dna.features["mcolor"] L["area"] = get_area_name(body, TRUE) var/stat = "error" switch(body.stat) diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 9318f1be4cd1..eb7eba82caae 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -17,7 +17,7 @@ heatmod = 0.67 //greatly appreciate heat, just not too much action_speed_coefficient = 1.05 //claws aren't as dextrous as hands payday_modifier = 0.85 //Full SIC citizens, but not quite given all the same rights- it's been an ongoing process for about half a decade - default_features = list("mcolor" = "0F0", "tail_lizard" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs") + default_features = list("mcolor" = "#00FF00", "tail_lizard" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs") changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT attack_verb = "slash" attack_sound = 'sound/weapons/slash.ogg' @@ -262,7 +262,7 @@ name = "Draconid" id = "draconid" limbs_id = "lizard" - fixed_mut_color = "A02720" //Deep red + fixed_mut_color = "#A02720" //Deep red species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE,HAS_FLESH,HAS_BONE,HAS_TAIL) inherent_traits = list(TRAIT_RESISTHEAT) //Dragons like fire, not cold blooded because they generate fire inside themselves or something burnmod = 0.8 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 0710dd19d017..d2322ecdfb00 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -6,8 +6,8 @@ default_features = list("caps" = "Round") changesource_flags = MIRROR_BADMIN | WABBAJACK | ERT_SPAWN | SLIME_EXTRACT - fixed_mut_color = "DBBF92" - hair_color = "FF4B19" //cap color, spot color uses eye color + fixed_mut_color = "#DBBF92" + hair_color = "#FF4B19" //cap color, spot color uses eye color nojumpsuit = TRUE say_mod = "poofs" //what does a mushroom sound like diff --git a/code/modules/mob/living/carbon/human/species_types/polysmorphs.dm b/code/modules/mob/living/carbon/human/species_types/polysmorphs.dm index a24b2575ce75..e726fc6c1941 100644 --- a/code/modules/mob/living/carbon/human/species_types/polysmorphs.dm +++ b/code/modules/mob/living/carbon/human/species_types/polysmorphs.dm @@ -32,7 +32,7 @@ attack_verb = "slash" attack_sound = 'sound/weapons/slash.ogg' miss_sound = 'sound/weapons/slashmiss.ogg' - fixed_mut_color = "444466" //don't mess with this if you don't feel like manually adjusting the mutant bodypart sprites + fixed_mut_color = "#444466" //don't mess with this if you don't feel like manually adjusting the mutant bodypart sprites mutant_bodyparts = list("tail_polysmorph", "dome", "dorsal_tubes", "teeth", "legs") default_features = list("tail_polysmorph" = "Polys", "dome" = "None", "dorsal_tubes" = "No", "teeth" = "None", "legs" = "Normal Legs") changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT 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 34f07eb02c67..6c99aea2ecce 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -5,7 +5,7 @@ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID - default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None") + default_features = list("mcolor" = "#FFFFFF", "tail_human" = "None", "ears" = "None", "wings" = "None") changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | ERT_SPAWN exotic_bloodtype = "U" use_skintones = TRUE diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index d11b79ba9054..a27263a89f3c 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -371,11 +371,18 @@ if(dna.temporary_mutations[mut] < world.time) if(mut == UI_CHANGED) if(dna.previous["UI"]) - dna.uni_identity = merge_text(dna.uni_identity,dna.previous["UI"]) + dna.unique_identity = merge_text(dna.unique_identity,dna.previous["UI"]) updateappearance(mutations_overlay_update=1) dna.previous.Remove("UI") dna.temporary_mutations.Remove(mut) continue + if(mut == UF_CHANGED) + if(dna.previous["UF"]) + dna.unique_features = merge_text(dna.unique_features,dna.previous["UF"]) + updateappearance(mutcolor_update=1, mutations_overlay_update=1) + dna.previous.Remove("UF") + dna.temporary_mutations.Remove(mut) + continue if(mut == UE_CHANGED) if(dna.previous["name"]) real_name = dna.previous["name"] diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 874678a64a64..62429840e650 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -36,7 +36,7 @@ if(radiation > RAD_MOB_MUTATE) if(prob(1)) to_chat(src, span_danger("You mutate!")) - easy_randmut(NEGATIVE+MINOR_NEGATIVE) + easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) INVOKE_ASYNC(src, PROC_REF(emote), "gasp") domutcheck() diff --git a/code/modules/mob/living/simple_animal/friendly/gondola.dm b/code/modules/mob/living/simple_animal/friendly/gondola.dm index 98fff0c1faa5..c790b2264766 100644 --- a/code/modules/mob/living/simple_animal/friendly/gondola.dm +++ b/code/modules/mob/living/simple_animal/friendly/gondola.dm @@ -1,5 +1,5 @@ #define GONDOLA_HEIGHT pick("gondola_body_long", "gondola_body_medium", "gondola_body_short") -#define GONDOLA_COLOR pick("A87855", "915E48", "683E2C") +#define GONDOLA_COLOR pick("#A87855", "#915E48", "#683E2C") #define GONDOLA_MOUSTACHE pick("gondola_moustache_large", "gondola_moustache_small") #define GONDOLA_EYES pick("gondola_eyes_close", "gondola_eyes_far") @@ -40,7 +40,7 @@ var/mutable_appearance/body_overlay = mutable_appearance(icon, height) var/mutable_appearance/eyes_overlay = mutable_appearance(icon, GONDOLA_EYES) var/mutable_appearance/moustache_overlay = mutable_appearance(icon, GONDOLA_MOUSTACHE) - body_overlay.color = ("#[GONDOLA_COLOR]") + body_overlay.color = GONDOLA_COLOR //Offset the face to match the Gondola's height. switch(height) diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index cdb90cfd1447..eda44fa0086d 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -1005,11 +1005,10 @@ . = ..() if(iscarbon(target)) var/mob/living/carbon/X = target - X.randmuti() if(prob(66)) - X.easy_randmut(NEGATIVE) + X.easy_random_mutate(NEGATIVE) else - X.easy_randmut(MINOR_NEGATIVE) + X.easy_random_mutate(MINOR_NEGATIVE) /obj/item/projectile/magic/runic_resizement diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index d62674e71ed9..bcbfe1c6c9e0 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -480,7 +480,7 @@ newcolor += ascii2text(ascii+31) //letters B to F - translates to lowercase else break - if(ReadHSV(newcolor)[3] >= ReadHSV("#7F7F7F")[3]) + if(ReadHSV(newcolor)[3] >= ReadHSV("#777777")[3]) N.dna.features["mcolor"] = newcolor N.regenerate_icons() @@ -509,7 +509,7 @@ N.skin_tone = "orange" else if(MUTCOLORS in N.dna.species.species_traits) //Aliens with custom colors simply get turned orange saved_color = N.dna.features["mcolor"] - N.dna.features["mcolor"] = "f80" + N.dna.features["mcolor"] = "#FF8800" N.regenerate_icons() if(prob(7)) if(N.w_uniform) @@ -776,6 +776,7 @@ to_chat(H, span_warning("You grit your teeth in pain as your body rapidly mutates!")) H.visible_message("[H] suddenly transforms!") randomize_human(H) + H.dna.update_dna_identity() /datum/reagent/aslimetoxin name = "Advanced Mutation Toxin" diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 8664ae15b8c9..5a1dc3794e5e 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -37,11 +37,12 @@ if(!M.has_dna() || HAS_TRAIT(M, TRAIT_GENELESS) || HAS_TRAIT(M, TRAIT_BADDNA)) return //No robots, AIs, aliens, Ians or other mobs should be affected by this. if(((methods & VAPOR) && prob(min(33, reac_volume) * permeability)) || ((methods & (INGEST|PATCH|INJECT)) && reac_volume >= 5)) - M.randmuti() + M.random_mutate_unique_identity() + M.random_mutate_unique_features() if(prob(98)) - M.easy_randmut(NEGATIVE+MINOR_NEGATIVE) + M.easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) else - M.easy_randmut(POSITIVE) + M.easy_random_mutate(POSITIVE) M.updateappearance() M.domutcheck() ..() diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 256606f8fbeb..f7e409653d01 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -793,6 +793,7 @@ datum/status_effect/stabilized/blue/on_remove() originalname = H.real_name H.dna.copy_dna(originalDNA) randomize_human(H) + H.dna.update_dna_identity() return ..() /datum/status_effect/stabilized/green/tick() //Only occasionally give examiners a warning. diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 6ece919e6b8c..e8f2f4e25a04 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -622,7 +622,8 @@ /obj/item/slime_extract/rainbow/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type) switch(activation_type) if(SLIME_ACTIVATE_MINOR) - user.dna.features["mcolor"] = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F") + user.dna.features["mcolor"] = pick("#FFFFFF","#7F7F7F", "#7FFF7F", "#7F7FFF", "#FF7F7F", "#7FFFFF", "#FF7FFF", "#FFFF7F") + user.dna.update_uf_block(DNA_MUTANT_COLOR_BLOCK) user.updateappearance(mutcolor_update=1) species.update_glow(user) to_chat(user, span_notice("You feel different...")) diff --git a/code/modules/ruins/icemoonruin_code/hotsprings.dm b/code/modules/ruins/icemoonruin_code/hotsprings.dm index 83d851a5b381..f0a70f246f12 100644 --- a/code/modules/ruins/icemoonruin_code/hotsprings.dm +++ b/code/modules/ruins/icemoonruin_code/hotsprings.dm @@ -26,6 +26,7 @@ GLOBAL_LIST_EMPTY(cursed_minds) randomize_human(H) var/random_race = GLOB.species_list[pick(GLOB.roundstart_races)] H.set_species(random_race) + H.dna.update_dna_identity() var/list/valid_jobs = list() for(var/random_job in subtypesof(/datum/job)) var/datum/job/J = new random_job() diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 72b27353509b..c54f5d265680 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -825,7 +825,7 @@ species_color = "" if(!dropping_limb && (H.dna.check_mutation(HULK) || H.dna.check_mutation(ACTIVE_HULK))) - mutation_color = "00aa00" + mutation_color = "#00aa00" else mutation_color = "" @@ -937,9 +937,9 @@ if(should_draw_greyscale) var/draw_color = mutation_color || species_color || (skin_tone && skintone2hex(skin_tone)) if(draw_color) - limb.color = "#[draw_color]" + limb.color = "[draw_color]" if(aux_zone) - aux.color = "#[draw_color]" + aux.color = "[draw_color]" /obj/item/bodypart/deconstruct(disassembled = TRUE) drop_organs() diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 4c91f7f05811..6c972749a473 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -158,7 +158,7 @@ if(S.hair_color == "mutcolor") facial_hair_color = H.dna.features["mcolor"] else if(hair_color == "fixedmutcolor") - facial_hair_color = "#[S.fixed_mut_color]" + facial_hair_color = "[S.fixed_mut_color]" else facial_hair_color = S.hair_color else @@ -175,7 +175,7 @@ if(S.hair_color == "mutcolor") hair_color = H.dna.features["mcolor"] else if(hair_color == "fixedmutcolor") - hair_color = "#[S.fixed_mut_color]" + hair_color = "[S.fixed_mut_color]" else hair_color = S.hair_color else @@ -218,7 +218,7 @@ var/datum/sprite_accessory/S = GLOB.facial_hair_styles_list[facial_hair_style] if(S) var/image/facial_overlay = image(S.icon, "[S.icon_state]", -HAIR_LAYER, SOUTH) - facial_overlay.color = "#" + facial_hair_color + facial_overlay.color = facial_hair_color facial_overlay.alpha = hair_alpha . += facial_overlay @@ -239,7 +239,7 @@ var/datum/sprite_accessory/S2 = GLOB.hair_styles_list[hair_style] if(S2) var/image/hair_overlay = image(S2.icon, "[S2.icon_state]", -HAIR_LAYER, SOUTH) - hair_overlay.color = "#" + hair_color + hair_overlay.color = hair_color hair_overlay.alpha = hair_alpha . += hair_overlay @@ -257,7 +257,7 @@ eyes_overlay.icon_state = eyes.eye_icon_state if(eyes.eye_color) - eyes_overlay.color = "#" + eyes.eye_color + eyes_overlay.color = eyes.eye_color /obj/item/bodypart/head/monkey icon = 'icons/mob/animal_parts.dmi' diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index d92175d3a763..ef4cededf4d7 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -250,31 +250,31 @@ . = 0 switch(skin_tone) if("caucasian1") - . = "ffe0d1" + . = "#ffe0d1" if("caucasian2") - . = "fcccb3" + . = "#fcccb3" if("caucasian3") - . = "e8b59b" + . = "#e8b59b" if("latino") - . = "d9ae96" + . = "#d9ae96" if("mediterranean") - . = "c79b8b" + . = "#c79b8b" if("asian1") - . = "ffdeb3" + . = "#ffdeb3" if("asian2") - . = "e3ba84" + . = "#e3ba84" if("arab") - . = "c4915e" + . = "#c4915e" if("indian") - . = "b87840" + . = "#b87840" if("african1") - . = "754523" + . = "#754523" if("african2") - . = "471c18" + . = "#471c18" if("albino") - . = "fff4e6" + . = "#fff4e6" if("orange") - . = "ffc905" + . = "#ffc905" /mob/living/carbon/proc/Digitigrade_Leg_Swap(swap_back) var/body_plan_changed = FALSE diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 95ba02f89bbd..5c094ff10f69 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -98,7 +98,7 @@ var/list/overlays = list(eye_overlay) if((EYECOLOR in parent.dna.species.species_traits)) - eye_overlay.color = "#" + eye_color + eye_overlay.color = eye_color // Cry emote overlay if (HAS_TRAIT(parent, TRAIT_CRYING)) // Caused by the *cry emote diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm index fd6d99ce83b3..3c54f34d130e 100644 --- a/code/modules/surgery/organs/tails.dm +++ b/code/modules/surgery/organs/tails.dm @@ -8,6 +8,7 @@ zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_TAIL process_flags = ORGANIC | SYNTHETIC // pretty much entirely cosmetic, if someone wants to make crimes against nature then sure + /// The sprite accessory this tail gives to the human it's attached to. If null, it will inherit its value from the human's DNA once attached. var/tail_type = "None" /obj/item/organ/tail/Remove(mob/living/carbon/human/H, special = 0) @@ -26,10 +27,14 @@ /obj/item/organ/tail/cat/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = TRUE) ..() if(istype(H)) - if(!("tail_human" in H.dna.species.mutant_bodyparts)) - H.dna.species.mutant_bodyparts |= "tail_human" - H.dna.features["tail_human"] = tail_type - H.update_body() + var/default_part = H.dna.species.mutant_bodyparts["tail_human"] + if(!default_part || default_part == "None") + if(tail_type) + H.dna.features["tail_human"] = H.dna.species.mutant_bodyparts["tail_human"] = tail_type + H.dna.update_uf_block(DNA_HUMAN_TAIL_BLOCK) + else + H.dna.species.mutant_bodyparts["tail_human"] = H.dna.features["tail_human"] + H.update_body() /obj/item/organ/tail/cat/Remove(mob/living/carbon/human/H, special = 0) ..() @@ -50,13 +55,21 @@ ..() if(istype(H)) // Checks here are necessary so it wouldn't overwrite the tail of a lizard it spawned in - if(!("tail_lizard" in H.dna.species.mutant_bodyparts)) - H.dna.features["tail_lizard"] = tail_type - H.dna.species.mutant_bodyparts |= "tail_lizard" - - if(!("spines" in H.dna.species.mutant_bodyparts)) - H.dna.features["spines"] = spines - H.dna.species.mutant_bodyparts |= "spines" + var/default_part = H.dna.species.mutant_bodyparts["tail_lizard"] + if(!default_part || default_part == "None") + if(tail_type) + H.dna.features["tail_lizard"] = H.dna.species.mutant_bodyparts["tail_lizard"] = tail_type + H.dna.update_uf_block(DNA_LIZARD_TAIL_BLOCK) + else + H.dna.species.mutant_bodyparts["tail_lizard"] = H.dna.features["tail_lizard"] + + default_part = H.dna.species.mutant_bodyparts["spines"] + if(!default_part || default_part == "None") + if(spines) + H.dna.features["spines"] = H.dna.species.mutant_bodyparts["spines"] = spines + H.dna.update_uf_block(DNA_SPINES_BLOCK) + else + H.dna.species.mutant_bodyparts["spines"] = H.dna.features["spines"] H.update_body() /obj/item/organ/tail/lizard/Remove(mob/living/carbon/human/H, special = 0) @@ -64,7 +77,7 @@ if(istype(H)) H.dna.species.mutant_bodyparts -= "tail_lizard" H.dna.species.mutant_bodyparts -= "spines" - color = "#" + H.dna.features["mcolor"] + color = H.dna.features["mcolor"] tail_type = H.dna.features["tail_lizard"] spines = H.dna.features["spines"] H.update_body() @@ -82,9 +95,13 @@ /obj/item/organ/tail/polysmorph/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = FALSE) ..() if(istype(H)) - if(!("tail_polysmorph" in H.dna.species.mutant_bodyparts)) - H.dna.features["tail_polysmorph"] = tail_type - H.dna.species.mutant_bodyparts |= "tail_polysmorph" + var/default_part = H.dna.species.mutant_bodyparts["tail_polysmorph"] + if(!default_part || default_part == "None") + if(tail_type) + H.dna.features["tail_polysmorph"] = H.dna.species.mutant_bodyparts["tail_polysmorph"] = tail_type + H.dna.update_uf_block(DNA_POLY_TAIL_BLOCK) + else + H.dna.species.mutant_bodyparts["tail_polysmorph"] = H.dna.features["tail_polysmorph"] H.update_body() /obj/item/organ/tail/polysmorph/Remove(mob/living/carbon/human/H, special = 0) diff --git a/icons/blank_title.png b/icons/blank_title.png deleted file mode 100644 index c3167a923bf8..000000000000 Binary files a/icons/blank_title.png and /dev/null differ diff --git a/tgui/packages/tgui/interfaces/DnaConsole.js b/tgui/packages/tgui/interfaces/DnaConsole.js index 194b9a4a6b58..f62db82dc1a8 100644 --- a/tgui/packages/tgui/interfaces/DnaConsole.js +++ b/tgui/packages/tgui/interfaces/DnaConsole.js @@ -26,6 +26,7 @@ const GENE_COLORS = { const CONSOLE_MODE_STORAGE = 'storage'; const CONSOLE_MODE_SEQUENCER = 'sequencer'; const CONSOLE_MODE_ENZYMES = 'enzymes'; +const CONSOLE_MODE_FEATURES = 'features'; const CONSOLE_MODE_INJECTORS = 'injectors'; const STORAGE_MODE_CONSOLE = 'console'; @@ -73,6 +74,8 @@ export const DnaConsole = (props, context) => { const { isPulsingRads, radPulseSeconds, + subjectUNI, + subjectUF, } = data; const { consoleMode } = data.view; return ( @@ -104,7 +107,16 @@ export const DnaConsole = (props, context) => { )} {consoleMode === CONSOLE_MODE_ENZYMES && ( - + + )} + {consoleMode === CONSOLE_MODE_FEATURES && ( + )} @@ -308,6 +320,12 @@ export const DnaConsoleCommands = (props, context) => { onClick={() => act('set_view', { consoleMode: CONSOLE_MODE_ENZYMES, })} /> + + + +