diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 5759cb356131..1f63ec6b2908 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -55,8 +55,9 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) var/datum/blood_type/blood_type ///The type of mutant race the player is if applicable (i.e. potato-man) var/datum/species/species = new /datum/species/human - ///first value is mutant color - var/list/features = list("FFF") + /// Assoc list of feature keys to their value + /// Note if you set these manually, and do not update [unique_features] afterwards, it will likely be reset. + var/list/features = list("mcolor" = COLOR_WHITE) ///Stores the hashed values of the person's non-human features var/unique_features ///Stores the real name of the person who originally got this dna datum. Used primarely for changelings, @@ -548,27 +549,28 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) return dna -/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, list/default_mutation_genes, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/mutations, force_transfer_mutations) +/// Sets the DNA of the mob to the given DNA. +/mob/living/carbon/human/proc/hardset_dna(unique_identity, list/mutation_index, list/default_mutation_genes, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/mutations, force_transfer_mutations) //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 newrace.copy_properties_from(mrace) - set_species(newrace, icon_update=0) + set_species(newrace, icon_update = 0) if(newreal_name) - real_name = newreal_name + dna.real_name = newreal_name dna.generate_unique_enzymes() if(newblood_type) dna.blood_type = newblood_type - if(ui) - dna.unique_identity = ui - updateappearance(icon_update=0) + if(unique_identity) + dna.unique_identity = unique_identity + updateappearance(icon_update = 0) + + if(newfeatures) + dna.features = newfeatures + dna.generate_unique_features() if(LAZYLEN(mutation_index)) dna.mutation_index = mutation_index.Copy() @@ -578,17 +580,14 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.default_mutation_genes = mutation_index.Copy() domutcheck() - if(mrace || newfeatures || ui) + if(mrace || newfeatures || unique_identity) update_body() update_hair() - update_body_parts() update_mutations_overlay() - if(LAZYLEN(mutations)) - for(var/M in mutations) - var/datum/mutation/human/HM = M - if(HM.allow_transfer || force_transfer_mutations) - dna.force_give(new HM.type(HM.class, copymut=HM)) //using force_give since it may include exotic mutations that otherwise wont be handled properly + if(LAZYLEN(mutations) && force_transfer_mutations) + for(var/datum/mutation/human/mutation as anything in mutations) + dna.force_give(new mutation.type(mutation.class, copymut = mutation)) //using force_give since it may include exotic mutations that otherwise won't be handled properly /mob/living/carbon/proc/create_dna() dna = new /datum/dna(src) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index a2bd62aa885f..c1872e0782c2 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -19,6 +19,7 @@ //select which parts of the diskette to load var/include_se = FALSE //mutations var/include_ui = FALSE //appearance + var/include_uf = FALSE //features var/include_ue = FALSE //blood type, UE, and name var/loading = FALSE // Nice loading text @@ -63,7 +64,22 @@ . = pod /proc/grow_clone_from_record(obj/machinery/clonepod/pod, datum/data/record/R, empty) - return pod.growclone(R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["makeup"], R.fields["mindref"], R.fields["last_death"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"], empty, R.fields["mood"]) + return pod.growclone( + clonename = R.fields["name"], + ui = R.fields["UI"], + mutation_index = R.fields["SE"], + makeup = R.fields["makeup"], + mindref = R.fields["mindref"], + last_death = R.fields["last_death"], + mrace = R.fields["mrace"], + features = R.fields["features"], + factions = R.fields["factions"], + quirks = R.fields["quirks"], + insurance = R.fields["bank_account"], + traumas = R.fields["traumas"], + empty = empty, + mood = R.fields["mood"], + ) /obj/machinery/computer/cloning/process() if(!(scanner && LAZYLEN(pods) && autoprocess)) @@ -259,6 +275,7 @@ dat += "Unable to locate Health Implant.

" dat += "Unique Identifier:
[span_highlight("[active_record.fields["UI"]]")]
" + dat += "Unique Features:
[span_highlight("[active_record.fields["UF"]]")]
" dat += "Structural Enzymes:
" for(var/key in active_record.fields["SE"]) if(key != RACEMUT) @@ -273,10 +290,13 @@ dat += "

Inserted Disk

" dat += "Contents: " var/list/L = list() - if(diskette.fields["UI"]) - L += "Unique Identifier" + if(diskette.fields["UE"] && diskette.fields["name"] && diskette.fields["blood_type"]) L += "Unique Enzymes" + if(diskette.fields["UI"]) + L += "Unique Identifier" + if(diskette.fields["UF"]) + L += "Unique Features" if(diskette.fields["SE"]) L += "Structural Enzymes" dat += english_list(L, "Empty", " + ", " + ") @@ -441,6 +461,7 @@ overwrite_field_if_available(active_record, diskette, "blood_type") if(include_ui) overwrite_field_if_available(active_record, diskette, "UI") + overwrite_field_if_available(active_record, diskette, "UF") if(include_se) overwrite_field_if_available(active_record, diskette, "SE") @@ -552,11 +573,12 @@ R.fields["name"] = mob_occupant.real_name R.fields["id"] = copytext_char(md5(mob_occupant.real_name), 2, 6) - R.fields["UE"] = dna.unique_enzymes - R.fields["UI"] = dna.unique_identity + R.fields["UE"] = "[dna.unique_enzymes]" + R.fields["UI"] = "[dna.unique_identity]" + R.fields["UF"] = "[dna.unique_features]" R.fields["SE"] = dna.mutation_index R.fields["blood_type"] = dna.blood_type - R.fields["features"] = dna.features + R.fields["features"] = dna.features.Copy() R.fields["makeup"] = dna.default_mutation_genes R.fields["factions"] = mob_occupant.faction R.fields["quirks"] = list() diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index 451b2b09bbb0..6886963b44f9 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -210,7 +210,7 @@ stored_research = SSresearch.science_tech /obj/machinery/computer/scan_consolenew/ui_interact(mob/user, datum/tgui/ui) - + . = ..() // Most of ui_interact is spent setting variables for passing to the tgui // interface. // We can also do some general state processing here too as it's a good @@ -302,7 +302,7 @@ 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 data["subjectName"] = null data["subjectStatus"] = null @@ -1143,7 +1143,13 @@ return I = new /obj/item/dnainjector/timed(loc) - 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"]) + 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 @@ -1506,7 +1512,7 @@ scanner_occupant.real_name = buffer_slot["name"] scanner_occupant.name = buffer_slot["name"] scanner_occupant.dna.unique_enzymes = buffer_slot["UE"] - scanner_occupant.dna.blood_type = buffer_slot["blood_type"] + scanner_occupant.dna.blood_type = get_blood_type(buffer_slot["blood_type"]) scanner_occupant.radiation += rad_increase scanner_occupant.domutcheck() return TRUE @@ -1524,7 +1530,7 @@ scanner_occupant.real_name = buffer_slot["name"] scanner_occupant.name = buffer_slot["name"] scanner_occupant.dna.unique_enzymes = buffer_slot["UE"] - scanner_occupant.dna.blood_type = buffer_slot["blood_type"] + scanner_occupant.dna.blood_type = get_blood_type(buffer_slot["blood_type"]) scanner_occupant.radiation += rad_increase scanner_occupant.domutcheck() return TRUE diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm index 33951f8e8d4b..906deac653f9 100644 --- a/code/game/machinery/exp_cloner.dm +++ b/code/game/machinery/exp_cloner.dm @@ -9,7 +9,7 @@ internal_radio = FALSE //Start growing a human clone in the pod! -/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, makeup, mindref, last_death, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance) +/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, makeup, mindref, last_death, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas, empty, mood) if(panel_open) return NONE if(mess || attempting) diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index be60945b4233..747b52904c15 100644 --- a/code/game/objects/items/dna_injector.dm +++ b/code/game/objects/items/dna_injector.dm @@ -45,7 +45,7 @@ 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) + M.updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE) log_attack("[log_msg] [loc_name(user)]") return TRUE return FALSE diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 059974178c25..256fb0feb04a 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -112,12 +112,11 @@ podman.ckey = ckey_holder podman.gender = blood_gender podman.faction |= factions - if(!features["mcolor"]) - features["mcolor"] = "#59CE00" + for(var/V in quirks) new V(podman) - podman.hardset_dna(null,null,null,podman.real_name,blood_type, new /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman - podman.set_cloned_appearance() + podman.hardset_dna(null, null, null, podman.real_name, blood_type, /datum/species/pod, features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman + podman.dna.species.exotic_blood = max(reagents_add) || /datum/reagent/water log_cloning("[key_name(mind)] cloned as a podman via [src] in [parent] at [AREACOORD(parent)].") to_chat(podman, span_userdanger("You do not remember your death, how you died, or who killed you. See rule 1.6.")) //yogs diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index af39fdd088d5..6cb8f5e9b1e9 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -514,6 +514,7 @@ underwear = "Nude" update_body() update_hair() + dna.update_dna_identity() /mob/living/carbon/human/singularity_pull(S, current_size) ..() diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index a892565fa24f..e48767e4b7c7 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -55,12 +55,10 @@ There are several things that need to be remembered: //used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body. /mob/living/carbon/human/proc/update_mutant_bodyparts() - dna.species.handle_mutant_bodyparts(src) - + dna?.species.handle_mutant_bodyparts(src) /mob/living/carbon/human/update_body() - remove_overlay(BODY_LAYER) - dna.species.handle_body(src) + dna?.species.handle_body(src) ..() /mob/living/carbon/human/update_fire() @@ -887,4 +885,3 @@ generate/load female uniform sprites matching all previously decided variables update_inv_wear_mask() #undef RESOLVE_ICON_STATE - diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 8a9406445741..4c4036b9b159 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1,5 +1,4 @@ /datum/reagent/blood - data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null) name = "Blood" color = COLOR_BLOOD metabolization_rate = 5 //fast rate so it disappears fast. @@ -10,6 +9,22 @@ glass_desc = "Are you sure this is tomato juice?" shot_glass_icon_state = "shotglassred" + data = list( + "donor" = null, + "viruses" = null, + "blood_DNA" = null, + "blood_type" = null, + "resistances" = null, + "trace_chem" = null, + "mind" = null, + "ckey" = null, + "gender" = null, + "real_name" = null, + "cloneable" = null, + "factions" = null, + "quirks" = null + ) + /datum/reagent/blood/reaction_mob(mob/living/L, methods=TOUCH, reac_volume, show_message = TRUE, permeability = 1) var/datum/antagonist/bloodsucker/bloodsuckerdatum = IS_BLOODSUCKER(L) //bloodsucker start if(bloodsuckerdatum)