From 41b8d99401ff15f5cb04e5a45d1de99896dbb87f Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Tue, 23 Nov 2021 03:09:09 +0100 Subject: [PATCH] DNA code now supports unique identity and features blocks of different size. (#62303) #61980 (694c2999b08cbbfbd30aa52a42eb7b0851d02569) has uncovered a few issues with our dna datum code. Mainly the lack of support for ui/uf blocks of different sizes. So, in order to fix this issues, I had to create four global lists, two for UI and UF blocks which sizes differ from DNA_BLOCK_SIZE and two more that store the points in the ui and uf strings where different dna blocks start (this way we avoid having to calculate them every getter and setter proc call). This will add support for heterogeneous ui/uf block sizes and make 24-bit color features and identities possible. To the maintainers of downstream codebases: Remember to add your modular code ui and uf color blocks to the identity_block_lengths and features_block_lengths global lists respectively ... Unless you have rewritten dna code on your end. If that's so, good luck. Tested and working (unless CI says otherwise). --- code/__DEFINES/DNA.dm | 2 + code/__DEFINES/colors.dm | 2 + code/__HELPERS/dna.dm | 5 + code/__HELPERS/sanitize_values.dm | 2 +- code/datums/dna.dm | 219 ++++++++++-------- .../organs/external/_external_organs.dm | 2 +- 6 files changed, 138 insertions(+), 94 deletions(-) diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 0a6e7f22acb..27c6bb8179c 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -86,6 +86,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_EYE_COLOR_BLOCK 4 #define DNA_FACIAL_HAIR_COLOR_BLOCK 2 #define DNA_FACIAL_HAIRSTYLE_BLOCK 6 diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 398e1bebd4c..423416ff4e7 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -199,3 +199,5 @@ /// 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 diff --git a/code/__HELPERS/dna.dm b/code/__HELPERS/dna.dm index b74dacdc096..0ec3e7ee8d4 100644 --- a/code/__HELPERS/dna.dm +++ b/code/__HELPERS/dna.dm @@ -11,3 +11,8 @@ #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) + +///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/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index cdfcdc6f81e..d4f91690696 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -51,7 +51,7 @@ return default return default -/proc/sanitize_hexcolor(color, desired_format = 6, include_crunch = TRUE, default) +/proc/sanitize_hexcolor(color, desired_format = DEFAULT_HEX_COLOR_LEN, include_crunch = TRUE, default) var/crunch = include_crunch ? "#" : "" if(!istext(color)) color = "" diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 1129f240e03..01b2c597fb7 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -1,4 +1,51 @@ +/** + * 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 @@ -96,8 +143,6 @@ if((HM.class in classes) && !(HM.mutadone_proof && mutadone)) force_lose(HM) -#define sanitize_shortcolor(color) sanitize_hexcolor(color, 3, include_crunch = FALSE) - /datum/dna/proc/generate_unique_identity() . = "" var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS) @@ -114,30 +159,25 @@ if(!GLOB.hairstyles_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/hair,GLOB.hairstyles_list, GLOB.hairstyles_male_list, GLOB.hairstyles_female_list) L[DNA_HAIRSTYLE_BLOCK] = construct_block(GLOB.hairstyles_list.Find(H.hairstyle), GLOB.hairstyles_list.len) - L[DNA_HAIR_COLOR_BLOCK] = sanitize_shortcolor(H.hair_color) + L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color, include_crunch = FALSE) if(!GLOB.facial_hairstyles_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hairstyles_list, GLOB.facial_hairstyles_male_list, GLOB.facial_hairstyles_female_list) L[DNA_FACIAL_HAIRSTYLE_BLOCK] = construct_block(GLOB.facial_hairstyles_list.Find(H.facial_hairstyle), GLOB.facial_hairstyles_list.len) - L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_shortcolor(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_shortcolor(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/data = list() - + . = "" var/list/L = new /list(DNA_FEATURE_BLOCKS) if(features["mcolor"]) - L[DNA_MUTANT_COLOR_BLOCK] = sanitize_shortcolor(features["mcolor"]) + L[DNA_MUTANT_COLOR_BLOCK] = sanitize_hexcolor(features["mcolor"], include_crunch = FALSE) if(features["ethcolor"]) - L[DNA_ETHEREAL_COLOR_BLOCK] = sanitize_shortcolor(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"]) @@ -165,10 +205,8 @@ if(features["tail_monkey"]) L[DNA_MONKEY_TAIL_BLOCK] = construct_block(GLOB.tails_list_monkey.Find(features["tail_monkey"]), GLOB.tails_list_monkey.len) - for(var/i in 1 to DNA_FEATURE_BLOCKS) - data += (L[i] || random_string(DNA_BLOCK_SIZE,GLOB.hex_characters)) - - return data.Join() + 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 @@ -222,6 +260,18 @@ . += 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) CRASH("UI block index is null") @@ -230,25 +280,25 @@ var/mob/living/carbon/human/H = holder switch(blocknumber) if(DNA_HAIR_COLOR_BLOCK) - setblock(unique_identity, blocknumber, sanitize_shortcolor(H.hair_color)) + set_uni_identity_block( blocknumber, sanitize_hexcolor(H.hair_color, include_crunch = FALSE)) if(DNA_FACIAL_HAIR_COLOR_BLOCK) - setblock(unique_identity, blocknumber, sanitize_shortcolor(H.facial_hair_color)) + set_uni_identity_block(blocknumber, sanitize_hexcolor(H.facial_hair_color, include_crunch = FALSE)) if(DNA_SKIN_TONE_BLOCK) - setblock(unique_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) - setblock(unique_identity, blocknumber, sanitize_shortcolor(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) - setblock(unique_identity, blocknumber, construct_block(G_MALE, 3)) + set_uni_identity_block(blocknumber, construct_block(G_MALE, 3)) if(FEMALE) - setblock(unique_identity, blocknumber, construct_block(G_FEMALE, 3)) + set_uni_identity_block(blocknumber, construct_block(G_FEMALE, 3)) else - setblock(unique_identity, blocknumber, construct_block(G_PLURAL, 3)) + set_uni_identity_block(blocknumber, construct_block(G_PLURAL, 3)) if(DNA_FACIAL_HAIRSTYLE_BLOCK) - setblock(unique_identity, blocknumber, construct_block(GLOB.facial_hairstyles_list.Find(H.facial_hairstyle), GLOB.facial_hairstyles_list.len)) + set_uni_identity_block(blocknumber, construct_block(GLOB.facial_hairstyles_list.Find(H.facial_hairstyle), GLOB.facial_hairstyles_list.len)) if(DNA_HAIRSTYLE_BLOCK) - setblock(unique_identity, blocknumber, construct_block(GLOB.hairstyles_list.Find(H.hairstyle), GLOB.hairstyles_list.len)) + set_uni_identity_block(blocknumber, construct_block(GLOB.hairstyles_list.Find(H.hairstyle), GLOB.hairstyles_list.len)) /datum/dna/proc/update_uf_block(blocknumber) if(!blocknumber) @@ -257,37 +307,35 @@ CRASH("Non-human mobs shouldn't have DNA") switch(blocknumber) if(DNA_MUTANT_COLOR_BLOCK) - setblock(unique_features, blocknumber, sanitize_shortcolor(features["mcolor"])) + set_uni_feature_block(blocknumber, sanitize_hexcolor(features["mcolor"], include_crunch = FALSE)) if(DNA_ETHEREAL_COLOR_BLOCK) - setblock(unique_features, blocknumber, sanitize_shortcolor(features["ethcolor"])) + set_uni_feature_block(blocknumber, sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE)) if(DNA_LIZARD_MARKINGS_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.body_markings_list.Find(features["body_markings"]), GLOB.body_markings_list.len)) + 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) - setblock(unique_features, blocknumber, construct_block(GLOB.tails_list_lizard.Find(features["tail_lizard"]), GLOB.tails_list_lizard.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_lizard.Find(features["tail_lizard"]), GLOB.tails_list_lizard.len)) if(DNA_SNOUT_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.snouts_list.Find(features["snout"]), GLOB.snouts_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.snouts_list.Find(features["snout"]), GLOB.snouts_list.len)) if(DNA_HORNS_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.horns_list.Find(features["horns"]), GLOB.horns_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.horns_list.Find(features["horns"]), GLOB.horns_list.len)) if(DNA_FRILLS_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.frills_list.Find(features["frills"]), GLOB.frills_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.frills_list.Find(features["frills"]), GLOB.frills_list.len)) if(DNA_SPINES_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.spines_list.Find(features["spines"]), GLOB.spines_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.spines_list.Find(features["spines"]), GLOB.spines_list.len)) if(DNA_HUMAN_TAIL_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.tails_list_human.Find(features["tail_human"]), GLOB.tails_list_human.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_human.Find(features["tail_human"]), GLOB.tails_list_human.len)) if(DNA_EARS_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.ears_list.Find(features["ears"]), GLOB.ears_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.ears_list.Find(features["ears"]), GLOB.ears_list.len)) if(DNA_MOTH_WINGS_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.moth_wings_list.Find(features["moth_wings"]), GLOB.moth_wings_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.moth_wings_list.Find(features["moth_wings"]), GLOB.moth_wings_list.len)) if(DNA_MOTH_ANTENNAE_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.moth_antennae_list.Find(features["moth_antennae"]), GLOB.moth_antennae_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.moth_antennae_list.Find(features["moth_antennae"]), GLOB.moth_antennae_list.len)) if(DNA_MOTH_MARKINGS_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.moth_markings_list.Find(features["moth_markings"]), GLOB.moth_markings_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.moth_markings_list.Find(features["moth_markings"]), GLOB.moth_markings_list.len)) if(DNA_MUSHROOM_CAPS_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.caps_list.Find(features["caps"]), GLOB.caps_list.len)) + set_uni_feature_block(blocknumber, construct_block(GLOB.caps_list.Find(features["caps"]), GLOB.caps_list.len)) if(DNA_MONKEY_TAIL_BLOCK) - setblock(unique_features, blocknumber, construct_block(GLOB.tails_list_monkey.Find(features["tail_monkey"]), GLOB.tails_list_monkey.len)) - -#undef sanitize_shortcolor + set_uni_feature_block(blocknumber, construct_block(GLOB.tails_list_monkey.Find(features["tail_monkey"]), GLOB.tails_list_monkey.len)) //Please use add_mutation or activate_mutation instead /datum/dna/proc/force_give(datum/mutation/human/HM) @@ -483,7 +531,7 @@ if(!has_dna()) return - switch(deconstruct_block(getblock(dna.unique_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) @@ -494,47 +542,47 @@ /mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) ..() var/structure = dna.unique_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_hairstyle = GLOB.facial_hairstyles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIRSTYLE_BLOCK), GLOB.facial_hairstyles_list.len)] - hairstyle = GLOB.hairstyles_list[deconstruct_block(getblock(structure, DNA_HAIRSTYLE_BLOCK), GLOB.hairstyles_list.len)] + 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_hairstyle = GLOB.facial_hairstyles_list[deconstruct_block(get_uni_identity_block(structure, DNA_FACIAL_HAIRSTYLE_BLOCK), GLOB.facial_hairstyles_list.len)] + hairstyle = GLOB.hairstyles_list[deconstruct_block(get_uni_identity_block(structure, DNA_HAIRSTYLE_BLOCK), GLOB.hairstyles_list.len)] var/features = dna.unique_features if(dna.features["mcolor"]) - dna.features["mcolor"] = sanitize_hexcolor(getblock(features, DNA_MUTANT_COLOR_BLOCK)) + dna.features["mcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_MUTANT_COLOR_BLOCK)) if(dna.features["ethcolor"]) - dna.features["ethcolor"] = sanitize_hexcolor(getblock(features, DNA_ETHEREAL_COLOR_BLOCK)) + 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(getblock(features, DNA_LIZARD_MARKINGS_BLOCK), GLOB.body_markings_list.len)] + 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(getblock(features, DNA_LIZARD_TAIL_BLOCK), GLOB.tails_list_lizard.len)] + 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(getblock(features, DNA_SNOUT_BLOCK), GLOB.snouts_list.len)] + 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(getblock(features, DNA_HORNS_BLOCK), GLOB.horns_list.len)] + 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(getblock(features, DNA_FRILLS_BLOCK), GLOB.frills_list.len)] + 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(getblock(features, DNA_SPINES_BLOCK), GLOB.spines_list.len)] + 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(getblock(features, DNA_HUMAN_TAIL_BLOCK), GLOB.tails_list_human.len)] + 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(getblock(features, DNA_EARS_BLOCK), GLOB.ears_list.len)] + 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(getblock(features, DNA_MOTH_WINGS_BLOCK), GLOB.moth_wings_list.len)] + 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 dna.features["moth_wings"] = genetic_value if(dna.features["moth_antennae"]) - var/genetic_value = GLOB.moth_antennae_list[deconstruct_block(getblock(features, DNA_MOTH_ANTENNAE_BLOCK), GLOB.moth_antennae_list.len)] + var/genetic_value = GLOB.moth_antennae_list[deconstruct_block(get_uni_feature_block(features, DNA_MOTH_ANTENNAE_BLOCK), GLOB.moth_antennae_list.len)] dna.features["original_moth_antennae"] = genetic_value dna.features["moth_antennae"] = genetic_value if(dna.features["moth_markings"]) - dna.features["moth_markings"] = GLOB.moth_markings_list[deconstruct_block(getblock(features, DNA_MOTH_MARKINGS_BLOCK), GLOB.moth_markings_list.len)] + dna.features["moth_markings"] = GLOB.moth_markings_list[deconstruct_block(get_uni_feature_block(features, DNA_MOTH_MARKINGS_BLOCK), GLOB.moth_markings_list.len)] if(dna.features["caps"]) - dna.features["caps"] = GLOB.caps_list[deconstruct_block(getblock(features, DNA_MUSHROOM_CAPS_BLOCK), GLOB.caps_list.len)] + dna.features["caps"] = GLOB.caps_list[deconstruct_block(get_uni_feature_block(features, DNA_MUSHROOM_CAPS_BLOCK), GLOB.caps_list.len)] if(dna.features["tail_monkey"]) - dna.features["tail_monkey"] = GLOB.tails_list_monkey[deconstruct_block(getblock(features, DNA_MONKEY_TAIL_BLOCK), GLOB.tails_list_monkey.len)] + dna.features["tail_monkey"] = GLOB.tails_list_monkey[deconstruct_block(get_uni_feature_block(features, DNA_MONKEY_TAIL_BLOCK), GLOB.tails_list_monkey.len)] for(var/obj/item/organ/external/external_organ in internal_organs) external_organ.mutate_feature(features, src) @@ -608,22 +656,6 @@ /////////////////////////// DNA HELPER-PROCS ////////////////////////////// -/proc/getleftblocks(input,blocknumber,blocksize) - if(blocknumber > 1) - return copytext(input,1,((blocksize*blocknumber)-(blocksize-1))) - -/proc/getrightblocks(input,blocknumber,blocksize) - if(blocknumber < (length(input)/blocksize)) - return copytext(input,blocksize*blocknumber+1,length(input)+1) - -/proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE) - return copytext(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 @@ -672,16 +704,14 @@ if(!has_dna()) CRASH("[src] does not have DNA") var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS) - var/newdna = setblock(dna.unique_identity, num, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) - dna.unique_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) - var/newdna = setblock(dna.unique_features, num, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) - dna.unique_features = newdna + 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() @@ -702,13 +732,13 @@ 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.unique_identity = setblock(M.dna.unique_identity, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) + M.dna.set_uni_feature_block(blocknum, random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters)) if(uf) - for(var/i in 1 to DNA_FEATURE_BLOCKS) + for(var/blocknum in 1 to DNA_FEATURE_BLOCKS) if(prob(probability)) - M.dna.unique_features = setblock(M.dna.unique_features, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) + 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) @@ -729,6 +759,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) @@ -806,7 +842,6 @@ to_chat(src, span_phobia("LOOK UP!")) addtimer(CALLBACK(src, .proc/something_horrible_mindmelt), 30) - /mob/living/carbon/human/proc/something_horrible_mindmelt() if(!is_blind()) var/obj/item/organ/eyes/eyes = locate(/obj/item/organ/eyes) in internal_organs diff --git a/code/modules/surgery/organs/external/_external_organs.dm b/code/modules/surgery/organs/external/_external_organs.dm index 360aa7d77ca..46ac2808ada 100644 --- a/code/modules/surgery/organs/external/_external_organs.dm +++ b/code/modules/surgery/organs/external/_external_organs.dm @@ -140,7 +140,7 @@ var/list/feature_list = get_global_feature_list() - set_sprite(feature_list[deconstruct_block(getblock(features, dna_block), feature_list.len)]) + set_sprite(feature_list[deconstruct_block(get_uni_feature_block(features, dna_block), feature_list.len)]) ///The horns of a lizard! /obj/item/organ/external/horns