/////////////////////////// DNA DATUM /datum/dna var/unique_enzymes var/struc_enzymes var/uni_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() //Timers for temporary mutations var/list/previous = list() //For temporary name/ui/ue/blood_type modifications var/mob/living/carbon/holder /datum/dna/New(mob/living/carbon/new_holder) if(new_holder) holder = new_holder /datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0) destination.dna.unique_enzymes = unique_enzymes destination.dna.uni_identity = uni_identity destination.dna.blood_type = blood_type destination.set_species(species.type, icon_update=0) destination.dna.features = features.Copy() destination.dna.real_name = real_name destination.dna.temporary_mutations = temporary_mutations.Copy() if(transfer_SE) destination.dna.struc_enzymes = struc_enzymes /datum/dna/proc/copy_dna(datum/dna/new_dna) new_dna.unique_enzymes = unique_enzymes new_dna.struc_enzymes = struc_enzymes new_dna.uni_identity = uni_identity new_dna.blood_type = blood_type new_dna.features = features.Copy() new_dna.species = new species.type new_dna.real_name = real_name new_dna.mutations = mutations.Copy() /datum/dna/proc/add_mutation(mutation_name) var/datum/mutation/human/HM = mutations_list[mutation_name] HM.on_acquiring(holder) /datum/dna/proc/remove_mutation(mutation_name) var/datum/mutation/human/HM = mutations_list[mutation_name] HM.on_losing(holder) /datum/dna/proc/check_mutation(mutation_name) var/datum/mutation/human/HM = mutations_list[mutation_name] return mutations.Find(HM) /datum/dna/proc/remove_all_mutations() remove_mutation_group(mutations) /datum/dna/proc/remove_mutation_group(list/group) if(!group) return for(var/datum/mutation/human/HM in group) HM.force_lose(holder) /datum/dna/proc/generate_uni_identity() . = "" var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS) L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2) if(ishuman(holder)) var/mob/living/carbon/human/H = holder if(!hair_styles_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, hair_styles_list, hair_styles_male_list, hair_styles_female_list) L[DNA_HAIR_STYLE_BLOCK] = construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len) L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color) if(!facial_hair_styles_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, facial_hair_styles_list, facial_hair_styles_male_list, facial_hair_styles_female_list) L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len) L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color) L[DNA_SKIN_TONE_BLOCK] = construct_block(skin_tones.Find(H.skin_tone), skin_tones.len) L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color) if(H.heterochromia) L[DNA_EYE_COLOR_TWO_BLOCK] = sanitize_hexcolor(H.heterochromia) L[DNA_EYE_COLOR_SWITCH_BLOCK] = construct_block(2,2) else L[DNA_EYE_COLOR_TWO_BLOCK] = sanitize_hexcolor(H.eye_color) L[DNA_EYE_COLOR_SWITCH_BLOCK] = construct_block(1,2) var/colour_switch=0 if(special_color[1]) L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(special_color[1]) colour_switch+=1 else L[DNA_COLOR_ONE_BLOCK] = random_string(DNA_BLOCK_SIZE,hex_characters) if(special_color[2]) L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(special_color[2]) colour_switch+=2 else L[DNA_COLOR_TWO_BLOCK] = random_string(DNA_BLOCK_SIZE,hex_characters) if(special_color[3]) L[DNA_COLOR_THR_BLOCK] = sanitize_hexcolor(special_color[3]) colour_switch+=4 else L[DNA_COLOR_THR_BLOCK] = random_string(DNA_BLOCK_SIZE,hex_characters) L[DNA_COLOR_SWITCH_BLOCK] = construct_block(colour_switch+1,DNA_COLOR_SWITCH_MAX+1) /*if(species_list[mutantrace]) L[DNA_MUTANTRACE_BLOCK] = construct_block(species_list.Find(mutantrace), species_list.len+1) else L[DNA_MUTANTRACE_BLOCK] = construct_block(species_list.len+1, species_list.len+1)*/ L[DNA_MUTANTRACE_BLOCK] = generate_race_block() if(mutant_tails.Find(mutanttail)) L[DNA_MUTANTTAIL_BLOCK] = construct_block(mutant_tails.Find(mutanttail), mutant_tails.len+1) else L[DNA_MUTANTTAIL_BLOCK] = construct_block(mutant_tails.len+1, mutant_tails.len+1) if(mutant_wings.Find(mutantwing)) L[DNA_MUTANTWING_BLOCK] = construct_block(mutant_wings.Find(mutantwing), mutant_wings.len+1) else L[DNA_MUTANTWING_BLOCK] = construct_block(mutant_wings.len+1, mutant_wings.len+1) L[DNA_WINGCOLOR_BLOCK] = sanitize_hexcolor(wingcolor) L[DNA_TAUR_BLOCK] = construct_block(taur+1, 2) var/cock_block=0 if(cock["has"]) cock_block+=1 if(vagina) cock_block+=2 L[DNA_COCK_BLOCK] = construct_block(cock_block+1, 4) for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) if(L[i]) . += L[i] else . += random_string(DNA_BLOCK_SIZE,hex_characters) return . /datum/dna/proc/generate_struc_enzymes() var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS) var/result = "" for(var/datum/mutation/human/A in good_mutations + bad_mutations + not_good_mutations) if(A.name == RACEMUT && ismonkey(holder)) sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE) mutations |= A else sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6")) for(var/B in sorting) result += B return result /datum/dna/proc/generate_unique_enzymes() . = "" if(istype(holder)) real_name = holder.real_name . += md5(holder.real_name) else . += random_string(DNA_UNIQUE_ENZYMES_LEN, hex_characters) return . /datum/dna/proc/update_ui_block(blocknumber) if(!blocknumber || !ishuman(holder)) return var/mob/living/carbon/human/H = holder switch(blocknumber) if(DNA_HAIR_COLOR_BLOCK) setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color)) if(DNA_FACIAL_HAIR_COLOR_BLOCK) setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color)) if(DNA_SKIN_TONE_BLOCK) setblock(uni_identity, blocknumber, construct_block(skin_tones.Find(H.skin_tone), skin_tones.len)) if(DNA_EYE_COLOR_BLOCK) setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color)) if(DNA_GENDER_BLOCK) setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2)) if(DNA_FACIAL_HAIR_STYLE_BLOCK) setblock(uni_identity, blocknumber, construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len)) if(DNA_HAIR_STYLE_BLOCK) setblock(uni_identity, blocknumber, construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len)) /datum/dna/proc/mutations_say_mods(message) if(message) for(var/datum/mutation/human/M in mutations) message = M.say_mod(message) return message /datum/dna/proc/mutations_get_spans() var/list/spans = list() for(var/datum/mutation/human/M in mutations) spans |= M.get_spans() return spans /datum/dna/proc/species_get_spans() var/list/spans = list() if(species) spans |= species.get_spans() return spans /datum/dna/proc/is_same_as(datum/dna/D) if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name) if(species.type == D.species.type && features == D.features && blood_type == D.blood_type) return 1 return 0 //used to update dna UI, UE, and dna.real_name. /datum/dna/proc/update_dna_identity() uni_identity = generate_uni_identity() unique_enzymes = generate_unique_enzymes() /datum/dna/proc/initialize_dna(newblood_type) if(newblood_type) blood_type = newblood_type unique_enzymes = generate_unique_enzymes() uni_identity = generate_uni_identity() struc_enzymes = generate_struc_enzymes() features = random_features() /////////////////////////// DNA MOB-PROCS ////////////////////// /mob/proc/set_species(datum/species/mrace, icon_update = 1) return /mob/living/carbon/set_species(datum/species/mrace, icon_update = 1) if(mrace && has_dna()) dna.species.on_species_loss(src) var/old_species = dna.species if(ispath(mrace)) dna.species = new mrace() else dna.species = mrace dna.species.on_species_gain(src, old_species) /mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1) ..() if(icon_update) update_body() update_hair() update_body_parts() update_mutations_overlay()// no lizard with human hulk overlay please. /mob/proc/has_dna() return /mob/living/carbon/has_dna() return dna /mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures) if(newfeatures) dna.features = newfeatures if(mrace) set_species(mrace, icon_update=0) if(newreal_name) real_name = newreal_name dna.generate_unique_enzymes() if(newblood_type) dna.blood_type = newblood_type if(ui) dna.uni_identity = ui updateappearance(icon_update=0) if(se) dna.struc_enzymes = se domutcheck() if(mrace || newfeatures || ui) update_body() update_hair() update_body_parts() update_mutations_overlay() /mob/living/carbon/proc/create_dna() dna = new /datum/dna(src) if(!dna.species) var/rando_race = pick(config.roundstart_races) dna.species = new rando_race() //proc used to update the mob's appearance after its dna UI has been changed /mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) if(!has_dna()) return gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE 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 = skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), skin_tones.len)] eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK)) facial_hair_style = facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), facial_hair_styles_list.len)] hair_style = hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), hair_styles_list.len)] var/mutantrace_c = deconstruct_block(getblock(structure, DNA_MUTANTRACE_BLOCK), species_list.len+1) if(mutantrace_c<=species_list.len && kpcode_race_restricted(species_list[mutantrace_c])!=2) dna.species=kpcode_race_get(species_list[mutantrace_c]) var/mutanttail_c = deconstruct_block(getblock(structure, DNA_MUTANTTAIL_BLOCK), mutant_tails.len+1) if(mutanttail_c<=mutant_tails.len) dna.mutanttail=mutant_tails[mutanttail_c] else dna.mutanttail=null var/mutantwing_c = deconstruct_block(getblock(structure, DNA_MUTANTWING_BLOCK), mutant_wings.len+1) if(mutantwing_c<=mutant_wings.len) dna.mutantwing=mutant_wings[mutantwing_c] else dna.mutantwing=null dna.wingcolor = sanitize_hexcolor(getblock(structure, DNA_WINGCOLOR_BLOCK)) var/colour_switch=deconstruct_block(getblock(structure, DNA_COLOR_SWITCH_BLOCK), DNA_COLOR_SWITCH_MAX+1) colour_switch-=1 if(colour_switch&1) dna.special_color[1]=sanitize_hexcolor(getblock(structure, DNA_COLOR_ONE_BLOCK)) else dna.special_color[1]=null if(colour_switch&2) dna.special_color[2]=sanitize_hexcolor(getblock(structure, DNA_COLOR_TWO_BLOCK)) else dna.special_color[2]=null if(colour_switch&4) dna.special_color[3]=sanitize_hexcolor(getblock(structure, DNA_COLOR_THR_BLOCK)) else dna.special_color[3]=null var/cock_block=deconstruct_block(getblock(structure, DNA_COCK_BLOCK), 4) cock_block-=1 if(!(cock_block&1)) dna.cock["has"]=0 else if(!dna.cock["has"]&&(cock_block&1)) dna.cock["has"]=1 if(cock_block&2) dna.vagina=1 else dna.vagina=0 dna.taur=deconstruct_block(getblock(structure, DNA_TAUR_BLOCK), 2)-1 if(icon_update) update_body() update_hair() if(mutcolor_update) update_body_parts() if(mutations_overlay_update) update_mutations_overlay() /mob/proc/domutcheck() return /mob/living/carbon/domutcheck() if(!has_dna()) return for(var/datum/mutation/human/A in good_mutations | bad_mutations | not_good_mutations) if(ismob(A.check_block(src))) return //we got monkeyized/humanized, this mob will be deleted, no need to continue. update_mutations_overlay() /////////////////////////// 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) /proc/randmut(mob/living/carbon/M, list/candidates, difficulty = 2) if(!M.has_dna()) return var/datum/mutation/human/num = pick(candidates) . = num.force_give(M) return /proc/randmutb(mob/living/carbon/M) if(!M.has_dna()) return var/datum/mutation/human/HM = pick((bad_mutations | not_good_mutations) - mutations_list[RACEMUT]) . = HM.force_give(M) /proc/randmutg(mob/living/carbon/M) if(!M.has_dna()) return var/datum/mutation/human/HM = pick(good_mutations) . = HM.force_give(M) /proc/randmuti(mob/living/carbon/M) if(!M.has_dna()) return var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS) var/newdna = setblock(M.dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, hex_characters)) M.dna.uni_identity = newdna return /proc/clean_dna(mob/living/carbon/M) if(!M.has_dna()) return M.dna.remove_all_mutations() /proc/clean_randmut(mob/living/carbon/M, list/candidates, difficulty = 2) clean_dna(M) randmut(M, candidates, difficulty) /proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability) if(!M.has_dna()) return 0 if(se) for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++) if(prob(probability)) M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, hex_characters)) M.domutcheck() if(ui) for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) if(prob(probability)) M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, hex_characters)) M.updateappearance(mutations_overlay_update=1) return 1 //value in range 1 to values. values must be greater than 0 //all arguments assumed to be positive integers /proc/construct_block(value, values, blocksize=DNA_BLOCK_SIZE) var/width = round((16**blocksize)/values) if(value < 1) value = 1 value = (value * width) - rand(1,width) return num2hex(value, blocksize) //value is hex /proc/deconstruct_block(value, values, blocksize=DNA_BLOCK_SIZE) var/width = round((16**blocksize)/values) value = round(hex2num(value) / width) + 1 if(value > values) value = values return value /////////////////////////// DNA HELPER-PROCS