From 93d03dc6bb5a9e23d4e72f071f7a82f2f833dcb4 Mon Sep 17 00:00:00 2001 From: Y0SH1M4S73R Date: Thu, 8 Jul 2021 11:04:19 -0400 Subject: [PATCH] [Alternative to #6407] Makes mutant bodyparts and mutcolors into editable genetic traits (#6750) * Makes mutant bodyparts and mutcolors into editable genetic traits (plus a whole shitload of otherwise out of scope code improvements because I just HAD to touch old code) * Mirror * genetically-editable mutant bodyparts and colors - skyrat edition Co-authored-by: Funce --- code/__DEFINES/DNA.dm | 32 +++ code/__HELPERS/sanitize_values.dm | 5 + code/datums/components/forensics.dm | 2 +- code/datums/datacore.dm | 4 +- .../diseases/advance/symptoms/genetics.dm | 2 +- code/datums/diseases/retrovirus.dm | 22 +- code/datums/dna.dm | 238 ++++++++++++++---- code/datums/mutations/actions.dm | 2 +- code/datums/mutations/body.dm | 13 +- .../weather/weather_types/radiation_storm.dm | 7 +- code/game/machinery/computer/dna_console.dm | 108 ++++++-- code/game/objects/items/dna_injector.dm | 19 +- code/game/objects/structures/mirror.dm | 1 + code/modules/admin/verbs/anonymousnames.dm | 2 + code/modules/admin/verbs/secrets.dm | 2 +- .../abductor/equipment/glands/transform.dm | 1 + .../eldritch_cult/eldritch_knowledge.dm | 2 +- code/modules/detectivework/scanner.dm | 2 +- code/modules/events/disease_outbreak.dm | 2 +- code/modules/events/spacevine.dm | 4 +- .../mob/living/carbon/human/species.dm | 2 +- .../carbon/human/species_types/jellypeople.dm | 1 + code/modules/mob/living/carbon/life.dm | 9 +- .../ninja_status_read.dm | 2 +- .../projectiles/projectile/special/floral.dm | 7 +- .../chemistry/reagents/other_reagents.dm | 1 + .../chemistry/reagents/toxin_reagents.dm | 7 +- .../crossbreeding/_status_effects.dm | 1 + .../research/xenobiology/xenobiology.dm | 1 + .../ruins/icemoonruin_code/hotsprings.dm | 2 +- code/modules/shuttle/medisim.dm | 1 + code/modules/station_goals/dna_vault.dm | 4 +- .../surgery/advanced/wingreconstruction.dm | 5 + code/modules/surgery/organs/tails.dm | 29 ++- .../modules/customization/__DEFINES/DNA.dm | 3 + .../modules/customization/__DEFINES/lists.dm | 4 + .../modules/customization/__HELPERS/dna.dm | 1 + .../customization/__HELPERS/global_lists.dm | 13 + .../modules/customization/datums/dna.dm | 190 +++++++++++++- .../mob/dead/new_player/sprite_accessories.dm | 4 + .../new_player/sprite_accessories/ears.dm | 1 + .../new_player/sprite_accessories/fluff.dm | 1 + .../new_player/sprite_accessories/frills.dm | 1 + .../new_player/sprite_accessories/genitals.dm | 5 + .../sprite_accessories/head_accessory.dm | 1 + .../new_player/sprite_accessories/horns.dm | 1 + .../dead/new_player/sprite_accessories/ipc.dm | 1 + .../sprite_accessories/moth_antennae.dm | 1 + .../sprite_accessories/neck_accessory.dm | 1 + .../sprite_accessories/skrell_hair.dm | 1 + .../new_player/sprite_accessories/snout.dm | 1 + .../new_player/sprite_accessories/synthliz.dm | 3 + .../new_player/sprite_accessories/tails.dm | 1 + .../sprite_accessories/taur_types.dm | 1 + .../new_player/sprite_accessories/wings.dm | 2 + .../new_player/sprite_accessories/xeno.dm | 2 + .../carbon/human/species/roundstartslime.dm | 17 +- tgstation.dme | 2 + .../DnaConsole/DnaConsoleEnzymes.js | 44 +++- .../DnaConsole/GeneticMakeupInfo.js | 3 + .../tgui/interfaces/DnaConsole/constants.js | 1 + .../tgui/interfaces/DnaConsole/index.js | 21 +- 62 files changed, 731 insertions(+), 138 deletions(-) create mode 100644 modular_skyrat/modules/customization/__DEFINES/DNA.dm create mode 100644 modular_skyrat/modules/customization/__HELPERS/dna.dm diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 34bbaf45444..3e3f140a711 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -64,6 +64,7 @@ #define UE_CHANGED "ue changed" #define UI_CHANGED "ui changed" +#define UF_CHANGED "uf changed" #define CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY 204 @@ -92,6 +93,37 @@ #define DNA_SKIN_TONE_BLOCK 3 #define DNA_UNI_IDENTITY_BLOCKS 7 +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/_DEFINES/DNA.dm) +/* +#define DNA_FEATURE_BLOCKS 15 +#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_MOTH_ANTENNAE_BLOCK 12 +#define DNA_MOTH_MARKINGS_BLOCK 13 +#define DNA_MUSHROOM_CAPS_BLOCK 14 +#define DNA_MONKEY_TAIL_BLOCK 15 +*/ //SKYRAT EDIT CHANGE - ORIGINAL +#define DNA_FEATURE_BLOCKS GLOB.dna_total_feature_blocks + +#define DNA_MANDATORY_COLOR_BLOCKS 5 +#define DNA_MUTANT_COLOR_BLOCK 1 +#define DNA_MUTANT_COLOR_2_BLOCK 2 +#define DNA_MUTANT_COLOR_3_BLOCK 3 +#define DNA_ETHEREAL_COLOR_BLOCK 4 +#define DNA_SKIN_COLOR_BLOCK 5 + +// SKYRAT EDIT CHANGE END + + #define DNA_SEQUENCE_LENGTH 4 #define DNA_MUTATION_BLOCKS 8 #define DNA_UNIQUE_ENZYMES_LEN 32 diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index 75ed837aae9..7cc24570a36 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -53,6 +53,11 @@ /proc/sanitize_hexcolor(color, desired_format = 3, include_crunch = FALSE, default) var/crunch = include_crunch ? "#" : "" + //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION + if(islist(color)) + var/list/color_list = color + color = color_list.Join() + //SKYRAT EDIT ADDITION END if(!istext(color)) color = "" diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm index 55244d83a7d..1b3ea517dd9 100644 --- a/code/datums/components/forensics.dm +++ b/code/datums/components/forensics.dm @@ -91,7 +91,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 diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 4b5dacfab62..9914c183ab1 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -266,7 +266,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 @@ -333,7 +333,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/genetics.dm b/code/datums/diseases/advance/symptoms/genetics.dm index b6395920f4c..094d12eb051 100644 --- a/code/datums/diseases/advance/symptoms/genetics.dm +++ b/code/datums/diseases/advance/symptoms/genetics.dm @@ -61,7 +61,7 @@ Bonus switch(A.stage) if(4, 5) to_chat(C, span_warning("[pick("Your skin feels itchy.", "You feel light headed.")]")) - C.easy_randmut((NEGATIVE | MINOR_NEGATIVE | POSITIVE) - excludemuts, TRUE, TRUE, TRUE, mutadone_proof) + C.easy_random_mutate((NEGATIVE | MINOR_NEGATIVE | POSITIVE) - excludemuts, TRUE, TRUE, TRUE, mutadone_proof) /datum/symptom/genetic_mutation/End(datum/disease/advance/A) . = ..() diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index 954ca675ab5..7cbcbb97394 100644 --- a/code/datums/diseases/retrovirus.dm +++ b/code/datums/diseases/retrovirus.dm @@ -61,20 +61,26 @@ if(DT_PROB(5, delta_time)) to_chat(affected_mob, span_danger("Your entire body vibrates.")) if(DT_PROB(19, delta_time)) - 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(restcure && affected_mob.body_position == LYING_DOWN && DT_PROB(10, delta_time)) to_chat(affected_mob, span_notice("You feel better.")) cure() return FALSE if(4) if(DT_PROB(37, delta_time)) - if(prob(50)) - scramble_dna(affected_mob, 1, 0, rand(50,75)) - else - scramble_dna(affected_mob, 0, 1, rand(50,75)) + 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)) if(restcure && affected_mob.body_position == LYING_DOWN && DT_PROB(2.5, delta_time)) to_chat(affected_mob, span_notice("You feel better.")) cure() diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 191adf5db1f..9c16b90a20a 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -1,11 +1,15 @@ /////////////////////////// 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 + ///Stores the hashed values of the person's non-human features + var/unique_features 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 @@ -39,10 +43,11 @@ 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) //ORIGINAL destination.set_species(species.type, TRUE, null, features.Copy(), mutant_bodyparts.Copy(), body_markings.Copy()) //SKYRAT EDIT CHANGE - CUSTOMIZATION + destination.dna.unique_features = unique_features destination.dna.features = features.Copy() destination.dna.real_name = real_name destination.dna.temporary_mutations = temporary_mutations.Copy() @@ -54,7 +59,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() //SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION @@ -96,7 +102,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) @@ -127,6 +133,51 @@ . += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) return . +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/code/datums/dna.dm) +/* +/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_hexcolor(features["mcolor"]) + if(features["ethcolor"]) + L[DNA_ETHEREAL_COLOR_BLOCK] = sanitize_hexcolor(features["ethcolor"]) + 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["moth_antennae"] != "Burnt Off") + L[DNA_MOTH_ANTENNAE_BLOCK] = construct_block(GLOB.moth_antennae_list.Find(features["moth_antennae"]), GLOB.moth_antennae_list.len) + if(features["moth_markings"]) + L[DNA_MOTH_MARKINGS_BLOCK] = construct_block(GLOB.moth_markings_list.Find(features["moth_markings"]), GLOB.moth_markings_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_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() +*/ +//SKYRAT EDIT REMOVAL END + /datum/dna/proc/generate_dna_blocks() var/bonus if(species?.inert_mutation) @@ -165,8 +216,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 @@ -180,30 +231,73 @@ return . /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) - setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color)) + setblock(unique_identity, blocknumber, sanitize_hexcolor(H.hair_color)) if(DNA_FACIAL_HAIR_COLOR_BLOCK) - setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color)) + setblock(unique_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color)) if(DNA_SKIN_TONE_BLOCK) - setblock(uni_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)) + setblock(unique_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)) if(DNA_EYE_COLOR_BLOCK) - setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color)) + setblock(unique_identity, blocknumber, sanitize_hexcolor(H.eye_color)) if(DNA_GENDER_BLOCK) switch(H.gender) if(MALE) - setblock(uni_identity, blocknumber, construct_block(G_MALE, 3)) + setblock(unique_identity, blocknumber, construct_block(G_MALE, 3)) if(FEMALE) - setblock(uni_identity, blocknumber, construct_block(G_FEMALE, 3)) + setblock(unique_identity, blocknumber, construct_block(G_FEMALE, 3)) else - setblock(uni_identity, blocknumber, construct_block(G_PLURAL, 3)) + setblock(unique_identity, blocknumber, construct_block(G_PLURAL, 3)) if(DNA_FACIAL_HAIRSTYLE_BLOCK) - setblock(uni_identity, blocknumber, construct_block(GLOB.facial_hairstyles_list.Find(H.facial_hairstyle), GLOB.facial_hairstyles_list.len)) + setblock(unique_identity, blocknumber, construct_block(GLOB.facial_hairstyles_list.Find(H.facial_hairstyle), GLOB.facial_hairstyles_list.len)) if(DNA_HAIRSTYLE_BLOCK) - setblock(uni_identity, blocknumber, construct_block(GLOB.hairstyles_list.Find(H.hairstyle), GLOB.hairstyles_list.len)) + setblock(unique_identity, blocknumber, construct_block(GLOB.hairstyles_list.Find(H.hairstyle), GLOB.hairstyles_list.len)) + +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/code/datums/dna.dm) +/* +/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) + setblock(unique_features, blocknumber, sanitize_hexcolor(features["mcolor"])) + if(DNA_ETHEREAL_COLOR_BLOCK) + setblock(unique_features, blocknumber, sanitize_hexcolor(features["ethcolor"])) + if(DNA_LIZARD_MARKINGS_BLOCK) + setblock(unique_features, 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)) + if(DNA_SNOUT_BLOCK) + setblock(unique_features, 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)) + if(DNA_FRILLS_BLOCK) + setblock(unique_features, 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)) + if(DNA_HUMAN_TAIL_BLOCK) + setblock(unique_features, 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)) + if(DNA_MOTH_WINGS_BLOCK) + setblock(unique_features, 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)) + if(DNA_MOTH_MARKINGS_BLOCK) + setblock(unique_features, 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)) + if(DNA_MONKEY_TAIL_BLOCK) + setblock(unique_features, blocknumber, construct_block(GLOB.tails_list_monkey.Find(features["tail_monkey"]), GLOB.tails_list_monkey.len)) +*/ +//SKYRAT EDIT REMOVAL END //Please use add_mutation or activate_mutation instead /datum/dna/proc/force_give(datum/mutation/human/HM) @@ -230,7 +324,7 @@ * * target_dna The DNA that we are comparing to */ /datum/dna/proc/is_same_as(datum/dna/target_dna) - if(uni_identity == target_dna.uni_identity && mutation_index == target_dna.mutation_index && real_name == target_dna.real_name) + if(unique_identity == target_dna.unique_identity && mutation_index == target_dna.mutation_index && real_name == target_dna.real_name) if(species.type == target_dna.species.type && compare_list(features, target_dna.features) && blood_type == target_dna.blood_type) return TRUE return FALSE @@ -263,8 +357,9 @@ //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() //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) /* @@ -272,10 +367,11 @@ 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() */ //SKYRAT EDIT REMOVAL END @@ -309,7 +405,7 @@ stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human -//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular) +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/code/datums/dna.dm) /* /mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) if(QDELETED(src)) @@ -355,6 +451,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 @@ -369,7 +466,7 @@ dna.blood_type = newblood_type if(ui) - dna.uni_identity = ui + dna.unique_identity = ui updateappearance(icon_update=0) if(LAZYLEN(mutation_index)) @@ -403,7 +500,7 @@ if(!has_dna()) return - switch(deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 3)) + switch(deconstruct_block(getblock(dna.unique_identity, DNA_GENDER_BLOCK), 3)) if(G_MALE) gender = MALE if(G_FEMALE) @@ -411,15 +508,55 @@ else gender = PLURAL +//SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION (moved to modular_skyrat/modules/customization/code/datums/dna.dm) +/* /mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) ..() - var/structure = dna.uni_identity + 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)] + var/features = dna.unique_features + if(dna.features["mcolor"]) + dna.features["mcolor"] = sanitize_hexcolor(getblock(features, DNA_MUTANT_COLOR_BLOCK)) + if(dna.features["ethcolor"]) + dna.features["ethcolor"] = sanitize_hexcolor(getblock(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)] + 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)] + if(dna.features["snout"]) + dna.features["snout"] = GLOB.snouts_list[deconstruct_block(getblock(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)] + if(dna.features["frills"]) + dna.features["frills"] = GLOB.frills_list[deconstruct_block(getblock(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)] + 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)] + if(dna.features["ears"]) + dna.features["ears"] = GLOB.ears_list[deconstruct_block(getblock(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)] + dna.features["original_moth_wings"] = genetic_value + if(dna.features["moth_wings"] != "Burnt Off") + 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)] + dna.features["original_moth_antennae"] = genetic_value + if(dna.features["moth_antennae"] != "Burnt Off") + 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)] + if(dna.features["caps"]) + dna.features["caps"] = GLOB.caps_list[deconstruct_block(getblock(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)] + if(icon_update) 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() @@ -427,7 +564,8 @@ update_body_parts() if(mutations_overlay_update) update_mutations_overlay() - +*/ +//SKYRAT EDIT REMOVAL END /mob/proc/domutcheck() return @@ -491,14 +629,14 @@ /proc/getleftblocks(input,blocknumber,blocksize) if(blocknumber > 1) - return copytext_char(input,1,((blocksize*blocknumber)-(blocksize-1))) + return copytext(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) + return copytext(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) + return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) /proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE) if(!istring || !blocknumber || !replacement || !blocksize) @@ -516,15 +654,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, resilient = NONE) +/mob/living/carbon/proc/easy_random_mutate(quality = POSITIVE + NEGATIVE + MINOR_NEGATIVE, scrambled = TRUE, sequence = TRUE, exclude_monkey = TRUE, resilient = NONE) if(!has_dna()) - return + CRASH("[src] does not have DNA") var/list/mutations = list() if(quality & POSITIVE) mutations += GLOB.good_mutations @@ -549,26 +687,34 @@ HM.mutadone_proof = 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 + var/newdna = setblock(dna.unique_identity, num, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) + dna.unique_identity = newdna 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 + 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 FALSE + CRASH("[M] does not have DNA") if(se) for(var/i=1, i<=DNA_MUTATION_BLOCKS, i++) if(prob(probability)) @@ -577,9 +723,13 @@ 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, GLOB.hex_characters)) - M.updateappearance(mutations_overlay_update=1) - return TRUE + M.dna.unique_identity = setblock(M.dna.unique_identity, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) + if(uf) + for(var/i 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)) + 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 diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm index fbeb30dafaa..0af9fe6d2cc 100644 --- a/code/datums/mutations/actions.dm +++ b/code/datums/mutations/actions.dm @@ -56,7 +56,7 @@ var/list/prints = sniffed.return_fingerprints() if(prints) for(var/mob/living/carbon/C in GLOB.carbon_list) - if(prints[md5(C.dna.uni_identity)]) + if(prints[md5(C.dna.unique_identity)]) possible |= C if(!length(possible)) to_chat(user,span_warning("Despite your best efforts, there are no scents to be found on [sniffed]...")) diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index 6b9db21b3be..5c28eec9e0d 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -36,12 +36,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 diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index 6a22e6c002c..bdb2f068012 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -35,12 +35,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/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index ad2d7544133..1971f67b239 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -37,6 +37,9 @@ /// The base cooldown of the ability to copy enzymes and genetic makeup to people. #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." @@ -88,6 +91,8 @@ 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) @@ -144,7 +149,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 @@ -308,7 +313,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 @@ -510,12 +516,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() @@ -1161,8 +1167,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) @@ -1203,6 +1210,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") if(!COOLDOWN_FINISHED(src, enzyme_copy_timer)) @@ -1248,6 +1256,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()) @@ -1256,12 +1279,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 @@ -1284,7 +1307,8 @@ // Expected results: // "ue" - Unique Enzyme, changes name and blood type // "ui" - Unique Identity, changes looks - // "mixed" - Combination of both ue and ui + // "uf" - Unique Features, changes mutant bodyparts and mutcolors + // "mixed" - Combination of ue, ui, and uf if("makeup_apply") // GUARD CHECK - Can we genetically modify the occupant? Includes scanner // operational guard checks. @@ -1324,7 +1348,8 @@ // Expected results: // "ue" - Unique Enzyme, changes name and blood type // "ui" - Unique Identity, changes looks - // "mixed" - Combination of both ue and ui + // "uf" - Unique Features, changes mutant bodyparts and mutcolors + // "mixed" - Combination of ue, ui, and uf if("makeup_delay") // Convert the index to a number and clamp within the array range, then // copy the data from the disk to that buffer @@ -1347,6 +1372,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") @@ -1355,9 +1384,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() @@ -1583,11 +1619,24 @@ 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.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 @@ -1607,12 +1656,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 COOLDOWN_START(src, enzyme_copy_timer, ENZYME_COPY_BASE_COOLDOWN) - scanner_occupant.dna.uni_identity = buffer_slot["UI"] - scanner_occupant.updateappearance(mutations_overlay_update=1) + 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"] @@ -2099,20 +2149,38 @@ // 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/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index de411e38e2c..d5ccf441bd1 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 @@ -484,10 +487,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 227b922e79b..7a2a91161ff 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -216,6 +216,7 @@ if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[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.")) diff --git a/code/modules/admin/verbs/anonymousnames.dm b/code/modules/admin/verbs/anonymousnames.dm index 83e4bf43cc2..fdbf33dd777 100644 --- a/code/modules/admin/verbs/anonymousnames.dm +++ b/code/modules/admin/verbs/anonymousnames.dm @@ -93,11 +93,13 @@ GLOBAL_DATUM(current_anonymous_theme, /datum/anonymous_theme) if(issilicon(player)) player.fully_replace_character_name(player.real_name, theme.anonymous_ai_name(isAI(player))) else + var/mob/living/carbon/human/human_mob = player var/original_name = player.real_name //id will not be changed if you do not do this randomize_human(player) //do this first so the special name can be given player.fully_replace_character_name(original_name, theme.anonymous_name(player)) if(extras_enabled) player_extras(player) + human_mob.dna.update_dna_identity() /** * restore_all_players: sets all crewmembers on station back to their preference name. diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index 0baf2b45c4f..e6ebd73c6b1 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -138,7 +138,7 @@ for(var/i in GLOB.human_list) var/mob/living/carbon/human/H = i if(H.ckey) - dat += "[H][md5(H.dna.uni_identity)]" + dat += "[H][md5(H.dna.unique_identity)]" dat += "" holder << browse(dat, "window=fingerprints;size=440x410") if("ctfbutton") diff --git a/code/modules/antagonists/abductor/equipment/glands/transform.dm b/code/modules/antagonists/abductor/equipment/glands/transform.dm index 71c8acc376b..7b7a00fde8a 100644 --- a/code/modules/antagonists/abductor/equipment/glands/transform.dm +++ b/code/modules/antagonists/abductor/equipment/glands/transform.dm @@ -13,3 +13,4 @@ randomize_human(owner) var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/moth, /datum/species/fly)) owner.set_species(species) + owner.dna.update_dna_identity() diff --git a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm index 4e8d50da730..955b6c8575e 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm @@ -156,7 +156,7 @@ var/list/compiled_list = list() for(var/mob/living/carbon/human/human_to_check as anything in GLOB.human_list) - if(fingerprints[md5(human_to_check.dna.uni_identity)]) + if(fingerprints[md5(human_to_check.dna.unique_identity)]) compiled_list |= human_to_check.real_name compiled_list[human_to_check.real_name] = human_to_check diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 0ca22a13d7c..04d92cfb662 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -98,7 +98,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 72493ab6a71..9cae45b5b8b 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 31864ed2769..2d08583d760 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -474,8 +474,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/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 792a51f711e..e8d318d2c43 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1285,7 +1285,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(radiation > RAD_MOB_MUTATE && DT_PROB(RAD_MOB_MUTATE_PROB, delta_time)) to_chat(source, span_danger("You mutate!")) - source.easy_randmut(NEGATIVE + MINOR_NEGATIVE) + source.easy_random_mutate(NEGATIVE + MINOR_NEGATIVE) source.emote("gasp") source.domutcheck() 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 ddc21c64f6b..a6e9f682e12 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -242,6 +242,7 @@ 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.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) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 3574646d94e..c8f3ff39510 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -437,11 +437,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/ninja/suit/ninja_equipment_actions/ninja_status_read.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_status_read.dm index 90824fe934b..720aa7967b5 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_status_read.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_status_read.dm @@ -19,7 +19,7 @@ info_list += "[span_info("SpiderOS Status: [s_initialized ? "Initialized" : "Disabled"]")]\n" info_list += "[span_info("Current Time: [station_time_timestamp()]")]\n" //Ninja status - info_list += "[span_info("Fingerprints: [md5(ninja.dna.uni_identity)]")]\n" + info_list += "[span_info("Fingerprints: [md5(ninja.dna.unique_identity)]")]\n" info_list += "[span_info("Unique Identity: [ninja.dna.unique_enzymes]")]\n" info_list += "[span_info("Overall Status: [ninja.stat > 1 ? "dead" : "[ninja.health]% healthy"]")]\n" info_list += "[span_info("Nutrition Status: [ninja.nutrition]")]\n" diff --git a/code/modules/projectiles/projectile/special/floral.dm b/code/modules/projectiles/projectile/special/floral.dm index eec59e009bd..221a19dce07 100644 --- a/code/modules/projectiles/projectile/special/floral.dm +++ b/code/modules/projectiles/projectile/special/floral.dm @@ -18,10 +18,11 @@ if(iscarbon(L) && L.has_dna()) var/mob/living/carbon/C = L if(prob(80)) - C.easy_randmut(NEGATIVE + MINOR_NEGATIVE) + C.easy_random_mutate(NEGATIVE + MINOR_NEGATIVE) else - C.easy_randmut(POSITIVE) - C.randmuti() + C.easy_random_mutate(POSITIVE) + C.random_mutate_unique_identity() + C.random_mutate_unique_features() C.domutcheck() else L.adjustFireLoss(rand(5, 15)) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index a21e5f4e550..6db590f9b48 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -717,6 +717,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 007a0c6310d..0ad7cb5541b 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -50,11 +50,12 @@ if(!exposed_mob.has_dna() || HAS_TRAIT(exposed_mob, TRAIT_GENELESS) || HAS_TRAIT(exposed_mob, TRAIT_BADDNA)) return //No robots, AIs, aliens, Ians or other mobs should be affected by this. if(((methods & VAPOR) && prob(min(33, reac_volume))) || (methods & (INGEST|PATCH|INJECT))) - exposed_mob.randmuti() + exposed_mob.random_mutate_unique_identity() + exposed_mob.random_mutate_unique_features() if(prob(98)) - exposed_mob.easy_randmut(NEGATIVE+MINOR_NEGATIVE) + exposed_mob.easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) else - exposed_mob.easy_randmut(POSITIVE) + exposed_mob.easy_random_mutate(POSITIVE) exposed_mob.updateappearance() exposed_mob.domutcheck() diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 7b279fd72ab..906ade0b1f7 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -776,6 +776,7 @@ 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 174af38a95e..68f07a8b71b 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -606,6 +606,7 @@ switch(activation_type) if(SLIME_ACTIVATE_MINOR) 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 6bba1917aae..f58361a85b3 100644 --- a/code/modules/ruins/icemoonruin_code/hotsprings.dm +++ b/code/modules/ruins/icemoonruin_code/hotsprings.dm @@ -42,7 +42,7 @@ GLOBAL_LIST_EMPTY(cursed_minds) all_species += stype var/random_race = pick(all_species) H.set_species(random_race) - H.dna.unique_enzymes = H.dna.generate_unique_enzymes() + H.dna.update_dna_identity() L = H var/turf/T = find_safe_turf() L.forceMove(T) diff --git a/code/modules/shuttle/medisim.dm b/code/modules/shuttle/medisim.dm index b9f06143ff2..d51297a786d 100644 --- a/code/modules/shuttle/medisim.dm +++ b/code/modules/shuttle/medisim.dm @@ -26,6 +26,7 @@ return var/mob/living/carbon/human/human_knight = . randomize_human(human_knight) + human_knight.dna.update_dna_identity() human_knight.dna.add_mutation(MEDIEVAL, MUT_OTHER) var/oldname = human_knight.name var/title = "error" diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index f0f6251feff..12ae1cc52ac 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/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/surgery/advanced/wingreconstruction.dm b/code/modules/surgery/advanced/wingreconstruction.dm index 0d5517fb617..9670ce11765 100644 --- a/code/modules/surgery/advanced/wingreconstruction.dm +++ b/code/modules/surgery/advanced/wingreconstruction.dm @@ -39,5 +39,10 @@ human_target.dna.features["moth_wings"] = human_target.dna.features["original_moth_wings"] else human_target.dna.features["moth_wings"] = "Plain" + //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION + /* + human_target.dna.update_uf_block(DNA_MOTH_WINGS_BLOCK) + */ + //SKYRAT EDIT REMOVAL END human_target.update_mutant_bodyparts() return ..() diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm index 8e05321c8b3..84be97c3fa5 100644 --- a/code/modules/surgery/organs/tails.dm +++ b/code/modules/surgery/organs/tails.dm @@ -6,6 +6,7 @@ icon_state = "severedtail" zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_TAIL + /// 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/Insert(mob/living/carbon/human/tail_owner, special = FALSE, drop_if_replaced = TRUE) @@ -28,13 +29,16 @@ if(istype(tail_owner)) var/default_part = tail_owner.dna.species.mutant_bodyparts["tail_human"] if(!default_part || default_part == "None") - tail_owner.dna.features["tail_human"] = tail_owner.dna.species.mutant_bodyparts["tail_human"] = tail_type + if(tail_type) + tail_owner.dna.features["tail_human"] = tail_owner.dna.species.mutant_bodyparts["tail_human"] = tail_type + tail_owner.dna.update_uf_block(DNA_HUMAN_TAIL_BLOCK) + else + tail_owner.dna.species.mutant_bodyparts["tail_human"] = tail_owner.dna.features["tail_human"] tail_owner.update_body() /obj/item/organ/tail/cat/Remove(mob/living/carbon/human/tail_owner, special = FALSE) ..() if(istype(tail_owner)) - tail_owner.dna.features["tail_human"] = "None" tail_owner.dna.species.mutant_bodyparts -= "tail_human" color = tail_owner.hair_color tail_owner.update_body() @@ -46,6 +50,7 @@ desc = "A severed lizard tail. Somewhere, no doubt, a lizard hater is very pleased with themselves." color = "#116611" tail_type = "Smooth" + /// 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/spines = "None" //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION @@ -60,18 +65,25 @@ // Checks here are necessary so it wouldn't overwrite the tail of a lizard it spawned in var/default_part = tail_owner.dna.species.mutant_bodyparts["tail_lizard"] if(!default_part || default_part == "None") - tail_owner.dna.features["tail_lizard"] = tail_owner.dna.species.mutant_bodyparts["tail_lizard"] = tail_type + if(tail_type) + tail_owner.dna.features["tail_lizard"] = tail_owner.dna.species.mutant_bodyparts["tail_lizard"] = tail_type + tail_owner.dna.update_uf_block(DNA_LIZARD_TAIL_BLOCK) + else + tail_owner.dna.species.mutant_bodyparts["tail_lizard"] = tail_owner.dna.features["tail_lizard"] default_part = tail_owner.dna.species.mutant_bodyparts["spines"] if(!default_part || default_part == "None") - tail_owner.dna.features["spines"] = tail_owner.dna.species.mutant_bodyparts["spines"] = spines + if(spines) + tail_owner.dna.features["spines"] = tail_owner.dna.species.mutant_bodyparts["spines"] = spines + tail_owner.dna.update_uf_block(DNA_SPINES_BLOCK) + else + tail_owner.dna.species.mutant_bodyparts["spines"] = tail_owner.dna.features["spines"] tail_owner.update_body() /obj/item/organ/tail/lizard/Remove(mob/living/carbon/human/tail_owner, special = FALSE) ..() if(istype(tail_owner)) tail_owner.dna.species.mutant_bodyparts -= "tail_lizard" - tail_owner.dna.species.mutant_bodyparts -= "spines" color = "#" + tail_owner.dna.features["mcolor"] tail_type = tail_owner.dna.features["tail_lizard"] spines = tail_owner.dna.features["spines"] @@ -92,6 +104,8 @@ /obj/item/organ/tail/lizard/fake name = "fabricated lizard tail" desc = "A fabricated severed lizard tail. This one's made of synthflesh. Probably not usable for lizard wine." + tail_type = null + spines = null /obj/item/organ/tail/monkey name = "monkey tail" @@ -106,13 +120,14 @@ if(istype(tail_owner)) if(!("tail_monkey" in tail_owner.dna.species.mutant_bodyparts)) tail_owner.dna.species.mutant_bodyparts |= "tail_monkey" - tail_owner.dna.features["tail_monkey"] = tail_type + if(tail_type) + tail_owner.dna.features["tail_monkey"] = tail_type + tail_owner.dna.update_uf_block(DNA_MONKEY_TAIL_BLOCK) tail_owner.update_body() /obj/item/organ/tail/monkey/Remove(mob/living/carbon/human/tail_owner, special = FALSE) ..() if(istype(tail_owner)) - tail_owner.dna.features["tail_monkey"] = "None" tail_owner.dna.species.mutant_bodyparts -= "tail_monkey" tail_owner.update_body() */ diff --git a/modular_skyrat/modules/customization/__DEFINES/DNA.dm b/modular_skyrat/modules/customization/__DEFINES/DNA.dm new file mode 100644 index 00000000000..390a60a87eb --- /dev/null +++ b/modular_skyrat/modules/customization/__DEFINES/DNA.dm @@ -0,0 +1,3 @@ +#define DNA_BLOCKS_PER_FEATURE 4 +#define DNA_BLOCKS_PER_MARKING 2 +#define DNA_BLOCKS_PER_MARKING_ZONE 1+MAXIMUM_MARKINGS_PER_LIMB*DNA_BLOCKS_PER_MARKING diff --git a/modular_skyrat/modules/customization/__DEFINES/lists.dm b/modular_skyrat/modules/customization/__DEFINES/lists.dm index 2973dbdfaa6..3be48a849c3 100644 --- a/modular_skyrat/modules/customization/__DEFINES/lists.dm +++ b/modular_skyrat/modules/customization/__DEFINES/lists.dm @@ -1,5 +1,6 @@ GLOBAL_LIST_EMPTY(sprite_accessories) GLOBAL_LIST_EMPTY(generic_accessories) +GLOBAL_LIST_EMPTY(genetic_accessories) GLOBAL_LIST_EMPTY(body_markings) GLOBAL_LIST_EMPTY_TYPED(body_markings_per_limb, /list) @@ -11,3 +12,6 @@ GLOBAL_LIST_EMPTY(loadout_category_to_subcategory_to_items) GLOBAL_LIST_EMPTY(augment_items) GLOBAL_LIST_EMPTY(augment_categories_to_slots) GLOBAL_LIST_EMPTY(augment_slot_to_items) + +GLOBAL_LIST_EMPTY(dna_mutant_bodypart_blocks) +GLOBAL_LIST_EMPTY(dna_body_marking_blocks) diff --git a/modular_skyrat/modules/customization/__HELPERS/dna.dm b/modular_skyrat/modules/customization/__HELPERS/dna.dm new file mode 100644 index 00000000000..188f4d821da --- /dev/null +++ b/modular_skyrat/modules/customization/__HELPERS/dna.dm @@ -0,0 +1 @@ +GLOBAL_VAR_INIT(dna_total_feature_blocks, DNA_MANDATORY_COLOR_BLOCKS) diff --git a/modular_skyrat/modules/customization/__HELPERS/global_lists.dm b/modular_skyrat/modules/customization/__HELPERS/global_lists.dm index e69e469f8db..e17f955fbe4 100644 --- a/modular_skyrat/modules/customization/__HELPERS/global_lists.dm +++ b/modular_skyrat/modules/customization/__HELPERS/global_lists.dm @@ -2,6 +2,7 @@ make_sprite_accessory_references() make_body_marking_references() make_body_marking_set_references() + make_body_marking_dna_block_references() make_loadout_references() make_augment_references() make_culture_references() @@ -38,6 +39,13 @@ if(!GLOB.sprite_accessories[P.key]) GLOB.sprite_accessories[P.key] = list() GLOB.sprite_accessories[P.key][P.name] = P + if(P.genetic) + if(!GLOB.dna_mutant_bodypart_blocks[P.key]) + GLOB.dna_mutant_bodypart_blocks[P.key] = GLOB.dna_total_feature_blocks+1 + if(!GLOB.genetic_accessories[P.key]) + GLOB.genetic_accessories[P.key] = list() + GLOB.dna_total_feature_blocks += DNA_BLOCKS_PER_FEATURE + GLOB.genetic_accessories[P.key] += P.name //TODO: Replace "generic" definitions with something better if(P.generic && !GLOB.generic_accessories[P.key]) GLOB.generic_accessories[P.key] = P.generic @@ -65,6 +73,11 @@ BM = new path() GLOB.body_marking_sets[BM.name] = BM +/proc/make_body_marking_dna_block_references() + for(var/marking_zone in GLOB.marking_zones) + GLOB.dna_body_marking_blocks[marking_zone] = GLOB.dna_total_feature_blocks+1 + GLOB.dna_total_feature_blocks += DNA_BLOCKS_PER_MARKING_ZONE + /proc/make_loadout_references() // Here we build the global loadout lists for(var/path in subtypesof(/datum/loadout_item)) diff --git a/modular_skyrat/modules/customization/datums/dna.dm b/modular_skyrat/modules/customization/datums/dna.dm index 4ae0cac112e..310f6619dd9 100644 --- a/modular_skyrat/modules/customization/datums/dna.dm +++ b/modular_skyrat/modules/customization/datums/dna.dm @@ -10,11 +10,117 @@ 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 = species.get_random_features() mutant_bodyparts = species.get_random_mutant_bodyparts(features) + unique_features = generate_unique_features() + +/datum/dna/proc/generate_unique_features() + var/list/data = list() + + if(features["mcolor"]) + data += sanitize_hexcolor(features["mcolor"]) + else + data += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) + if(features["mcolor2"]) + data += sanitize_hexcolor(features["mcolor2"]) + else + data += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) + if(features["mcolor3"]) + data += sanitize_hexcolor(features["mcolor3"]) + else + data += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) + if(features["ethcolor"]) + data += sanitize_hexcolor(features["ethcolor"]) + else + data += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) + if(features["skin_color"]) + data += sanitize_hexcolor(features["skin_color"]) + else + data += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) + for(var/key in GLOB.genetic_accessories) + if(mutant_bodyparts[key] && (mutant_bodyparts[key][MUTANT_INDEX_NAME] in GLOB.genetic_accessories[key])) + var/list/accessories_for_key = GLOB.genetic_accessories[key] + data += construct_block(accessories_for_key.Find(mutant_bodyparts[key][MUTANT_INDEX_NAME]), accessories_for_key.len) + var/colors_to_randomize = DNA_BLOCKS_PER_FEATURE-1 + for(var/color in mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST]) + colors_to_randomize-- + data += sanitize_hexcolor(color) + if(colors_to_randomize) + data += random_string(DNA_BLOCK_SIZE*colors_to_randomize,GLOB.hex_characters) + else + data += random_string(DNA_BLOCK_SIZE*DNA_BLOCKS_PER_FEATURE,GLOB.hex_characters) + for(var/zone in GLOB.marking_zones) + if(body_markings[zone]) + data += construct_block(body_markings[zone].len+1, MAXIMUM_MARKINGS_PER_LIMB+1) + var/list/marking_list = GLOB.body_markings_per_limb[zone] + var/markings_to_randomize = MAXIMUM_MARKINGS_PER_LIMB + for(var/marking in body_markings[zone]) + markings_to_randomize-- + data += construct_block(marking_list.Find(marking), marking_list.len) + data += sanitize_hexcolor(body_markings[zone][marking]) + if(markings_to_randomize) + data += random_string(DNA_BLOCK_SIZE*markings_to_randomize*DNA_BLOCKS_PER_MARKING,GLOB.hex_characters) + else + data += construct_block(1, MAXIMUM_MARKINGS_PER_LIMB+1) + data += random_string(DNA_BLOCK_SIZE*MAXIMUM_MARKINGS_PER_LIMB*DNA_BLOCKS_PER_MARKING,GLOB.hex_characters) + return data.Join() + +/datum/dna/proc/update_uf_block(blocknumber) + if(!blocknumber) + CRASH("UF block index is null") + if(blocknumber<1 || blocknumber>DNA_FEATURE_BLOCKS) + CRASH("UF block index out of bounds") + if(!ishuman(holder)) + CRASH("Non-human mobs shouldn't have DNA") + if(blocknumber <= DNA_MANDATORY_COLOR_BLOCKS) + switch(blocknumber) + if(DNA_MUTANT_COLOR_BLOCK) + setblock(unique_features, blocknumber, sanitize_hexcolor(features["mcolor"])) + if(DNA_MUTANT_COLOR_2_BLOCK) + setblock(unique_features, blocknumber, sanitize_hexcolor(features["mcolor2"])) + if(DNA_MUTANT_COLOR_3_BLOCK) + setblock(unique_features, blocknumber, sanitize_hexcolor(features["mcolor3"])) + if(DNA_ETHEREAL_COLOR_BLOCK) + setblock(unique_features, blocknumber, sanitize_hexcolor(features["ethcolor"])) + if(DNA_SKIN_COLOR_BLOCK) + setblock(unique_features, blocknumber, sanitize_hexcolor(features["skin_color"])) + else if(blocknumber <= DNA_MANDATORY_COLOR_BLOCKS+(GLOB.genetic_accessories.len*DNA_BLOCKS_PER_FEATURE)) + var/block_index = blocknumber - DNA_MANDATORY_COLOR_BLOCKS + var/block_zero_index = block_index-1 + var/bodypart_index = (block_zero_index/DNA_BLOCKS_PER_FEATURE)+1 + var/color_index = block_zero_index%DNA_BLOCKS_PER_FEATURE + var/key = GLOB.genetic_accessories[bodypart_index] + if(mutant_bodyparts[key]) + var/list/color_list = mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] + if(color_index && color_index <= color_list.len) + setblock(unique_features, blocknumber, sanitize_hexcolor(color_list[color_index])) + else + var/list/accessories_for_key = GLOB.genetic_accessories[key] + if(mutant_bodyparts[key][MUTANT_INDEX_NAME] in accessories_for_key) + setblock(unique_features, blocknumber, construct_block(mutant_bodyparts.Find(mutant_bodyparts[key][MUTANT_INDEX_NAME]), accessories_for_key.len)) + else + var/block_index = blocknumber - (DNA_MANDATORY_COLOR_BLOCKS+(GLOB.genetic_accessories.len*DNA_BLOCKS_PER_FEATURE)) + var/block_zero_index = block_index-1 + var/zone_index = (block_zero_index/DNA_BLOCKS_PER_MARKING_ZONE)+1 + var/zone = GLOB.marking_zones[zone_index] + if(blocknumber == GLOB.dna_body_marking_blocks[zone]) + var/markings = 0 + if(body_markings[zone]) + markings = body_markings[zone].len + setblock(unique_features, blocknumber, construct_block(markings+1, MAXIMUM_MARKINGS_PER_LIMB+1)) + else + var/color_block = ((block_zero_index%DNA_BLOCKS_PER_MARKING_ZONE)+1)%DNA_BLOCKS_PER_MARKING + var/marking_index = (((block_zero_index-1)%DNA_BLOCKS_PER_MARKING_ZONE)/DNA_BLOCKS_PER_MARKING)+1 + if(body_markings[zone] && marking_index <= body_markings[zone].len) + var/marking = body_markings[zone][marking_index] + if(color_block) + setblock(unique_features, blocknumber, sanitize_hexcolor(body_markings[zone][marking])) + else + var/list/marking_list = GLOB.body_markings_per_limb[zone] + setblock(unique_features, blocknumber, construct_block(marking_list.Find(marking), marking_list.len)) /datum/dna/proc/update_body_size() if(!holder || current_body_size == features["body_size"]) @@ -42,7 +148,6 @@ var/datum/species/old_species = dna.species dna.species = new_race //BODYPARTS AND FEATURES - var/list/bodyparts_to_add if(pref_load) dna.features = pref_load.features.Copy() dna.real_name = pref_load.real_name @@ -65,15 +170,8 @@ dna.body_markings = override_markings || new_race.get_random_body_markings(dna.features) dna.species.body_markings = dna.body_markings.Copy() - bodyparts_to_add = dna.mutant_bodyparts.Copy() - - for(var/key in bodyparts_to_add) - var/datum/sprite_accessory/SP = GLOB.sprite_accessories[key][bodyparts_to_add[key][MUTANT_INDEX_NAME]] - if(!SP.factual) - bodyparts_to_add -= key - continue - - dna.species.mutant_bodyparts = bodyparts_to_add.Copy() + copy_mutant_parts_to_species() + dna.unique_features = dna.generate_unique_features() dna.update_body_size() @@ -84,3 +182,73 @@ var/species_holder = initial(mrace.species_language_holder) language_holder = new species_holder(src, pref_load) update_atom_languages() + +/mob/living/carbon/proc/copy_mutant_parts_to_species() + if(!has_dna()) + CRASH("[src] does not have DNA") + var/list/bodyparts_to_add = dna.mutant_bodyparts.Copy() + for(var/key in bodyparts_to_add) + var/datum/sprite_accessory/SP = GLOB.sprite_accessories[key][bodyparts_to_add[key][MUTANT_INDEX_NAME]] + if(!SP.factual) + bodyparts_to_add -= key + continue + dna.species.mutant_bodyparts = bodyparts_to_add.Copy() + +/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)] + var/features = dna.unique_features + if(dna.features["mcolor"]) + dna.features["mcolor"] = sanitize_hexcolor(getblock(features, DNA_MUTANT_COLOR_BLOCK)) + if(dna.features["mcolor2"]) + dna.features["mcolor2"] = sanitize_hexcolor(getblock(features, DNA_MUTANT_COLOR_2_BLOCK)) + if(dna.features["mcolor3"]) + dna.features["mcolor3"] = sanitize_hexcolor(getblock(features, DNA_MUTANT_COLOR_3_BLOCK)) + if(dna.features["ethcolor"]) + dna.features["ethcolor"] = sanitize_hexcolor(getblock(features, DNA_ETHEREAL_COLOR_BLOCK)) + if(dna.features["skin_color"]) + dna.features["skin_color"] = sanitize_hexcolor(getblock(features, DNA_SKIN_COLOR_BLOCK)) + for(var/key in GLOB.genetic_accessories) + if(dna.mutant_bodyparts[key] && (dna.mutant_bodyparts[key][MUTANT_INDEX_NAME] in GLOB.genetic_accessories[key])) + var/bodypart_block = GLOB.dna_mutant_bodypart_blocks[key] + var/list/accessories_for_key = GLOB.sprite_accessories[key] + var/list/possible_accessories = GLOB.genetic_accessories[key] + var/accessory_name = GLOB.genetic_accessories[key][deconstruct_block(getblock(features, bodypart_block), possible_accessories.len)] + dna.mutant_bodyparts[key][MUTANT_INDEX_NAME] = accessory_name + var/datum/sprite_accessory/accessory_to_apply = accessories_for_key[accessory_name] + if(accessory_to_apply.factual) + switch(accessory_to_apply.color_src) + if(USE_ONE_COLOR) + dna.mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] = list(sanitize_hexcolor(getblock(features,bodypart_block+1))) + if(USE_MATRIXED_COLORS) + dna.mutant_bodyparts[key][MUTANT_INDEX_COLOR_LIST] = list(sanitize_hexcolor(getblock(features,bodypart_block+1)), sanitize_hexcolor(getblock(features,bodypart_block+2)), sanitize_hexcolor(getblock(features,bodypart_block+3))) + for(var/zone in GLOB.marking_zones) + var/marking_count_block = GLOB.dna_body_marking_blocks[zone] + var/first_marking_block = marking_count_block+1 + var/marking_count = deconstruct_block(getblock(features, marking_count_block), 4)-1 + if(!marking_count && dna.body_markings[zone]) + dna.body_markings -= zone + if(marking_count) + if(!dna.body_markings[zone]) + dna.body_markings[zone] = list() + dna.body_markings[zone].len = marking_count + for(var/i in 1 to marking_count) + var/marking = GLOB.body_markings_per_limb[zone][deconstruct_block(getblock(features, first_marking_block+(i-1)*DNA_BLOCKS_PER_MARKING), GLOB.body_markings_per_limb[zone].len)] + dna.body_markings[zone][i] = marking + dna.body_markings[zone][marking] = sanitize_hexcolor(getblock(features, first_marking_block+(i-1)*DNA_BLOCKS_PER_MARKING+1)) + dna.species.body_markings = dna.body_markings.Copy() + copy_mutant_parts_to_species() + + if(icon_update) + 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() + if(mutations_overlay_update) + update_mutations_overlay() diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm index 3dcab75c3dd..0faa779a232 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories.dm @@ -39,6 +39,8 @@ var/extra2_color_src ///If defined, the accessory will be only available to ckeys inside the list. ITS ASSOCIATIVE, ie. ("ckey" = TRUE). For speed var/list/ckey_whitelist + ///Whether this feature is genetic, and thus modifiable by DNA consoles + var/genetic = FALSE /datum/sprite_accessory/New() if(!default_color) @@ -106,6 +108,7 @@ default_color = DEFAULT_SECONDARY recommended_species = list("lizard", "unathi", "ashlizard", "silverlizard") relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER) + genetic = TRUE /datum/sprite_accessory/spines/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) var/obj/item/organ/tail/T = H.getorganslot(ORGAN_SLOT_TAIL) @@ -132,6 +135,7 @@ key = "legs" generic = "Leg Type" color_src = null + genetic = TRUE /datum/sprite_accessory/socks icon = 'modular_skyrat/master_files/icons/mob/clothing/underwear.dmi' diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ears.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ears.dm index c8121d9ef75..758cd534b41 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ears.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ears.dm @@ -3,6 +3,7 @@ generic = "Ears" organ_type = /obj/item/organ/ears/mutant relevent_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /datum/sprite_accessory/ears/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if(H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/fluff.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/fluff.dm index 86519df41fd..3a3876e678d 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/fluff.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/fluff.dm @@ -5,6 +5,7 @@ generic = "Fluff" recommended_species = list("moth", "synthmammal", "mammal", "insect") relevent_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /datum/sprite_accessory/fluff/moth/none name = "None" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/frills.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/frills.dm index 6265a7384b1..4d31102a957 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/frills.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/frills.dm @@ -3,6 +3,7 @@ generic = "Frills" default_color = DEFAULT_SECONDARY relevent_layers = list(BODY_ADJ_LAYER) + genetic = TRUE /datum/sprite_accessory/frills/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if(H.head && (H.try_hide_mutant_parts || (H.head.flags_inv & HIDEEARS) || !HD || HD.status == BODYPART_ROBOTIC)) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm index f71f3fd65bc..2192abb2d8a 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/genitals.dm @@ -39,6 +39,7 @@ special_x_dimension = TRUE //default_color = DEFAULT_SKIN_OR_PRIMARY //This is the price we're paying for sheaths relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) + genetic = TRUE var/can_have_sheath = TRUE /datum/sprite_accessory/genital/penis/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) @@ -118,6 +119,7 @@ special_x_dimension = TRUE default_color = DEFAULT_SKIN_OR_PRIMARY relevent_layers = list(BODY_ADJ_LAYER, BODY_BEHIND_LAYER) + genetic = TRUE var/has_size = TRUE /datum/sprite_accessory/genital/testicles/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) @@ -166,6 +168,7 @@ always_color_customizable = TRUE default_color = "fcc" relevent_layers = list(BODY_FRONT_LAYER) + genetic = TRUE var/alt_aroused = TRUE /datum/sprite_accessory/genital/vagina/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) @@ -226,6 +229,7 @@ organ_type = /obj/item/organ/genital/womb associated_organ_slot = ORGAN_SLOT_WOMB key = "womb" + genetic = TRUE /datum/sprite_accessory/genital/womb/none icon_state = "none" @@ -248,6 +252,7 @@ relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) uses_skintones = TRUE genital_location = CHEST + genetic = TRUE /datum/sprite_accessory/genital/breasts/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if(H.undershirt != "Nude" && !(H.underwear_visibility & UNDERWEAR_HIDE_SHIRT)) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/head_accessory.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/head_accessory.dm index 89d8d253885..d3bb3156229 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/head_accessory.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/head_accessory.dm @@ -3,6 +3,7 @@ key = "head_acc" generic = "Head Accessory" relevent_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /datum/sprite_accessory/head_accessory/none name = "None" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/horns.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/horns.dm index 81baebcb39e..b48dc588bdf 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/horns.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/horns.dm @@ -4,6 +4,7 @@ relevent_layers = list(BODY_FRONT_LAYER) icon = 'modular_skyrat/master_files/icons/mob/sprite_accessory/horns.dmi' default_color = "555" + genetic = TRUE /datum/sprite_accessory/horns/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if(H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ipc.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ipc.dm index eaf77ef6689..2814febdb6e 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ipc.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/ipc.dm @@ -141,6 +141,7 @@ key = "ipc_antenna" generic = "Antenna" relevent_layers = list(BODY_ADJ_LAYER) + genetic = FALSE /datum/sprite_accessory/antenna/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if(H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/moth_antennae.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/moth_antennae.dm index 325ddc95c58..9765eb549df 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/moth_antennae.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/moth_antennae.dm @@ -2,6 +2,7 @@ generic = "Moth Antennae" key = "moth_antennae" relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /datum/sprite_accessory/moth_antennae/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if(H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/neck_accessory.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/neck_accessory.dm index 3c1223d2252..187e9bb7afc 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/neck_accessory.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/neck_accessory.dm @@ -3,6 +3,7 @@ key = "neck_acc" generic = "Neck Accessory" relevent_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /datum/sprite_accessory/neck_accessory/none name = "None" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/skrell_hair.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/skrell_hair.dm index 9db3327cc51..84934a2f3b5 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/skrell_hair.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/skrell_hair.dm @@ -4,6 +4,7 @@ key = "skrell_hair" color_src = USE_ONE_COLOR relevent_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /datum/sprite_accessory/skrell_hair/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if(H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR))) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm index 609b0c9ed2a..4e7cbd05299 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm @@ -5,6 +5,7 @@ var/use_muzzled_sprites = TRUE recommended_species = list("synthmammal", "mammal", "lizard", "unathi", "ashlizard", "silverlizard") relevent_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /datum/sprite_accessory/snouts/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) || (H.head && (H.head.flags_inv & HIDEFACE)) || !HD) diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/synthliz.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/synthliz.dm index 2e3589da443..5beb11e7b1b 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/synthliz.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/synthliz.dm @@ -6,6 +6,7 @@ default_color = null name = "Synthetic Lizard - Snout" icon_state = "synthliz_basic" + genetic = FALSE /datum/sprite_accessory/snouts/synthliz/synthliz_under color_src = USE_MATRIXED_COLORS @@ -77,6 +78,7 @@ name = "Synthetic Lizard" icon_state = "synthliz" general_type = "lizard" + genetic = FALSE //Synth Antennae /datum/sprite_accessory/antenna/synthliz @@ -143,6 +145,7 @@ icon_state = "synthlizard" taur_mode = STYLE_TAUR_PAW recommended_species = list("synthliz") + genetic = FALSE /datum/sprite_accessory/taur/synthliz/inv name = "Cybernetic Lizard (Inverted)" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm index d365b5608db..952bd6dacd0 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/tails.dm @@ -7,6 +7,7 @@ special_icon_case = TRUE special_colorize = TRUE relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /// A generalisation of the tail-type, e.g. lizard or feline, for hardsuit or other sprites var/general_type diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm index 0de965e9bd7..3fc25a80eb9 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/taur_types.dm @@ -6,6 +6,7 @@ dimension_x = 64 center = TRUE relevent_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) + genetic = TRUE var/taur_mode = NONE //Must be a single specific tauric suit variation bitflag. Don't do FLAG_1|FLAG_2 var/alt_taur_mode = NONE //Same as above. var/hide_legs = TRUE diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm index 827ff49be5e..af14d5f20f1 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm @@ -9,6 +9,7 @@ recommended_species = list("human", "synthhuman", "felinid", "lizard", "synthmammal", "mammal", "synthliz") organ_type = /obj/item/organ/wings relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER, BODY_ADJ_LAYER) + genetic = TRUE /datum/sprite_accessory/wings/is_hidden(mob/living/carbon/human/H, obj/item/bodypart/HD) if(H.wear_suit && H.try_hide_mutant_parts) @@ -165,6 +166,7 @@ name = "Dragon (synthetic alt)" icon_state = "dragonsynth" color_src = USE_MATRIXED_COLORS + genetic = FALSE /datum/sprite_accessory/wings/mammal/dragon_alt1 name = "Dragon (alt 1)" diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/xeno.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/xeno.dm index 00a77bb8660..9dde393d798 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/xeno.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/xeno.dm @@ -4,6 +4,7 @@ key = "xenodorsal" color_src = USE_ONE_COLOR relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) + genetic = TRUE /datum/sprite_accessory/xenodorsal/standard name = "Standard" @@ -30,6 +31,7 @@ generic = "Caste Head" key = "xenohead" relevent_layers = list(BODY_ADJ_LAYER) + genetic = TRUE /datum/sprite_accessory/xenohead/standard name = "Standard" diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm index 0234524268b..60d918ce3db 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm @@ -71,15 +71,25 @@ DNA.features["mcolor"] = sanitize_hexcolor(new_mutantcolor) DNA.features["mcolor2"] = sanitize_hexcolor(new_mutantcolor) DNA.features["mcolor3"] = sanitize_hexcolor(new_mutantcolor) + DNA.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + DNA.update_uf_block(DNA_MUTANT_COLOR_2_BLOCK) + DNA.update_uf_block(DNA_MUTANT_COLOR_3_BLOCK) else DNA.features[color_target] = sanitize_hexcolor(new_mutantcolor) + switch(color_target) + if("mcolor") + DNA.update_uf_block(DNA_MUTANT_COLOR_BLOCK) + if("mcolor2") + DNA.update_uf_block(DNA_MUTANT_COLOR_2_BLOCK) + if("mcolor3") + DNA.update_uf_block(DNA_MUTANT_COLOR_3_BLOCK) if(marking_reset && marking_reset == "Yes") - for(var/zone in DNA.body_markings) - for(var/key in DNA.body_markings[zone]) + for(var/zone in DNA.species.body_markings) + for(var/key in DNA.species.body_markings[zone]) var/datum/body_marking/BD = GLOB.body_markings[key] if(BD.always_color_customizable) continue - DNA.body_markings[zone][key] = BD.get_default_color(DNA.features, DNA.species) + DNA.species.body_markings[zone][key] = BD.get_default_color(DNA.features, DNA.species) H.icon_render_key = "" //Currently the render key doesnt recognize the markings colors if(mutantpart_reset && mutantpart_reset == "Yes") H.mutant_renderkey = "" //Just in case @@ -146,6 +156,7 @@ new_acc_list[MUTANT_INDEX_COLOR_LIST] = SA.get_default_color(DNA.features, DNA.species) DNA.species.mutant_bodyparts[chosen_key] = new_acc_list DNA.mutant_bodyparts[chosen_key] = new_acc_list.Copy() + DNA.update_uf_block(GLOB.dna_mutant_bodypart_blocks[chosen_key]) if (chosen_key == "legs" && chosen_name_key != "Cancel") if (chosen_name_key == "Digitigrade Legs" && !(DIGITIGRADE in DNA.species.species_traits)) DNA.species.species_traits += DIGITIGRADE diff --git a/tgstation.dme b/tgstation.dme index 632af6e52d1..6b6c0ffc346 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3950,8 +3950,10 @@ #include "modular_skyrat\modules\cum\effects\cumface.dm" #include "modular_skyrat\modules\cum\effects\cumstain.dm" #include "modular_skyrat\modules\customization\__DEFINES\augment.dm" +#include "modular_skyrat\modules\customization\__DEFINES\DNA.dm" #include "modular_skyrat\modules\customization\__DEFINES\lists.dm" #include "modular_skyrat\modules\customization\__DEFINES\loadout.dm" +#include "modular_skyrat\modules\customization\__HELPERS\dna.dm" #include "modular_skyrat\modules\customization\__HELPERS\global_lists.dm" #include "modular_skyrat\modules\customization\__HELPERS\mobs.dm" #include "modular_skyrat\modules\customization\__HELPERS\names.dm" diff --git a/tgui/packages/tgui/interfaces/DnaConsole/DnaConsoleEnzymes.js b/tgui/packages/tgui/interfaces/DnaConsole/DnaConsoleEnzymes.js index 23819a67c97..fa4eb9fc15d 100644 --- a/tgui/packages/tgui/interfaces/DnaConsole/DnaConsoleEnzymes.js +++ b/tgui/packages/tgui/interfaces/DnaConsole/DnaConsoleEnzymes.js @@ -69,6 +69,25 @@ const GeneticMakeupBufferInfo = (props, context) => { {!isViableSubject && ' (Delayed)'} + + +