DNA code now supports unique identity and features blocks of different size. (#62303)

#61980 (694c2999b0) 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).
This commit is contained in:
Ghom
2021-11-23 03:09:09 +01:00
committed by GitHub
parent 272a5f0001
commit 41b8d99401
6 changed files with 138 additions and 94 deletions
+2
View File
@@ -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
+2
View File
@@ -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
+5
View File
@@ -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)
+1 -1
View File
@@ -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 = ""
+127 -92
View File
@@ -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
+1 -1
View File
@@ -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