From 3121e4fb2d63fed8682ddee3bf8bb5311a8e125a Mon Sep 17 00:00:00 2001 From: Rob Nelson Date: Thu, 6 Feb 2014 23:07:35 -0800 Subject: [PATCH] DNA2 Bug Fixes - Part 2 We discovered that most of the problems were were having was because of BYOND passing lists (e.g. SE and UI) by-ref instead of the assumed by-val. This commit adds dna.Clone() and (UI|SE).Copy() where needed. These should be used where DNA or SE/UI lists are COPIED, otherwise changes made in the reference will affect the real strand. This change also messes with the gene activation logic. --- code/datums/diseases/dna_spread.dm | 16 +- code/game/dna/dna2.dm | 39 +- code/game/dna/dna2_domutcheck.dm | 345 +----------------- code/game/dna/dna2_helpers.dm | 4 +- code/game/dna/dna_modifier.dm | 62 ++-- code/game/dna/genes/disabilities.dm | 4 + code/game/dna/genes/gene.dm | 52 ++- code/game/dna/genes/monkey.dm | 6 +- code/game/dna/genes/powers.dm | 33 +- .../gamemodes/changeling/changeling_powers.dm | 10 +- code/game/gamemodes/events.dm | 8 +- code/game/machinery/cloning.dm | 4 +- .../objects/items/weapons/dna_injector.dm | 4 +- code/modules/admin/admin.dm | 19 + code/modules/admin/verbs/debug.dm | 18 +- code/modules/admin/verbs/randomverbs.dm | 8 +- code/modules/events/disease_outbreak.dm | 4 +- .../mob/living/carbon/brain/brain_item.dm | 2 +- .../mob/living/carbon/human/update_icons.dm | 11 + code/modules/mob/mob_transformation_simple.dm | 2 +- code/modules/mob/transform_procs.dm | 7 +- code/modules/organs/organ_external.dm | 2 +- 22 files changed, 242 insertions(+), 418 deletions(-) diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index 69a8eb6500..a4d85a5640 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -39,12 +39,14 @@ //Save original dna for when the disease is cured. src.original_dna["name"] = affected_mob.real_name - src.original_dna["UI"] = affected_mob.dna.UI - src.original_dna["SE"] = affected_mob.dna.SE + src.original_dna["UI"] = affected_mob.dna.UI.Copy() + src.original_dna["SE"] = affected_mob.dna.SE.Copy() affected_mob << "\red You don't feel like yourself.." - affected_mob.UpdateAppearance(strain_data["UI"]) - affected_mob.dna.SE = strain_data["SE"] + var/list/newUI=strain_data["UI"] + var/list/newSE=strain_data["SE"] + affected_mob.UpdateAppearance(newUI.Copy()) + affected_mob.dna.SE = newSE.Copy() affected_mob.dna.UpdateSE() affected_mob.real_name = strain_data["name"] domutcheck(affected_mob) @@ -56,8 +58,10 @@ /datum/disease/dnaspread/Del() if ((original_dna["name"]) && (original_dna["UI"]) && (original_dna["SE"])) - affected_mob.UpdateAppearance(original_dna["UI"]) - affected_mob.dna.SE = original_dna["SE"] + var/list/newUI=original_dna["UI"] + var/list/newSE=original_dna["SE"] + affected_mob.UpdateAppearance(newUI.Copy()) + affected_mob.dna.SE = newSE.Copy() affected_mob.dna.UpdateSE() affected_mob.real_name = original_dna["name"] diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index e8f4ddc4a8..744ef24eb4 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -16,17 +16,6 @@ #define DNA_HARDER_BOUNDS list(1,3049,3050,4095) #define DNA_HARD_BOUNDS list(1,3490,3500,4095) -// Defines which values mean "on" or "off". -// This is to make some of the more OP superpowers a larger PITA to activate, -// and to tell our new DNA datum which values to set in order to turn something -// on or off. -var/global/list/dna_activity_bounds[STRUCDNASIZE] - -// Used to determine what each block means (admin hax and species stuff on /vg/, mostly) -var/global/list/assigned_blocks[STRUCDNASIZE] - -var/global/list/datum/dna/gene/dna_genes[0] - // UI Indices (can change to mutblock style, if desired) #define DNA_UI_HAIR_R 1 #define DNA_UI_HAIR_G 2 @@ -43,6 +32,22 @@ var/global/list/datum/dna/gene/dna_genes[0] #define DNA_UI_HAIR_STYLE 13 #define DNA_UI_LENGTH 13 // Update this when you add something, or you WILL break shit. +#define DNA_SE_LENGTH 27 +// For later: +//#define DNA_SE_LENGTH 50 // Was STRUCDNASIZE, size 27. 15 new blocks added = 42, plus room to grow. + + +// Defines which values mean "on" or "off". +// This is to make some of the more OP superpowers a larger PITA to activate, +// and to tell our new DNA datum which values to set in order to turn something +// on or off. +var/global/list/dna_activity_bounds[DNA_SE_LENGTH] + +// Used to determine what each block means (admin hax and species stuff on /vg/, mostly) +var/global/list/assigned_blocks[DNA_SE_LENGTH] + +var/global/list/datum/dna/gene/dna_genes[0] + ///////////////// // GENE DEFINES ///////////////// @@ -64,7 +69,7 @@ var/global/list/datum/dna/gene/dna_genes[0] // Okay to read, but you're an idiot if you do. // BLOCK = VALUE - var/list/SE[STRUCDNASIZE] + var/list/SE[DNA_SE_LENGTH] var/list/UI[DNA_UI_LENGTH] // From old dna. @@ -84,7 +89,7 @@ var/global/list/datum/dna/gene/dna_genes[0] new_dna.mutantrace=mutantrace new_dna.real_name=real_name new_dna.species=species - for(var/b=1;b<=STRUCDNASIZE;b++) + for(var/b=1;b<=DNA_SE_LENGTH;b++) new_dna.SE[b]=SE[b] if(b<=DNA_UI_LENGTH) new_dna.UI[b]=UI[b] @@ -224,13 +229,12 @@ var/global/list/datum/dna/gene/dna_genes[0] // "Zeroes out" all of the blocks. /datum/dna/proc/ResetSE() - for(var/i = 1, i <= STRUCDNASIZE, i++) + for(var/i = 1, i <= DNA_SE_LENGTH, i++) SetSEValue(i,rand(1,1024),1) UpdateSE() // Set a DNA SE block's raw value. /datum/dna/proc/SetSEValue(var/block,var/value,var/defer=0) - //testing("SetSEBlock([block],[value],[defer]): [value] -> [nval]") if (block<=0) return ASSERT(value>=0) ASSERT(value<=4095) @@ -335,7 +339,7 @@ var/global/list/datum/dna/gene/dna_genes[0] if(UI.len != DNA_UI_LENGTH) ResetUIFrom(character) - if(length(struc_enzymes)!= 3*STRUCDNASIZE) + if(length(struc_enzymes)!= 3*DNA_SE_LENGTH) ResetSE() if(length(unique_enzymes) != 32) @@ -343,7 +347,7 @@ var/global/list/datum/dna/gene/dna_genes[0] else if(length(uni_identity) != 3*DNA_UI_LENGTH) uni_identity = "00600200A00E0110148FC01300B0095BD7FD3F4" - if(length(struc_enzymes)!= 3*STRUCDNASIZE) + if(length(struc_enzymes)!= 3*DNA_SE_LENGTH) struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6" // BACK-COMPAT! @@ -355,4 +359,3 @@ var/global/list/datum/dna/gene/dna_genes[0] unique_enzymes = md5(character.real_name) reg_dna[unique_enzymes] = character.real_name - diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm index a53fc49c29..954c86f2a6 100644 --- a/code/game/dna/dna2_domutcheck.dm +++ b/code/game/dna/dna2_domutcheck.dm @@ -23,336 +23,21 @@ // Prior state var/gene_prior_status = (gene.type in M.active_genes) + var/changed = gene_active != gene_prior_status || (gene.flags & GENE_ALWAYS_ACTIVATE) - if((gene_active && !gene_prior_status) || (gene.flags & GENE_ALWAYS_ACTIVATE)) - //testing("[gene.name] activated!") - gene.activate(M,connected,flags) - if(M) - if(!(gene.flags & GENE_ALWAYS_ACTIVATE)) + // If gene state has changed: + if(changed) + // Gene active (or ALWAYS ACTIVATE) + if(gene_active || (gene.flags & GENE_ALWAYS_ACTIVATE)) + testing("[gene.name] activated!") + gene.activate(M,connected,flags) + if(M) M.active_genes |= gene.type - M.update_icon=1 - else if(!gene_active && gene_prior_status) - //testing("[gene.name] deactivated!") - gene.deactivate(M,connected,flags) - if(M) - M.active_genes -= gene.type - M.update_icon = 1 - //else - // testing("[M] - Failed to activate [gene.name] - [gene_active?"+":"-"]active, [gene_prior_status?"+":"-"]prior") - - - // PROC CONTINUES BELOW AFTER COMMENTED CODE. - -/* Old, inflexibile -/proc/domutcheck(var/mob/living/M, var/connected, var/flags) - if (!M) return - - M.dna.check_integrity() - - M.disabilities = 0 - M.sdisabilities = 0 - var/old_mutations = M.mutations - M.mutations = list() - M.pass_flags = 0 -// M.see_in_dark = 2 -// M.see_invisible = 0 - - if(PLANT in old_mutations) - M.mutations.Add(PLANT) - if(SKELETON in old_mutations) - M.mutations.Add(SKELETON) - if(FAT in old_mutations) - M.mutations.Add(FAT) - if(HUSK in old_mutations) - M.mutations.Add(HUSK) - - var/inj = (flags & MUTCHK_FROM_INJECTOR) == MUTCHK_FROM_INJECTOR - var/forced = (flags & MUTCHK_FORCED) == MUTCHK_FORCED - - if(M.dna.GetSEState(NOBREATHBLOCK)) - if(forced || probinj(45,inj) || (mNobreath in old_mutations)) - M << "\blue You feel no need to breathe." - M.mutations.Add(mNobreath) - if(M.dna.GetSEState(REMOTEVIEWBLOCK)) - if(forced || probinj(45,inj) || (mRemote in old_mutations)) - M << "\blue Your mind expands" - M.mutations.Add(mRemote) - M.verbs += /mob/living/carbon/human/proc/remoteobserve - if(M.dna.GetSEState(REGENERATEBLOCK)) - if(forced || probinj(45,inj) || (mRegen in old_mutations)) - M << "\blue You feel better" - M.mutations.Add(mRegen) - if(M.dna.GetSEState(INCREASERUNBLOCK)) - if(forced || probinj(45,inj) || (mRun in old_mutations)) - M << "\blue Your leg muscles pulsate." - M.mutations.Add(mRun) - if(M.dna.GetSEState(REMOTETALKBLOCK)) - if(forced || probinj(45,inj) || (mRemotetalk in old_mutations)) - M << "\blue You expand your mind outwards" - M.mutations.Add(mRemotetalk) - M.verbs += /mob/living/carbon/human/proc/remotesay - if(M.dna.GetSEState(MORPHBLOCK)) - if(forced || probinj(45,inj) || (mMorph in old_mutations)) - M.mutations.Add(mMorph) - M << "\blue Your skin feels strange" - M.verbs += /mob/living/carbon/human/proc/morph - if(M.dna.GetSEState(COLDBLOCK)) - if(!(COLD_RESISTANCE in old_mutations)) - if(forced || probinj(15,inj) || (mHeatres in old_mutations)) - M.mutations.Add(mHeatres) - M << "\blue Your skin is icy to the touch" - else - if(forced || probinj(5,inj) || (mHeatres in old_mutations)) - M.mutations.Add(mHeatres) - M << "\blue Your skin is icy to the touch" - if(M.dna.GetSEState(HALLUCINATIONBLOCK)) - if(forced || probinj(45,inj) || (mHallucination in old_mutations)) - M.mutations.Add(mHallucination) - M << "\red Your mind says 'Hello'" - if(M.dna.GetSEState(NOPRINTSBLOCK)) - if(forced || probinj(45,inj) || (mFingerprints in old_mutations)) - M.mutations.Add(mFingerprints) - M << "\blue Your fingers feel numb" - if(M.dna.GetSEState(SHOCKIMMUNITYBLOCK)) - if(forced || probinj(45,inj) || (mShock in old_mutations)) - M.mutations.Add(mShock) - M << "\blue Your skin feels strange" - if(M.dna.GetSEState(SMALLSIZEBLOCK)) - if(forced || probinj(45,inj) || (mSmallsize in old_mutations)) - M << "\blue Your skin feels rubbery" - M.mutations.Add(mSmallsize) - M.pass_flags |= 1 - - - - if (M.dna.GetSEState(HULKBLOCK)) - if(forced || probinj(5,inj) || (HULK in old_mutations)) - M << "\blue Your muscles hurt." - M.mutations.Add(HULK) - if (M.dna.GetSEState(HEADACHEBLOCK)) - M.disabilities |= EPILEPSY - M << "\red You get a headache." - if (M.dna.GetSEState(FAKEBLOCK)) - M << "\red You feel strange." - if (prob(95)) - if(prob(50)) - randmutb(M) + M.update_icon = 1 + // If Gene is NOT active: else - randmuti(M) - else - randmutg(M) - if (M.dna.GetSEState(COUGHBLOCK)) - M.disabilities |= COUGHING - M << "\red You start coughing." - if (M.dna.GetSEState(CLUMSYBLOCK)) - M << "\red You feel lightheaded." - M.mutations.Add(CLUMSY) - if (M.dna.GetSEState(TWITCHBLOCK)) - M.disabilities |= TOURETTES - M << "\red You twitch." - if (M.dna.GetSEState(XRAYBLOCK)) - if(forced || probinj(30,inj) || (XRAY in old_mutations)) - M << "\blue The walls suddenly disappear." -// M.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) -// M.see_in_dark = 8 -// M.see_invisible = 2 - M.mutations.Add(XRAY) - if (M.dna.GetSEState(NERVOUSBLOCK)) - M.disabilities |= NERVOUS - M << "\red You feel nervous." - if (M.dna.GetSEState(FIREBLOCK)) - if(!(mHeatres in old_mutations)) - if(forced || probinj(30,inj) || (COLD_RESISTANCE in old_mutations)) - M << "\blue Your body feels warm." - M.mutations.Add(COLD_RESISTANCE) - else - if(forced || probinj(5,inj) || (COLD_RESISTANCE in old_mutations)) - M << "\blue Your body feels warm." - M.mutations.Add(COLD_RESISTANCE) - if (M.dna.GetSEState(BLINDBLOCK)) - M.sdisabilities |= BLIND - M << "\red You can't seem to see anything." - if (M.dna.GetSEState(TELEBLOCK)) - if(forced || probinj(15,inj) || (TK in old_mutations)) - M << "\blue You feel smarter." - M.mutations.Add(TK) - if (M.dna.GetSEState(DEAFBLOCK)) - M.sdisabilities |= DEAF - M.ear_deaf = 1 - M << "\red Its kinda quiet.." - if (M.dna.GetSEState(GLASSESBLOCK)) - M.disabilities |= NEARSIGHTED - M << "Your eyes feel weird..." - - /* If you want the new mutations to work, UNCOMMENT THIS. - if(istype(M, /mob/living/carbon)) - for (var/datum/mutations/mut in global_mutations) - mut.check_mutation(M) - */ - -//////////////////////////////////////////////////////////// Monkey Block - if (M.dna.GetSEState(MONKEYBLOCK) && istype(M, /mob/living/carbon/human)) - // human > monkey - var/mob/living/carbon/human/H = M - H.monkeyizing = 1 - var/list/implants = list() //Try to preserve implants. - for(var/obj/item/weapon/implant/W in H) - implants += W - W.loc = null - - if(!connected) - for(var/obj/item/W in (H.contents-implants)) - if (W==H.w_uniform) // will be teared - continue - H.drop_from_inventory(W) - M.monkeyizing = 1 - M.canmove = 0 - M.icon = null - M.invisibility = 101 - var/atom/movable/overlay/animation = new( M.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - flick("h2monkey", animation) - sleep(48) - del(animation) - - - var/mob/living/carbon/monkey/O = null - if(H.species.primitive) - O = new H.species.primitive(src) - else - H.gib() //Trying to change the species of a creature with no primitive var set is messy. - return - - if(M) - if (M.dna) - O.dna = M.dna - M.dna = null - - if (M.suiciding) - O.suiciding = M.suiciding - M.suiciding = null - - - for(var/datum/disease/D in M.viruses) - O.viruses += D - D.affected_mob = O - M.viruses -= D - - - for(var/obj/T in (M.contents-implants)) - del(T) - - O.loc = M.loc - - if(M.mind) - M.mind.transfer_to(O) //transfer our mind to the cute little monkey - - if (connected) //inside dna thing - var/obj/machinery/dna_scannernew/C = connected - O.loc = C - C.occupant = O - connected = null - O.real_name = text("monkey ([])",copytext(md5(M.real_name), 2, 6)) - O.take_overall_damage(M.getBruteLoss() + 40, M.getFireLoss()) - O.adjustToxLoss(M.getToxLoss() + 20) - O.adjustOxyLoss(M.getOxyLoss()) - O.stat = M.stat - O.a_intent = "hurt" - for (var/obj/item/weapon/implant/I in implants) - I.loc = O - I.implanted = O -// O.update_icon = 1 //queue a full icon update at next life() call - del(M) - return - - if (!M.dna.GetSEState(MONKEYBLOCK) && !istype(M, /mob/living/carbon/human)) - // monkey > human, - var/mob/living/carbon/monkey/Mo = M - Mo.monkeyizing = 1 - var/list/implants = list() //Still preserving implants - for(var/obj/item/weapon/implant/W in Mo) - implants += W - W.loc = null - if(!connected) - for(var/obj/item/W in (Mo.contents-implants)) - Mo.drop_from_inventory(W) - M.monkeyizing = 1 - M.canmove = 0 - M.icon = null - M.invisibility = 101 - var/atom/movable/overlay/animation = new( M.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - flick("monkey2h", animation) - sleep(48) - del(animation) - - var/mob/living/carbon/human/O = new( src ) - if(Mo.greaterform) - O.set_species(Mo.greaterform) - - if (M.dna.GetUIState(DNA_UI_GENDER)) - O.gender = FEMALE - else - O.gender = MALE - - if (M) - if (M.dna) - O.dna = M.dna - M.dna = null - - if (M.suiciding) - O.suiciding = M.suiciding - M.suiciding = null - - for(var/datum/disease/D in M.viruses) - O.viruses += D - D.affected_mob = O - M.viruses -= D - - //for(var/obj/T in M) - // del(T) - - O.loc = M.loc - - if(M.mind) - M.mind.transfer_to(O) //transfer our mind to the human - - if (connected) //inside dna thing - var/obj/machinery/dna_scannernew/C = connected - O.loc = C - C.occupant = O - connected = null - - var/i - while (!i) - var/randomname - if (O.gender == MALE) - randomname = capitalize(pick(first_names_male) + " " + capitalize(pick(last_names))) - else - randomname = capitalize(pick(first_names_female) + " " + capitalize(pick(last_names))) - if (findname(randomname)) - continue - else - O.real_name = randomname - i++ - O.UpdateAppearance() - O.take_overall_damage(M.getBruteLoss(), M.getFireLoss()) - O.adjustToxLoss(M.getToxLoss()) - O.adjustOxyLoss(M.getOxyLoss()) - O.stat = M.stat - for (var/obj/item/weapon/implant/I in implants) - I.loc = O - I.implanted = O -// O.update_icon = 1 //queue a full icon update at next life() call - del(M) - return -//////////////////////////////////////////////////////////// Monkey Block - if(M) - M.update_icon = 1 //queue a full icon update at next life() call - return null -/////////////////////////// DNA MISC-PROCS -*/ + testing("[gene.name] deactivated!") + gene.deactivate(M,connected,flags) + if(M) + M.active_genes -= gene.type + M.update_icon = 1 diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 216832f3cf..be6ced7907 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -38,7 +38,7 @@ /proc/randmuti(var/mob/living/M) if(!M) return M.dna.check_integrity() - M.dna.SetUIValue(rand(1,UNIDNASIZE),rand(1,4095)) + M.dna.SetUIValue(rand(1,DNA_UI_LENGTH),rand(1,4095)) // Scramble UI or SE. /proc/scramble(var/UI, var/mob/M, var/prob) @@ -52,7 +52,7 @@ M.UpdateAppearance() else - for(var/i = 1, i <= STRUCDNASIZE-1, i++) + for(var/i = 1, i <= DNA_SE_LENGTH-1, i++) if(prob(prob)) M.dna.SetSEValue(i,rand(1,4095),1) M.dna.UpdateSE() diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 335bbad426..eadbfb06e1 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -19,17 +19,18 @@ /datum/dna2/record/proc/GetData() var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0) - ser["ue"] = (types & DNA2_BUF_UE) == DNA2_BUF_UE - if(types & DNA2_BUF_SE) - ser["data"] = dna.SE - else - ser["data"] = dna.UI - ser["owner"] = src.dna.real_name - ser["label"] = name - if(types & DNA2_BUF_UI) - ser["type"] = "ui" - else - ser["type"] = "se" + if(dna) + ser["ue"] = (types & DNA2_BUF_UE) == DNA2_BUF_UE + if(types & DNA2_BUF_SE) + ser["data"] = dna.SE + else + ser["data"] = dna.UI + ser["owner"] = src.dna.real_name + ser["label"] = name + if(types & DNA2_BUF_UI) + ser["type"] = "ui" + else + ser["type"] = "se" return ser /////////////////////////// DNA MACHINES @@ -311,6 +312,8 @@ /obj/machinery/computer/scan_consolenew/New() ..() + for(var/i=0;i<3;i++) + buffers[i+1]=new /datum/dna2/record spawn(5) for(dir in list(NORTH,EAST,SOUTH,WEST)) connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir)) @@ -400,8 +403,8 @@ data["disk"] = diskData var/list/new_buffers = list() - for(var/datum/dna2/record/buf in buffers) - new_buffers.Add(buf.GetData()) + for(var/datum/dna2/record/buf in src.buffers) + new_buffers += list(buf.GetData()) data["buffers"]=new_buffers data["radiationIntensity"] = radiation_intensity @@ -635,7 +638,7 @@ if (href_list["selectSEBlock"] && href_list["selectSESubblock"]) // This chunk of code updates selected block / sub-block based on click (se stands for strutural enzymes) var/select_block = text2num(href_list["selectSEBlock"]) var/select_subblock = text2num(href_list["selectSESubblock"]) - if ((select_block <= STRUCDNASIZE) && (select_block >= 1)) + if ((select_block <= DNA_SE_LENGTH) && (select_block >= 1)) src.selected_se_block = select_block if ((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1)) src.selected_se_subblock = select_subblock @@ -663,9 +666,9 @@ var/real_SE_block=selected_se_block block = miniscramble(block, src.radiation_intensity, src.radiation_duration) if(prob(20)) - if (src.selected_se_block > 1 && src.selected_se_block < STRUCDNASIZE/2) + if (src.selected_se_block > 1 && src.selected_se_block < DNA_SE_LENGTH/2) real_SE_block++ - else if (src.selected_se_block > STRUCDNASIZE/2 && src.selected_se_block < STRUCDNASIZE) + else if (src.selected_se_block > DNA_SE_LENGTH/2 && src.selected_se_block < DNA_SE_LENGTH) real_SE_block-- //testing("Irradiated SE block [real_SE_block]:[src.selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!") @@ -730,7 +733,9 @@ if(src.connected.occupant && src.connected.occupant.dna) var/datum/dna2/record/databuf=new databuf.types = DNA2_BUF_UE - databuf.dna = src.connected.occupant.dna + databuf.dna = src.connected.occupant.dna.Clone() + if(ishuman(connected.occupant)) + databuf.dna.real_name=connected.occupant.name databuf.name = "Unique Identifier" src.buffers[bufferId] = databuf return 1 @@ -739,7 +744,9 @@ if(src.connected.occupant && src.connected.occupant.dna) var/datum/dna2/record/databuf=new databuf.types = DNA2_BUF_UI|DNA2_BUF_UE - databuf.dna = src.connected.occupant.dna + databuf.dna = src.connected.occupant.dna.Clone() + if(ishuman(connected.occupant)) + databuf.dna.real_name=connected.occupant.name databuf.name = "Unique Identifier + Unique Enzymes" src.buffers[bufferId] = databuf return 1 @@ -748,19 +755,21 @@ if(src.connected.occupant && src.connected.occupant.dna) var/datum/dna2/record/databuf=new databuf.types = DNA2_BUF_SE - databuf.dna = src.connected.occupant.dna + databuf.dna = src.connected.occupant.dna.Clone() + if(ishuman(connected.occupant)) + databuf.dna.real_name=connected.occupant.name databuf.name = "Structural Enzymes" src.buffers[bufferId] = databuf return 1 if (bufferOption == "clear") - src.buffers[bufferId]=null + src.buffers[bufferId]=new /datum/dna2/record() return 1 if (bufferOption == "changeLabel") var/datum/dna2/record/buf = src.buffers[bufferId] - buf.name = buf.name ? src.buffers[bufferId]["label"] : "New Label" - buf.name = sanitize(input("New Label:", "Edit Label", buf.name)) + var/text = sanitize(input(usr, "New Label:", "Edit Label", buf.name) as text|null) + buf.name = text src.buffers[bufferId] = buf return 1 @@ -784,7 +793,7 @@ if ((buf.types & DNA2_BUF_UE)) src.connected.occupant.real_name = buf.dna.real_name src.connected.occupant.name = buf.dna.real_name - src.connected.occupant.UpdateAppearance(buf.dna.UI) + src.connected.occupant.UpdateAppearance(buf.dna.UI.Copy()) else if (buf.types & DNA2_BUF_SE) src.connected.occupant.dna.SE = buf.dna.SE src.connected.occupant.dna.UpdateSE() @@ -800,7 +809,12 @@ var/datum/dna2/record/buf = src.buffers[bufferId] if(href_list["createBlockInjector"]) waiting_for_user_input=1 - var/blk = input(usr,"Select Block","Block") in all_dna_blocks(buf.GetData()) + var/list/selectedbuf + if(buf.types & DNA2_BUF_SE) + selectedbuf=buf.dna.SE + else + selectedbuf=buf.dna.UI + var/blk = input(usr,"Select Block","Block") in all_dna_blocks(selectedbuf) success = setInjectorBlock(I,blk,buf) else I.buf = buf diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm index e312111f6f..d844a61f89 100644 --- a/code/game/dna/genes/disabilities.dm +++ b/code/game/dna/genes/disabilities.dm @@ -36,6 +36,8 @@ M.sdisabilities|=sdisability if(activation_message) M << "\red [activation_message]" + else + testing("[name] has no activation message.") /datum/dna/gene/disability/deactivate(var/mob/M, var/connected, var/flags) if(mutation && (mutation in M.mutations)) @@ -46,6 +48,8 @@ M.sdisabilities &= ~sdisability if(deactivation_message) M << "\red [deactivation_message]" + else + testing("[name] has no deactivation message.") // Note: Doesn't seem to do squat, at the moment. /datum/dna/gene/disability/hallucinate diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm index 3bf5b5e5f7..21eec348bd 100644 --- a/code/game/dna/genes/gene.dm +++ b/code/game/dna/genes/gene.dm @@ -23,6 +23,12 @@ // Any of a number of GENE_ flags. var/flags=0 +/** +* Is the gene active in this mob's DNA? +*/ +/datum/dna/gene/proc/is_active(var/mob/M) + return M.active_genes && type in M.active_genes + // Return 1 if we can activate. // HANDLE MUTCHK_FORCED HERE! /datum/dna/gene/proc/can_activate(var/mob/M, var/flags) @@ -32,11 +38,43 @@ /datum/dna/gene/proc/activate(var/mob/M, var/connected, var/flags) return -// Called when the gene deactivates. Undo your magic here. -// Only called when the block is deactivated. +/** +* Called when the gene deactivates. Undo your magic here. +* Only called when the block is deactivated. +*/ /datum/dna/gene/proc/deactivate(var/mob/M, var/connected, var/flags) return +// This section inspired by goone's bioEffects. + +/** +* Called in each life() tick. +*/ +/datum/dna/gene/proc/OnMobLife(var/mob/M) + return + +/** +* Called when the mob dies +*/ +/datum/dna/gene/proc/OnMobDeath(var/mob/M) + return + +/** +* Called when the mob says shit +*/ +/datum/dna/gene/proc/OnSay(var/mob/M, var/message) + return message + +/** +* Called after the mob runs update_icons. +* +* @params M The subject. +* @params g Gender (m or f) +* @params fat Fat? (0 or 1) +*/ +/datum/dna/gene/proc/OnDrawUnderlays(var/mob/M, var/g, var/fat) + return 0 + ///////////////////// // BASIC GENES @@ -66,14 +104,10 @@ var/list/deactivation_messages=list() /datum/dna/gene/basic/can_activate(var/mob/M,var/flags) - if(mutation==0) - return 0 - - // Probability check - if(flags & MUTCHK_FORCED || probinj(activation_prob,(flags&MUTCHK_FORCED))) + if(flags & MUTCHK_FORCED) return 1 - - return 0 + // Probability check + return probinj(activation_prob,(flags&MUTCHK_FORCED)) /datum/dna/gene/basic/activate(var/mob/M) M.mutations.Add(mutation) diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm index 952f7df0f4..c3f1b0db88 100644 --- a/code/game/dna/genes/monkey.dm +++ b/code/game/dna/genes/monkey.dm @@ -9,6 +9,7 @@ /datum/dna/gene/monkey/activate(var/mob/living/M, var/connected, var/flags) if(!istype(M,/mob/living/carbon/human)) + //testing("Cannot monkey-ify [M], type is [M.type].") return var/mob/living/carbon/human/H = M H.monkeyizing = 1 @@ -44,7 +45,7 @@ if(M) if (M.dna) - O.dna = M.dna + O.dna = M.dna.Clone() M.dna = null if (M.suiciding) @@ -86,6 +87,7 @@ /datum/dna/gene/monkey/deactivate(var/mob/living/M, var/connected, var/flags) if(!istype(M,/mob/living/carbon/monkey)) + //testing("Cannot humanize [M], type is [M.type].") return var/mob/living/carbon/monkey/Mo = M Mo.monkeyizing = 1 @@ -119,7 +121,7 @@ if (M) if (M.dna) - O.dna = M.dna + O.dna = M.dna.Clone() M.dna = null if (M.suiciding) diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index a8a9eefee7..6684af4584 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -72,12 +72,17 @@ block=COLDBLOCK can_activate(var/mob/M,var/flags) + if(flags & MUTCHK_FORCED) + return !(/datum/dna/gene/basic/cold_resist in M.active_genes) // Probability check var/_prob = 15 if(COLD_RESISTANCE in M.mutations) _prob=5 if(probinj(_prob,(flags&MUTCHK_FORCED))) return 1 + + OnDrawUnderlays(var/mob/M,var/g,var/fat) + return "cold[fat]_s" */ /datum/dna/gene/basic/cold_resist @@ -89,7 +94,9 @@ block=FIREBLOCK can_activate(var/mob/M,var/flags) - + if(flags & MUTCHK_FORCED) + return 1 + // return !(/datum/dna/gene/basic/heat_resist in M.active_genes) // Probability check var/_prob=30 //if(mHeatres in M.mutations) @@ -97,6 +104,9 @@ if(probinj(_prob,(flags&MUTCHK_FORCED))) return 1 + OnDrawUnderlays(var/mob/M,var/g,var/fat) + return "fire[fat]_s" + /datum/dna/gene/basic/noprints name="No Prints" activation_messages=list("Your fingers feel numb.") @@ -149,6 +159,22 @@ return 0 return ..(M,flags) + OnDrawUnderlays(var/mob/M,var/g,var/fat) + if(fat) + return "hulk_[fat]_s" + else + return "hulk_[g]_s" + return 0 + + OnMobLife(var/mob/living/carbon/human/M) + if(!istype(M)) return + if(M.health <= 25) + M.mutations.Remove(HULK) + M.update_mutations() //update our mutation overlays + M << "\red You suddenly feel very weak." + M.Weaken(3) + M.emote("collapse") + /datum/dna/gene/basic/xray name="X-Ray Vision" activation_messages=list("The walls suddenly disappear.") @@ -164,4 +190,7 @@ activation_prob=15 New() - block=TELEBLOCK \ No newline at end of file + block=TELEBLOCK + + OnDrawUnderlays(var/mob/M,var/g,var/fat) + return "telekinesishead[fat]_s" \ No newline at end of file diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index a552ac1cd7..9652a90978 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -184,7 +184,7 @@ changeling.chem_charges -= 5 src.visible_message("[src] transforms!") changeling.geneticdamage = 30 - src.dna = chosen_dna + src.dna = chosen_dna.Clone() src.real_name = chosen_dna.real_name src.flavor_text = "" src.UpdateAppearance() @@ -236,7 +236,7 @@ del(animation) var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey(src) - O.dna = C.dna + O.dna = C.dna.Clone() C.dna = null for(var/obj/item/W in C) @@ -289,7 +289,7 @@ changeling.chem_charges-- C.remove_changeling_powers() C.visible_message("[C] transforms!") - C.dna = chosen_dna + C.dna = chosen_dna.Clone() var/list/implants = list() for (var/obj/item/weapon/implant/I in C) //Still preserving implants @@ -322,7 +322,7 @@ O.gender = FEMALE else O.gender = MALE - O.dna = C.dna + O.dna = C.dna.Clone() C.dna = null O.real_name = chosen_dna.real_name @@ -721,7 +721,7 @@ var/list/datum/dna/hivemind_bank = list() src << "Our sting appears ineffective against its DNA." return 0 T.visible_message("[T] transforms!") - T.dna = chosen_dna + T.dna = chosen_dna.Clone() T.real_name = chosen_dna.real_name T.UpdateAppearance() domutcheck(T, null) diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index 5b1b1494b5..51bcc39a37 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -163,8 +163,8 @@ continue var/datum/disease/dnaspread/D = new D.strain_data["name"] = H.real_name - D.strain_data["UI"] = H.dna.UI - D.strain_data["SE"] = H.dna.SE + D.strain_data["UI"] = H.dna.uni_identity + D.strain_data["SE"] = H.dna.struc_enzymes D.carrier = 1 D.holder = H D.affected_mob = H @@ -233,10 +233,10 @@ if (prob(25)) if (prob(75)) randmutb(H) - domutcheck(H,null,1) + domutcheck(H,null,MUTCHK_FORCED) else randmutg(H) - domutcheck(H,null,1) + domutcheck(H,null,MUTCHK_FORCED) for(var/mob/living/carbon/monkey/M in living_mob_list) var/turf/T = get_turf(M) if(!T) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index a7ad25934a..6f9d50053b 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -60,10 +60,10 @@ Initialize() buf.types=DNA2_BUF_SE var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4) - for(var/i=new_SE.len;i<=STRUCDNASIZE;i++) + for(var/i=new_SE.len;i<=DNA_SE_LENGTH;i++) new_SE += rand(1,1024) buf.dna.SE=new_SE - buf.dna.SetSEValue(MONKEYBLOCK,0xFFF) + buf.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) //Find a dead mob with a brain and client. diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index d0b19f88e9..95cf77dd21 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -72,7 +72,7 @@ if (!(NOCLONE in M.mutations)) // prevents drained people from having their DNA changed if (buf.types & DNA2_BUF_UI) if (!block) //isolated block? - M.UpdateAppearance(buf.dna) + M.UpdateAppearance(buf.dna.UI.Copy()) if (buf.types & DNA2_BUF_UE) //unique enzymes? yes M.real_name = buf.dna.real_name M.name = buf.dna.real_name @@ -83,7 +83,7 @@ uses-- if (buf.types & DNA2_BUF_SE) if (!block) //isolated block? - M.dna.SE = buf.dna.SE + M.dna.SE = buf.dna.SE.Copy() M.dna.UpdateSE() else M.dna.SetSEValue(block,src.GetValue()) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 3a5c7c2393..16b94ba54e 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -119,6 +119,25 @@ var/global/floorIsLava = 0 else body += "Animalize | " + // DNA2 - Admin Hax + if(iscarbon(M)) + body += "

" + body += "DNA Blocks:
" + var/bname + for(var/block=1;block<=DNA_SE_LENGTH;block++) + if(((block-1)%5)==0) + body += "" + bname = assigned_blocks[block] + body += "" + body += "
 12345
[block-1]" + if(bname) + var/bstate=M.dna.GetSEState(block) + var/bcolor="[(bstate)?"#006600":"#ff0000"]" + body += "[bname][block]" + else + body += "[block]" + body+="
" + body += {"

Rudimentary transformation:
These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.

Observer | diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 241c34d5d8..4131e46411 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -273,7 +273,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that if(istype(M, /mob/living/carbon/human)) log_admin("[key_name(src)] has made [M.key] a changeling.") spawn(10) - M.absorbed_dna[M.real_name] = M.dna + M.absorbed_dna[M.real_name] = M.dna.Clone() M.make_changeling() if(M.mind) M.mind.special_role = "Changeling" @@ -986,3 +986,19 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that usr << list2text(dead_mob_list,",") if("Clients") usr << list2text(clients,",") + +// DNA2 - Admin Hax +/client/proc/cmd_admin_toggle_block(var/mob/M,var/block) + if(!ticker) + alert("Wait until the game starts") + return + if(istype(M, /mob/living/carbon)) + M.dna.SetSEState(block,!M.dna.GetSEState(block)) + domutcheck(M,null,MUTCHK_FORCED) + M.update_mutations() + var/state="[M.dna.GetSEState(block)?"on":"off"]" + var/blockname=assigned_blocks[block] + message_admins("[key_name_admin(src)] has toggled [M.key]'s [blockname] block [state]!") + log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!") + else + alert("Invalid mob") diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 871567cc0a..77c972a40d 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -447,9 +447,13 @@ Traitors and the like can also be revived with the previous role mostly intact. if(record_found)//Pull up their name from database records if they did have a mind. new_character.dna = new()//Let's first give them a new DNA. new_character.dna.unique_enzymes = record_found.fields["b_dna"]//Enzymes are based on real name but we'll use the record for conformity. - new_character.dna.SE = record_found.fields["enzymes"]//This is the default of enzymes so I think it's safe to go with. + + // I HATE BYOND. HATE. HATE. - N3X + var/list/newSE= record_found.fields["enzymes"] + var/list/newUI = record_found.fields["identity"] + new_character.dna.SE = newSE.Copy() //This is the default of enzymes so I think it's safe to go with. new_character.dna.UpdateSE() - new_character.UpdateAppearance(record_found.fields["identity"])//Now we configure their appearance based on their unique identity, same as with a DNA machine or somesuch. + new_character.UpdateAppearance(newUI.Copy())//Now we configure their appearance based on their unique identity, same as with a DNA machine or somesuch. else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile. new_character.dna.ready_dna(new_character) diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index a424cdd72a..37ec642259 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -30,8 +30,8 @@ continue var/datum/disease/dnaspread/D = new D.strain_data["name"] = H.real_name - D.strain_data["UI"] = H.dna.UI - D.strain_data["SE"] = H.dna.SE + D.strain_data["UI"] = H.dna.UI.Copy() + D.strain_data["SE"] = H.dna.SE.Copy() D.carrier = 1 D.holder = H D.affected_mob = H diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 8fdf3c7976..93f56618a0 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -28,7 +28,7 @@ brainmob = new(src) brainmob.name = H.real_name brainmob.real_name = H.real_name - brainmob.dna = H.dna + brainmob.dna = H.dna.Clone() brainmob.timeofhostdeath = H.timeofdeath if(H.mind) H.mind.transfer_to(brainmob) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 636273993b..e982675891 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -366,8 +366,18 @@ proc/get_damage_icon_part(damage_state, body_part) var/add_image = 0 var/g = "m" if(gender == FEMALE) g = "f" + // DNA2 - Drawing underlays. + for(var/datum/dna/gene/gene in dna_genes) + if(!gene.block) + continue + if(gene.is_active(src)) + var/underlay=gene.OnDrawUnderlays(src,g,fat) + if(underlay) + standing.underlays += underlay + add_image = 1 for(var/mut in mutations) switch(mut) + /* if(HULK) if(fat) standing.underlays += "hulk_[fat]_s" @@ -380,6 +390,7 @@ proc/get_damage_icon_part(damage_state, body_part) if(TK) standing.underlays += "telekinesishead[fat]_s" add_image = 1 + */ if(LASER) standing.overlays += "lasereyes_s" add_image = 1 diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm index d4c91e4cfc..bea08693fb 100644 --- a/code/modules/mob/mob_transformation_simple.dm +++ b/code/modules/mob/mob_transformation_simple.dm @@ -41,7 +41,7 @@ M.real_name = src.real_name if(src.dna) - M.dna = src.dna + M.dna = src.dna.Clone() if(mind) mind.transfer_to(M) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 5ae6f0a7a3..9a2493f23a 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -29,10 +29,9 @@ O = new species.primitive(loc) - O.dna = dna - //O.dna.uni_identity = "000000000000000000DC00000660004DA0A0E00" - //O.dna.struc_enzymes = "[copytext(O.dna.struc_enzymes,1,1+3*(STRUCDNASIZE-1))]BB8" + O.dna = dna.Clone() O.dna.SetSEState(MONKEYBLOCK,1) + O.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) O.loc = loc O.viruses = viruses O.a_intent = "hurt" @@ -166,7 +165,7 @@ mind.transfer_to(O) if(O.mind.assigned_role == "Cyborg") O.mind.original = O - else if(mind.special_role) + else if(mind&&mind.special_role) O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") else O.key = key diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index f91fe51177..8ba5c0939a 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -903,7 +903,7 @@ obj/item/weapon/organ/head/proc/transfer_identity(var/mob/living/carbon/human/H) brainmob = new(src) brainmob.name = H.real_name brainmob.real_name = H.real_name - brainmob.dna = H.dna + brainmob.dna = H.dna.Clone() if(H.mind) H.mind.transfer_to(brainmob) brainmob.container = src