From f90ee4aa8c3c48741cc7e0ed792e5eab3b2703a1 Mon Sep 17 00:00:00 2001 From: phil235 Date: Sat, 19 Sep 2015 22:18:28 +0200 Subject: [PATCH] - Fixed monkey starting with no dna. - Fixed bugs with monkeyize/humanize: 7803 (humanized monkey nobloodtype) - Fixes 9298 monkeyed ling have troubles humanizing themself (already fixed?) - Fixes despawning clothes when monkeyizing. 11855 - Replaced check_dna_integrity proc by simpler has_dna proc when required. - created set_species() proc - fixed space retrovirus not transfering SE (despite having a domutcheck()). Still need to check if it needs a name = real_name. - I renamed mecha/var/dna to dna_lock to avoid confusion - I renamed an armor var in a species proc to armor_block to avoid confusion with species/var/armor. - I removed many if(dna) checks in lots of files. - I removed duplicate defense procs between human/proc/X and dna.species/proc/X since dna is now always set. - Anatomic panacea from changeling removes alien embryo correctly. 6247 - Fixes runtime when trying to put dna-less brain mmi into a dnalocked mech. - Removed carbon/var/list/features, we now only have dna.features and prefs.features - Remove hulk mutation from lizards and other species (Fixed 6413); only real humans can acquire hulk. (less work on sprites for each ones, fixes lizard tail not in hulk color) - Fixes cloning not setting up correctly dna UE and dna.real_name - I fixed the issue with sucked+cloned ling being unable to absorb - I fixed issue with changeling proc checking if they have the dna already not working. - Fixed 4095, low health hulk with DAA getting stuck in loop of acquiring/losing hulk. - I added a second layer for mutations to differientate mutations that go below and above the body layer (Fixes 7858) - Fixes 10048, the transform to initial appearence button was fucking up the dna. - Fixes cloning not setting up correctly dna UE and dna.real_name - Fixed the issue with sucked+cloned ling being unable to absorb - Fixed issue with changeling proc checking if they have the dna already not working. - Fixed 4095, low health hulk with DAA getting stuck in loop of acquiring/losing hulk. - Added a second layer for mutations to differientate mutations that go below and above the body layer (Fixes 7858) - Fixes 10048, the transform to initial appearence button was fucking up the dna. --- code/__DEFINES/misc.dm | 9 +- code/__HELPERS/unsorted.dm | 2 +- code/controllers/subsystem/objects.dm | 1 + code/controllers/subsystem/ticker.dm | 1 - code/datums/datumvars.dm | 5 +- .../diseases/advance/symptoms/genetics.dm | 11 +- code/datums/diseases/dna_spread.dm | 20 +- code/datums/diseases/transformation.dm | 5 +- code/datums/martial.dm | 44 +- code/datums/mind.dm | 8 +- code/datums/mutations.dm | 59 +- code/datums/spells/lichdom.dm | 4 +- code/datums/spells/wizard.dm | 3 +- code/game/atoms.dm | 6 +- code/game/dna.dm | 984 ++++-------------- code/game/gamemodes/abduction/abduction.dm | 16 +- .../gamemodes/abduction/abduction_gear.dm | 7 +- .../gamemodes/abduction/abduction_surgery.dm | 2 +- code/game/gamemodes/abduction/gland.dm | 6 +- .../gamemodes/abduction/machinery/console.dm | 2 - code/game/gamemodes/antag_spawner.dm | 1 + code/game/gamemodes/changeling/changeling.dm | 10 +- .../gamemodes/changeling/powers/absorb.dm | 2 +- .../changeling/powers/chameleon_skin.dm | 13 +- .../gamemodes/changeling/powers/humanform.dm | 9 +- .../gamemodes/changeling/powers/lesserform.dm | 6 +- .../gamemodes/changeling/powers/panacea.dm | 5 +- .../gamemodes/changeling/powers/tiny_prick.dm | 20 +- code/game/gamemodes/nuclear/pinpointer.dm | 8 +- code/game/gamemodes/objective.dm | 2 +- code/game/gamemodes/setupgame.dm | 2 +- .../shadowling/shadowling_abilities.dm | 4 +- .../special_shadowling_abilities.dm | 2 +- code/game/gamemodes/wizard/artefact.dm | 33 +- code/game/gamemodes/wizard/raginmages.dm | 2 +- code/game/jobs/job/job.dm | 6 +- code/game/machinery/cloning.dm | 30 +- code/game/machinery/computer/cloning.dm | 2 +- code/game/machinery/computer/dna_console.dm | 482 +++++++++ code/game/machinery/dna_scanner.dm | 167 +++ code/game/machinery/iv_drip.dm | 4 +- code/game/machinery/teleporter.dm | 4 +- code/game/mecha/combat/honker.dm | 2 +- code/game/mecha/mecha.dm | 14 +- code/game/mecha/mecha_topic.dm | 6 +- .../objects/items/devices/laserpointer.dm | 2 +- code/game/objects/items/devices/scanners.dm | 3 +- .../objects/items/weapons/dna_injector.dm | 4 +- code/game/objects/items/weapons/twohanded.dm | 2 +- code/game/objects/structures/mirror.dm | 25 +- code/modules/admin/secrets.dm | 12 +- code/modules/admin/verbs/one_click_antag.dm | 8 +- code/modules/admin/verbs/randomverbs.dm | 19 +- .../awaymissions/mission_code/wildwest.dm | 12 +- code/modules/client/preferences.dm | 26 +- code/modules/detectivework/detective_work.dm | 16 +- code/modules/detectivework/scanner.dm | 2 +- code/modules/events/holiday/halloween.dm | 9 +- code/modules/events/radiation_storm.dm | 4 +- code/modules/events/wizard/imposter.dm | 11 +- code/modules/events/wizard/race.dm | 9 +- .../kitchen machinery/processor.dm | 4 +- code/modules/hydroponics/hydroponics.dm | 2 +- code/modules/mob/interactive.dm | 30 +- code/modules/mob/living/carbon/brain/MMI.dm | 15 +- .../mob/living/carbon/brain/brain_item.dm | 11 +- .../mob/living/carbon/brain/posibrain.dm | 19 +- .../mob/living/carbon/carbon_defines.dm | 3 - code/modules/mob/living/carbon/human/blood.dm | 7 +- code/modules/mob/living/carbon/human/death.dm | 11 +- code/modules/mob/living/carbon/human/emote.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 19 +- .../living/carbon/human/human_attackhand.dm | 6 +- .../mob/living/carbon/human/human_damage.dm | 37 +- .../mob/living/carbon/human/human_defense.dm | 91 +- .../mob/living/carbon/human/human_helpers.dm | 8 +- .../mob/living/carbon/human/human_movement.dm | 9 +- .../mob/living/carbon/human/inventory.dm | 159 +-- code/modules/mob/living/carbon/human/life.dm | 26 +- code/modules/mob/living/carbon/human/say.dm | 6 +- .../mob/living/carbon/human/species.dm | 96 +- .../mob/living/carbon/human/species_types.dm | 6 +- .../mob/living/carbon/human/update_icons.dm | 38 +- code/modules/mob/living/carbon/monkey/life.dm | 2 +- .../mob/living/carbon/monkey/monkey.dm | 10 +- code/modules/mob/living/living.dm | 4 +- .../mob/living/silicon/pai/software.dm | 2 +- .../mob/living/simple_animal/slime/life.dm | 5 +- code/modules/mob/mob_transformation_simple.dm | 10 +- code/modules/mob/new_player/new_player.dm | 6 +- code/modules/mob/transform_procs.dm | 85 +- code/modules/ninja/ninja_event.dm | 2 +- code/modules/projectiles/gun.dm | 2 +- code/modules/projectiles/projectile/magic.dm | 12 +- .../Chemistry-Reagents/Drug-Reagents.dm | 4 +- .../Chemistry-Reagents/Medicine-Reagents.dm | 2 +- .../Chemistry-Reagents/Other-Reagents.dm | 3 +- .../Chemistry-Reagents/Toxin-Reagents.dm | 6 +- .../reagents/reagent_containers/syringes.dm | 14 +- .../research/xenobiology/xenobiology.dm | 7 +- icons/effects/genetics.dmi | Bin 7288 -> 7286 bytes tgstation.dme | 2 + 102 files changed, 1298 insertions(+), 1680 deletions(-) create mode 100644 code/game/machinery/computer/dna_console.dm create mode 100644 code/game/machinery/dna_scanner.dm diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index b03c73b01c0..9c9d1da8b9d 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -23,12 +23,13 @@ #define FRIDAY_13TH "Friday the 13th" //Human Overlays Indexes///////// -#define SPECIES_LAYER 26 // mutantrace colors... these are on a seperate layer in order to prvent +#define SPECIES_LAYER 27 // mutantrace colors... these are on a seperate layer in order to prvent +#define MUTATIONS_LAYER 26 //mutations. Hulk, Tk headglows, etc #define BODY_BEHIND_LAYER 25 #define BODY_LAYER 24 //underwear, undershirts, socks, eyes, lips(makeup) #define BODY_ADJ_LAYER 23 -#define MUTATIONS_LAYER 22 //Tk headglows etc. -#define AUGMENTS_LAYER 21 +#define AUGMENTS_LAYER 22 +#define FRONT_MUTATIONS_LAYER 21 //mutations that should appear above body and augments layer (e.g. laser eyes) #define DAMAGE_LAYER 20 //damage indicators (cuts and burns) #define UNIFORM_LAYER 19 #define ID_LAYER 18 @@ -49,7 +50,7 @@ #define R_HAND_LAYER 3 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands #define BODY_FRONT_LAYER 2 #define FIRE_LAYER 1 //If you're on fire -#define TOTAL_LAYERS 26 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; +#define TOTAL_LAYERS 27 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; //Human Overlay Index Shortcuts for alternate_worn_layer, layers //Because I *KNOW* somebody will think layer+1 means "above" diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 1bc6978f701..c4404bbb030 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1427,7 +1427,7 @@ B --><-- A stop_orbit() sleep(1) //sadly this is the only way to ensure the original orbit proc stops and resets the atom's transform. if (orbiting || !istype(A)) //post sleep re-check - return + return orbiting = A var/angle = 0 var/matrix/initial_transform = matrix(transform) diff --git a/code/controllers/subsystem/objects.dm b/code/controllers/subsystem/objects.dm index 61c7b804aea..24e206139b7 100644 --- a/code/controllers/subsystem/objects.dm +++ b/code/controllers/subsystem/objects.dm @@ -15,6 +15,7 @@ var/datum/subsystem/objects/SSobj NEW_SS_GLOBAL(SSobj) /datum/subsystem/objects/Initialize(timeofday, zlevel) + setupGenetics() for(var/atom/movable/AM in world) if (zlevel && AM.z != zlevel) continue diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index f351bd6d9cb..46f76fb41cd 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -59,7 +59,6 @@ var/datum/subsystem/ticker/ticker return ..() if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase() if(!syndicate_code_response) syndicate_code_response = generate_code_phrase() - setupGenetics() setupFactions() ..() diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 45f8ddab2f6..dc9d79c6b1b 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -813,8 +813,7 @@ body if(result) var/newtype = species_list[result] - hardset_dna(H, null, null, null, null, newtype) - H.regenerate_icons() + H.set_species(newtype) else if(href_list["purrbation"]) if(!check_rights(R_SPAWN)) return @@ -828,7 +827,7 @@ body usr << "Mob doesn't exist anymore" return - if(H.dna && H.dna.species.id == "human") + if(H.dna.species.id == "human") if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None") usr << "Put [H] on purrbation." H << "You suddenly feel valid." diff --git a/code/datums/diseases/advance/symptoms/genetics.dm b/code/datums/diseases/advance/symptoms/genetics.dm index cb730215ee9..68875694060 100644 --- a/code/datums/diseases/advance/symptoms/genetics.dm +++ b/code/datums/diseases/advance/symptoms/genetics.dm @@ -31,7 +31,8 @@ Bonus ..() if(prob(SYMPTOM_ACTIVATION_PROB * 5)) // 15% chance var/mob/living/carbon/M = A.affected_mob - if(!check_dna_integrity(M)) return + if(!M.has_dna()) + return switch(A.stage) if(4, 5) M << "[pick("Your skin feels itchy.", "You feel light headed.")]" @@ -44,7 +45,7 @@ Bonus possible_mutations = (bad_mutations | not_good_mutations) - mutations_list[RACEMUT] var/mob/living/carbon/M = A.affected_mob if(M) - if(!check_dna_integrity(M)) + if(!M.has_dna()) return archived_dna = M.dna.struc_enzymes @@ -52,10 +53,10 @@ Bonus /datum/symptom/genetic_mutation/End(datum/disease/advance/A) var/mob/living/carbon/M = A.affected_mob if(M && archived_dna) - if(!check_dna_integrity(M)) + if(!M.has_dna()) return - hardset_dna(M, se = archived_dna) - domutcheck(M) + M.dna.struc_enzymes = archived_dna + M.domutcheck() /* ////////////////////////////////////// diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index eb38e8689af..1ee18603a61 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -43,7 +43,7 @@ affected_mob.adjustToxLoss(2) affected_mob.updatehealth() if(4) - if(!src.transformed && !src.carrier) + if(!transformed && !carrier) //Save original dna for when the disease is cured. original_dna = new affected_mob.dna.type affected_mob.dna.copy_dna(original_dna) @@ -51,24 +51,22 @@ affected_mob << "You don't feel like yourself.." var/datum/dna/transform_dna = strain_data["dna"] - transform_dna.transfer_identity(affected_mob) + transform_dna.transfer_identity(affected_mob, transfer_SE = 1) affected_mob.real_name = affected_mob.dna.real_name + affected_mob.updateappearance(mutcolor_update=1) + affected_mob.domutcheck() - updateappearance(affected_mob) - domutcheck(affected_mob) - - src.transformed = 1 - src.carrier = 1 //Just chill out at stage 4 + transformed = 1 + carrier = 1 //Just chill out at stage 4 return /datum/disease/dnaspread/Del() if (original_dna && transformed && affected_mob) - original_dna.transfer_identity(affected_mob) + original_dna.transfer_identity(affected_mob, transfer_SE = 1) affected_mob.real_name = affected_mob.dna.real_name - - updateappearance(affected_mob) - domutcheck(affected_mob) + affected_mob.updateappearance(mutcolor_update=1) + affected_mob.domutcheck() affected_mob << "You feel more like yourself." ..() \ No newline at end of file diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 1b83792a13c..b5913c3e71a 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -201,9 +201,8 @@ if(3) if(ishuman(affected_mob)) var/mob/living/carbon/human/human = affected_mob - if(human.dna && human.dna.species.id != "slime") - hardset_dna(human, null, null, null, null, /datum/species/slime) - human.regenerate_icons() + if(human.dna.species.id != "slime") + human.set_species(/datum/species/slime) /datum/disease/transformation/corgi name = "The Barkening" diff --git a/code/datums/martial.dm b/code/datums/martial.dm index 96d8726d596..2929c4b0a2e 100644 --- a/code/datums/martial.dm +++ b/code/datums/martial.dm @@ -27,34 +27,22 @@ /datum/martial_art/proc/basic_hit(mob/living/carbon/human/A,mob/living/carbon/human/D) A.do_attack_animation(D) - var/damage = rand(0,9) + var/damage = rand(0,9) + A.dna.species.punchmod - var/atk_verb = "punch" + var/atk_verb = A.dna.species.attack_verb if(D.lying) atk_verb = "kick" - else if(A.dna) - atk_verb = A.dna.species.attack_verb - - if(A.dna) - damage += A.dna.species.punchmod if(!damage) - if(A.dna) - playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) - else - playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - D.visible_message("[A] has attempted to [atk_verb] [D]!") - add_logs(A, D, "attempted to [atk_verb]") - return 0 + playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) + D.visible_message("[A] has attempted to [atk_verb] [D]!") + add_logs(A, D, "attempted to [atk_verb]") + return 0 var/obj/item/organ/limb/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) var/armor_block = D.run_armor_check(affecting, "melee") - if(A.dna) - playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1) - else - playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) - + playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1) D.visible_message("[A] has [atk_verb]ed [D]!", \ "[A] has [atk_verb]ed [D]!") @@ -104,24 +92,18 @@ var/atk_verb = pick("left hook","right hook","straight punch") - var/damage = rand(5,8) - if(A.dna) - damage += A.dna.species.punchmod + var/damage = rand(5,8) + A.dna.species.punchmod if(!damage) - if(A.dna) - playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) - else - playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!") - add_logs(A, D, "attempted to hit", atk_verb) - return 0 + playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) + D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!") + add_logs(A, D, "attempted to hit", atk_verb) + return 0 var/obj/item/organ/limb/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) var/armor_block = D.run_armor_check(affecting, "melee") - playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) - + playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1) D.visible_message("[A] has hit [D] with a [atk_verb]!", \ "[A] has hit [D] with a [atk_verb]!") diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 116bc8ac19c..f84c04f531a 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -976,10 +976,10 @@ usr << "Resetting DNA failed!" else var/mob/living/carbon/C = current - C.dna = changeling.first_prof.dna + changeling.first_prof.dna.transfer_identity(C, transfer_SE=1) C.real_name = changeling.first_prof.name - updateappearance(C) - domutcheck(C) + C.updateappearance(mutcolor_update=1) + C.domutcheck() else if (href_list["nuclear"]) switch(href_list["nuclear"]) @@ -1409,7 +1409,7 @@ var/mob/living/carbon/human/H = current - hardset_dna(H,null,null,null,null,/datum/species/abductor,null) + H.set_species(/datum/species/abductor) var/datum/species/abductor/S = H.dna.species switch(role) diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm index 83455d194f7..dab76ebf7d9 100644 --- a/code/datums/mutations.dm +++ b/code/datums/mutations.dm @@ -16,6 +16,9 @@ var/text_gain_indication = "" var/text_lose_indication = "" var/list/visual_indicators = list() + var/above_body = 0 //wether the mutation appear above or below the body layer + var/list/species_allowed = list() //to restrict mutation to only certain species + var/health_req //minimum health required to acquire the mutation /datum/mutation/human/proc/force_give(mob/living/carbon/human/owner) set_block(owner) @@ -33,7 +36,7 @@ return before + injection + after /datum/mutation/human/proc/set_block(mob/living/carbon/owner, on = 1) - if(owner && istype(owner) && owner.dna) + if(owner && owner.has_dna()) owner.dna.struc_enzymes = set_se(owner.dna.struc_enzymes, on) /datum/mutation/human/proc/check_block_string(se_string) @@ -51,17 +54,19 @@ /datum/mutation/human/proc/on_acquiring(mob/living/carbon/human/owner) if(!owner || !istype(owner) || (src in owner.dna.mutations)) return 1 + if(species_allowed.len && !species_allowed.Find(owner.dna.species.id)) + return 1 + if(health_req && owner.health < health_req) + return 1 owner.dna.mutations.Add(src) - owner << text_gain_indication + if(text_gain_indication) + owner << text_gain_indication if(visual_indicators.len) - owner.update_mutation_overlays() + owner.update_mutations_overlay() /datum/mutation/human/proc/get_visual_indicator(mob/living/carbon/human/owner) return -/datum/mutation/human/proc/lose_indication(mob/living/carbon/human/owner) - owner.overlays.Remove(visual_indicators) - /datum/mutation/human/proc/on_attack_hand(mob/living/carbon/human/owner, atom/target) return @@ -76,9 +81,10 @@ /datum/mutation/human/proc/on_losing(mob/living/carbon/human/owner) if(owner && istype(owner) && (owner.dna.mutations.Remove(src))) - owner << text_lose_indication + if(text_lose_indication) + owner << text_lose_indication if(visual_indicators.len) - owner.update_mutation_overlays() + owner.update_mutations_overlay() return 0 return 1 @@ -96,6 +102,8 @@ get_chance = 15 lowest_value = 256 * 12 text_gain_indication = "Your muscles hurt!" + species_allowed = list("human") //no skeleton/lizard hulk + health_req = 25 /datum/mutation/human/hulk/New() ..() @@ -583,32 +591,47 @@ message = replacetext(message," muh valids "," getting my kicks ") return trim(message) - /datum/mutation/human/laser_eyes - name = "Laser Eyes" quality = POSITIVE dna_block = NON_SCANNABLE text_gain_indication = "You feel pressure building up behind your eyes." + above_body = 1 + +/datum/mutation/human/laser_eyes/New() + ..() + visual_indicators |= image("icon"='icons/effects/genetics.dmi', "icon_state"="lasereyes_s", "layer"=-FRONT_MUTATIONS_LAYER) + +/datum/mutation/human/laser_eyes/get_visual_indicator(mob/living/carbon/human/owner) + return visual_indicators[1] /datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target) if(owner.a_intent == "harm") owner.LaserEyes(target) +/mob/living/carbon/proc/update_mutations_overlay() + return -/mob/living/carbon/human/proc/update_mutation_overlays() - remove_overlay(MUTATIONS_LAYER) - var/image/standing +/mob/living/carbon/human/update_mutations_overlay() + remove_overlay(MUTATIONS_LAYER) //MUTATIONS_LAYER is behind the body layer + remove_overlay(FRONT_MUTATIONS_LAYER) //FRONT_MUTATIONS_LAYER is above the body layer + var/list/standing = list() + var/list/frontstanding = list() for(var/datum/mutation/human/CM in dna.mutations) + if(CM.species_allowed.len && !CM.species_allowed.Find(dna.species.id)) + CM.force_lose(src) + continue if(CM.visual_indicators.len) var/image/V = CM.get_visual_indicator(src) - if(!standing) - standing = V + if(CM.above_body) + frontstanding += V else - standing.overlays += V + standing += V - if(standing) + if(standing.len) overlays_standing[MUTATIONS_LAYER] = standing + if(frontstanding.len) + overlays_standing[FRONT_MUTATIONS_LAYER] = frontstanding apply_overlay(MUTATIONS_LAYER) - + apply_overlay(FRONT_MUTATIONS_LAYER) diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm index ee2189c36f4..f199a06048f 100644 --- a/code/datums/spells/lichdom.dm +++ b/code/datums/spells/lichdom.dm @@ -55,7 +55,7 @@ lich.real_name = user.mind.name user.mind.transfer_to(lich) - hardset_dna(lich,null,null,lich.real_name,null,/datum/species/skeleton) + lich.hardset_dna(null,null,lich.real_name,null,/datum/species/skeleton) lich << "Your bones clatter and shutter as they're pulled back into this world!" charge_max += 600 var/mob/old_body = current_body @@ -98,7 +98,7 @@ marked_item.desc = "A terrible aura surrounds this item, its very existence is offensive to life itself..." marked_item.color = "#003300" user << "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!" - hardset_dna(user, null, null, null, null, /datum/species/skeleton) + user.set_species(/datum/species/skeleton) current_body = user.mind.current if(ishuman(user)) var/mob/living/carbon/human/H = user diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm index a32bae29911..75d971cced4 100644 --- a/code/datums/spells/wizard.dm +++ b/code/datums/spells/wizard.dm @@ -41,7 +41,6 @@ clothes_req = 1 invocation = "BIRUZ BENNAR" invocation_type = "shout" - message = "You feel strong! You feel a pressure building behind your eyes!" range = -1 include_user = 1 centcom_cancast = 0 @@ -248,7 +247,7 @@ sound="sound/magic/Blind.ogg" /obj/effect/proc_holder/spell/targeted/genetic/blind - disabilities = 1 + disabilities = BLIND duration = 300 sound="sound/magic/Blind.ogg" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index a59c0d7c867..373d98c3b36 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -280,11 +280,11 @@ var/list/blood_splatter_icons = list() //returns 1 if made bloody, returns 0 otherwise /atom/proc/add_blood(mob/living/carbon/M) - if(ishuman(M) && M.dna) + if(ishuman(M)) var/mob/living/carbon/human/H = M if(NOBLOOD in H.dna.species.specflags) return 0 - if(rejects_blood() || !istype(M) || !check_dna_integrity(M)) + if(rejects_blood() || !M.has_dna()) return 0 return 1 @@ -358,7 +358,7 @@ var/list/blood_splatter_icons = list() // Only adds blood on the floor -- Skie /atom/proc/add_blood_floor(mob/living/carbon/M) if(istype(src, /turf/simulated)) - if(check_dna_integrity(M)) //mobs with dna = (monkeys + humans at time of writing) + if(M.has_dna()) //mobs with dna = (monkeys + humans at time of writing) var/obj/effect/decal/cleanable/blood/B = locate() in contents if(!B) blood_splatter(src,M,1) diff --git a/code/game/dna.dm b/code/game/dna.dm index b402edbda36..59ae91cce50 100644 --- a/code/game/dna.dm +++ b/code/game/dna.dm @@ -1,19 +1,4 @@ -#define INJECTOR_TIMEOUT 300 -#define REJUVENATORS_INJECT 15 -#define REJUVENATORS_MAX 90 -#define NUMBER_OF_BUFFERS 3 -#define RADIATION_STRENGTH_MAX 15 -#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has a more range - -#define RADIATION_DURATION_MAX 30 -#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate - -#define RADIATION_IRRADIATION_MULTIPLIER 0.2 //multiplier for how much radiation a test subject recieves - -#define BAD_MUTATION_DIFFICULTY 2 -#define GOOD_MUTATION_DIFFICULTY 4 -#define OP_MUTATION_DIFFICULTY 5 /////////////////////////// DNA DATUM /datum/dna var/unique_enzymes @@ -27,26 +12,26 @@ var/mob/living/carbon/holder /datum/dna/New(mob/living/carbon/new_holder) - if(new_holder && istype(new_holder)) + if(new_holder) holder = new_holder -/datum/dna/proc/transfer_identity(mob/living/carbon/destination) - if(check_dna_integrity(destination)) - destination.dna.unique_enzymes = unique_enzymes - destination.dna.uni_identity = uni_identity - destination.dna.blood_type = blood_type - hardset_dna(destination, null, null, null, null, species.type) - destination.dna.features = features - destination.dna.real_name = real_name - destination.dna.mutations = mutations +/datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0) + destination.dna.unique_enzymes = unique_enzymes + destination.dna.uni_identity = uni_identity + destination.dna.blood_type = blood_type + destination.set_species(species.type, icon_update=0) + destination.dna.features = features + destination.dna.real_name = real_name + if(transfer_SE) + destination.dna.struc_enzymes = struc_enzymes /datum/dna/proc/copy_dna(datum/dna/new_dna) new_dna.unique_enzymes = unique_enzymes new_dna.struc_enzymes = struc_enzymes new_dna.uni_identity = uni_identity new_dna.blood_type = blood_type - new_dna.species = new species.type new_dna.features = features + new_dna.species = new species.type new_dna.real_name = real_name new_dna.mutations = mutations @@ -70,55 +55,72 @@ for(var/datum/mutation/human/HM in group) HM.force_lose(holder) -/datum/dna/proc/generate_uni_identity(mob/living/carbon/character) +/datum/dna/proc/generate_uni_identity() . = "" var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS) - if(istype(character)) - L[DNA_GENDER_BLOCK] = construct_block((character.gender!=MALE)+1, 2) - if(istype(character, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = character - if(!H.dna.species) - hardset_dna(H, null, null, null, null, /datum/species/human) - if(!hair_styles_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, hair_styles_list, hair_styles_male_list, hair_styles_female_list) - L[DNA_HAIR_STYLE_BLOCK] = construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len) - L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color) - if(!facial_hair_styles_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, facial_hair_styles_list, facial_hair_styles_male_list, facial_hair_styles_female_list) - L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len) - L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color) - L[DNA_SKIN_TONE_BLOCK] = construct_block(skin_tones.Find(H.skin_tone), skin_tones.len) - L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color) + + L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2) + if(ishuman(holder)) + var/mob/living/carbon/human/H = holder + if(!hair_styles_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, hair_styles_list, hair_styles_male_list, hair_styles_female_list) + L[DNA_HAIR_STYLE_BLOCK] = construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len) + L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color) + if(!facial_hair_styles_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, facial_hair_styles_list, facial_hair_styles_male_list, facial_hair_styles_female_list) + L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len) + L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color) + L[DNA_SKIN_TONE_BLOCK] = construct_block(skin_tones.Find(H.skin_tone), skin_tones.len) + L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color) for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) if(L[i]) . += L[i] else . += random_string(DNA_BLOCK_SIZE,hex_characters) return . -/datum/dna/proc/generate_struc_enzymes(mob/living/carbon/character) - var/list/L = list("0","1","2","3","4","5","6") +/datum/dna/proc/generate_struc_enzymes() var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS) var/result = "" for(var/datum/mutation/human/A in good_mutations + bad_mutations + not_good_mutations) - if(A.name == RACEMUT && istype(character,/mob/living/carbon/monkey)) + if(A.name == RACEMUT && ismonkey(holder)) sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE) - character.dna.mutations.Add(A) + mutations |= A else - sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, L) + sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6")) for(var/B in sorting) result += B return result -/datum/dna/proc/generate_unique_enzymes(mob/living/carbon/character) +/datum/dna/proc/generate_unique_enzymes() . = "" - if(istype(character)) - real_name = character.real_name - . += md5(character.real_name) + if(istype(holder)) + real_name = holder.real_name + . += md5(holder.real_name) else - . += repeat_string(DNA_UNIQUE_ENZYMES_LEN, "0") + . += random_string(DNA_UNIQUE_ENZYMES_LEN, hex_characters) return . +/datum/dna/proc/update_ui_block(blocknumber) + if(!blocknumber || !ishuman(holder)) + return + var/mob/living/carbon/human/H = holder + switch(blocknumber) + if(DNA_HAIR_COLOR_BLOCK) + setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color)) + if(DNA_FACIAL_HAIR_COLOR_BLOCK) + setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color)) + if(DNA_SKIN_TONE_BLOCK) + setblock(uni_identity, blocknumber, construct_block(skin_tones.Find(H.skin_tone), skin_tones.len)) + if(DNA_EYE_COLOR_BLOCK) + setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color)) + if(DNA_GENDER_BLOCK) + setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2)) + if(DNA_FACIAL_HAIR_STYLE_BLOCK) + setblock(uni_identity, blocknumber, construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len)) + if(DNA_HAIR_STYLE_BLOCK) + setblock(uni_identity, blocknumber, construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len)) + /datum/dna/proc/mutations_say_mods(message) if(message) for(var/datum/mutation/human/M in mutations) @@ -131,79 +133,130 @@ spans |= M.get_spans() return spans -/proc/hardset_dna(mob/living/carbon/owner, ui, se, real_name, blood_type, datum/species/mrace, features) - if(!ismonkey(owner) && !ishuman(owner)) - return - if(!owner.dna) - create_dna(owner, mrace) +/datum/dna/proc/is_same_as(datum/dna/D) + if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name) + if(species.type == D.species.type && features == D.features && blood_type == D.blood_type) + return 1 + return 0 - if(mrace && !ismonkey(owner)) - if(owner.dna.species.exotic_blood) - var/datum/reagent/exotic_blood = new owner.dna.species.exotic_blood - owner.reagents.del_reagent(exotic_blood.id) - owner.dna.species = new mrace() +//used to update dna UI, UE, and dna.real_name. +/datum/dna/proc/update_dna_identity() + uni_identity = generate_uni_identity() + unique_enzymes = generate_unique_enzymes() - if(features) - owner.dna.features = features +/datum/dna/proc/initialize_dna(newblood_type) + if(newblood_type) + blood_type = newblood_type + unique_enzymes = generate_unique_enzymes() + uni_identity = generate_uni_identity() + struc_enzymes = generate_struc_enzymes() + features = list("mcolor" = "FFF", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None") - if(real_name) - owner.real_name = real_name - owner.dna.generate_unique_enzymes(owner) - if(blood_type) - owner.dna.blood_type = blood_type - if(ui) - owner.dna.uni_identity = ui - updateappearance(owner) +/////////////////////////// DNA MOB-PROCS ////////////////////// - if(se) - owner.dna.struc_enzymes = se - domutcheck(owner) - - check_dna_integrity(owner) - - owner.regenerate_icons() +/mob/proc/set_species(datum/species/mrace, icon_update = 1) return -/proc/check_dna_integrity(mob/living/carbon/character) - if(!character || !(istype(character, /mob/living/carbon/human) || istype(character, /mob/living/carbon/monkey))) //Evict xenos from carbon 2012 +/mob/living/carbon/set_species(datum/species/mrace, icon_update = 1) + if(has_dna()) + if(dna.species.exotic_blood) + var/datum/reagent/EB = dna.species.exotic_blood + reagents.del_reagent(initial(EB.id)) + dna.species = new mrace() + +/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1) + ..() + if(icon_update) + update_body() + update_hair() + update_mutcolor() + update_mutations_overlay()// no lizard with human hulk overlay please. + + +/mob/proc/has_dna() + return + +/mob/living/carbon/has_dna() + return dna + + +/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures) + + if(newfeatures) + dna.features = newfeatures + + if(mrace) + set_species(mrace, icon_update=0) + + if(newreal_name) + real_name = newreal_name + dna.generate_unique_enzymes() + + if(newblood_type) + dna.blood_type = newblood_type + + if(ui) + dna.uni_identity = ui + updateappearance(icon_update=0) + + if(se) + dna.struc_enzymes = se + domutcheck() + + if(mrace || newfeatures || ui) + update_body() + update_hair() + update_mutcolor() + update_mutations_overlay() + + +/mob/living/carbon/proc/create_dna() + dna = new /datum/dna(src) + if(!dna.species) + dna.species = new /datum/species/human() + +//proc used to update the mob's appearance after its dna UI has been changed +/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) + if(!has_dna()) return - if(!character.dna) - if(ready_dna(character)) - return character.dna + gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE + +mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) + ..() + var/structure = dna.uni_identity + hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK)) + facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK)) + skin_tone = skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), skin_tones.len)] + eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK)) + facial_hair_style = facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), facial_hair_styles_list.len)] + hair_style = hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), hair_styles_list.len)] + if(icon_update) + update_body() + update_hair() + if(mutcolor_update) + update_mutcolor() + if(mutations_overlay_update) + update_mutations_overlay() + + +/mob/proc/domutcheck() + return + +/mob/living/carbon/domutcheck() + if(!has_dna()) return - if(length(character.dna.uni_identity) != DNA_UNI_IDENTITY_BLOCKS*DNA_BLOCK_SIZE) - character.dna.uni_identity = character.dna.generate_uni_identity(character) - if(length(character.dna.struc_enzymes)!= DNA_STRUC_ENZYMES_BLOCKS*DNA_BLOCK_SIZE) - character.dna.struc_enzymes = character.dna.generate_struc_enzymes() - if(!character.dna.real_name || length(character.dna.unique_enzymes) != DNA_UNIQUE_ENZYMES_LEN) - character.dna.unique_enzymes = character.dna.generate_unique_enzymes(character) - return character.dna + for(var/datum/mutation/human/A in good_mutations | bad_mutations | not_good_mutations) + if(ismob(A.check_block(src))) + return //we got monkeyized/humanized, this mob will be deleted, no need to continue. -/proc/ready_dna(mob/living/carbon/character, blood_type) - if(!istype(character, /mob/living/carbon/monkey) && !istype(character, /mob/living/carbon/human)) - return - if(!character.dna) - create_dna(character) - if(blood_type) - character.dna.blood_type = blood_type - character.dna.real_name = character.real_name - character.dna.uni_identity = character.dna.generate_uni_identity(character) - character.dna.struc_enzymes = character.dna.generate_struc_enzymes(character) - character.dna.unique_enzymes = character.dna.generate_unique_enzymes(character) - character.dna.features = character.features - return character.dna + update_mutations_overlay() -/proc/create_dna(mob/living/carbon/C, datum/species/S) //don't use this unless you're about to use hardset_dna or ready_dna - C.dna = new /datum/dna(C) - C.dna.holder = C - if(S) C.dna.species = new S() // do not remove; this is here to prevent runtimes -/////////////////////////// DNA DATUM -/////////////////////////// DNA HELPER-PROCS +/////////////////////////// DNA HELPER-PROCS ////////////////////////////// /proc/getleftblocks(input,blocknumber,blocksize) if(blocknumber > 1) return copytext(input,1,((blocksize*blocknumber)-(blocksize-1))) @@ -219,45 +272,35 @@ if(!istring || !blocknumber || !replacement || !blocksize) return 0 return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize) -/proc/scramble(input,rs,rd) - var/length = length(input) - var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER) - if(ran == 0) ran = pick(-1,1) //hacky, statistically should almost never happen. 0-change makes people mad though - else if(ran < 0) ran = round(ran) //negative, so floor it - else ran = -round(-ran) //positive, so ceiling it - return num2hex(Wrap(hex2num(input)+ran, 0, 16**length), length) - -/proc/randomize_radiation_accuracy(position_we_were_supposed_to_hit, radduration, number_of_blocks) - return Wrap(round(position_we_were_supposed_to_hit + gaussian(0, RADIATION_ACCURACY_MULTIPLIER/radduration), 1), 1, number_of_blocks+1) - /proc/randmut(mob/living/carbon/M, list/candidates, difficulty = 2) - if(!check_dna_integrity(M)) + if(!M.has_dna()) return var/datum/mutation/human/num = pick(candidates) . = num.force_give(M) return /proc/randmutb(mob/living/carbon/M) - if(!check_dna_integrity(M)) + if(!M.has_dna()) return var/datum/mutation/human/HM = pick((bad_mutations | not_good_mutations) - mutations_list[RACEMUT]) . = HM.force_give(M) /proc/randmutg(mob/living/carbon/M) - if(!check_dna_integrity(M)) + if(!M.has_dna()) return var/datum/mutation/human/HM = pick(good_mutations) . = HM.force_give(M) /proc/randmuti(mob/living/carbon/M) - if(!check_dna_integrity(M)) return - var/num = rand(1, DNA_STRUC_ENZYMES_BLOCKS) + if(!M.has_dna()) + return + var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS) var/newdna = setblock(M.dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, hex_characters)) M.dna.uni_identity = newdna return /proc/clean_dna(mob/living/carbon/M) - if(!check_dna_integrity(M)) + if(!M.has_dna()) return M.dna.remove_all_mutations() @@ -266,691 +309,20 @@ randmut(M, candidates, difficulty) /proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability) - if(!check_dna_integrity(M)) + if(!M.has_dna()) return 0 if(se) for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++) if(prob(probability)) M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, hex_characters)) - domutcheck(M) + M.domutcheck() if(ui) for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) if(prob(probability)) M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, hex_characters)) - updateappearance(M) + M.updateappearance() return 1 -/////////////////////////// DNA HELPER-PROCS - -/////////////////////////// DNA MISC-PROCS -/proc/updateappearance(mob/living/carbon/C) - if(!check_dna_integrity(C)) - return 0 - - var/structure = C.dna.uni_identity - C.gender = (deconstruct_block(getblock(structure, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE - if(istype(C, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = C - H.hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK)) - H.facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK)) - H.skin_tone = skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), skin_tones.len)] - H.eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK)) - H.facial_hair_style = facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), facial_hair_styles_list.len)] - H.hair_style = hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), hair_styles_list.len)] - - H.update_body() - H.update_hair() - return 1 - -/proc/domutcheck(mob/living/carbon/M) - if(!check_dna_integrity(M)) - return 0 - - var/mob/living/carbon/C = M - var/mob/living/carbon/temp - - for(var/datum/mutation/human/A in good_mutations | bad_mutations | not_good_mutations) - temp = A.check_block(C) - if(ismob(temp)) - C = temp - -//////////////////////////////////////////////////////////// Monkey Block - if(M) - M.regenerate_icons() - return 1 -/////////////////////////// DNA MISC-PROCS - - -/////////////////////////// DNA MACHINES -/obj/machinery/dna_scannernew - name = "\improper DNA scanner" - desc = "It scans DNA structures." - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "scanner" - density = 1 - var/locked = 0 - anchored = 1 - use_power = 1 - idle_power_usage = 50 - active_power_usage = 300 - var/damage_coeff - var/scan_level - var/precision_coeff - -/obj/machinery/dna_scannernew/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/clonescanner(null) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(null) - component_parts += new /obj/item/weapon/stock_parts/console_screen(null) - component_parts += new /obj/item/stack/cable_coil(null, 1) - component_parts += new /obj/item/stack/cable_coil(null, 1) - RefreshParts() - - -/obj/machinery/dna_scannernew/RefreshParts() - scan_level = 0 - damage_coeff = 0 - precision_coeff = 0 - for(var/obj/item/weapon/stock_parts/scanning_module/P in component_parts) - scan_level += P.rating - for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts) - precision_coeff = P.rating - for(var/obj/item/weapon/stock_parts/micro_laser/P in component_parts) - damage_coeff = P.rating - -/obj/machinery/dna_scannernew/update_icon() - - //no power or maintenance - if(stat & (NOPOWER|BROKEN)) - icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_unpowered" - return - - if((stat & MAINT) || panel_open) - icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_maintenance" - return - - //running and someone in there - if(occupant) - icon_state = initial(icon_state)+ "_occupied" - return - - //running - icon_state = initial(icon_state)+ (state_open ? "_open" : "") - -/obj/machinery/dna_scannernew/power_change() - ..() - update_icon() - -/obj/machinery/dna_scannernew/proc/toggle_open(mob/user) - if(panel_open) - user << "Close the maintenance panel first." - return - - if(state_open) - close_machine() - return - - else if(locked) - user << "The bolts are locked down, securing the door shut." - return - - open_machine() - -/obj/machinery/dna_scannernew/container_resist() - var/mob/living/user = usr - var/breakout_time = 2 - if(state_open || !locked) //Open and unlocked, no need to escape - state_open = 1 - return - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT - user << "You lean on the back of [src] and start pushing the door open... (this will take about [breakout_time] minutes.)" - user.visible_message("You hear a metallic creaking from [src]!") - - if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds - if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked) - return - - locked = 0 - visible_message("[user] successfully broke out of [src]!") - user << "You successfully break out of [src]!" - - open_machine() - -/obj/machinery/dna_scannernew/close_machine() - if(!state_open) - return 0 - - ..() - - // search for ghosts, if the corpse is empty and the scanner is connected to a cloner - if(occupant) - if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \ - || locate(/obj/machinery/computer/cloning, get_step(src, SOUTH)) \ - || locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \ - || locate(/obj/machinery/computer/cloning, get_step(src, WEST))) - - occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!") - return 1 - -/obj/machinery/dna_scannernew/open_machine() - if(state_open) - return 0 - - ..() - - return 1 - -/obj/machinery/dna_scannernew/relaymove(mob/user as mob) - if(user.stat || locked) - return - - open_machine() - return - -/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params) - - if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant... - update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed - return - - if(exchange_parts(user, I)) - return - - if(default_pry_open(I)) - return - - if(default_deconstruction_crowbar(I)) - return - - if(istype(I, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = I - if(!ismob(G.affecting)) - return - - if(!state_open) - user << "Open the scanner first." - return - - var/mob/M = G.affecting - M.loc = loc - user.stop_pulling() - qdel(G) - -/obj/machinery/dna_scannernew/attack_hand(mob/user) - if(..(user,1,0)) //don't set the machine, since there's no dialog - return - - toggle_open(user) - -/obj/machinery/dna_scannernew/blob_act() - if(prob(75)) - qdel(src) - - -//DNA COMPUTER -/obj/machinery/computer/scan_consolenew - name = "\improper DNA scanner access console" - desc = "Scan DNA." - icon_screen = "dna" - icon_keyboard = "med_key" - density = 1 - circuit = /obj/item/weapon/circuitboard/scan_consolenew - var/radduration = 2 - var/radstrength = 1 - - var/list/buffer[NUMBER_OF_BUFFERS] - - var/injectorready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete - var/current_screen = "mainmenu" - var/obj/machinery/dna_scannernew/connected = null - var/obj/item/weapon/disk/data/diskette = null - anchored = 1 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 400 - -/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params) - if (istype(I, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES - if (!src.diskette) - if(!user.drop_item()) - return - I.loc = src - src.diskette = I - user << "You insert [I]." - src.updateUsrDialog() - return - else - ..() - return - -/obj/machinery/computer/scan_consolenew/New() - ..() - - spawn(5) - for(dir in list(NORTH,EAST,SOUTH,WEST)) - connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir)) - if(!isnull(connected)) - break - spawn(250) - injectorready = 1 - return - return - -/obj/machinery/computer/scan_consolenew/attack_hand(mob/user) - if(..()) - return - ShowInterface(user) - -/obj/machinery/computer/scan_consolenew/proc/ShowInterface(mob/user, last_change) - if(!user) return - var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window - if(!( in_range(src, user) || istype(user, /mob/living/silicon) )) - popup.close() - return - popup.add_stylesheet("scannernew", 'html/browser/scannernew.css') - - var/mob/living/carbon/viable_occupant - var/occupant_status = "
Subject Status:
" - var/scanner_status - var/temp_html - if(connected && connected.is_operational()) - if(connected.occupant) //set occupant_status message - viable_occupant = connected.occupant - if(check_dna_integrity(viable_occupant) && (!(viable_occupant.disabilities & NOCLONE) || (connected.scan_level == 3))) //occupent is viable for dna modification - occupant_status += "[viable_occupant.name] => " - switch(viable_occupant.stat) - if(CONSCIOUS) occupant_status += "Conscious" - if(UNCONSCIOUS) occupant_status += "Unconscious" - else occupant_status += "DEAD - Cannot Operate" - occupant_status += "
" - occupant_status += "
Health:
[viable_occupant.health] %
" - occupant_status += "
Radiation Level:
[viable_occupant.radiation] %
" - var/rejuvenators = viable_occupant.reagents.get_reagent_amount("epinephrine") - occupant_status += "
Rejuvenators:
[rejuvenators] units
" - occupant_status += "
Unique Enzymes :
[viable_occupant.dna.unique_enzymes]
" - occupant_status += "
Last Operation:
[last_change ? last_change : "----"]
" - else - viable_occupant = null - occupant_status += "Invalid DNA structure" - if (viable_occupant && viable_occupant.stat == DEAD) - viable_occupant = null // No editing the dead. - else - occupant_status += "No subject detected" - - if(connected.state_open) - scanner_status = "Open" - else - scanner_status = "Closed" - if(connected.locked) - scanner_status += " (Locked)" - else - scanner_status += " (Unlocked)" - - - else - occupant_status += "----" - scanner_status += "Error: No scanner detected" - - var/status = "
" - status += "
Scanner:
[scanner_status]
" - status += "[occupant_status]" - - - status += "

Radiation Emitter Status

" - var/stddev = radstrength*RADIATION_STRENGTH_MULTIPLIER - status += "
Output Level:
[radstrength]
" - status += "
  \> Mutation:
(-[stddev] to +[stddev] = 68 %) (-[2*stddev] to +[2*stddev] = 95 %)
" - if(connected) - stddev = RADIATION_ACCURACY_MULTIPLIER/(radduration + (connected.precision_coeff ** 2)) - else - stddev = RADIATION_ACCURACY_MULTIPLIER/radduration - var/chance_to_hit - switch(stddev) //hardcoded values from a z-table for a normal distribution - if(0 to 0.25) chance_to_hit = ">95 %" - if(0.25 to 0.5) chance_to_hit = "68-95 %" - if(0.5 to 0.75) chance_to_hit = "55-68 %" - else chance_to_hit = "<38 %" - status += "
Pulse Duration:
[radduration]
" - status += "
  \> Accuracy:
[chance_to_hit]
" - status += "
" // Close statusDisplay div - var/buttons = "Scan " - if(connected) - buttons += " [connected.state_open ? "Close" : "Open"] Scanner " - if (connected.state_open) - buttons += "[connected.locked ? "Unlock" : "Lock"] Scanner " - else - buttons += "[connected.locked ? "Unlock" : "Lock"] Scanner " - else buttons += "Open Scanner Lock Scanner " - if(viable_occupant) buttons += "Inject Rejuvenators " - else buttons += "Inject Rejuvenators " - if(diskette) buttons += "Eject Disk " - else buttons += "Eject Disk " - if(current_screen == "buffer") buttons += "Radiation Emitter Menu " - else buttons += "Buffer Menu " - - switch(current_screen) - if("working") - temp_html += status - temp_html += "

System Busy

" - temp_html += "Working ... Please wait ([radduration] Seconds)" - if("buffer") - temp_html += status - temp_html += buttons - temp_html += "

Buffer Menu

" - - if(istype(buffer)) - for(var/i=1, i<=buffer.len, i++) - temp_html += "
Slot [i]: " - var/list/buffer_slot = buffer[i] - if( !buffer_slot || !buffer_slot.len || !buffer_slot["name"] || !((buffer_slot["UI"] && buffer_slot["UE"]) || buffer_slot["SE"]) ) - temp_html += "
\tNo Data" - if(viable_occupant) temp_html += "
Save to Buffer " - else temp_html += "
Save to Buffer " - temp_html += "Clear Buffer " - if(diskette) temp_html += "Load from Disk " - else temp_html += "Load from Disk " - temp_html += "Save to Disk " - else - var/ui = buffer_slot["UI"] - var/se = buffer_slot["SE"] - var/ue = buffer_slot["UE"] - var/name = buffer_slot["name"] - var/label = buffer_slot["label"] - var/blood_type = buffer_slot["blood_type"] - temp_html += "
\tLabel: [label ? label : name]" - temp_html += "
\tSubject: [name]" - if(ue && name && blood_type) - temp_html += "
\tBlood Type: [blood_type]" - temp_html += "
\tUE: [ue] " - if(viable_occupant) temp_html += "Occupant " - else temp_html += "Occupant" - if(injectorready) temp_html += "Injector" - else temp_html += "Injector" - else - temp_html += "
\tBlood Type: No Data" - temp_html += "
\tUE: No Data" - if(ui) - temp_html += "
\tUI: [ui] " - if(viable_occupant) temp_html += "Occupant " - else temp_html += "Occupant" - if(injectorready) temp_html += "Injector" - else temp_html += "Injector" - else - temp_html += "
\tUI: No Data" - if(se) - temp_html += "
\tSE: [se] " - if(viable_occupant && viable_occupant.stat != DEAD) temp_html += "Occupant " - else temp_html += "Occupant " - if(injectorready) temp_html += "Injector" - else temp_html += "Injector" - else - temp_html += "
\tSE: No Data" - if(viable_occupant) temp_html += "
Save to Buffer " - else temp_html += "
Save to Buffer " - temp_html += "Clear Buffer " - if(diskette) temp_html += "Load from Disk " - else temp_html += "Load from Disk " - if(diskette && !diskette.read_only) temp_html += "Save to Disk " - else temp_html += "Save to Disk " - else - temp_html += status - temp_html += buttons - temp_html += "

Radiation Emitter Menu

" - - temp_html += "-- Output Level ++" - temp_html += "
-- Pulse Duration ++" - - temp_html += "

Irradiate Subject

" - temp_html += "
Unique Identifier:
" - - var/max_line_len = 7*DNA_BLOCK_SIZE - if(viable_occupant) - temp_html += "
1
" - var/len = length(viable_occupant.dna.uni_identity) - for(var/i=1, i<=len, i++) - temp_html += "[copytext(viable_occupant.dna.uni_identity,i,i+1)]" - if ((i % max_line_len) == 0) - temp_html += "
" - if((i % DNA_BLOCK_SIZE) == 0 && i < len) - temp_html += "
[(i / DNA_BLOCK_SIZE) + 1]
" - else - temp_html += "----" - temp_html += "

" - - temp_html += "
Structural Enzymes:
" - if(viable_occupant) - temp_html += "
1
" - var/len = length(viable_occupant.dna.struc_enzymes) - for(var/i=1, i<=len, i++) - temp_html += "[copytext(viable_occupant.dna.struc_enzymes,i,i+1)]" - if ((i % max_line_len) == 0) - temp_html += "
" - if((i % DNA_BLOCK_SIZE) == 0 && i < len) - temp_html += "
[(i / DNA_BLOCK_SIZE) + 1]
" - else - temp_html += "----" - temp_html += "
" - - popup.set_content(temp_html) - popup.open() - - -/obj/machinery/computer/scan_consolenew/Topic(href, href_list) - if(..()) - return - if(!isturf(usr.loc)) - return - if(!( (isturf(loc) && in_range(src, usr)) || istype(usr, /mob/living/silicon) )) - return - if(current_screen == "working") - return - - add_fingerprint(usr) - usr.set_machine(src) - - var/mob/living/carbon/viable_occupant - if(connected) - viable_occupant = connected.occupant - if(!istype(viable_occupant) || !viable_occupant.dna || (viable_occupant.disabilities & NOCLONE)) - viable_occupant = null - - //Basic Tasks/////////////////////////////////////////// - var/num = round(text2num(href_list["num"])) - var/last_change - switch(href_list["task"]) - if("togglelock") - if(connected) connected.locked = !connected.locked - if("toggleopen") - if(connected) connected.toggle_open(usr) - if("setduration") - if(!num) - num = round(input(usr, "Choose pulse duration:", "Input an Integer", null) as num|null) - if(num) - radduration = Wrap(num, 1, RADIATION_DURATION_MAX+1) - if("setstrength") - if(!num) - num = round(input(usr, "Choose pulse strength:", "Input an Integer", null) as num|null) - if(num) - radstrength = Wrap(num, 1, RADIATION_STRENGTH_MAX+1) - if("screen") - current_screen = href_list["text"] - if("rejuv") - if(viable_occupant && viable_occupant.reagents) - var/epinephrine_amount = viable_occupant.reagents.get_reagent_amount("epinephrine") - var/can_add = max(min(REJUVENATORS_MAX - epinephrine_amount, REJUVENATORS_INJECT), 0) - viable_occupant.reagents.add_reagent("epinephrine", can_add) - if("setbufferlabel") - var/text = sanitize(input(usr, "Input a new label:", "Input an Text", null) as text|null) - if(num && text) - num = Clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) - buffer_slot["label"] = text - if("setbuffer") - if(num && viable_occupant) - num = Clamp(num, 1, NUMBER_OF_BUFFERS) - buffer[num] = list( - "label"="Buffer[num]:[viable_occupant.real_name]", - "UI"=viable_occupant.dna.uni_identity, - "SE"=viable_occupant.dna.struc_enzymes, - "UE"=viable_occupant.dna.unique_enzymes, - "name"=viable_occupant.real_name, - "blood_type"=viable_occupant.dna.blood_type - ) - if("clearbuffer") - if(num) - num = Clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) - buffer_slot.Cut() - if("transferbuffer") - if(num && viable_occupant && viable_occupant.stat != DEAD) - num = Clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) //15 and 40 are just magic numbers that were here before so i didnt touch them, they are initial boundaries of damage - viable_occupant.radiation += rand(15/(connected.damage_coeff ** 2),40/(connected.damage_coeff ** 2)) //Each laser level reduces damage by lvl^2, so no effect on 1 lvl, 4 times less damage on 2 and 9 times less damage on 3 - switch(href_list["text"]) //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove - if("se") - if(buffer_slot["SE"]) - viable_occupant.dna.struc_enzymes = buffer_slot["SE"] - domutcheck(viable_occupant) - if("ui") - if(buffer_slot["UI"]) - viable_occupant.dna.uni_identity = buffer_slot["UI"] - updateappearance(viable_occupant) - else - if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"]) - viable_occupant.real_name = buffer_slot["name"] - viable_occupant.name = buffer_slot["name"] - viable_occupant.dna.unique_enzymes = buffer_slot["UE"] - viable_occupant.dna.blood_type = buffer_slot["blood_type"] - updateappearance(viable_occupant) - if("injector") - if(num && injectorready) - num = Clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) - var/obj/item/weapon/dnainjector/I - switch(href_list["text"]) - if("se") - if(buffer_slot["SE"]) - I = new /obj/item/weapon/dnainjector(loc) - for(var/datum/mutation/human/HM in good_mutations + bad_mutations + not_good_mutations) - if(HM.check_block_string(buffer_slot["SE"])) - if(prob(HM.get_chance)) - I.add_mutations.Add(HM) - else - I.remove_mutations.Add(HM) - I.damage_coeff = connected.damage_coeff - if("ui") - if(buffer_slot["UI"]) - I = new /obj/item/weapon/dnainjector(loc) - I.fields = list("UI"=buffer_slot["UI"]) - I.damage_coeff = connected.damage_coeff - else - if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"]) - I = new /obj/item/weapon/dnainjector(loc) - I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"]) - I.damage_coeff = connected.damage_coeff - if(I) - injectorready = 0 - spawn(INJECTOR_TIMEOUT) - injectorready = 1 - if("loaddisk") - if(num && diskette && diskette.fields) - num = Clamp(num, 1, NUMBER_OF_BUFFERS) - buffer[num] = diskette.fields.Copy() - if("savedisk") - if(num && diskette && !diskette.read_only) - num = Clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) - diskette.name = "data disk \[[buffer_slot["label"]]\]" - diskette.fields = buffer_slot.Copy() - if("ejectdisk") - if(diskette) - diskette.loc = get_turf(src) - diskette = null - if("pulseui","pulsese") - if(num && viable_occupant && connected && viable_occupant.stat != DEAD) - radduration = Wrap(radduration, 1, RADIATION_DURATION_MAX+1) - radstrength = Wrap(radstrength, 1, RADIATION_STRENGTH_MAX+1) - - var/locked_state = connected.locked - connected.locked = 1 - - current_screen = "working" - ShowInterface(usr) - - sleep(radduration*10) - current_screen = "mainmenu" - - if(viable_occupant && connected && connected.occupant==viable_occupant) - viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation - switch(href_list["task"]) //Same thing as there but values are even lower, on best part they are about 0.0*, effectively no damage - if("pulseui") - var/len = length(viable_occupant.dna.uni_identity) - num = Wrap(num, 1, len+1) - num = randomize_radiation_accuracy(num, radduration + (connected.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/block = round((num-1)/DNA_BLOCK_SIZE)+1 - var/subblock = num - block*DNA_BLOCK_SIZE - last_change = "UI #[block]-[subblock]; " - - var/hex = copytext(viable_occupant.dna.uni_identity, num, num+1) - last_change += "[hex]" - hex = scramble(hex, radstrength, radduration) - last_change += "->[hex]" - - viable_occupant.dna.uni_identity = copytext(viable_occupant.dna.uni_identity, 1, num) + hex + copytext(viable_occupant.dna.uni_identity, num+1, 0) - updateappearance(viable_occupant) - if("pulsese") - var/len = length(viable_occupant.dna.struc_enzymes) - num = Wrap(num, 1, len+1) - num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) - - var/block = round((num-1)/DNA_BLOCK_SIZE)+1 - var/subblock = num - block*DNA_BLOCK_SIZE - last_change = "SE #[block]-[subblock]; " - - var/hex = copytext(viable_occupant.dna.struc_enzymes, num, num+1) - last_change += "[hex]" - hex = scramble(hex, radstrength, radduration) - last_change += "->[hex]" - - viable_occupant.dna.struc_enzymes = copytext(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext(viable_occupant.dna.struc_enzymes, num+1, 0) - domutcheck(viable_occupant) - else - current_screen = "mainmenu" - - if(connected) - connected.locked = locked_state - - ShowInterface(usr,last_change) - - -/////////////////////////// DNA MACHINES -#undef INJECTOR_TIMEOUT -#undef REJUVENATORS_INJECT -#undef REJUVENATORS_MAX -#undef NUMBER_OF_BUFFERS - -#undef RADIATION_STRENGTH_MAX -#undef RADIATION_STRENGTH_MULTIPLIER - -#undef RADIATION_DURATION_MAX -#undef RADIATION_ACCURACY_MULTIPLIER - -#undef RADIATION_IRRADIATION_MULTIPLIER - -//#undef BAD_MUTATION_DIFFICULTY -//#undef GOOD_MUTATION_DIFFICULTY -//#undef OP_MUTATION_DIFFICULTY - //value in range 1 to values. values must be greater than 0 //all arguments assumed to be positive integers /proc/construct_block(value, values, blocksize=DNA_BLOCK_SIZE) @@ -968,10 +340,4 @@ value = values return value - -/datum/dna/proc/is_same_as(datum/dna/D) - if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name) - if(species == D.species && features == D.features && blood_type == D.blood_type) - return 1 - return 0 - +/////////////////////////// DNA HELPER-PROCS \ No newline at end of file diff --git a/code/game/gamemodes/abduction/abduction.dm b/code/game/gamemodes/abduction/abduction.dm index 0b710001f38..1151de4f55f 100644 --- a/code/game/gamemodes/abduction/abduction.dm +++ b/code/game/gamemodes/abduction/abduction.dm @@ -107,7 +107,7 @@ H = agent.current L = agent_landmarks[team_number] H.loc = L.loc - hardset_dna(H, null, null, null, null, /datum/species/abductor) + H.set_species(/datum/species/abductor) S = H.dna.species S.agent = 1 S.team = team_number @@ -115,13 +115,12 @@ equip_common(H,team_number) equip_agent(H,team_number) greet_agent(agent,team_number) - H.regenerate_icons() scientist = scientists[team_number] H = scientist.current L = scientist_landmarks[team_number] H.loc = L.loc - hardset_dna(H, null, null, null, null, /datum/species/abductor) + H.set_species(/datum/species/abductor) S = H.dna.species S.scientist = 1 S.team = team_number @@ -129,7 +128,6 @@ equip_common(H,team_number) equip_scientist(H,team_number) greet_scientist(scientist,team_number) - H.regenerate_icons() return ..() //Used for create antag buttons @@ -156,7 +154,7 @@ H = agent.current L = agent_landmarks[team_number] H.loc = L.loc - hardset_dna(H, null, null, null, null, /datum/species/abductor) + H.set_species(/datum/species/abductor) S = H.dna.species S.agent = 1 S.team = team_number @@ -164,13 +162,13 @@ equip_common(H,team_number) equip_agent(H,team_number) greet_agent(agent,team_number) - H.regenerate_icons() + scientist = scientists[team_number] H = scientist.current L = scientist_landmarks[team_number] H.loc = L.loc - hardset_dna(H, null, null, null, null, /datum/species/abductor) + H.set_species(/datum/species/abductor) S = H.dna.species S.scientist = 1 S.team = team_number @@ -178,7 +176,7 @@ equip_common(H,team_number) equip_scientist(H,team_number) greet_scientist(scientist,team_number) - H.regenerate_icons() + /datum/game_mode/abduction/proc/greet_agent(datum/mind/abductor,team_number) @@ -332,7 +330,7 @@ if(!owner.current || !ishuman(owner.current)) return 0 var/mob/living/carbon/human/H = owner.current - if(!H.dna || !H.dna.species || !(H.dna.species.id == "abductor")) + if(H.dna.species.id != "abductor") return 0 var/datum/species/abductor/S = H.dna.species ab_team = S.team diff --git a/code/game/gamemodes/abduction/abduction_gear.dm b/code/game/gamemodes/abduction/abduction_gear.dm index 9595f0883b9..3d73042202a 100644 --- a/code/game/gamemodes/abduction/abduction_gear.dm +++ b/code/game/gamemodes/abduction/abduction_gear.dm @@ -288,7 +288,7 @@ var/obj/machinery/abductor/console/console if(ishuman(source)) var/mob/living/carbon/human/H = source - if(H.dna && istype(H.dna.species, /datum/species/abductor)) + if(H.dna.species.id == "abductor") var/datum/species/abductor/S = H.dna.species console = get_team_console(S.team) home = console.pad @@ -405,8 +405,6 @@ Congratulations! You are now trained for xenobiology research!"} if(!ishuman(user)) return 0 var/mob/living/carbon/human/H = user - if(!H.dna) - return 0 if(H.dna.species.id != "abductor") return 0 return 1 @@ -492,8 +490,7 @@ Congratulations! You are now trained for xenobiology research!"} var/species = "Unknown species" if(ishuman(L)) var/mob/living/carbon/human/H = L - if(H.dna && H.dna.species) - species = "[H.dna.species.name]" + species = "[H.dna.species.name]" if(L.mind && L.mind.changeling) species = "Changeling lifeform" user << "Probing result:[species]" diff --git a/code/game/gamemodes/abduction/abduction_surgery.dm b/code/game/gamemodes/abduction/abduction_surgery.dm index f22f188945b..a97011d53db 100644 --- a/code/game/gamemodes/abduction/abduction_surgery.dm +++ b/code/game/gamemodes/abduction/abduction_surgery.dm @@ -8,7 +8,7 @@ if(!ishuman(user)) return 0 var/mob/living/carbon/human/H = user - if(H.dna && istype(H.dna.species, /datum/species/abductor)) + if(H.dna.species.id == "abductor") return 1 if((locate(/obj/item/weapon/implant/abductor) in H)) return 1 diff --git a/code/game/gamemodes/abduction/gland.dm b/code/game/gamemodes/abduction/gland.dm index fd2ecdcce4c..db0aa0c32dc 100644 --- a/code/game/gamemodes/abduction/gland.dm +++ b/code/game/gamemodes/abduction/gland.dm @@ -120,9 +120,7 @@ /obj/item/organ/internal/gland/pop/activate() owner << "You feel unlike yourself." var/species = pick(list(/datum/species/lizard,/datum/species/slime,/datum/species/plant/pod,/datum/species/fly)) - hardset_dna(owner, null, null, null, null, species) - owner.regenerate_icons() - return + owner.set_species(species) /obj/item/organ/internal/gland/ventcrawling origin_tech = "materials=4;biotech=5;bluespace=3" @@ -241,7 +239,7 @@ /obj/effect/cocoon/abductor/proc/Copy(mob/living/carbon/human/H) var/mob/living/carbon/human/interactive/greytide/clone = new(src) - hardset_dna(clone,H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species.type, H.dna.features) + clone.hardset_dna(H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species.type, H.dna.features) //There's no define for this / get all items ? var/list/slots = list(slot_back,slot_w_uniform,slot_wear_suit,\ diff --git a/code/game/gamemodes/abduction/machinery/console.dm b/code/game/gamemodes/abduction/machinery/console.dm index 725ebf46091..24f17a5ce92 100644 --- a/code/game/gamemodes/abduction/machinery/console.dm +++ b/code/game/gamemodes/abduction/machinery/console.dm @@ -4,8 +4,6 @@ var/team = 0 /obj/machinery/abductor/proc/IsAbductor(mob/living/carbon/human/H) - if(!H.dna) - return 0 return H.dna.species.id == "abductor" /obj/machinery/abductor/proc/IsAgent(mob/living/carbon/human/H) diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index 78e195f331c..722f1bce2af 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -98,6 +98,7 @@ M.mind.name = newname M.real_name = newname M.name = newname + M.dna.update_dna_identity() var/datum/objective/protect/new_objective = new /datum/objective/protect new_objective.owner = M:mind new_objective:target = usr:mind diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index a88707f19cc..d4613fac399 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -346,7 +346,7 @@ var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mas return if(has_dna(target.dna)) user << "We already have this DNA in storage!" - if(!check_dna_integrity(target)) + if(!target.has_dna()) user << "[target] is not compatible with our biology." return return 1 @@ -404,11 +404,9 @@ var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mas /proc/changeling_transform(var/mob/living/carbon/human/user, var/datum/changelingprofile/chosen_prof) var/datum/dna/chosen_dna = chosen_prof.dna - user.real_name = chosen_prof.name - user.dna = chosen_dna - hardset_dna(user, null, null, null, null, chosen_dna.species.type, chosen_dna.features) - domutcheck(user) - updateappearance(user) + chosen_dna.transfer_identity(user, 1) + user.updateappearance(mutcolor_update=1) + user.domutcheck() //vars hackery. not pretty, but better than the alternative. for(var/slot in slots) diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 054035f2e14..2d8316edfa5 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -130,7 +130,7 @@ if((target.disabilities & NOCLONE) || (target.disabilities & HUSK)) user << "DNA of [target] is ruined beyond usability!" return - if(!check_dna_integrity(target) || !ishuman(target)) + if(!ishuman(target)) user << "[target] is not compatible with this ability." return return 1 diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm index 36b7ba87339..5d6ca21c5ac 100644 --- a/code/game/gamemodes/changeling/powers/chameleon_skin.dm +++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm @@ -10,15 +10,14 @@ /obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user) - var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 - if(!istype(H)) + var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 //phil235 so why is it needd? + if(!istype(H)) // req_human could be done in can_sting stuff. return var/datum/mutation/human/HM = mutations_list[CHAMELEON] - if(H.dna && H.dna.mutations) - if(HM in H.dna.mutations) - HM.force_lose(H) - else - HM.force_give(H) + if(HM in H.dna.mutations) + HM.force_lose(H) + else + HM.force_give(H) feedback_add_details("changeling_powers","CS") return 1 diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index 04d36c169ac..5fde1238159 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -24,12 +24,11 @@ if(!user || user.notransform) return 0 user << "We transform our appearance." - - user.humanize((TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPSRC), chosen_prof.name) - - changeling_transform(user, chosen_prof) changeling.purchasedpowers -= src + + var/newmob = user.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS) + + changeling_transform(newmob, chosen_prof) feedback_add_details("changeling_powers","LFT") - qdel(user) return 1 diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index 2ce8470c19c..05406b02bdf 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -12,9 +12,7 @@ return 0 user << "Our genes cry out!" - user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPSE | TR_KEEPSRC) + user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) - // Human-form power now handled in monkeyize() feedback_add_details("changeling_powers","LF") - .=1 - qdel(user) \ No newline at end of file + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm index b6880a371e7..d466f2b774d 100644 --- a/code/game/gamemodes/changeling/powers/panacea.dm +++ b/code/game/gamemodes/changeling/powers/panacea.dm @@ -16,6 +16,9 @@ for(var/datum/disease/D in user.viruses) D.cure() - + for(var/obj/item/organ/internal/I in user) + if(istype(I,/obj/item/organ/internal/body_egg/alien_embryo)) + I.Remove(user) + I.loc = get_turf(user) feedback_add_details("changeling_powers","AP") return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index 5cd021fff74..a94ff6fc68e 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -81,7 +81,7 @@ /obj/effect/proc_holder/changeling/sting/transformation/can_sting(mob/user, mob/target) if(!..()) return - if((target.disabilities & HUSK) || !check_dna_integrity(target)) + if((target.disabilities & HUSK) || !target.has_dna()) user << "Our sting appears ineffective against its DNA." return 0 return 1 @@ -92,15 +92,17 @@ if(ismonkey(target)) user << "Our genes cry out as we sting [target.name]!" - if(iscarbon(target) && (target.status_flags & CANWEAKEN)) + if(iscarbon(target)) var/mob/living/carbon/C = target - C.do_jitter_animation(500) - C.take_organ_damage(20, 0) //The process is extremely painful + if(C.status_flags & CANWEAKEN) + C.do_jitter_animation(500) + C.take_organ_damage(20, 0) //The process is extremely painful - target.visible_message("[target] begins to violenty convulse!","You feel a tiny prick and a begin to uncontrollably convulse!") - spawn(10) - hardset_dna(target, NewDNA.uni_identity, NewDNA.struc_enzymes, NewDNA.real_name, NewDNA.blood_type, NewDNA.species.type, NewDNA.features) - updateappearance(target) + target.visible_message("[target] begins to violenty convulse!","You feel a tiny prick and a begin to uncontrollably convulse!") + spawn(10) + NewDNA.transfer_identity(C, transfer_SE=1) + C.updateappearance(mutcolor_update=1) + C.domutcheck() feedback_add_details("changeling_powers","TS") return 1 @@ -125,7 +127,7 @@ /obj/effect/proc_holder/changeling/sting/false_armblade/can_sting(mob/user, mob/target) if(!..()) return - if((target.disabilities & HUSK) || !check_dna_integrity(target)) + if((target.disabilities & HUSK) || !target.has_dna()) user << "Our sting appears ineffective against its DNA." return 0 return 1 diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index a16b2946415..e3ce3bf5ea1 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -147,11 +147,11 @@ var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "") if(!DNAstring) return - for(var/mob/living/carbon/M in mob_list) - if(!M.dna) + for(var/mob/living/carbon/C in mob_list) + if(!C.dna) continue - if(M.dna.unique_enzymes == DNAstring) - target = M + if(C.dna.unique_enzymes == DNAstring) + target = C break return attack_self() diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index e485a62657d..cb4d5ace22f 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -807,7 +807,7 @@ var/global/list/possible_items_special = list() var/turf/cloc = get_turf(changeling.current) if(cloc && cloc.onCentcom() && (changeling.current.stat != DEAD)) //Living changeling on centcomm.... for(var/name in check_names) //Is he (disguised as) one of the staff? - if(H.dna && H.dna.real_name == name) + if(H.dna.real_name == name) check_names -= name //This staff member is accounted for, remove them, so the team don't succeed by escape as 7 of the same engineer success++ //A living changeling staff member made it to centcomm continue changelings diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 2e5721b5fe7..e2a6af4e114 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -1,4 +1,4 @@ -/datum/subsystem/ticker/proc/setupGenetics() +/datum/subsystem/objects/proc/setupGenetics() var/list/avnums = new /list(DNA_STRUC_ENZYMES_BLOCKS) for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++) avnums[i] = i diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index eb0a55a9ee9..2d7caaaff2d 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -297,7 +297,7 @@ user.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(usr), slot_gloves) user.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(usr), slot_wear_mask) user.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/shadowling(usr), slot_glasses) - hardset_dna(user, null, null, null, null, /datum/species/shadow/ling) + user.set_species(/datum/species/shadow/ling) /obj/effect/proc_holder/spell/targeted/collective_mind //Lets a shadowling bring together their thralls' strength, granting new abilities and a headcount @@ -568,7 +568,7 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell thrallToRevive.visible_message("[thrallToRevive] slowly rises, no longer recognizable as human.", \ "You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \ darkness but wither slowly in light. In addition, Lesser Glare and Guise have been upgraded into their true forms.") - hardset_dna(thrallToRevive, null, null, null, null, /datum/species/shadow/ling/lesser) + thrallToRevive.set_species(/datum/species/shadow/ling/lesser) thrallToRevive.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_glare) thrallToRevive.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk) thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null)) diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm index 97a36b06255..f1aecf339be 100644 --- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm @@ -84,7 +84,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N H.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(H), slot_gloves) H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(H), slot_wear_mask) H.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/shadowling(H), slot_glasses) - hardset_dna(H, null, null, null, null, /datum/species/shadow/ling) //can't be a shadowling without being a shadowling + H.set_species(/datum/species/shadow/ling) //can't be a shadowling without being a shadowling sleep(10) H << "Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies." diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index 06a94232ece..582eb0ebceb 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -22,9 +22,9 @@ /obj/item/weapon/veilrender/attack_self(mob/user) if(charges > 0) - new /obj/effect/rend(get_turf(usr), spawn_type, spawn_amt, rend_desc, spawn_fast) + new /obj/effect/rend(get_turf(user), spawn_type, spawn_amt, rend_desc, spawn_fast) charges-- - user.visible_message("[src] hums with power as [usr] deals a blow to [activate_descriptor] itself!") + user.visible_message("[src] hums with power as [user] deals a blow to [activate_descriptor] itself!") else user << "The unearthly energies that powered the blade are now dormant." @@ -59,7 +59,7 @@ /obj/effect/rend/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/weapon/nullrod)) - user.visible_message("[usr] seals \the [src] with \the [I].") + user.visible_message("[user] seals \the [src] with \the [I].") qdel(src) return ..() @@ -97,7 +97,7 @@ /obj/item/weapon/scrying/attack_self(mob/user) user << "You can see...everything!" - visible_message("[usr] stares into [src], their eyes glazing over.") + visible_message("[user] stares into [src], their eyes glazing over.") user.ghostize(1) return @@ -118,7 +118,7 @@ unlimited = 1 /obj/item/device/necromantic_stone/attack(mob/living/carbon/human/M, mob/living/carbon/human/user) - if(!istype(M, /mob/living/carbon/human)) + if(!istype(M)) return ..() if(!istype(user) || !user.canUseTopic(M,1)) @@ -137,7 +137,7 @@ user << "This artifact can only affect three undead at a time!" return - hardset_dna(M, null, null, null, null, /datum/species/skeleton) + M.set_species(/datum/species/skeleton, icon_update=0) M.revive() spooky_scaries |= M M << "You have been revived by [user.real_name]!" @@ -261,13 +261,24 @@ var/global/list/multiverse = list() /obj/item/weapon/multisword/proc/spawn_copy(var/client/C, var/turf/T) var/mob/living/carbon/human/M = new/mob/living/carbon/human(T) - C.prefs.copy_to(M) + C.prefs.copy_to(M, icon_updates=0) M.key = C.key M.mind.name = usr.real_name M << "You are an alternate version of [usr.real_name] from another universe! Help them accomplish their goals at all costs." M.real_name = usr.real_name M.name = usr.real_name M.faction = list("[usr.real_name]") + if(prob(50)) + var/list/all_species = list() + for(var/speciestype in typesof(/datum/species) - /datum/species) + var/datum/species/S = new speciestype() + if(!S.dangerous_existence) + all_species += speciestype + M.set_species(pick(all_species), icon_update=0) + M.update_body() + M.update_hair() + M.update_mutcolor() + M.dna.update_dna_identity() equip_copy(M) if(evil) @@ -440,14 +451,6 @@ var/global/list/multiverse = list() else return - ready_dna(M) - if(M.dna && prob(50)) - var/list/all_species = list() - for(var/speciestype in typesof(/datum/species) - /datum/species) - var/datum/species/S = new speciestype() - if(!S.dangerous_existence) - all_species += speciestype - hardset_dna(M, null, null, null, null, pick(all_species)) M.update_icons() M.update_augments() diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm index d59f47796b5..d53f5fa2dba 100644 --- a/code/game/gamemodes/wizard/raginmages.dm +++ b/code/game/gamemodes/wizard/raginmages.dm @@ -130,7 +130,7 @@ var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. G_found.client.prefs.copy_to(new_character) - ready_dna(new_character) + new_character.dna.update_dna_identity() new_character.key = G_found.key return new_character diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index a7b0ab3ca3b..ca5fb09823c 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -50,14 +50,12 @@ return 0 //Equip the rest of the gear - if(H.dna) - H.dna.species.before_equip_job(src, H) + H.dna.species.before_equip_job(src, H) if(outfit) H.equipOutfit(outfit) - if(H.dna) - H.dna.species.after_equip_job(src, H) + H.dna.species.after_equip_job(src, H) /datum/job/proc/apply_fingerprints(mob/living/carbon/human/H) if(!istype(H)) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index e11ebd25a9e..221d898227c 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -185,7 +185,7 @@ H.ckey = ckey H << "Consciousness slowly creeps over you as your body regenerates.
So this is what cloning feels like?
" - hardset_dna(H, ui, se, null, null, mrace, features) + H.hardset_dna(ui, se, H.real_name, null, mrace, features) H.faction |= factions H.set_cloned_appearance() @@ -301,13 +301,13 @@ return /obj/machinery/clonepod/proc/go_out() - if (src.locked) + if (locked) return - if (src.mess) //Clean that mess and dump those gibs! - src.mess = 0 - gibs(src.loc) - src.icon_state = "pod_0" + if (mess) //Clean that mess and dump those gibs! + mess = 0 + gibs(loc) + icon_state = "pod_0" /* for(var/obj/O in src) @@ -315,22 +315,22 @@ */ return - if (!(src.occupant)) + if (!occupant) return /* for(var/obj/O in src) O.loc = src.loc */ - if (src.occupant.client) - src.occupant.client.eye = src.occupant.client.mob - src.occupant.client.perspective = MOB_PERSPECTIVE + if (occupant.client) + occupant.client.eye = occupant.client.mob + occupant.client.perspective = MOB_PERSPECTIVE if(occupant.loc == src) - src.occupant.loc = src.loc - src.icon_state = "pod_0" - src.eject_wait = 0 //If it's still set somehow. - domutcheck(src.occupant) //Waiting until they're out before possible monkeyizing. - src.occupant = null + occupant.loc = loc + icon_state = "pod_0" + eject_wait = 0 //If it's still set somehow. + occupant.domutcheck() //Waiting until they're out before possible monkeyizing. + occupant = null return /obj/machinery/clonepod/proc/malfunction() diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 65f0690047d..8cfd51a294f 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -350,7 +350,7 @@ return /obj/machinery/computer/cloning/proc/scan_mob(mob/living/carbon/human/subject) - if (!check_dna_integrity(subject) || !istype(subject)) + if (!istype(subject)) scantemp = "Unable to locate valid genetic data." return if (!subject.getorgan(/obj/item/organ/internal/brain)) diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm new file mode 100644 index 00000000000..5de7d5b4adb --- /dev/null +++ b/code/game/machinery/computer/dna_console.dm @@ -0,0 +1,482 @@ +#define INJECTOR_TIMEOUT 300 +#define REJUVENATORS_INJECT 15 +#define REJUVENATORS_MAX 90 +#define NUMBER_OF_BUFFERS 3 + +#define RADIATION_STRENGTH_MAX 15 +#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has a more range + +#define RADIATION_DURATION_MAX 30 +#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate + +#define RADIATION_IRRADIATION_MULTIPLIER 0.2 //multiplier for how much radiation a test subject recieves + +/obj/machinery/computer/scan_consolenew + name = "\improper DNA scanner access console" + desc = "Scan DNA." + icon_screen = "dna" + icon_keyboard = "med_key" + density = 1 + circuit = /obj/item/weapon/circuitboard/scan_consolenew + var/radduration = 2 + var/radstrength = 1 + + var/list/buffer[NUMBER_OF_BUFFERS] + + var/injectorready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete + var/current_screen = "mainmenu" + var/obj/machinery/dna_scannernew/connected = null + var/obj/item/weapon/disk/data/diskette = null + anchored = 1 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 400 + +/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params) + if (istype(I, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES + if (!src.diskette) + if(!user.drop_item()) + return + I.loc = src + src.diskette = I + user << "You insert [I]." + src.updateUsrDialog() + return + else + ..() + return + +/obj/machinery/computer/scan_consolenew/New() + ..() + + spawn(5) + for(dir in list(NORTH,EAST,SOUTH,WEST)) + connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir)) + if(!isnull(connected)) + break + spawn(250) + injectorready = 1 + return + return + +/obj/machinery/computer/scan_consolenew/attack_hand(mob/user) + if(..()) + return + ShowInterface(user) + +/obj/machinery/computer/scan_consolenew/proc/ShowInterface(mob/user, last_change) + if(!user) return + var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window + if(!( in_range(src, user) || istype(user, /mob/living/silicon) )) + popup.close() + return + popup.add_stylesheet("scannernew", 'html/browser/scannernew.css') + + var/mob/living/carbon/viable_occupant + var/occupant_status = "
Subject Status:
" + var/scanner_status + var/temp_html + if(connected && connected.is_operational()) + if(connected.occupant) //set occupant_status message + viable_occupant = connected.occupant + if(viable_occupant.has_dna() && (!(viable_occupant.disabilities & NOCLONE) || (connected.scan_level == 3))) //occupent is viable for dna modification + occupant_status += "[viable_occupant.name] => " + switch(viable_occupant.stat) + if(CONSCIOUS) occupant_status += "Conscious" + if(UNCONSCIOUS) occupant_status += "Unconscious" + else occupant_status += "DEAD - Cannot Operate" + occupant_status += "
" + occupant_status += "
Health:
[viable_occupant.health] %
" + occupant_status += "
Radiation Level:
[viable_occupant.radiation] %
" + var/rejuvenators = viable_occupant.reagents.get_reagent_amount("epinephrine") + occupant_status += "
Rejuvenators:
[rejuvenators] units
" + occupant_status += "
Unique Enzymes :
[viable_occupant.dna.unique_enzymes]
" + occupant_status += "
Last Operation:
[last_change ? last_change : "----"]
" + else + viable_occupant = null + occupant_status += "Invalid DNA structure" + if (viable_occupant && viable_occupant.stat == DEAD) + viable_occupant = null // No editing the dead. + else + occupant_status += "No subject detected" + + if(connected.state_open) + scanner_status = "Open" + else + scanner_status = "Closed" + if(connected.locked) + scanner_status += " (Locked)" + else + scanner_status += " (Unlocked)" + + + else + occupant_status += "----" + scanner_status += "Error: No scanner detected" + + var/status = "
" + status += "
Scanner:
[scanner_status]
" + status += "[occupant_status]" + + + status += "

Radiation Emitter Status

" + var/stddev = radstrength*RADIATION_STRENGTH_MULTIPLIER + status += "
Output Level:
[radstrength]
" + status += "
  \> Mutation:
(-[stddev] to +[stddev] = 68 %) (-[2*stddev] to +[2*stddev] = 95 %)
" + if(connected) + stddev = RADIATION_ACCURACY_MULTIPLIER/(radduration + (connected.precision_coeff ** 2)) + else + stddev = RADIATION_ACCURACY_MULTIPLIER/radduration + var/chance_to_hit + switch(stddev) //hardcoded values from a z-table for a normal distribution + if(0 to 0.25) chance_to_hit = ">95 %" + if(0.25 to 0.5) chance_to_hit = "68-95 %" + if(0.5 to 0.75) chance_to_hit = "55-68 %" + else chance_to_hit = "<38 %" + status += "
Pulse Duration:
[radduration]
" + status += "
  \> Accuracy:
[chance_to_hit]
" + status += "
" // Close statusDisplay div + var/buttons = "Scan " + if(connected) + buttons += " [connected.state_open ? "Close" : "Open"] Scanner " + if (connected.state_open) + buttons += "[connected.locked ? "Unlock" : "Lock"] Scanner " + else + buttons += "[connected.locked ? "Unlock" : "Lock"] Scanner " + else buttons += "Open Scanner Lock Scanner " + if(viable_occupant) buttons += "Inject Rejuvenators " + else buttons += "Inject Rejuvenators " + if(diskette) buttons += "Eject Disk " + else buttons += "Eject Disk " + if(current_screen == "buffer") buttons += "Radiation Emitter Menu " + else buttons += "Buffer Menu " + + switch(current_screen) + if("working") + temp_html += status + temp_html += "

System Busy

" + temp_html += "Working ... Please wait ([radduration] Seconds)" + if("buffer") + temp_html += status + temp_html += buttons + temp_html += "

Buffer Menu

" + + if(istype(buffer)) + for(var/i=1, i<=buffer.len, i++) + temp_html += "
Slot [i]: " + var/list/buffer_slot = buffer[i] + if( !buffer_slot || !buffer_slot.len || !buffer_slot["name"] || !((buffer_slot["UI"] && buffer_slot["UE"]) || buffer_slot["SE"]) ) + temp_html += "
\tNo Data" + if(viable_occupant) temp_html += "
Save to Buffer " + else temp_html += "
Save to Buffer " + temp_html += "Clear Buffer " + if(diskette) temp_html += "Load from Disk " + else temp_html += "Load from Disk " + temp_html += "Save to Disk " + else + var/ui = buffer_slot["UI"] + var/se = buffer_slot["SE"] + var/ue = buffer_slot["UE"] + var/name = buffer_slot["name"] + var/label = buffer_slot["label"] + var/blood_type = buffer_slot["blood_type"] + temp_html += "
\tLabel: [label ? label : name]" + temp_html += "
\tSubject: [name]" + if(ue && name && blood_type) + temp_html += "
\tBlood Type: [blood_type]" + temp_html += "
\tUE: [ue] " + if(viable_occupant) temp_html += "Occupant " + else temp_html += "Occupant" + if(injectorready) temp_html += "Injector" + else temp_html += "Injector" + else + temp_html += "
\tBlood Type: No Data" + temp_html += "
\tUE: No Data" + if(ui) + temp_html += "
\tUI: [ui] " + if(viable_occupant) temp_html += "Occupant " + else temp_html += "Occupant" + if(injectorready) temp_html += "Injector" + else temp_html += "Injector" + else + temp_html += "
\tUI: No Data" + if(se) + temp_html += "
\tSE: [se] " + if(viable_occupant && viable_occupant.stat != DEAD) temp_html += "Occupant " + else temp_html += "Occupant " + if(injectorready) temp_html += "Injector" + else temp_html += "Injector" + else + temp_html += "
\tSE: No Data" + if(viable_occupant) temp_html += "
Save to Buffer " + else temp_html += "
Save to Buffer " + temp_html += "Clear Buffer " + if(diskette) temp_html += "Load from Disk " + else temp_html += "Load from Disk " + if(diskette && !diskette.read_only) temp_html += "Save to Disk " + else temp_html += "Save to Disk " + else + temp_html += status + temp_html += buttons + temp_html += "

Radiation Emitter Menu

" + + temp_html += "-- Output Level ++" + temp_html += "
-- Pulse Duration ++" + + temp_html += "

Irradiate Subject

" + temp_html += "
Unique Identifier:
" + + var/max_line_len = 7*DNA_BLOCK_SIZE + if(viable_occupant) + temp_html += "
1
" + var/len = length(viable_occupant.dna.uni_identity) + for(var/i=1, i<=len, i++) + temp_html += "[copytext(viable_occupant.dna.uni_identity,i,i+1)]" + if ((i % max_line_len) == 0) + temp_html += "
" + if((i % DNA_BLOCK_SIZE) == 0 && i < len) + temp_html += "
[(i / DNA_BLOCK_SIZE) + 1]
" + else + temp_html += "----" + temp_html += "

" + + temp_html += "
Structural Enzymes:
" + if(viable_occupant) + temp_html += "
1
" + var/len = length(viable_occupant.dna.struc_enzymes) + for(var/i=1, i<=len, i++) + temp_html += "[copytext(viable_occupant.dna.struc_enzymes,i,i+1)]" + if ((i % max_line_len) == 0) + temp_html += "
" + if((i % DNA_BLOCK_SIZE) == 0 && i < len) + temp_html += "
[(i / DNA_BLOCK_SIZE) + 1]
" + else + temp_html += "----" + temp_html += "
" + + popup.set_content(temp_html) + popup.open() + + +/obj/machinery/computer/scan_consolenew/Topic(href, href_list) + if(..()) + return + if(!isturf(usr.loc)) + return + if(!( (isturf(loc) && in_range(src, usr)) || istype(usr, /mob/living/silicon) )) + return + if(current_screen == "working") + return + + add_fingerprint(usr) + usr.set_machine(src) + + var/mob/living/carbon/viable_occupant + if(connected) + viable_occupant = connected.occupant + if(!istype(viable_occupant) || !viable_occupant.dna || (viable_occupant.disabilities & NOCLONE)) + viable_occupant = null + + //Basic Tasks/////////////////////////////////////////// + var/num = round(text2num(href_list["num"])) + var/last_change + switch(href_list["task"]) + if("togglelock") + if(connected) connected.locked = !connected.locked + if("toggleopen") + if(connected) connected.toggle_open(usr) + if("setduration") + if(!num) + num = round(input(usr, "Choose pulse duration:", "Input an Integer", null) as num|null) + if(num) + radduration = Wrap(num, 1, RADIATION_DURATION_MAX+1) + if("setstrength") + if(!num) + num = round(input(usr, "Choose pulse strength:", "Input an Integer", null) as num|null) + if(num) + radstrength = Wrap(num, 1, RADIATION_STRENGTH_MAX+1) + if("screen") + current_screen = href_list["text"] + if("rejuv") + if(viable_occupant && viable_occupant.reagents) + var/epinephrine_amount = viable_occupant.reagents.get_reagent_amount("epinephrine") + var/can_add = max(min(REJUVENATORS_MAX - epinephrine_amount, REJUVENATORS_INJECT), 0) + viable_occupant.reagents.add_reagent("epinephrine", can_add) + if("setbufferlabel") + var/text = sanitize(input(usr, "Input a new label:", "Input an Text", null) as text|null) + if(num && text) + num = Clamp(num, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = buffer[num] + if(istype(buffer_slot)) + buffer_slot["label"] = text + if("setbuffer") + if(num && viable_occupant) + num = Clamp(num, 1, NUMBER_OF_BUFFERS) + buffer[num] = list( + "label"="Buffer[num]:[viable_occupant.real_name]", + "UI"=viable_occupant.dna.uni_identity, + "SE"=viable_occupant.dna.struc_enzymes, + "UE"=viable_occupant.dna.unique_enzymes, + "name"=viable_occupant.real_name, + "blood_type"=viable_occupant.dna.blood_type + ) + if("clearbuffer") + if(num) + num = Clamp(num, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = buffer[num] + if(istype(buffer_slot)) + buffer_slot.Cut() + if("transferbuffer") + if(num && viable_occupant && viable_occupant.stat != DEAD) + num = Clamp(num, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = buffer[num] + if(istype(buffer_slot)) //15 and 40 are just magic numbers that were here before so i didnt touch them, they are initial boundaries of damage + viable_occupant.radiation += rand(15/(connected.damage_coeff ** 2),40/(connected.damage_coeff ** 2)) //Each laser level reduces damage by lvl^2, so no effect on 1 lvl, 4 times less damage on 2 and 9 times less damage on 3 + switch(href_list["text"]) //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove + if("se") + if(buffer_slot["SE"]) + viable_occupant.dna.struc_enzymes = buffer_slot["SE"] + viable_occupant.domutcheck() + if("ui") + if(buffer_slot["UI"]) + viable_occupant.dna.uni_identity = buffer_slot["UI"] + viable_occupant.updateappearance(mutations_overlay_update=1) + else + if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"]) + viable_occupant.real_name = buffer_slot["name"] + viable_occupant.name = buffer_slot["name"] + viable_occupant.dna.unique_enzymes = buffer_slot["UE"] + viable_occupant.dna.blood_type = buffer_slot["blood_type"] + if("injector") + if(num && injectorready) + num = Clamp(num, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = buffer[num] + if(istype(buffer_slot)) + var/obj/item/weapon/dnainjector/I + switch(href_list["text"]) + if("se") + if(buffer_slot["SE"]) + I = new /obj/item/weapon/dnainjector(loc) + for(var/datum/mutation/human/HM in good_mutations + bad_mutations + not_good_mutations) + if(HM.check_block_string(buffer_slot["SE"])) + if(prob(HM.get_chance)) + I.add_mutations.Add(HM) + else + I.remove_mutations.Add(HM) + I.damage_coeff = connected.damage_coeff + if("ui") + if(buffer_slot["UI"]) + I = new /obj/item/weapon/dnainjector(loc) + I.fields = list("UI"=buffer_slot["UI"]) + I.damage_coeff = connected.damage_coeff + else + if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"]) + I = new /obj/item/weapon/dnainjector(loc) + I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"]) + I.damage_coeff = connected.damage_coeff + if(I) + injectorready = 0 + spawn(INJECTOR_TIMEOUT) + injectorready = 1 + if("loaddisk") + if(num && diskette && diskette.fields) + num = Clamp(num, 1, NUMBER_OF_BUFFERS) + buffer[num] = diskette.fields.Copy() + if("savedisk") + if(num && diskette && !diskette.read_only) + num = Clamp(num, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = buffer[num] + if(istype(buffer_slot)) + diskette.name = "data disk \[[buffer_slot["label"]]\]" + diskette.fields = buffer_slot.Copy() + if("ejectdisk") + if(diskette) + diskette.loc = get_turf(src) + diskette = null + if("pulseui","pulsese") + if(num && viable_occupant && connected && viable_occupant.stat != DEAD) + radduration = Wrap(radduration, 1, RADIATION_DURATION_MAX+1) + radstrength = Wrap(radstrength, 1, RADIATION_STRENGTH_MAX+1) + + var/locked_state = connected.locked + connected.locked = 1 + + current_screen = "working" + ShowInterface(usr) + + sleep(radduration*10) + current_screen = "mainmenu" + + if(viable_occupant && connected && connected.occupant==viable_occupant) + viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation + switch(href_list["task"]) //Same thing as there but values are even lower, on best part they are about 0.0*, effectively no damage + if("pulseui") + var/len = length(viable_occupant.dna.uni_identity) + num = Wrap(num, 1, len+1) + num = randomize_radiation_accuracy(num, radduration + (connected.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/block = round((num-1)/DNA_BLOCK_SIZE)+1 + var/subblock = num - block*DNA_BLOCK_SIZE + last_change = "UI #[block]-[subblock]; " + + var/hex = copytext(viable_occupant.dna.uni_identity, num, num+1) + last_change += "[hex]" + hex = scramble(hex, radstrength, radduration) + last_change += "->[hex]" + + viable_occupant.dna.uni_identity = copytext(viable_occupant.dna.uni_identity, 1, num) + hex + copytext(viable_occupant.dna.uni_identity, num+1, 0) + viable_occupant.updateappearance(mutations_overlay_update=1) + if("pulsese") + var/len = length(viable_occupant.dna.struc_enzymes) + num = Wrap(num, 1, len+1) + num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) + + var/block = round((num-1)/DNA_BLOCK_SIZE)+1 + var/subblock = num - block*DNA_BLOCK_SIZE + last_change = "SE #[block]-[subblock]; " + + var/hex = copytext(viable_occupant.dna.struc_enzymes, num, num+1) + last_change += "[hex]" + hex = scramble(hex, radstrength, radduration) + last_change += "->[hex]" + + viable_occupant.dna.struc_enzymes = copytext(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext(viable_occupant.dna.struc_enzymes, num+1, 0) + viable_occupant.domutcheck() + else + current_screen = "mainmenu" + + if(connected) + connected.locked = locked_state + + ShowInterface(usr,last_change) + +/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd) + var/length = length(input) + var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER) + if(ran == 0) ran = pick(-1,1) //hacky, statistically should almost never happen. 0-change makes people mad though + else if(ran < 0) ran = round(ran) //negative, so floor it + else ran = -round(-ran) //positive, so ceiling it + return num2hex(Wrap(hex2num(input)+ran, 0, 16**length), length) + +/obj/machinery/computer/scan_consolenew/proc/randomize_radiation_accuracy(position_we_were_supposed_to_hit, radduration, number_of_blocks) + return Wrap(round(position_we_were_supposed_to_hit + gaussian(0, RADIATION_ACCURACY_MULTIPLIER/radduration), 1), 1, number_of_blocks+1) + + + +/////////////////////////// DNA MACHINES +#undef INJECTOR_TIMEOUT +#undef REJUVENATORS_INJECT +#undef REJUVENATORS_MAX +#undef NUMBER_OF_BUFFERS + +#undef RADIATION_STRENGTH_MAX +#undef RADIATION_STRENGTH_MULTIPLIER + +#undef RADIATION_DURATION_MAX +#undef RADIATION_ACCURACY_MULTIPLIER + +#undef RADIATION_IRRADIATION_MULTIPLIER + +//#undef BAD_MUTATION_DIFFICULTY +//#undef GOOD_MUTATION_DIFFICULTY +//#undef OP_MUTATION_DIFFICULTY \ No newline at end of file diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm new file mode 100644 index 00000000000..ac18b3fe445 --- /dev/null +++ b/code/game/machinery/dna_scanner.dm @@ -0,0 +1,167 @@ +/obj/machinery/dna_scannernew + name = "\improper DNA scanner" + desc = "It scans DNA structures." + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "scanner" + density = 1 + var/locked = 0 + anchored = 1 + use_power = 1 + idle_power_usage = 50 + active_power_usage = 300 + var/damage_coeff + var/scan_level + var/precision_coeff + +/obj/machinery/dna_scannernew/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/clonescanner(null) + component_parts += new /obj/item/weapon/stock_parts/scanning_module(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/micro_laser(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/stack/cable_coil(null, 1) + component_parts += new /obj/item/stack/cable_coil(null, 1) + RefreshParts() + + +/obj/machinery/dna_scannernew/RefreshParts() + scan_level = 0 + damage_coeff = 0 + precision_coeff = 0 + for(var/obj/item/weapon/stock_parts/scanning_module/P in component_parts) + scan_level += P.rating + for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts) + precision_coeff = P.rating + for(var/obj/item/weapon/stock_parts/micro_laser/P in component_parts) + damage_coeff = P.rating + +/obj/machinery/dna_scannernew/update_icon() + + //no power or maintenance + if(stat & (NOPOWER|BROKEN)) + icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_unpowered" + return + + if((stat & MAINT) || panel_open) + icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_maintenance" + return + + //running and someone in there + if(occupant) + icon_state = initial(icon_state)+ "_occupied" + return + + //running + icon_state = initial(icon_state)+ (state_open ? "_open" : "") + +/obj/machinery/dna_scannernew/power_change() + ..() + update_icon() + +/obj/machinery/dna_scannernew/proc/toggle_open(mob/user) + if(panel_open) + user << "Close the maintenance panel first." + return + + if(state_open) + close_machine() + return + + else if(locked) + user << "The bolts are locked down, securing the door shut." + return + + open_machine() + +/obj/machinery/dna_scannernew/container_resist() + var/mob/living/user = usr + var/breakout_time = 2 + if(state_open || !locked) //Open and unlocked, no need to escape + state_open = 1 + return + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user << "You lean on the back of [src] and start pushing the door open... (this will take about [breakout_time] minutes.)" + user.visible_message("You hear a metallic creaking from [src]!") + + if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds + if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked) + return + + locked = 0 + visible_message("[user] successfully broke out of [src]!") + user << "You successfully break out of [src]!" + + open_machine() + +/obj/machinery/dna_scannernew/close_machine() + if(!state_open) + return 0 + + ..() + + // search for ghosts, if the corpse is empty and the scanner is connected to a cloner + if(occupant) + if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \ + || locate(/obj/machinery/computer/cloning, get_step(src, SOUTH)) \ + || locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \ + || locate(/obj/machinery/computer/cloning, get_step(src, WEST))) + + occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!") + return 1 + +/obj/machinery/dna_scannernew/open_machine() + if(state_open) + return 0 + + ..() + + return 1 + +/obj/machinery/dna_scannernew/relaymove(mob/user as mob) + if(user.stat || locked) + return + + open_machine() + return + +/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params) + + if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant... + update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed + return + + if(exchange_parts(user, I)) + return + + if(default_pry_open(I)) + return + + if(default_deconstruction_crowbar(I)) + return + + if(istype(I, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = I + if(!ismob(G.affecting)) + return + + if(!state_open) + user << "Open the scanner first." + return + + var/mob/M = G.affecting + M.loc = loc + user.stop_pulling() + qdel(G) + +/obj/machinery/dna_scannernew/attack_hand(mob/user) + if(..(user,1,0)) //don't set the machine, since there's no dialog + return + + toggle_open(user) + +/obj/machinery/dna_scannernew/blob_act() + if(prob(75)) + qdel(src) \ No newline at end of file diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 6c073ceb95e..143d5d30029 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -124,9 +124,9 @@ var/mob/living/carbon/human/T = attached - if(!istype(T)) return - if(!T.dna) + if(!istype(T)) return + if(T.disabilities & NOCLONE) return diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 1cbf53376ea..a1c1e470b03 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -315,8 +315,8 @@ var/mob/living/carbon/human/human = M if(human.dna && human.dna.species.id == "human") M << "You hear a buzzing in your ears." - hardset_dna(human, null, null, null, null, /datum/species/fly) - human.regenerate_icons() + human.set_species(/datum/species/fly) + human.apply_effect((rand(120 - accurate * 40, 180 - accurate * 60)), IRRADIATE, 0) calibrated = 0 return diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm index 55b9d068630..c6a3a347726 100644 --- a/code/game/mecha/combat/honker.dm +++ b/code/game/mecha/combat/honker.dm @@ -45,7 +45,7 @@ HONK pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
HONK temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
Lights: [lights?"on":"off"]
- [src.dna?"DNA-locked:
[src.dna] \[Reset\]
":null] + [dna_lock?"DNA-locked:
[dna_lock] \[Reset\]
":null] "} return output diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 0225ac4ee3b..17d095f2911 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -34,7 +34,7 @@ var/last_message = 0 var/add_req_access = 1 var/maint_access = 0 - var/dna //dna-locking the mech + var/dna_lock//dna-locking the mech var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference var/datum/effect/effect/system/spark_spread/spark_system = new var/lights = 0 @@ -557,7 +557,7 @@ else if(AI.stat || !AI.client) user << "[AI.name] is currently unresponsive, and cannot be uploaded." return - else if(occupant || dna) //Normal AIs cannot steal mechs! + else if(occupant || dna_lock) //Normal AIs cannot steal mechs! user << "Access denied. [name] is [occupant ? "currently occupied" : "secured with a DNA lock"]." return AI.control_disabled = 0 @@ -653,10 +653,10 @@ log_append_to_last("Permission denied.") return var/passed - if(dna) - if(check_dna_integrity(user)) + if(dna_lock) + if(user.has_dna()) var/mob/living/carbon/C = user - if(C.dna.unique_enzymes==src.dna) + if(C.dna.unique_enzymes==dna_lock) passed = 1 else if(operation_allowed(user)) passed = 1 @@ -711,8 +711,8 @@ else if(occupant) user << "Occupant detected!" return 0 - else if(dna && dna!=mmi_as_oc.brainmob.dna.unique_enzymes) - user << "Stop it!" + else if(dna_lock && (!mmi_as_oc.brainmob.dna || dna_lock!=mmi_as_oc.brainmob.dna.unique_enzymes)) + user << "Access denied. [name] is secured with a DNA lock." return 0 visible_message("[user] starts to insert an MMI into [src.name].") diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index 25ba30fde4a..8dc4dfde8c6 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -83,7 +83,7 @@ Airtank temperature: [tank_temperature]°K|[tank_temperature - T0C]°C
Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
- [src.dna?"DNA-locked:
[src.dna] \[Reset\]
":null] + [dna_lock?"DNA-locked:
[dna_lock] \[Reset\]
":null] "} return output @@ -300,11 +300,11 @@ if(occupant && !iscarbon(occupant)) occupant << " You do not have any DNA!" return - dna = src.occupant.dna.unique_enzymes + dna_lock = occupant.dna.unique_enzymes occupant_message("You feel a prick as the needle takes your DNA sample.") if(href_list["reset_dna"]) - dna = null + dna_lock = null if(href_list["repair_int_control_lost"]) occupant_message("Recalibrating coordination system...") diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index ad8574211f8..6f90e2d9f92 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -80,7 +80,7 @@ return if(ishuman(user)) var/mob/living/carbon/human/H = user - if(H.dna && (H.dna.check_mutation(HULK) || NOGUNS in H.dna.species.specflags)) + if(H.dna.check_mutation(HULK) || NOGUNS in H.dna.species.specflags) user << "Your fingers can't press the button!" return diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index a80e0d4eb31..c9311f53a64 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -162,8 +162,7 @@ MASS SPECTROMETER // Species and body temperature if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.dna) - user << "Species: [H.dna.species.name]" + user << "Species: [H.dna.species.name]" user << "Body temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)" // Time of death diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index 9276fce55bc..960b38ad0ba 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -17,7 +17,7 @@ /obj/item/weapon/dnainjector/proc/inject(mob/living/carbon/M, mob/user) - if(check_dna_integrity(M) && !(M.disabilities & NOCLONE)) + if(M.has_dna() && !(M.disabilities & NOCLONE)) if(M.stat == DEAD) //prevents dead people from having their DNA changed user << "You can't modify [M]'s DNA while \he's dead." return @@ -38,7 +38,7 @@ M.dna.blood_type = fields["blood_type"] if(fields["UI"]) //UI+UE M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"]) - updateappearance(M) + M.updateappearance() log_attack(log_msg) else user << "It appears that [M] does not have compatible DNA." diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 3fd5b7cf096..e342de7ac9a 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -244,7 +244,7 @@ return 1 /obj/item/weapon/twohanded/dualsaber/wield(mob/living/carbon/M) //Specific wield () hulk checks due to reflection chance for balance issues and switches hitsounds. - if(istype(M)) + if(M.has_dna()) if(M.dna.check_mutation(HULK)) M << "You lack the grace to wield this!" return diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index b0c939443c1..9c3f73faf40 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -148,16 +148,17 @@ var/racechoice = input(H, "What are we again?", "Race change") as null|anything in choosable_races newrace = species_list[racechoice] - if(!newrace || !H.dna) + if(!newrace) return - hardset_dna(H, null, null, null, null, newrace) + H.set_species(newrace, icon_update=0) if(H.dna.species.use_skintones) var/new_s_tone = input(user, "Choose your skin tone:", "Race change") as null|anything in skin_tones if(new_s_tone) H.skin_tone = new_s_tone + H.dna.update_ui_block(DNA_SKIN_TONE_BLOCK) if(MUTCOLORS in H.dna.species.specflags) var/new_mutantcolor = input(user, "Choose your skin color:", "Race change") as color|null @@ -170,7 +171,10 @@ else H << "Invalid color. Your color is not bright enough." - H.regenerate_icons() + H.update_body() + H.update_hair() + H.update_mutcolor() + H.update_mutations_overlay() // no hulk lizard if("gender") if(!(H.gender in list("male", "female"))) //blame the patriarchy @@ -180,12 +184,19 @@ if(alert(H, "Become a Witch?", "Confirmation", "Yes", "No") == "Yes") H.gender = "female" H << "Man, you feel like a woman!" - H.regenerate_icons() + else + return + else if(alert(H, "Become a Warlock?", "Confirmation", "Yes", "No") == "Yes") H.gender = "male" H << "Whoa man, you feel like a man!" - H.regenerate_icons() + else + return + H.dna.update_ui_block(DNA_GENDER_BLOCK) + H.update_body() + H.update_mutations_overlay() //(hulk male/female) + if("hair") var/hairchoice = alert(H, "Hair style or hair color?", "Change Hair", "Style", "Color") @@ -196,15 +207,17 @@ var/new_hair_color = input(H, "Choose your hair color", "Hair Color") as null|color if(new_hair_color) H.hair_color = sanitize_hexcolor(new_hair_color) + H.dna.update_ui_block(DNA_HAIR_COLOR_BLOCK) if(H.gender == "male") var/new_face_color = input(H, "Choose your facial hair color", "Hair Color") as null|color if(new_face_color) H.facial_hair_color = sanitize_hexcolor(new_face_color) - + H.dna.update_ui_block(DNA_FACIAL_HAIR_COLOR_BLOCK) H.update_hair() if("eyes") var/new_eye_color = input(H, "Choose your eye color", "Eye Color") as null|color if(new_eye_color) H.eye_color = sanitize_hexcolor(new_eye_color) + H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK) H.update_body() \ No newline at end of file diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index 2861e298a53..86eb11de26f 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -220,7 +220,7 @@ var/dat = "Showing DNA from blood.
" dat += "" for(var/mob/living/carbon/human/H in mob_list) - if(H.dna && H.ckey) + if(H.ckey) dat += "" dat += "
NameDNABlood Type
[H][H.dna.unique_enzymes][H.dna.blood_type]
" usr << browse(dat, "window=DNA;size=440x410") @@ -231,12 +231,7 @@ dat += "" for(var/mob/living/carbon/human/H in mob_list) if(H.ckey) - if(H.dna && H.dna.uni_identity) - dat += "" - else if(H.dna && !H.dna.uni_identity) - dat += "" - else if(!H.dna) - dat += "" + dat += "" dat += "
NameFingerprints
[H][md5(H.dna.uni_identity)]
[H]H.dna.uni_identity = null
[H]H.dna = null
[H][md5(H.dna.uni_identity)]
" usr << browse(dat, "window=fingerprints;size=440x410") @@ -259,8 +254,7 @@ message_admins("\blue [key_name_admin(usr)] turned all humans into [result]") var/newtype = species_list[result] for(var/mob/living/carbon/human/H in mob_list) - hardset_dna(H, null, null, null, null, newtype) - H.regenerate_icons() + H.set_species(newtype) if("corgi") if(!check_rights(R_FUN)) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 03d01a2cf24..09626b0d0ff 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -326,13 +326,13 @@ //Spawn and equip the commando var/mob/living/carbon/human/Commando = new(spawnloc) chosen_candidate.client.prefs.copy_to(Commando) - ready_dna(Commando) if(numagents == 1) //If Squad Leader Commando.real_name = "Officer [pick(commando_names)]" Commando.equipOutfit(/datum/outfit/death_commando/officer) else Commando.real_name = "Trooper [pick(commando_names)]" Commando.equipOutfit(/datum/outfit/death_commando) + Commando.dna.update_dna_identity() Commando.key = chosen_candidate.key Commando.mind.assigned_role = "Death Commando" for(var/obj/machinery/door/poddoor/ert/door in airlocks) @@ -420,8 +420,8 @@ //Create the official var/mob/living/carbon/human/newmob = new (pick(emergencyresponseteamspawn)) chosen_candidate.client.prefs.copy_to(newmob) - ready_dna(newmob) newmob.real_name = newmob.dna.species.random_name(newmob.gender,1) + newmob.dna.update_dna_identity() newmob.key = chosen_candidate.key newmob.mind.assigned_role = "Centcom Official" newmob.equipOutfit(/datum/outfit/centcom_official) @@ -490,7 +490,6 @@ var/mob/living/carbon/human/ERTOperative = new(spawnloc) var/list/lastname = last_names chosen_candidate.client.prefs.copy_to(ERTOperative) - ready_dna(ERTOperative) var/ertname = pick(lastname) switch(numagents) if(1) @@ -514,6 +513,7 @@ if(7) ERTOperative.real_name = "Engineer [ertname]" ERTOperative.equipOutfit(redalert ? /datum/outfit/ert/engineer/alert : /datum/outfit/ert/engineer) + ERTOperative.dna.update_dna_identity() ERTOperative.key = chosen_candidate.key ERTOperative.mind.assigned_role = "ERT" @@ -690,7 +690,7 @@ var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. G_found.client.prefs.copy_to(new_character) - ready_dna(new_character) + new_character.dna.update_dna_identity() new_character.key = G_found.key return new_character diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 7cb4c9f4994..6e314d19ee0 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -300,15 +300,13 @@ Traitors and the like can also be revived with the previous role mostly intact. new_character.real_name = record_found.fields["name"] new_character.gender = record_found.fields["sex"] new_character.age = record_found.fields["age"] - new_character.dna.blood_type = record_found.fields["blood_type"] + new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], record_found.fields["name"], record_found.fields["blood_type"], record_found.fields["species"], record_found.fields["features"]) else - new_character.gender = pick(MALE,FEMALE) var/datum/preferences/A = new() - A.real_name = G_found.real_name A.copy_to(new_character) + A.real_name = G_found.real_name + new_character.dna.update_dna_identity() - if(!new_character.real_name) - new_character.real_name = new_character.dna.species.random_name(new_character.gender,1) new_character.name = new_character.real_name if(G_found.mind && !G_found.mind.active) @@ -316,13 +314,8 @@ Traitors and the like can also be revived with the previous role mostly intact. new_character.mind.special_verbs = list() else new_character.mind_initialize() - if(!new_character.mind.assigned_role) new_character.mind.assigned_role = "Assistant"//If they somehow got a null assigned role. - - //DNA - if(record_found)//Pull up their name from database records if they did have a mind. - hardset_dna(new_character, record_found.fields["identity"], record_found.fields["enzymes"], record_found.fields["name"], record_found.fields["blood_type"], record_found.fields["species"], record_found.fields["features"]) - else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile. - ready_dna(new_character) + if(!new_character.mind.assigned_role) + new_character.mind.assigned_role = "Assistant"//If they somehow got a null assigned role. new_character.key = G_found.key @@ -822,7 +815,7 @@ var/list/datum/outfit/custom_outfits = list() //Admin created outfits id_select += "" id_select += "" - var/dat = {" + var/dat = {" Create Outfit
diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index 450d153a94f..54b0a0953c2 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -80,20 +80,17 @@ user.dna.add_mutation(LASEREYES) user.dna.add_mutation(COLDRES) user.dna.add_mutation(XRAY) - hardset_dna(user, null, null, null, null, /datum/species/shadow) - user.regenerate_icons() + user.set_species(/datum/species/shadow) if("Wealth") user << "Your wish is granted, but at a terrible cost..." user << "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart." new /obj/structure/closet/syndicate/resources/everything(loc) - hardset_dna(user, null, null, null, null, /datum/species/shadow) - user.regenerate_icons() + user.set_species(/datum/species/shadow) if("Immortality") user << "Your wish is granted, but at a terrible cost..." user << "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart." user.verbs += /mob/living/carbon/proc/immortality - hardset_dna(user, null, null, null, null, /datum/species/shadow) - user.regenerate_icons() + user.set_species(/datum/species/shadow) if("To Kill") user << "Your wish is granted, but at a terrible cost..." user << "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart." @@ -107,8 +104,7 @@ for(var/datum/objective/OBJ in user.mind.objectives) user << "Objective #[obj_count]: [OBJ.explanation_text]" obj_count++ - hardset_dna(user, null, null, null, null, /datum/species/shadow) - user.regenerate_icons() + user.set_species(/datum/species/shadow) if("Peace") user << "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence." user << "You feel as if you just narrowly avoided a terrible fate..." diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 24fe636eeff..95cd0a176d4 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1049,7 +1049,7 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set ShowChoices(user) return 1 -/datum/preferences/proc/copy_to(mob/living/carbon/human/character) +/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1) if(be_random_name) real_name = pref_species.random_name(gender) @@ -1081,19 +1081,19 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set character.undershirt = undershirt character.socks = socks - character.features = features - character.backbag = backbag - if(character.dna) - var/datum/species/chosen_species - - character.dna.real_name = character.real_name - if(pref_species != /datum/species/human && config.mutant_races) - chosen_species = pref_species.type - else - chosen_species = /datum/species/human - hardset_dna(character, null, null, null, blood_type, chosen_species, features) + character.dna.blood_type = blood_type + character.dna.features = features + character.dna.real_name = character.real_name + var/datum/species/chosen_species + if(pref_species != /datum/species/human && config.mutant_races) + chosen_species = pref_species.type else + chosen_species = /datum/species/human + character.set_species(chosen_species, icon_update=0) + + if(icon_updates) character.update_body() - character.update_hair() \ No newline at end of file + character.update_hair() + character.update_mutcolor() \ No newline at end of file diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm index 9d4981c9e80..fa324c1886c 100644 --- a/code/modules/detectivework/detective_work.dm +++ b/code/modules/detectivework/detective_work.dm @@ -52,21 +52,19 @@ if(isnull(M.key)) return if(ishuman(M)) var/mob/living/carbon/human/H = M - if(!istype(H.dna, /datum/dna)) - return 0 if(H.gloves) if(fingerprintslast != H.ckey) - fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key) + fingerprintshidden += "\[[time_stamp()]\] (Wearing gloves). Real name: [H.real_name], Key: [H.key]" fingerprintslast = H.ckey return 0 - if(!( fingerprints )) + if(!fingerprints) if(fingerprintslast != H.ckey) - fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",H.real_name, H.key) + fingerprintshidden += "\[[time_stamp()]\] Real name: [H.real_name], Key: [H.key]" fingerprintslast = H.ckey return 1 else if(fingerprintslast != M.ckey) - fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",M.real_name, M.key) + fingerprintshidden += "\[[time_stamp()]\] Real name: [M.real_name], Key: [M.key]" fingerprintslast = M.ckey return @@ -75,17 +73,15 @@ if(isnull(M)) return if(isnull(M.key)) return if(ishuman(M)) + var/mob/living/carbon/human/H = M //Add the list if it does not exist. if(!fingerprintshidden) fingerprintshidden = list() //Fibers~ - add_fibers(M) + add_fibers(H) //Now, lets get to the dirty work. - //First, make sure their DNA makes sense. - var/mob/living/carbon/human/H = M - check_dna_integrity(H) //sets up dna and its variables if it was missing somehow //Check if the gloves (if any) hide fingerprints if(H.gloves) diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index a35fe5de224..f31a4f9d81f 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -82,7 +82,7 @@ if(ishuman(A)) var/mob/living/carbon/human/H = A - if (istype(H.dna, /datum/dna) && !H.gloves) + if(!H.gloves) fingerprints += md5(H.dna.uni_identity) else if(!ismob(A)) diff --git a/code/modules/events/holiday/halloween.dm b/code/modules/events/holiday/halloween.dm index a08a507a907..107c8f10920 100644 --- a/code/modules/events/holiday/halloween.dm +++ b/code/modules/events/holiday/halloween.dm @@ -11,11 +11,10 @@ for(var/mob/living/carbon/human/H in mob_list) var/obj/item/weapon/storage/backpack/b = locate() in H.contents new /obj/item/weapon/storage/spooky(b) - if(H.dna) - if(prob(50)) - hardset_dna(H, null, null, null, null, /datum/species/skeleton) - else - hardset_dna(H, null, null, null, null, /datum/species/zombie) + if(prob(50)) + H.set_species(/datum/species/skeleton) + else + H.set_species(/datum/species/zombie) for(var/mob/living/simple_animal/pet/dog/corgi/Ian/Ian in mob_list) Ian.place_on_head(new /obj/item/weapon/bedsheet(Ian)) diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index f86ecdb5c42..1857a625da0 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -43,10 +43,10 @@ if(prob(25)) if(prob(75)) randmutb(H) - domutcheck(H, null, 1) + H.domutcheck() else randmutg(H) - domutcheck(H, null, 1) + H.domutcheck() else if(istype(C, /mob/living/carbon/monkey)) var/mob/living/carbon/monkey/M = C diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm index cda6dc2d41f..fdfdd98f451 100644 --- a/code/modules/events/wizard/imposter.dm +++ b/code/modules/events/wizard/imposter.dm @@ -17,13 +17,10 @@ PoolOrNew(/obj/effect/effect/smoke, W.loc) var/mob/living/carbon/human/I = new /mob/living/carbon/human(W.loc) - I.real_name = W.real_name - I.dna.unique_enzymes = W.dna.unique_enzymes - I.name = W.real_name - I.dna.blood_type = W.dna.blood_type - I.dna.uni_identity = W.dna.uni_identity - I.dna.struc_enzymes = W.dna.struc_enzymes - updateappearance(I) + W.dna.transfer_identity(I, transfer_SE=1) + I.real_name = I.dna.real_name + I.name = I.dna.real_name + I.updateappearance(mutcolor_update=1) if(W.ears) I.equip_to_slot_or_del(new W.ears.type, slot_ears) if(W.w_uniform) I.equip_to_slot_or_del(new W.w_uniform.type , slot_w_uniform) if(W.shoes) I.equip_to_slot_or_del(new W.shoes.type, slot_shoes) diff --git a/code/modules/events/wizard/race.dm b/code/modules/events/wizard/race.dm index 54c3cbf6877..7bbee2ba98c 100644 --- a/code/modules/events/wizard/race.dm +++ b/code/modules/events/wizard/race.dm @@ -21,10 +21,9 @@ all_the_same = 1 for(var/mob/living/carbon/human/H in mob_list) //yes, even the dead - if(H.dna) - hardset_dna(H, null, null, null, null, new_species) - H.real_name = new_species.random_name(H.gender,1) - H.regenerate_icons() - H << "You feel somehow... different?" + H.set_species(new_species) + H.real_name = new_species.random_name(H.gender,1) + H.dna.unique_enzymes = H.dna.generate_unique_enzymes() + H << "You feel somehow... different?" if(!all_the_same) new_species = pick(all_species) diff --git a/code/modules/food&drinks/kitchen machinery/processor.dm b/code/modules/food&drinks/kitchen machinery/processor.dm index 431dee34309..5db38bbc970 100644 --- a/code/modules/food&drinks/kitchen machinery/processor.dm +++ b/code/modules/food&drinks/kitchen machinery/processor.dm @@ -112,8 +112,8 @@ for(var/datum/disease/D in O.viruses) if(!(D.spread_flags & SPECIAL)) B.data["viruses"] += D.Copy() - if(check_dna_integrity(O)) - B.data["blood_DNA"] = copytext(O.dna.unique_enzymes,1,0) + if(O.has_dna()) + B.data["blood_DNA"] = O.dna.unique_enzymes if(O.resistances&&O.resistances.len) B.data["resistances"] = O.resistances.Copy() diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index a0d3d291abb..83c531362bc 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -897,7 +897,7 @@ podman.faction |= factions if(!features["mcolor"]) features["mcolor"] = "#59CE00" - hardset_dna(podman,null,null,podman.real_name,blood_type,/datum/species/plant/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman + podman.hardset_dna(null,null,podman.real_name,blood_type,/datum/species/plant/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman podman.set_cloned_appearance() else //else, one packet of seeds. maybe two diff --git a/code/modules/mob/interactive.dm b/code/modules/mob/interactive.dm index 0660e8e4f99..3c24e017066 100644 --- a/code/modules/mob/interactive.dm +++ b/code/modules/mob/interactive.dm @@ -86,22 +86,14 @@ /mob/living/carbon/human/interactive/proc/random() //this is here because this has no client/prefs/brain whatever. - underwear = random_underwear(gender) - skin_tone = random_skin_tone() - hair_style = random_hair_style(gender) - facial_hair_style = random_facial_hair_style(gender) - hair_color = random_short_color() - facial_hair_color = hair_color - eye_color = "blue" age = rand(AGE_MIN,AGE_MAX) - ready_dna(src,random_blood_type()) //job handling var/list/jobs = SSjob.occupations for(var/datum/job/J in jobs) if(J.title == "Cyborg" || J.title == "AI" || J.title == "Chaplain" || J.title == "Mime") jobs -= J myjob = pick(jobs) - src.job = myjob.title + job = myjob.title if(!graytide) myjob.equip(src) myjob.apply_fingerprints(src) @@ -120,25 +112,18 @@ /mob/living/carbon/human/interactive/New() ..() - gender = pick(MALE,FEMALE) - if(gender == MALE) - name = "[pick(first_names_male)] [pick(last_names)]" - real_name = name - else - name = "[pick(first_names_female)] [pick(last_names)]" - real_name = name random() MYID = new(src) MYID.name = "[src.real_name]'s ID Card ([myjob.title])" MYID.assignment = "[myjob.title]" MYID.registered_name = src.real_name MYID.access = myjob.access - src.equip_to_slot_or_del(MYID, slot_wear_id) + equip_to_slot_or_del(MYID, slot_wear_id) MYPDA = new(src) - MYPDA.owner = src.real_name + MYPDA.owner = real_name MYPDA.ownjob = "Crew" - MYPDA.name = "PDA-[src.real_name] ([myjob.title])" - src.equip_to_slot_or_del(MYPDA, slot_belt) + MYPDA.name = "PDA-[real_name] ([myjob.title])" + equip_to_slot_or_del(MYPDA, slot_belt) zone_sel = new /obj/screen/zone_sel() zone_sel.selecting = "chest" if(prob(10)) //my x is augmented @@ -371,9 +356,7 @@ if(!l_hand || !r_hand) var/obj/item/clothing/C = TARGET take_to_slot(C) - if(equip_to_appropriate_slot(C)) - C.update_icon() - else + if(!equip_to_appropriate_slot(C)) var/obj/item/I = get_item_by_slot(C) unEquip(I) equip_to_appropriate_slot(C) @@ -384,7 +367,6 @@ equip_to_appropriate_slot(MYPDA) if(MYID in src.loc) equip_to_appropriate_slot(MYID) - update_icons() //THIEVING SKILLS END //-------------TOUCH ME if(istype(TARGET,/obj/structure)) diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 248d147de43..f615908affe 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -85,15 +85,18 @@ update_icon() name = "Man-Machine Interface" -/obj/item/device/mmi/proc/transfer_identity(mob/living/carbon/human/H) //Same deal as the regular brain proc. Used for human-->robot people. +/obj/item/device/mmi/proc/transfer_identity(mob/living/L) //Same deal as the regular brain proc. Used for human-->robot people. brainmob = new(src) - brainmob.name = H.real_name - brainmob.real_name = H.real_name - if(check_dna_integrity(H)) - brainmob.dna = H.dna + brainmob.name = L.real_name + brainmob.real_name = L.real_name + if(L.has_dna()) + var/mob/living/carbon/C = L + brainmob.dna = C.dna + brainmob.dna.holder = brainmob brainmob.container = src - if(istype(H)) + if(ishuman(L)) + var/mob/living/carbon/human/H = L var/obj/item/organ/internal/brain/newbrain = H.getorgan(/obj/item/organ/internal/brain) newbrain.loc = src brain = newbrain diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 981facfcc9b..81c7deec716 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -26,10 +26,10 @@ qdel(brainmob) - //Update the body's icon so it doesnt appear debrained anymore - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.update_hair(0) + //Update the body's icon so it doesnt appear debrained anymore + if(ishuman(M)) + var/mob/living/carbon/human/H = M + H.update_hair(0) /obj/item/organ/internal/brain/Remove(mob/living/carbon/M, special = 0) ..() @@ -56,9 +56,10 @@ brainmob.name = L.real_name brainmob.real_name = L.real_name brainmob.timeofhostdeath = L.timeofdeath - if(iscarbon(L)) + if(L.has_dna()) var/mob/living/carbon/C = L brainmob.dna = C.dna + brainmob.dna.holder = brainmob if(L.mind) L.mind.transfer_to(brainmob) brainmob << "You feel slightly disoriented. That's normal when you're just a brain." diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index 7f8445b95fc..ae7508be604 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -55,17 +55,20 @@ var/global/posibrain_notif_cooldown = 0 return transfer_personality(user) -/obj/item/device/mmi/posibrain/transfer_identity(mob/living/carbon/H) - name = "positronic brain ([H])" - brainmob.name = H.real_name - brainmob.real_name = H.real_name - brainmob.dna = H.dna - brainmob.timeofhostdeath = H.timeofdeath +/obj/item/device/mmi/posibrain/transfer_identity(mob/living/carbon/C) + name = "positronic brain ([C])" + brainmob.name = C.real_name + brainmob.real_name = C.real_name + brainmob.dna = C.dna + if(C.has_dna()) + brainmob.dna = C.dna + brainmob.dna.holder = brainmob + brainmob.timeofhostdeath = C.timeofdeath brainmob.stat = 0 if(brainmob.mind) brainmob.mind.assigned_role = "Positronic Brain" - if(H.mind) - H.mind.transfer_to(brainmob) + if(C.mind) + C.mind.transfer_to(brainmob) brainmob.mind.remove_all_antag() brainmob.mind.wipe_memory() diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 580b0b5919d..89af6c2f4ca 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -9,9 +9,6 @@ var/obj/item/handcuffed = null //Whether or not the mob is handcuffed var/obj/item/legcuffed = null //Same as handcuffs but for legs. Bear traps use this. - var/list/features = list("mcolor" = "FFF", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None") - - //inventory slots var/obj/item/back = null var/obj/item/clothing/mask/wear_mask = null diff --git a/code/modules/mob/living/carbon/human/blood.dm b/code/modules/mob/living/carbon/human/blood.dm index e91eca45fb3..86ab99bf505 100644 --- a/code/modules/mob/living/carbon/human/blood.dm +++ b/code/modules/mob/living/carbon/human/blood.dm @@ -272,10 +272,9 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 source = M.get_blood(M.vessel) else if(istype(source,/mob/living/carbon/monkey)) var/mob/living/carbon/monkey/donor = source - if(donor.dna) - source = new() - source.data["blood_DNA"] = donor.dna.unique_enzymes - source.data["blood_type"] = donor.dna.blood_type + source = new() + source.data["blood_DNA"] = donor.dna.unique_enzymes + source.data["blood_type"] = donor.dna.blood_type // Are we dripping or splattering? var/list/drips = list() diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 147a0a7f016..a24e880ed7a 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -8,10 +8,7 @@ ..() /mob/living/carbon/human/spawn_gibs() - if(dna) - hgibs(loc, viruses, dna) - else - hgibs(loc, viruses, null) + hgibs(loc, viruses, dna) /mob/living/carbon/human/spawn_dust() new /obj/effect/decal/remains/human(loc) @@ -35,8 +32,7 @@ update_canmove() if(client) blind.layer = 0 - if(dna) - dna.species.spec_death(gibbed,src) + dna.species.spec_death(gibbed,src) tod = worldtime2text() //weasellos time of death patch if(mind) mind.store_memory("Time of death: [tod]", 0) @@ -47,9 +43,8 @@ return ..(gibbed) /mob/living/carbon/human/proc/makeSkeleton() - if(!check_dna_integrity(src)) return status_flags |= DISFIGURED - hardset_dna(src, null, null, null, null, /datum/species/skeleton) + set_species(/datum/species/skeleton) return 1 /mob/living/carbon/proc/ChangeToHusk() diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index c90c5171808..2ab52c617ef 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -308,7 +308,7 @@ m_type = 2 if("wag","wags") - if(dna && dna.species && (("tail_lizard" in dna.species.mutant_bodyparts) || (features["tail_human"] != "None"))) + if(dna && dna.species && (("tail_lizard" in dna.species.mutant_bodyparts) || (dna.features["tail_human"] != "None"))) message = "[src] wags \his tail." startTailWag() else diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b2e031465b2..2b585fa1f89 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -16,6 +16,12 @@ /mob/living/carbon/human/New() verbs += /mob/living/proc/mob_sleep verbs += /mob/living/proc/lay_down + + //initialize dna. for spawned humans; overwritten by other code + create_dna(src) + randomize_human(src) + dna.initialize_dna() + //initialise organs organs = newlist(/obj/item/organ/limb/chest, /obj/item/organ/limb/head, /obj/item/organ/limb/l_arm, /obj/item/organ/limb/r_arm, /obj/item/organ/limb/r_leg, /obj/item/organ/limb/l_leg) @@ -28,11 +34,6 @@ for(var/obj/item/organ/internal/I in internal_organs) I.Insert(src) - // for spawned humans; overwritten by other code - create_dna(src) - randomize_human(src) - ready_dna(src) - make_blood() ..() @@ -90,9 +91,8 @@ stat("Energy Charge:", "[round(SN.cell.charge/100)]%") stat("Smoke Bombs:", "\Roman [SN.s_bombs]") //Ninja status - if(dna) - stat("Fingerprints:", "[md5(dna.uni_identity)]") - stat("Unique Identity:", "[dna.unique_enzymes]") + stat("Fingerprints:", "[md5(dna.uni_identity)]") + stat("Unique Identity:", "[dna.unique_enzymes]") stat("Overall Status:", "[stat > 1 ? "dead" : "[health]% healthy"]") stat("Nutrition Status:", "[nutrition]") stat("Oxygen Loss:", "[getOxyLoss()]") @@ -663,7 +663,8 @@ facial_hair_style = "Shaved" hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") underwear = "Nude" - regenerate_icons() + update_body() + update_hair() /mob/living/carbon/human/singularity_act() var/gain = 20 diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 39ba01934e5..b1502b73eef 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -7,11 +7,7 @@ /mob/living/carbon/human/attack_hand(mob/living/carbon/human/M) if(..()) //to allow surgery to return properly. return - - if(dna) - dna.species.spec_attack_hand(M, src) - - return + dna.species.spec_attack_hand(M, src) /mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params) return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 4cd0b1b833a..37f501760a5 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -160,38 +160,5 @@ /mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0) - if(dna) // if you have a species, it will run the apply_damage code there instead - dna.species.apply_damage(damage, damagetype, def_zone, blocked, src) - else - if((damagetype != BRUTE) && (damagetype != BURN)) - ..(damage, damagetype, def_zone, blocked) - return 1 - - else - blocked = (100-blocked)/100 - if(blocked <= 0) return 0 - - var/obj/item/organ/limb/organ = null - if(islimb(def_zone)) - organ = def_zone - else - if(!def_zone) def_zone = ran_zone(def_zone) - organ = get_organ(check_zone(def_zone)) - if(!organ) return 0 - - damage = (damage * blocked) - - switch(damagetype) - if(BRUTE) - damageoverlaytemp = 20 - if(organ.take_damage(damage, 0)) - update_damage_overlays(0) - if(BURN) - damageoverlaytemp = 20 - if(organ.take_damage(0, damage)) - update_damage_overlays(0) - - // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life(). - - updatehealth() - return 1 + // depending on the species, it will run the corresponding apply_damage code there + return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index b06507cff74..d11d0e389e2 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -37,9 +37,7 @@ emp_act return protection /mob/living/carbon/human/on_hit(proj_type) - if(dna) - dna.species.on_hit(proj_type, src) - return + dna.species.on_hit(proj_type, src) /mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone) if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) @@ -128,91 +126,8 @@ emp_act feedback_add_details("item_used_for_combat","[I.type]|[I.force]") feedback_add_details("zone_targeted","[target_area]") - if(dna) // allows your species to affect the attacked_by code - return dna.species.spec_attacked_by(I,user,def_zone,affecting,hit_area,src.a_intent,target_limb,target_area,src) - - else - if(user != src) - user.do_attack_animation(src) - if(check_shields(I.force, "the [I.name]", I)) - return 0 - - if(I.attack_verb && I.attack_verb.len) - visible_message("[user] has [pick(I.attack_verb)] [src] in the [hit_area] with [I]!", \ - "[user] has [pick(I.attack_verb)] [src] in the [hit_area] with [I]!") - else if(I.force) - visible_message("[user] has attacked [src] in the [hit_area] with [I]!", \ - "[user] has attacked [src] in the [hit_area] with [I]!") - else - return 0 - - var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened a hit to your [hit_area].", I.armour_penetration) - armor = min(90,armor) //cap damage reduction at 90% - - var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) - - apply_damage(I.force, I.damtype, affecting, armor , I) - var/bloody = 0 - if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2)))) - if(affecting.status == ORGAN_ORGANIC) - I.add_blood(src) //Make the weapon bloody, not the person. - if(prob(I.force * 2)) //blood spatter! - bloody = 1 - var/turf/location = loc - if(istype(location, /turf/simulated)) - location.add_blood(src) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood - if(H.wear_suit) - H.wear_suit.add_blood(src) - H.update_inv_wear_suit() //updates mob overlays to show the new blood (no refresh) - else if(H.w_uniform) - H.w_uniform.add_blood(src) - H.update_inv_w_uniform() //updates mob overlays to show the new blood (no refresh) - if (H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - G.add_blood(H) - else - H.add_blood(H) - H.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves - - switch(hit_area) - if("head") //Harder to score a stun but if you do it lasts a bit longer - if(stat == CONSCIOUS) - if(prob(I.force)) - visible_message("[src] has been knocked unconscious!", \ - "[src] has been knocked unconscious!") - apply_effect(20, PARALYZE, armor) - if(prob(I.force + min(100,100 - src.health)) && src != user && I.damtype == BRUTE) - ticker.mode.remove_revolutionary(mind) - if(bloody) //Apply blood - if(wear_mask) - wear_mask.add_blood(src) - update_inv_wear_mask() - if(head) - head.add_blood(src) - update_inv_head() - if(glasses && prob(33)) - glasses.add_blood(src) - update_inv_glasses() - - if("chest") //Easier to score a stun but lasts less time - if(stat == CONSCIOUS && I.force && prob(I.force + 10)) - visible_message("[src] has been knocked down!", \ - "[src] has been knocked down!") - apply_effect(5, WEAKEN, armor) - - if(bloody) - if(wear_suit) - wear_suit.add_blood(src) - update_inv_wear_suit() - if(w_uniform) - w_uniform.add_blood(src) - update_inv_w_uniform() - - if(Iforce > 10 || Iforce >= 5 && prob(33)) - forcesay(hit_appends) //forcesay checks stat already + // the attacked_by code varies among species + return dna.species.spec_attacked_by(I,user,def_zone,affecting,hit_area,src.a_intent,target_limb,target_area,src) /mob/living/carbon/human/emp_act(severity) var/informed = 0 diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index f63e04ad3cf..ed0add4de62 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -128,11 +128,9 @@ return (health <= config.health_threshold_crit && stat == UNCONSCIOUS) /mob/living/carbon/human/reagent_check(datum/reagent/R) - if(dna) - var/bypass = dna.species.handle_chemicals(R,src) - return bypass // if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species. - else - return 0 + return dna.species.handle_chemicals(R,src) + // if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species. + /mob/living/carbon/human/can_track(mob/living/user) if(wear_id && istype(wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 69412112239..ca451659a7e 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -1,6 +1,6 @@ /mob/living/carbon/human/movement_delay() - if(dna) - . += dna.species.movement_delay(src) + + . += dna.species.movement_delay(src) . += ..() . += config.human_delay @@ -46,9 +46,8 @@ /mob/living/carbon/human/Move(NewLoc, direct) . = ..() - if(dna) - for(var/datum/mutation/human/HM in dna.mutations) - HM.on_move(src, NewLoc) + for(var/datum/mutation/human/HM in dna.mutations) + HM.on_move(src, NewLoc) if(shoes) if(!lying) if(loc == NewLoc) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index db4591a230d..5968b88647e 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -1,158 +1,5 @@ /mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0) - if(dna) - return dna.species.can_equip(I, slot, disable_warning, src) - else - switch(slot) - if(slot_l_hand) - if(l_hand) - return 0 - return 1 - if(slot_r_hand) - if(r_hand) - return 0 - return 1 - if(slot_wear_mask) - if(wear_mask) - return 0 - if( !(I.slot_flags & SLOT_MASK) ) - return 0 - return 1 - if(slot_back) - if(back) - return 0 - if( !(I.slot_flags & SLOT_BACK) ) - return 0 - return 1 - if(slot_wear_suit) - if(wear_suit) - return 0 - if( !(I.slot_flags & SLOT_OCLOTHING) ) - return 0 - return 1 - if(slot_gloves) - if(gloves) - return 0 - if( !(I.slot_flags & SLOT_GLOVES) ) - return 0 - return 1 - if(slot_shoes) - if(shoes) - return 0 - if( !(I.slot_flags & SLOT_FEET) ) - return 0 - return 1 - if(slot_belt) - if(belt) - return 0 - if(!w_uniform) - if(!disable_warning) - src << "You need a jumpsuit before you can attach this [I.name]!" - return 0 - if( !(I.slot_flags & SLOT_BELT) ) - return - return 1 - if(slot_glasses) - if(glasses) - return 0 - if( !(I.slot_flags & SLOT_EYES) ) - return 0 - return 1 - if(slot_head) - if(head) - return 0 - if( !(I.slot_flags & SLOT_HEAD) ) - return 0 - return 1 - if(slot_ears) - if(ears) - return 0 - if( !(I.slot_flags & SLOT_EARS) ) - return 0 - return 1 - if(slot_w_uniform) - if(w_uniform) - return 0 - if( !(I.slot_flags & SLOT_ICLOTHING) ) - return 0 - return 1 - if(slot_wear_id) - if(wear_id) - return 0 - if(!w_uniform) - if(!disable_warning) - src << "You need a jumpsuit before you can attach this [I.name]!" - return 0 - if( !(I.slot_flags & SLOT_ID) ) - return 0 - return 1 - if(slot_l_store) - if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them. - return 0 - if(l_store) - return 0 - if(!w_uniform) - if(!disable_warning) - src << "You need a jumpsuit before you can attach this [I.name]!" - return 0 - if(I.slot_flags & SLOT_DENYPOCKET) - return - if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) - return 1 - if(slot_r_store) - if(I.flags & NODROP) - return 0 - if(r_store) - return 0 - if(!w_uniform) - if(!disable_warning) - src << "You need a jumpsuit before you can attach this [I.name]!" - return 0 - if(I.slot_flags & SLOT_DENYPOCKET) - return 0 - if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) - return 1 - return 0 - if(slot_s_store) - if(I.flags & NODROP) //Suit storage NODROP items drop if you take a suit off, this is to prevent people exploiting this. - return 0 - if(s_store) - return 0 - if(!wear_suit) - if(!disable_warning) - src << "You need a suit before you can attach this [I.name]!" - return 0 - if(!wear_suit.allowed) - if(!disable_warning) - usr << "You somehow have a suit with no defined allowed items for suit storage, stop that!" //should be src? - return 0 - if(I.w_class > 4) - if(!disable_warning) - usr << "The [I.name] is too big to attach!" //should be src? - return 0 - if( istype(I, /obj/item/device/pda) || istype(I, /obj/item/weapon/pen) || is_type_in_list(I, wear_suit.allowed) ) //ugly and un-polymorphic. - return 1 - return 0 - if(slot_handcuffed) - if(handcuffed) - return 0 - if(!istype(I, /obj/item/weapon/restraints/handcuffs)) - return 0 - return 1 - if(slot_legcuffed) - if(legcuffed) - return 0 - if(!istype(I, /obj/item/weapon/restraints/legcuffs)) - return 0 - return 1 - if(slot_in_backpack) - if (back && istype(back, /obj/item/weapon/storage/backpack)) - var/obj/item/weapon/storage/backpack/B = back - if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class) - return 1 - return 0 - return 0 //Unsupported slot - - + return dna.species.can_equip(I, slot, disable_warning, src) /mob/living/carbon/human/verb/quick_equip() set name = "quick-equip" @@ -477,7 +324,7 @@ /mob/living/carbon/human/proc/equipOutfit(outfit) var/datum/outfit/O = null - + if(ispath(outfit)) O = new outfit else @@ -486,5 +333,5 @@ return 0 if(!O) return 0 - + return O.equip(src) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 0d51f2f5d0d..b4f66fe3ccc 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -38,9 +38,8 @@ tinttotal = tintcheck() //here as both hud updates and status updates call it if(..()) - if(dna) - for(var/datum/mutation/human/HM in dna.mutations) - HM.on_life(src) + for(var/datum/mutation/human/HM in dna.mutations) + HM.on_life(src) //heart attack stuff handle_heart() @@ -50,8 +49,7 @@ //Update our name based on whether our face is obscured/disfigured name = get_visible_name() - if(dna) - dna.species.spec_life(src) // for mutantraces + dna.species.spec_life(src) // for mutantraces /mob/living/carbon/human/calculate_affecting_pressure(pressure) @@ -98,16 +96,15 @@ reagents.metabolize(src, can_overdose=1) /mob/living/carbon/human/breathe() - if(!dna || !dna.species.breathe(src)) + if(!dna.species.breathe(src)) ..() /mob/living/carbon/human/check_breath(datum/gas_mixture/breath) - if(!dna || !dna.species.check_breath(breath, src)) + if(!dna.species.check_breath(breath, src)) ..() /mob/living/carbon/human/handle_environment(datum/gas_mixture/environment) - if(dna) - dna.species.handle_environment(environment, src) + dna.species.handle_environment(environment, src) ///FIRE CODE /mob/living/carbon/human/handle_fire() @@ -263,10 +260,7 @@ /mob/living/carbon/human/handle_chemicals_in_body() ..() - if(dna) - dna.species.handle_chemicals_in_body(src) - - return //TODO: DEFERRED + dna.species.handle_chemicals_in_body(src) /mob/living/carbon/human/handle_vision() client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask) @@ -275,12 +269,10 @@ else if(!client.adminobs) reset_view(null) - if(dna) - dna.species.handle_vision(src) + dna.species.handle_vision(src) /mob/living/carbon/human/handle_hud_icons() - if(dna) - dna.species.handle_hud_icons(src) + dna.species.handle_hud_icons(src) /mob/living/carbon/human/handle_random_events() // Puke if toxloss is too high diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 8b0fdbe16d5..4720ac6a5cf 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -9,8 +9,7 @@ return ..() /mob/living/carbon/human/treat_message(message) - if(dna) - message = dna.species.handle_speech(message,src) + message = dna.species.handle_speech(message,src) if(viruses.len) for(var/datum/disease/pierrot_throat/D in viruses) var/list/temp_message = text2list(message, " ") //List each word in the message @@ -25,8 +24,7 @@ pick_list -= H //Make sure that you dont HONK the same word twice message = list2text(temp_message, " ") message = ..(message) - if(dna) - message = dna.mutations_say_mods(message) + message = dna.mutations_say_mods(message) return message /mob/living/carbon/human/get_spans() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 5ffd1419253..f9973ea991d 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -247,7 +247,7 @@ if(H.undershirt) var/datum/sprite_accessory/undershirt/U2 = undershirt_list[H.undershirt] if(U2) - if(H.dna && H.dna.species.sexes && H.gender == FEMALE) + if(H.dna.species.sexes && H.gender == FEMALE) standing += H.wear_female_version(U2.icon_state, U2.icon, BODY_LAYER) else standing += image("icon"=U2.icon, "icon_state"="[U2.icon_state]_s", "layer"=-BODY_LAYER) @@ -804,8 +804,8 @@ if(prob(1)) H << "You mutate!" randmutb(H) - domutcheck(H,null) H.emote("gasp") + H.domutcheck() return 0 return 1 @@ -907,22 +907,14 @@ else M.do_attack_animation(H) - var/atk_verb = "punch" + var/atk_verb = M.dna.species.attack_verb if(H.lying) atk_verb = "kick" - else if(M.dna) - atk_verb = M.dna.species.attack_verb - var/damage = rand(0, 9) - if(M.dna) - damage += M.dna.species.punchmod + var/damage = rand(0, 9) + M.dna.species.punchmod if(!damage) - if(M.dna) - playsound(H.loc, M.dna.species.miss_sound, 25, 1, -1) - else - playsound(H.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - + playsound(H.loc, M.dna.species.miss_sound, 25, 1, -1) H.visible_message("[M] has attempted to [atk_verb] [H]!") return 0 @@ -930,11 +922,7 @@ var/obj/item/organ/limb/affecting = H.get_organ(ran_zone(M.zone_sel.selecting)) var/armor_block = H.run_armor_check(affecting, "melee") - if(M.dna) - playsound(H.loc, M.dna.species.attack_sound, 25, 1, -1) - else - playsound(H.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) - + playsound(H.loc, M.dna.species.attack_sound, 25, 1, -1) H.visible_message("[M] has [atk_verb]ed [H]!", \ "[M] has [atk_verb]ed [H]!") @@ -1008,9 +996,9 @@ /datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, def_zone, obj/item/organ/limb/affecting, hit_area, intent, obj/item/organ/limb/target_limb, target_area, mob/living/carbon/human/H) // Allows you to put in item-specific reactions based on species - if(user != src) + if(user != H) user.do_attack_animation(H) - if((user != H) && H.check_shields(I.force, "the [I.name]", I)) + if(H.check_shields(I.force, "the [I.name]", I)) return 0 if(I.attack_verb && I.attack_verb.len) @@ -1022,11 +1010,11 @@ else return 0 - var/armor = H.run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened a hit to your [hit_area].",I.armour_penetration) - armor = min(90,armor) //cap damage reduction at 90% + var/armor_block = H.run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened a hit to your [hit_area].",I.armour_penetration) + armor_block = min(90,armor_block) //cap damage reduction at 90% var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) - apply_damage(I.force, I.damtype, affecting, armor, H) + apply_damage(I.force, I.damtype, affecting, armor_block, H) var/bloody = 0 if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2)))) @@ -1037,28 +1025,30 @@ var/turf/location = H.loc if(istype(location, /turf/simulated)) location.add_blood(H) - if(get_dist(H, H) <= 1) //people with TK won't get smeared with blood - if(H.wear_suit) - H.wear_suit.add_blood(H) - H.update_inv_wear_suit() //updates mob overlays to show the new blood (no refresh) - else if(H.w_uniform) - H.w_uniform.add_blood(H) - H.update_inv_w_uniform() //updates mob overlays to show the new blood (no refresh) - if (H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - G.add_blood(H) - else - H.add_blood(H) - H.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves + if(ishuman(user)) + var/mob/living/carbon/human/M = user + if(get_dist(M, H) <= 1) //people with TK won't get smeared with blood + if(M.wear_suit) + M.wear_suit.add_blood(H) + M.update_inv_wear_suit() //updates mob overlays to show the new blood (no refresh) + else if(M.w_uniform) + M.w_uniform.add_blood(H) + M.update_inv_w_uniform() //updates mob overlays to show the new blood (no refresh) + if (M.gloves) + var/obj/item/clothing/gloves/G = M.gloves + G.add_blood(H) + else + M.add_blood(H) + M.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves switch(hit_area) if("head") //Harder to score a stun but if you do it lasts a bit longer - if(H.stat == CONSCIOUS && armor < 50) + if(H.stat == CONSCIOUS && armor_block < 50) if(prob(I.force)) H.visible_message("[H] has been knocked unconscious!", \ "[H] has been knocked unconscious!") - H.apply_effect(20, PARALYZE, armor) + H.apply_effect(20, PARALYZE, armor_block) if(prob(I.force + ((100 - H.health)/2)) && H != user && I.damtype == BRUTE) ticker.mode.remove_revolutionary(H.mind) @@ -1077,7 +1067,7 @@ if(H.stat == CONSCIOUS && I.force && prob(I.force + 10)) H.visible_message("[H] has been knocked down!", \ "[H] has been knocked down!") - H.apply_effect(5, WEAKEN, armor) + H.apply_effect(5, WEAKEN, armor_block) if(bloody) if(H.wear_suit) @@ -1091,34 +1081,9 @@ H.forcesay(hit_appends) //forcesay checks stat already. return -/datum/species/proc/attacked_by(obj/item/I, mob/living/user, def_zone, mob/living/carbon/human/H) - H.apply_damage(I.force, I.damtype) - if(I.damtype == "brute") - if(prob(33) && I.force && !(NOBLOOD in specflags)) - var/turf/location = H.loc - if(istype(location, /turf/simulated)) - location.add_blood_floor(H) - - var/message_verb = "" - if(I.attack_verb && I.attack_verb.len) - message_verb = "[pick(I.attack_verb)]" - else if(I.force) - message_verb = "attacked" - - var/attack_message = "[H] has been [message_verb] with [I]." - if(user) - user.do_attack_animation(src) - if(user in viewers(src, null)) - attack_message = "[user] has [message_verb] [H] with [I]!" - if(message_verb) - H.visible_message("[attack_message]", - "[attack_message]") - - return - /datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H) blocked = (100-(blocked+armor))/100 - if(blocked <= 0) return 0 + if(!damage || blocked <= 0) return 0 var/obj/item/organ/limb/organ = null if(islimb(def_zone)) @@ -1147,6 +1112,7 @@ H.adjustCloneLoss(damage * blocked) if(STAMINA) H.adjustStaminaLoss(damage * blocked) + return 1 /datum/species/proc/on_hit(obj/item/projectile/proj_type, mob/living/carbon/human/H) // called when hit by a projectile diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm index 2549b1635bf..cd5c473014b 100644 --- a/code/modules/mob/living/carbon/human/species_types.dm +++ b/code/modules/mob/living/carbon/human/species_types.dm @@ -38,8 +38,7 @@ /datum/species/human/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) if(chem.id == "mutationtoxin") H << "Your flesh rapidly mutates!" - hardset_dna(H, null, null, null, null, /datum/species/slime) - H.regenerate_icons() + H.set_species(/datum/species/slime) H.reagents.del_reagent(chem.type) H.faction |= "slime" return 1 @@ -128,10 +127,9 @@ datum/species/human/spec_death(gibbed, mob/living/carbon/human/H) H.visible_message("[H] writhes in pain as \his vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.") if(prob(80)) randmutb(H) - domutcheck(H,null) else randmutg(H) - domutcheck(H,null) + H.domutcheck() else H.adjustFireLoss(rand(5,15)) H.show_message("The radiation beam singes you!") diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 0ec31fdd1a3..1b3da71d25d 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -53,30 +53,10 @@ Please contact me on #coderbus IRC. ~Carnie x */ /mob/living/carbon/human/proc/update_base_icon_state() - if(dna) - base_icon_state = dna.species.update_base_icon_state(src) - else - if(disabilities & HUSK) - base_icon_state = "husk" - else - base_icon_state = "[skin_tone]_[(gender == FEMALE) ? "f" : "m"]" - + base_icon_state = dna.species.update_base_icon_state(src) icon_state = "[base_icon_state]_s" -//UPDATES OVERLAYS FROM OVERLAYS_STANDING -//TODO: Remove all instances where this proc is called. It used to be the fastest way to swap between standing/lying. -/mob/living/carbon/human/update_icons() - update_hud() //TODO: remove the need for this - - if(overlays.len != overlays_standing.len) - overlays.Cut() - - for(var/thing in overlays_standing) - if(thing) overlays += thing - - update_transform() - //DAMAGE OVERLAYS //constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists /mob/living/carbon/human/update_damage_overlays() @@ -105,25 +85,21 @@ Please contact me on #coderbus IRC. ~Carnie x if((wear_suit) && (wear_suit.hooded) && (wear_suit.suittoggled == 1)) return - if(dna) - dna.species.handle_hair(src) + dna.species.handle_hair(src) /mob/living/carbon/human/proc/update_mutcolor() - if(dna && !(disabilities & HUSK)) + if(!(disabilities & HUSK)) dna.species.update_color(src) +//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() - if(dna) - dna.species.handle_mutant_bodyparts(src) + dna.species.handle_mutant_bodyparts(src) /mob/living/carbon/human/proc/update_body() remove_overlay(BODY_LAYER) - update_base_icon_state() - - if(dna) - dna.species.handle_body(src) + dna.species.handle_body(src) /mob/living/carbon/human/update_fire() ..("Standing") @@ -181,6 +157,8 @@ Please contact me on #coderbus IRC. ~Carnie x update_hud() // Mutantrace colors update_mutcolor() + //mutations + update_mutations_overlay() /* --------------------------------------- */ //vvvvvv UPDATE_INV PROCS vvvvvv diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index fc9f30829cd..909d769ac74 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -38,8 +38,8 @@ if(prob(1)) src << "You mutate!" randmutb(src) - domutcheck(src,null) emote("gasp") + domutcheck() ..() /mob/living/carbon/monkey/handle_chemicals_in_body() diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index a1f11e9167f..64f73ca3980 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -16,16 +16,24 @@ verbs += /mob/living/proc/mob_sleep verbs += /mob/living/proc/lay_down + gender = pick(MALE, FEMALE) + real_name = name + if(good_mutations.len) //genetic mutations have been set up. + initialize() + internal_organs += new /obj/item/organ/internal/appendix internal_organs += new /obj/item/organ/internal/heart internal_organs += new /obj/item/organ/internal/brain for(var/obj/item/organ/internal/I in internal_organs) I.Insert(src) - gender = pick(MALE, FEMALE) ..() +/mob/living/carbon/monkey/initialize() + create_dna(src) + dna.initialize_dna(random_blood_type()) + /mob/living/carbon/monkey/prepare_data_huds() //Prepare our med HUD... ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 05fed0bff86..7d7b67a5d69 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -605,8 +605,8 @@ Sorry Giacom. Please don't be mad :( if((!(newdir in H.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && H.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) H.existing_dirs += newdir H.overlays.Add(image('icons/effects/blood.dmi',trail_type,dir = newdir)) - if(check_dna_integrity(M)) //blood DNA - var/mob/living/carbon/DNA_helper = pulling + if(M.has_dna()) //blood DNA + var/mob/living/carbon/DNA_helper = M H.blood_DNA[DNA_helper.dna.unique_enzymes] = DNA_helper.dna.blood_type /mob/living/proc/getTrail() //silicon and simple_animals don't get blood trails diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 67e827da796..ccabb8a7ece 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -375,7 +375,7 @@ M.visible_message("[M] presses \his thumb against [P].",\ "You press your thumb against [P].",\ "[P] makes a sharp clicking sound as it extracts DNA material from [M].") - if(!check_dna_integrity(M)) + if(!M.has_dna()) P << "No DNA detected" return P << "

[M]'s UE string : [M.dna.unique_enzymes]

" diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 5531fcd6a85..c0756da1c8b 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -251,9 +251,8 @@ if(istype(L, /mob/living/carbon/human)) //Ignore slime(wo)men var/mob/living/carbon/human/H = L - if(H.dna) - if(src.type in H.dna.species.ignored_by) - continue + if(src.type in H.dna.species.ignored_by) + continue if(!L.canmove) // Only one slime can latch on at a time. var/notarget = 0 diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm index 2608561867d..4d1e46f595a 100644 --- a/code/modules/mob/mob_transformation_simple.dm +++ b/code/modules/mob/mob_transformation_simple.dm @@ -40,15 +40,11 @@ M.name = src.name M.real_name = src.real_name - if(check_dna_integrity(src)) + if(has_dna() && M.has_dna()) var/mob/living/carbon/C = src var/mob/living/carbon/D = M - D.dna = C.dna - updateappearance(D) - else - if(istype(M, /mob/living/carbon/human)) - src.client.prefs.copy_to(M) - ready_dna(M) + C.dna.transfer_identity(D) + D.updateappearance(mutcolor_update=1, mutations_overlay_update=1) if(mind && istype(M, /mob/living)) mind.transfer_to(M) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index f8f6eea2413..a274a75ccde 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -362,21 +362,17 @@ var/mob/living/carbon/human/new_character = new(loc) new_character.lastarea = get_area(loc) - create_dna(new_character) - if(config.force_random_names || appearance_isbanned(src)) client.prefs.random_character() client.prefs.real_name = client.prefs.pref_species.random_name(gender,1) client.prefs.copy_to(new_character) - + new_character.dna.update_dna_identity() if(mind) mind.active = 0 //we wish to transfer the key manually mind.transfer_to(new_character) //won't transfer key since the mind is not active new_character.name = real_name - ready_dna(new_character, client.prefs.blood_type) - new_character.key = key //Manually transfer the key to log them in new_character.stopLobbySound() diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 4bbc1b2a8ee..9d5515a900a 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG), newname = null) +/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG)) if (notransform) return //Handle items on mob @@ -16,8 +16,11 @@ int_organs += I I.Remove(src, 1) + if(tr_flags & TR_KEEPITEMS) + for(var/obj/item/W in (src.contents-implants-int_organs)) + unEquip(W) + //Make mob invisible and spawn animation - regenerate_icons() notransform = 1 canmove = 0 stunned = 1 @@ -35,18 +38,18 @@ qdel(animation) // hash the original name? - if (tr_flags & TR_HASHNAME) + if(tr_flags & TR_HASHNAME) O.name = "monkey ([copytext(md5(real_name), 2, 6)])" O.real_name = "monkey ([copytext(md5(real_name), 2, 6)])" - if (newname) //if there's a name as an argument, always take that one over the current name - O.name = newname - O.real_name = newname //handle DNA and other attributes - if(dna) - dna.transfer_identity(O) - if(tr_flags & TR_KEEPSE) - O.dna.struc_enzymes = dna.struc_enzymes + dna.transfer_identity(O) + O.updateappearance(icon_update=0) + + if(tr_flags & TR_KEEPSE) + O.dna.struc_enzymes = dna.struc_enzymes + var/datum/mutation/human/race/R = mutations_list[RACEMUT] //we don't want to keep the race block inactive + O.dna.struc_enzymes = setblock(O.dna.struc_enzymes, R.dna_block, random_string(DNA_BLOCK_SIZE, list("8","9","a","b","c","d","e", "f"))) if(suiciding) O.suiciding = suiciding @@ -70,9 +73,10 @@ O.radiation = radiation //re-add implants to new mob - for(var/obj/item/weapon/implant/I in implants) - I.loc = O - I.implanted = O + if (tr_flags & TR_KEEPIMPLANTS) + for(var/obj/item/weapon/implant/I in implants) + I.loc = O + I.implanted = O //re-add organs to new mob if(tr_flags & TR_KEEPORGANS) @@ -96,16 +100,14 @@ if(loc.vars[A] == src) loc.vars[A] = O - updateappearance(O) . = O - if ( !(tr_flags & TR_KEEPSRC) ) //flag should be used if monkeyize() is called inside another proc of src so that one does not crash - qdel(src) + qdel(src) ////////////////////////// Humanize ////////////////////////////// //Could probably be merged with monkeyize but other transformations got their own procs, too -/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG), newname = null) +/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG)) if (notransform) return //Handle items on mob @@ -125,7 +127,7 @@ //now the rest if (tr_flags & TR_KEEPITEMS) - for(var/obj/item/W in (src.contents-implants)) + for(var/obj/item/W in (src.contents-implants-int_organs)) unEquip(W) if (client) client.screen -= W @@ -134,11 +136,7 @@ W.dropped(src) W.layer = initial(W.layer) - // for(var/obj/item/W in src) - // unEquip(W) - //Make mob invisible and spawn animation - regenerate_icons() notransform = 1 canmove = 0 stunned = 1 @@ -156,27 +154,21 @@ O.equip_to_appropriate_slot(C) qdel(animation) - O.gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE + dna.transfer_identity(O) + O.updateappearance(mutcolor_update=1) - if(dna) - dna.transfer_identity(O) - O.update_icons() - if(tr_flags & TR_KEEPSE) - O.dna.struc_enzymes = dna.struc_enzymes - domutcheck(O) - - if(!dna.species) - hardset_dna(O, null, null, null, null, /datum/species/human) + if(cmptext("monkey",copytext(O.dna.real_name,1,7))) + O.real_name = random_unique_name(O.gender) + O.dna.generate_unique_enzymes(O) else - hardset_dna(O, null, null, null, null, dna.species.type) - - if(newname) //if there's a name as an argument, always take that one over the current name - O.real_name = newname - else - if(cmptext("monkey",copytext(O.dna.real_name,1,7))) - O.dna.real_name = random_unique_name(O.gender) O.real_name = O.dna.real_name - O.name = O.real_name + O.name = O.real_name + + if(tr_flags & TR_KEEPSE) + O.dna.struc_enzymes = dna.struc_enzymes + var/datum/mutation/human/race/R = mutations_list[RACEMUT] //we don't want to keep the race block active + O.dna.struc_enzymes = setblock(O.dna.struc_enzymes, R.dna_block, random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6"))) + O.domutcheck() if(suiciding) O.suiciding = suiciding @@ -201,10 +193,11 @@ O.radiation = radiation //re-add implants to new mob - for(var/obj/item/weapon/implant/I in implants) - I.loc = O - I.implanted = O - O.sec_hud_set_implants() + if (tr_flags & TR_KEEPIMPLANTS) + for(var/obj/item/weapon/implant/I in implants) + I.loc = O + I.implanted = O + O.sec_hud_set_implants() if(tr_flags & TR_KEEPORGANS) for(var/obj/item/organ/internal/I in O.internal_organs) @@ -221,15 +214,13 @@ O.update_pipe_vision() - updateappearance(O) . = O for(var/A in loc.vars) if(loc.vars[A] == src) loc.vars[A] = O - if ( !(tr_flags & TR_KEEPSRC) ) //don't delete src yet if it's needed to finish calling proc - qdel(src) + qdel(src) /mob/new_player/AIize() diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm index 4146165206b..2e1e6528256 100644 --- a/code/modules/ninja/ninja_event.dm +++ b/code/modules/ninja/ninja_event.dm @@ -170,7 +170,7 @@ Contents: var/datum/preferences/A = new()//Randomize appearance for the ninja. A.real_name = "[pick(ninja_titles)] [pick(ninja_names)]" A.copy_to(new_ninja) - ready_dna(new_ninja) + new_ninja.dna.update_dna_identity() new_ninja.equip_space_ninja() return new_ninja diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 3f64abf3237..27c0e396e49 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -155,7 +155,7 @@ return 0 if(trigger_guard) - if(istype(user) && user.dna) + if(user.has_dna()) if(user.dna.check_mutation(HULK)) user << "Your meaty finger is much too large for the trigger guard!" return 0 diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 3fb86384fbb..3238db399ec 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -216,19 +216,21 @@ new_mob = new /mob/living/carbon/human(M.loc) var/datum/preferences/A = new() //Randomize appearance for the human - A.copy_to(new_mob) + A.copy_to(new_mob, icon_updates=0) var/mob/living/carbon/human/H = new_mob - ready_dna(H) - if(H.dna && prob(50)) + if(prob(50)) var/list/all_species = list() for(var/speciestype in typesof(/datum/species) - /datum/species) var/datum/species/S = new speciestype() if(!S.dangerous_existence) all_species += speciestype - hardset_dna(H, null, null, null, null, pick(all_species)) + H.set_species(pick(all_species), icon_update=0) H.real_name = H.dna.species.random_name(H.gender,1) - H.update_icons() + H.update_body() + H.update_hair() + H.update_mutcolor() + H.dna.update_dna_identity() else return diff --git a/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm index da54674aba5..df33fc5c594 100644 --- a/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents/Drug-Reagents.dm @@ -132,10 +132,10 @@ return /datum/reagent/drug/krokodil/addiction_act_stage4(mob/living/carbon/human/M) - if(M.dna && !istype(M.dna.species, /datum/species/cosmetic_zombie)) + if(M.has_dna() && M.dna.species.id != "zombie") M << "Your skin falls off easily!" M.adjustBruteLoss(50*REM) // holy shit your skin just FELL THE FUCK OFF - hardset_dna(M, null, null, null, null, /datum/species/cosmetic_zombie) + M.set_species(/datum/species/cosmetic_zombie) else M.adjustBruteLoss(5*REM) ..() diff --git a/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm index 5d738957633..43a4c5c8a39 100644 --- a/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm @@ -724,7 +724,7 @@ /datum/reagent/medicine/mutadone/on_mob_life(mob/living/carbon/human/M) M.jitteriness = 0 - if(istype(M) && M.dna) + if(M.has_dna()) M.dna.remove_all_mutations() ..() return diff --git a/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm index 3b7b5066c1e..4e0b0fbeb02 100644 --- a/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm @@ -356,8 +356,7 @@ var/datum/species/mutation = pick(possible_morphs) if(prob(90) && mutation && H.dna.species != /datum/species/golem && H.dna.species != /datum/species/golem/adamantine) H << "The pain subsides. You feel... different." - hardset_dna(H, null, null, null, null, mutation) - H.regenerate_icons() + H.set_species(mutation) if(mutation == /datum/species/slime) H.faction |= "slime" else diff --git a/code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm index 8b5fd49055a..aaaaf09c20e 100644 --- a/code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm @@ -31,7 +31,7 @@ /datum/reagent/toxin/mutagen/reaction_mob(mob/living/carbon/M, method=TOUCH, reac_volume) if(!..()) return - if(!istype(M) || !M.dna) + if(!M.has_dna()) return //No robots, AIs, aliens, Ians or other mobs should be affected by this. if((method==VAPOR && prob(min(33, reac_volume))) || method==INGEST || method == PATCH) randmuti(M) @@ -39,8 +39,8 @@ randmutb(M) else randmutg(M) - domutcheck(M, null) - updateappearance(M) + M.updateappearance() + M.domutcheck() ..() /datum/reagent/toxin/mutagen/on_mob_life(mob/living/carbon/M) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 1095e93cbd2..7fdd33e9955 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -66,20 +66,16 @@ if(ismob(target)) //Blood! if(ishuman(target)) var/mob/living/carbon/human/H = target - if(H.dna) - if(NOBLOOD in H.dna.species.specflags && !H.dna.species.exotic_blood) - user << "You are unable to locate any blood!" - return + if(NOBLOOD in H.dna.species.specflags && !H.dna.species.exotic_blood) + user << "You are unable to locate any blood!" + return if(reagents.has_reagent("blood")) user << "There is already a blood sample in this syringe!" return if(istype(target, /mob/living/carbon)) //maybe just add a blood reagent to all mobs. Then you can suck them dry...With hundreds of syringes. Jolly good idea. var/amount = src.reagents.maximum_volume - src.reagents.total_volume var/mob/living/carbon/T = target - if(!check_dna_integrity(T)) - user << "You are unable to locate any blood!" - return - if(T.disabilities & NOCLONE) //target done been eat, no more blood in him + if(!T.has_dna() || (T.disabilities & NOCLONE)) //target done been eat, no more blood in him user << "You are unable to locate any blood!" return if(target != user) @@ -95,7 +91,7 @@ if(!B && ishuman(target)) var/mob/living/carbon/human/H = target - if(H.dna && H.dna.species.exotic_blood && H.reagents.total_volume) + if(H.dna.species.exotic_blood && H.reagents.total_volume) target.reagents.trans_to(src, amount) else user << "You are unable to locate any blood!" diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 4792688be1f..fb55059cbcf 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -394,11 +394,10 @@ user << "The rune fizzles uselessly! There is no spirit nearby." return var/mob/living/carbon/human/G = new /mob/living/carbon/human - if(prob(50)) G.gender = "female" - hardset_dna(G, null, null, null, null, /datum/species/golem/adamantine) - + G.set_species(/datum/species/golem/adamantine) G.set_cloned_appearance() - G.real_name = text("Adamantine Golem ([rand(1, 1000)])") + G.real_name = "Adamantine Golem ([rand(1, 1000)])" + G.dna.unique_enzymes = G.dna.generate_unique_enzymes() G.dna.species.auto_equip(G) G.loc = src.loc G.key = ghost.key diff --git a/icons/effects/genetics.dmi b/icons/effects/genetics.dmi index ba81afe9d11038cb640634e03f600673ee5ec194..768be9b92310649dd312e82243bf40fd01d4e22f 100644 GIT binary patch delta 7073 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 delta 7075 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 E04S=kCIA2c diff --git a/tgstation.dme b/tgstation.dme index 23408636bb2..ce89e7b0486 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -399,6 +399,7 @@ #include "code\game\machinery\cloning.dm" #include "code\game\machinery\constructable_frame.dm" #include "code\game\machinery\deployable.dm" +#include "code\game\machinery\dna_scanner.dm" #include "code\game\machinery\doppler_array.dm" #include "code\game\machinery\droneDispenser.dm" #include "code\game\machinery\flasher.dm" @@ -463,6 +464,7 @@ #include "code\game\machinery\computer\communications.dm" #include "code\game\machinery\computer\computer.dm" #include "code\game\machinery\computer\crew.dm" +#include "code\game\machinery\computer\dna_console.dm" #include "code\game\machinery\computer\HolodeckControl.dm" #include "code\game\machinery\computer\law.dm" #include "code\game\machinery\computer\medical.dm"