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 += "
"
- 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((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 += "
"
+ 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((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 += "| Name | DNA | Blood Type |
"
for(var/mob/living/carbon/human/H in mob_list)
- if(H.dna && H.ckey)
+ if(H.ckey)
dat += "| [H] | [H.dna.unique_enzymes] | [H.dna.blood_type] |
"
dat += "
"
usr << browse(dat, "window=DNA;size=440x410")
@@ -231,12 +231,7 @@
dat += "| Name | Fingerprints |
"
for(var/mob/living/carbon/human/H in mob_list)
if(H.ckey)
- if(H.dna && H.dna.uni_identity)
- dat += "| [H] | [md5(H.dna.uni_identity)] |
"
- else if(H.dna && !H.dna.uni_identity)
- dat += "| [H] | H.dna.uni_identity = null |
"
- else if(!H.dna)
- dat += "| [H] | H.dna = null |
"
+ dat += "| [H] | [md5(H.dna.uni_identity)] |
"
dat += "
"
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