diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm
index 687cebfb786..7c4135a2f91 100644
--- a/code/__DEFINES/genetics.dm
+++ b/code/__DEFINES/genetics.dm
@@ -26,6 +26,9 @@
#define CHAV "Chav"
#define ELVIS "Elvis"
+#define UI_CHANGED "ui changed"
+#define UE_CHANGED "ue changed"
+
#define CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY 204
// String identifiers for associative list lookup
diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm
index 1572fd4cf97..c7e53d39b64 100644
--- a/code/datums/mutations.dm
+++ b/code/datums/mutations.dm
@@ -19,6 +19,7 @@
var/layer_used = MUTATIONS_LAYER //which mutation layer to use
var/list/species_allowed = list() //to restrict mutation to only certain species
var/health_req //minimum health required to acquire the mutation
+ var/time_coeff = 1 //coefficient for timed mutations
/datum/mutation/human/proc/force_give(mob/living/carbon/human/owner)
set_block(owner)
@@ -177,6 +178,7 @@
get_chance = 25
lowest_value = 256 * 12
text_gain_indication = "Your body feels warm!"
+ time_coeff = 5
/datum/mutation/human/cold_resistance/New()
..()
@@ -197,6 +199,7 @@
get_chance = 25
lowest_value = 256 * 12
text_gain_indication = "The walls suddenly disappear!"
+ time_coeff = 2
/datum/mutation/human/x_ray/on_acquiring(mob/living/carbon/human/owner)
if(..())
@@ -378,6 +381,7 @@
name = "Monkified"
quality = NEGATIVE
+ time_coeff = 2
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
if(..())
@@ -396,6 +400,7 @@
lowest_value = 256 * 12
text_gain_indication = "You begin to fade into the shadows."
text_lose_indication = "You become fully visible."
+ time_coeff = 5
/datum/mutation/human/stealth/on_life(mob/living/carbon/human/owner)
@@ -420,6 +425,7 @@
lowest_value = 256 * 12
text_gain_indication = "You feel one with your surroundings."
text_lose_indication = "You feel oddly exposed."
+ time_coeff = 5
/datum/mutation/human/chameleon/on_acquiring(mob/living/carbon/human/owner)
if(..())
diff --git a/code/game/dna.dm b/code/game/dna.dm
index 098f89c9dd2..b15fc10715a 100644
--- a/code/game/dna.dm
+++ b/code/game/dna.dm
@@ -9,6 +9,8 @@
var/list/features = list("FFF") //first value is mutant color
var/real_name //Stores the real name of the person who originally got this dna datum. Used primarely for changelings,
var/list/mutations = list() //All mutations are from now on here
+ var/list/temporary_mutations = list() //Timers for temporary mutations
+ var/list/previous = list() //For temporary name/ui/ue/blood_type modifications
var/mob/living/carbon/holder
/datum/dna/New(mob/living/carbon/new_holder)
@@ -22,6 +24,7 @@
destination.set_species(species.type, icon_update=0)
destination.dna.features = features
destination.dna.real_name = real_name
+ destination.dna.temporary_mutations = temporary_mutations
if(transfer_SE)
destination.dna.struc_enzymes = struc_enzymes
diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm
index dd5332623e0..e3ead355f11 100644
--- a/code/game/machinery/computer/dna_console.dm
+++ b/code/game/machinery/computer/dna_console.dm
@@ -1,4 +1,4 @@
-#define INJECTOR_TIMEOUT 300
+#define INJECTOR_TIMEOUT 100
#define REJUVENATORS_INJECT 15
#define REJUVENATORS_MAX 90
#define NUMBER_OF_BUFFERS 3
@@ -11,6 +11,11 @@
#define RADIATION_IRRADIATION_MULTIPLIER 0.2 //multiplier for how much radiation a test subject recieves
+#define SCANNER_ACTION_SE 1
+#define SCANNER_ACTION_UI 2
+#define SCANNER_ACTION_UE 3
+#define SCANNER_ACTION_MIXED 4
+
/obj/machinery/computer/scan_consolenew
name = "\improper DNA scanner access console"
desc = "Scan DNA."
@@ -27,6 +32,7 @@
var/current_screen = "mainmenu"
var/obj/machinery/dna_scannernew/connected = null
var/obj/item/weapon/disk/data/diskette = null
+ var/list/delayed_action = null
anchored = 1
use_power = 1
idle_power_usage = 10
@@ -185,6 +191,7 @@
temp_html += "
\tUE: [ue] "
if(viable_occupant) temp_html += "Occupant "
else temp_html += "Occupant"
+ temp_html += "Occupant:Delayed "
if(injectorready) temp_html += "Injector"
else temp_html += "Injector"
else
@@ -194,14 +201,23 @@
temp_html += "
\tUI: [ui] "
if(viable_occupant) temp_html += "Occupant "
else temp_html += "Occupant"
+ temp_html += "Occupant:Delayed "
if(injectorready) temp_html += "Injector"
else temp_html += "Injector"
else
temp_html += "
\tUI: No Data"
+ if(ue && name && blood_type && ui)
+ temp_html += "
\tUI+UE: [ui]/[ue] "
+ if(viable_occupant) temp_html += "Occupant "
+ else temp_html += "Occupant"
+ temp_html += "Occupant:Delayed "
+ if(injectorready) temp_html += "UI+UE Injector"
+ else temp_html += "UI+UE Injector"
if(se)
temp_html += "
\tSE: [se] "
if(viable_occupant) temp_html += "Occupant "
else temp_html += "Occupant "
+ temp_html += "Occupant:Delayed "
if(injectorready) temp_html += "Injector"
else temp_html += "Injector"
else
@@ -269,11 +285,7 @@
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
+ var/mob/living/carbon/viable_occupant = get_viable_occupant()
//Basic Tasks///////////////////////////////////////////
var/num = round(text2num(href_list["num"]))
@@ -326,55 +338,57 @@
buffer_slot.Cut()
if("transferbuffer")
if(num && viable_occupant)
- 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"]
+ 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")
+ apply_buffer(SCANNER_ACTION_SE,num)
+ if("ui")
+ apply_buffer(SCANNER_ACTION_UI,num)
+ if("ue")
+ apply_buffer(SCANNER_ACTION_UE,num)
+ if("mixed")
+ apply_buffer(SCANNER_ACTION_MIXED,num)
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
+ var/obj/item/weapon/dnainjector/timed/I
switch(href_list["text"])
if("se")
if(buffer_slot["SE"])
- I = new /obj/item/weapon/dnainjector(loc)
+ I = new /obj/item/weapon/dnainjector/timed(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)
+ I.add_mutations.Add(HM)
else
I.remove_mutations.Add(HM)
+ var/time_coeff
+ for(var/datum/mutation/human/HM in I.add_mutations)
+ if(!time_coeff)
+ time_coeff = HM.time_coeff
+ continue
+ time_coeff = min(time_coeff,HM.time_coeff)
if(connected)
+ I.duration = I.duration * time_coeff * connected.damage_coeff
I.damage_coeff = connected.damage_coeff
if("ui")
if(buffer_slot["UI"])
- I = new /obj/item/weapon/dnainjector(loc)
+ I = new /obj/item/weapon/dnainjector/timed(loc)
I.fields = list("UI"=buffer_slot["UI"])
if(connected)
I.damage_coeff = connected.damage_coeff
- else
+ if("ue")
if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"])
- I = new /obj/item/weapon/dnainjector(loc)
+ I = new /obj/item/weapon/dnainjector/timed(loc)
I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"])
if(connected)
I.damage_coeff = connected.damage_coeff
+ if("mixed")
+ if(buffer_slot["UI"] && buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"])
+ I = new /obj/item/weapon/dnainjector/timed(loc)
+ I.fields = list("UI"=buffer_slot["UI"],"name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"])
+ if(connected)
+ I.damage_coeff = connected.damage_coeff
if(I)
injectorready = 0
spawn(INJECTOR_TIMEOUT)
@@ -394,6 +408,9 @@
if(diskette)
diskette.loc = get_turf(src)
diskette = null
+ if("setdelayed")
+ if(num)
+ delayed_action = list("action"=text2num(href_list["delayaction"]),"buffer"=num)
if("pulseui","pulsese")
if(num && viable_occupant && connected)
radduration = Wrap(radduration, 1, RADIATION_DURATION_MAX+1)
@@ -462,7 +479,54 @@
/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)
+/obj/machinery/computer/scan_consolenew/proc/get_viable_occupant()
+ var/mob/living/carbon/viable_occupant = null
+ if(connected)
+ viable_occupant = connected.occupant
+ if(!istype(viable_occupant) || !viable_occupant.dna || (viable_occupant.disabilities & NOCLONE))
+ viable_occupant = null
+ return viable_occupant
+/obj/machinery/computer/scan_consolenew/proc/apply_buffer(action,buffer_num)
+ buffer_num = Clamp(buffer_num, 1, NUMBER_OF_BUFFERS)
+ var/list/buffer_slot = buffer[buffer_num]
+ var/mob/living/carbon/viable_occupant = get_viable_occupant()
+ if(istype(buffer_slot))
+ viable_occupant.radiation += rand(10/(connected.damage_coeff ** 2),25/(connected.damage_coeff ** 2))
+ //15 and 40 are just magic numbers that were here before so i didnt touch them, they are initial boundaries of damage
+ //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
+ //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
+ switch(action)
+ if(SCANNER_ACTION_SE)
+ if(buffer_slot["SE"])
+ viable_occupant.dna.struc_enzymes = buffer_slot["SE"]
+ viable_occupant.domutcheck()
+ if(SCANNER_ACTION_UI)
+ if(buffer_slot["UI"])
+ viable_occupant.dna.uni_identity = buffer_slot["UI"]
+ viable_occupant.updateappearance(mutations_overlay_update=1)
+ if(SCANNER_ACTION_UE)
+ 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(SCANNER_ACTION_MIXED)
+ if(buffer_slot["UI"])
+ viable_occupant.dna.uni_identity = buffer_slot["UI"]
+ viable_occupant.updateappearance(mutations_overlay_update=1)
+ 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"]
+
+/obj/machinery/computer/scan_consolenew/proc/on_scanner_close()
+ connected.occupant << "[src] activates!"
+ if(delayed_action)
+ apply_buffer(delayed_action["action"],delayed_action["buffer"])
+ delayed_action = null //or make it stick + reset button ?
+ return
/////////////////////////// DNA MACHINES
#undef INJECTOR_TIMEOUT
@@ -478,6 +542,11 @@
#undef RADIATION_IRRADIATION_MULTIPLIER
+#undef SCANNER_ACTION_SE
+#undef SCANNER_ACTION_UI
+#undef SCANNER_ACTION_UE
+#undef SCANNER_ACTION_MIXED
+
//#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
index 8f5e8f6c8b1..e6e730428f6 100644
--- a/code/game/machinery/dna_scanner.dm
+++ b/code/game/machinery/dna_scanner.dm
@@ -110,6 +110,13 @@
|| 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!", source = src)
+
+ var/obj/machinery/computer/scan_consolenew/console
+ for(dir in list(NORTH,EAST,SOUTH,WEST))
+ console = locate(/obj/machinery/computer/scan_consolenew, get_step(src, dir))
+ if(console)
+ console.on_scanner_close()
+ break
return 1
/obj/machinery/dna_scannernew/open_machine()
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 094faaffb86..43f30818de7 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -11,6 +11,7 @@
var/list/fields
var/list/add_mutations = list()
var/list/remove_mutations = list()
+ var/used = 0
/obj/item/weapon/dnainjector/attack_paw(mob/user)
return attack_hand(user)
@@ -45,6 +46,9 @@
if(!user.IsAdvancedToolUser())
user << "You don't have the dexterity to do this!"
return
+ if(used)
+ user << "This injector is used up!"
+ return
if(ishuman(target))
var/mob/living/carbon/human/humantarget = target
if (!humantarget.can_inject(user, 1))
@@ -63,7 +67,9 @@
add_logs(user, target, "injected", src)
inject(target, user) //Now we actually do the heavy lifting.
- qdel(src)
+ used = 1
+ icon_state = "dnainjector0"
+ desc += " This one is used up."
/obj/item/weapon/dnainjector/antihulk
@@ -385,4 +391,70 @@
name = "\improper DNA injector (Anti-Laser Eyes)"
New()
..()
- remove_mutations.Add(mutations_list[LASEREYES])
\ No newline at end of file
+ remove_mutations.Add(mutations_list[LASEREYES])
+
+/obj/item/weapon/dnainjector/timed
+ var/duration = 600
+
+/obj/item/weapon/dnainjector/timed/inject(mob/living/carbon/M, mob/user)
+ 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
+ M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
+ var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
+ var/endtime = world.time+duration
+ for(var/datum/mutation/human/HM in remove_mutations)
+ if(HM.name == RACEMUT)
+ if(ishuman(M))
+ continue
+ M = HM.force_lose(M)
+ else
+ HM.force_lose(M)
+ for(var/datum/mutation/human/HM in add_mutations)
+ if((HM in M.dna.mutations) && !(M.dna.temporary_mutations[HM.name]))
+ continue //Skip permanent mutations we already have.
+ if(HM.name == RACEMUT && ishuman(M))
+ message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] (MONKEY)")
+ log_msg += " (MONKEY)"
+ M = HM.force_give(M)
+ else
+ HM.force_give(M)
+ M.dna.temporary_mutations[HM.name] = endtime
+ if(fields)
+ if(fields["name"] && fields["UE"] && fields["blood_type"])
+ if(!M.dna.previous["name"])
+ M.dna.previous["name"] = M.real_name
+ if(!M.dna.previous["UE"])
+ M.dna.previous["UE"] = M.dna.unique_enzymes
+ if(!M.dna.previous["blood_type"])
+ M.dna.previous["blood_type"] = M.dna.blood_type
+ M.real_name = fields["name"]
+ M.dna.unique_enzymes = fields["UE"]
+ M.name = M.real_name
+ M.dna.blood_type = fields["blood_type"]
+ M.dna.temporary_mutations[UE_CHANGED] = endtime
+ if(fields["UI"]) //UI+UE
+ if(!M.dna.previous["UI"])
+ M.dna.previous["UI"] = M.dna.uni_identity
+ M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"])
+ M.updateappearance(mutations_overlay_update=1)
+ M.dna.temporary_mutations[UI_CHANGED] = endtime
+ log_attack(log_msg)
+ else
+ user << "It appears that [M] does not have compatible DNA."
+ return
+
+/obj/item/weapon/dnainjector/timed/hulk
+ name = "\improper DNA injector (Hulk)"
+ desc = "This will make you big and strong, but give you a bad skin condition."
+ New()
+ ..()
+ add_mutations.Add(mutations_list[HULK])
+
+/obj/item/weapon/dnainjector/timed/h2m
+ name = "\improper DNA injector (Human > Monkey)"
+ desc = "Will make you a flea bag."
+ New()
+ ..()
+ add_mutations.Add(mutations_list[RACEMUT])
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 15ef338af86..27ea1b59382 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -207,6 +207,34 @@
/mob/living/carbon/handle_mutations_and_radiation()
+ if(dna && dna.temporary_mutations.len)
+ var/datum/mutation/human/HM
+ for(var/mut in dna.temporary_mutations)
+ if(dna.temporary_mutations[mut] < world.time)
+ if(mut == UI_CHANGED)
+ if(dna.previous["UI"])
+ dna.uni_identity = merge_text(dna.uni_identity,dna.previous["UI"])
+ updateappearance(mutations_overlay_update=1)
+ dna.previous.Remove("UI")
+ dna.temporary_mutations.Remove(mut)
+ continue
+ if(mut == UE_CHANGED)
+ if(dna.previous["name"])
+ real_name = dna.previous["name"]
+ name = real_name
+ dna.previous.Remove("name")
+ if(dna.previous["UE"])
+ dna.unique_enzymes = dna.previous["UE"]
+ dna.previous.Remove("UE")
+ if(dna.previous["blood_type"])
+ dna.blood_type = dna.previous["blood_type"]
+ dna.previous.Remove("blood_type")
+ dna.temporary_mutations.Remove(mut)
+ continue
+ HM = mutations_list[mut]
+ HM.force_lose(src)
+ dna.temporary_mutations.Remove(mut)
+
if(radiation)
switch(radiation)
diff --git a/html/changelogs/injectors.yml b/html/changelogs/injectors.yml
new file mode 100644
index 00000000000..14e562d30ee
--- /dev/null
+++ b/html/changelogs/injectors.yml
@@ -0,0 +1,9 @@
+author: AnturK
+
+delete-after: True
+
+changes:
+ - tweak: "DNA Injectors now grant temporary powers on every use. Duration dependent on activated powers and machine upgrades"
+ - rscadd: "Delayed Transfer added to DNA Scanner - It will activate on the next closing of scanner door "
+ - rscadd: "UI+UE injectors/buffer transfers added for convinience "
+ - tweak: "Injector creation timeout cut in half"