Bioengineering Part 1

This commit is contained in:
c0
2016-03-13 13:20:26 +03:00
parent 9d6752ad78
commit e4f2d0c064
10 changed files with 454 additions and 17 deletions
+387
View File
@@ -0,0 +1,387 @@
/obj/machinery/plantgenes
name = "plant DNA manipulator"
desc = "An advanced device designed to manipulate plant genetic makeup."
icon = 'icons/obj/hydroponics/equipment.dmi'
icon_state = "dnamod"
density = 1
anchored = 1
var/obj/item/seeds/seed
var/obj/item/weapon/disk/plantgene/disk
var/list/core_genes = list()
var/list/reagent_genes = list()
var/list/trait_genes = list()
var/datum/plant_gene/target
var/operation = ""
var/rating = 0 // TODO: add failures, make it useful
/obj/machinery/plantgenes/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/plantgenes(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
RefreshParts()
/obj/machinery/plantgenes/RefreshParts()
rating = 0
for(var/obj/item/weapon/stock_parts/S in component_parts)
rating += S.rating-1
/obj/machinery/plantgenes/update_icon()
..()
overlays.Cut()
if((stat & (BROKEN|NOPOWER)))
icon_state = "dnamod-off"
else
icon_state = "dnamod"
if(seed)
overlays += "dnamod-dna"
if(panel_open)
overlays += "dnamod-open"
/obj/machinery/plantgenes/attackby(obj/item/I, mob/user, params)
if(default_deconstruction_screwdriver(user, "dnamod", "dnamod", I))
update_icon()
return
if(exchange_parts(user, I))
return
if(default_deconstruction_crowbar(I))
return
if(isrobot(user))
return
if(istype(I, /obj/item/seeds))
if(seed)
user << "<span class='warning'>A sample is already loaded into the machine!</span>"
else
if(!user.drop_item())
return
insert_seed(I)
user << "<span class='notice'>You add [I] to the machine.</span>"
interact(user)
return
else if(istype(I, /obj/item/weapon/disk/plantgene))
if(disk)
user << "<span class='warning'>A data disk is already loaded into the machine!</span>"
else
if(!user.drop_item())
return
disk = I
disk.loc = src
user << "<span class='notice'>You add [I] to the machine.</span>"
interact(user)
else
..()
/obj/machinery/plantgenes/attack_hand(mob/user)
if(..())
return
interact(user)
/obj/machinery/plantgenes/interact(mob/user)
user.set_machine(src)
if(!user)
return
var/datum/browser/popup = new(user, "plantdna", "Plant DNA Manipulator", 450, 600) // Set up the popup browser window
if(!( in_range(src, user) || istype(user, /mob/living/silicon) ))
popup.close()
return
var/dat = ""
if(operation)
if(!seed || (!target && operation != "insert"))
operation = ""
target = null
interact(user)
return
if((operation == "replace" || operation == "insert") && (!disk || !disk.gene))
operation = ""
target = null
interact(user)
return
dat += "<div class='line'><h3>Confirm Operation</h3></div>"
dat += "<div class='statusDisplay'>Are you sure you want to [operation] "
switch(operation)
if("remove")
dat += "<span class='highlight'>[target.get_name()]</span> gene from \the <span class='highlight'>[seed]</span>?<br>"
// dat += "<span class='bad'>Failure may damage or destroy the sample!</span>" // No failures yet. TODO: add failures
if("extract")
dat += "<span class='highlight'>[target.get_name()]</span> gene from \the <span class='highlight'>[seed]</span>?<br>"
dat += "<span class='bad'>The sample will be destroyed in process!</span>"
if("replace")
dat += "<span class='highlight'>[target.get_name()]</span> gene with <span class='highlight'>[disk.gene.get_name()]</span>?<br>"
// dat += "<span class='bad'>Failure may damage or destroy the sample!</span>" // No failures yet. TODO: add failures
if("insert")
dat += "<span class='highlight'>[disk.gene.get_name()]</span> gene into \the <span class='highlight'>[seed]</span>?<br>"
// dat += "<span class='bad'>Failure may damage or destroy the sample!</span>" // No failures yet. TODO: add failures
dat += "</div><div class='line'><a href='?src=\ref[src];gene=\ref[target];op=[operation]'>Confirm</a> "
dat += "<a href='?src=\ref[src];abort=1'>Abort</a></div>"
popup.set_content(dat)
popup.open()
return
dat+= "<div class='statusDisplay'>"
dat += "<div class='line'><div class='statusLabel'>Plant Sample:</div><div class='statusValue'><a href='?src=\ref[src];eject_seed=1'>"
dat += seed ? seed.name : "None"
dat += "</a></div></div>"
dat += "<div class='line'><div class='statusLabel'>Data Disk:</div><div class='statusValue'><a href='?src=\ref[src];eject_disk=1'>"
if(!disk)
dat += "None"
else if(!disk.gene)
dat += "Empty Disk"
else
dat += disk.gene.get_name()
if(disk && disk.read_only)
dat += " (RO)"
dat += "</a></div></div>"
dat += "<br></div>"
if(seed)
var/can_insert = disk && disk.gene && disk.gene.can_add(seed)
var/can_extract = disk && !disk.read_only
dat += "<div class='line'><h3>Core Genes</h3></div><div class='statusDisplay'><table>"
for(var/a in core_genes)
var/datum/plant_gene/G = a
if(!G)
continue
dat += "<tr><td width='260px'>[G.get_name()]</td><td>"
if(can_extract)
dat += "<a href='?src=\ref[src];gene=\ref[G];op=extract'>Extract</a>"
if(can_insert && istype(disk.gene, G.type))
dat += "<a href='?src=\ref[src];gene=\ref[G];op=replace'>Replace</a>"
dat += "</td></tr>"
dat += "</table></div>"
if(seed.yield != -1)
dat += "<div class='line'><h3>Content Genes</h3></div><div class='statusDisplay'>"
if(reagent_genes.len)
dat += "<table>"
for(var/a in reagent_genes)
var/datum/plant_gene/G = a
dat += "<tr><td width='260px'>[G.get_name()]</td><td>"
if(can_extract)
dat += "<a href='?src=\ref[src];gene=\ref[G];op=extract'>Extract</a>"
dat += "<a href='?src=\ref[src];gene=\ref[G];op=remove'>Remove</a>"
dat += "</td></tr>"
dat += "</table>"
else
dat += "No content-related genes detected in sample.<br>"
dat += "</div>"
if(can_insert && istype(disk.gene, /datum/plant_gene/reagent))
dat += "<a href='?src=\ref[src];op=insert'>Insert: [disk.gene.get_name()]</a>"
dat += "<div class='line'><h3>Trait Genes</h3></div><div class='statusDisplay'>"
if(trait_genes.len)
dat += "<table>"
for(var/a in trait_genes)
var/datum/plant_gene/G = a
dat += "<tr><td width='260px'>[G.get_name()]</td><td>"
if(can_extract)
dat += "<a href='?src=\ref[src];gene=\ref[G];op=extract'>Extract</a>"
dat += "<a href='?src=\ref[src];gene=\ref[G];op=remove'>Remove</a>"
dat += "</td></tr>"
dat += "</table>"
else
dat += "No trait-related genes detected in sample.<br>"
if(can_insert && istype(disk.gene, /datum/plant_gene/trait))
dat += "<a href='?src=\ref[src];op=insert'>Insert: [disk.gene.get_name()]</a>"
dat += "</div>"
else
dat += "<br>No sample found.<br><br>Please, insert a plant sample to use this device."
popup.set_content(dat)
popup.open()
/obj/machinery/plantgenes/Topic(var/href, var/list/href_list)
if(..())
return
usr.set_machine(src)
if(href_list["eject_seed"] && !operation)
if (seed)
seed.loc = src.loc
seed.verb_pickup()
seed = null
update_genes()
update_icon()
else
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/seeds))
if(!usr.drop_item())
return
insert_seed(I)
usr << "<span class='notice'>You add [I] to the machine.</span>"
update_icon()
else if(href_list["eject_disk"] && !operation)
if (disk)
disk.loc = src.loc
disk.verb_pickup()
disk = null
update_genes()
else
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/weapon/disk/plantgene))
if(!usr.drop_item())
return
disk = I
disk.loc = src
usr << "<span class='notice'>You add [I] to the machine.</span>"
else if(href_list["op"] == "insert" && disk && disk.gene && seed)
if(!operation) // Wait for confirmation
operation = "insert"
else
if(!istype(disk.gene, /datum/plant_gene/core) && disk.gene.can_add(seed))
seed.genes += disk.gene.Copy()
if(istype(disk.gene, /datum/plant_gene/reagent))
seed.reagents_from_genes()
update_genes()
operation = ""
target = null
else if(href_list["gene"] && seed)
var/datum/plant_gene/G = seed.get_gene(href_list["gene"])
if(!G || !href_list["op"] || !(href_list["op"] in list("remove", "extract", "replace")))
interact(usr)
return
if(!operation || target != G) // Wait for confirmation
target = G
operation = href_list["op"]
else if(operation == href_list["op"] && target == G)
switch(href_list["op"])
if("remove")
if(!istype(G, /datum/plant_gene/core))
seed.genes -= G
if(istype(G, /datum/plant_gene/reagent))
seed.reagents_from_genes()
if("extract")
if(disk && !disk.read_only)
disk.gene = G
disk.update_name()
qdel(seed)
seed = null
update_icon()
if("replace")
if(disk && disk.gene && istype(disk.gene, G.type) && istype(G, /datum/plant_gene/core))
seed.genes -= G
var/datum/plant_gene/core/C = disk.gene.Copy()
seed.genes += C
C.apply_stat(seed)
if("insert")
if(disk && disk.gene && !istype(disk.gene, /datum/plant_gene/core) && disk.gene.can_add(seed))
seed.genes += disk.gene.Copy()
if(istype(disk.gene, /datum/plant_gene/reagent))
seed.reagents_from_genes()
update_genes()
operation = ""
target = null
else if(href_list["abort"])
operation = ""
target = null
interact(usr)
/obj/machinery/plantgenes/proc/insert_seed(obj/item/seeds/S)
if(!istype(S) || seed)
return
S.loc = src
seed = S
update_genes()
update_icon()
/obj/machinery/plantgenes/proc/update_genes()
core_genes = list()
reagent_genes = list()
trait_genes = list()
if(seed)
var/gene_paths = list(
/datum/plant_gene/core/potency,
/datum/plant_gene/core/yield,
/datum/plant_gene/core/production,
/datum/plant_gene/core/endurance,
/datum/plant_gene/core/lifespan
)
for(var/a in gene_paths)
core_genes += seed.get_gene(a)
for(var/datum/plant_gene/reagent/G in seed.genes)
reagent_genes += G
for(var/datum/plant_gene/trait/G in seed.genes)
trait_genes += G
/*
* Plant DNA disk
*/
/obj/item/weapon/disk/plantgene
name = "plant data disk"
desc = "A disk for storing plant genetic data."
icon_state = "datadisk2"
materials = list(MAT_METAL=30, MAT_GLASS=10)
var/datum/plant_gene/gene
var/read_only = 0 //Well, it's still a floppy disk
/obj/item/weapon/disk/plantgene/New()
..()
overlays += "datadisk_gene"
src.pixel_x = rand(-5, 5)
src.pixel_y = rand(-5, 5)
/obj/item/weapon/disk/plantgene/attackby(obj/item/weapon/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/pen))
var/t = stripped_input(user, "What would you like the label to be?", name, null)
if(user.get_active_hand() != W)
return
if(!in_range(src, user) && loc != user)
return
if(t)
name = "plant data disk - '[t]'"
else
name = "plant data disk"
/obj/item/weapon/disk/plantgene/proc/update_name()
if(gene)
name = "plant data disk - '[gene.get_name()]'"
else
name = "plant data disk"
/obj/item/weapon/disk/plantgene/attack_self(mob/user)
read_only = !read_only
user << "<span class='notice'>You flip the write-protect tab to [src.read_only ? "protected" : "unprotected"].</span>"
/obj/item/weapon/disk/plantgene/examine(mob/user)
..()
user << "The write-protect tab is set to [src.read_only ? "protected" : "unprotected"]."
/*
* Plant DNA Disks Box
*/
/obj/item/weapon/storage/box/disks_plantgene
name = "plant data disks box"
icon_state = "disk_kit"
/obj/item/weapon/storage/box/disks_plantgene/New()
..()
for(var/i in 1 to 7)
new /obj/item/weapon/disk/plantgene(src)
+4 -4
View File
@@ -23,7 +23,7 @@
else if(ispath(seed))
// This is for adminspawn or map-placed growns. They get the default stats of their seed type.
seed = new seed()
seed.potency = 50
seed.adjust_potency(50-seed.potency)
else // Something is terribly wrong
qdel(src)
return
@@ -77,7 +77,7 @@
if(reag_txt)
msg += reag_txt
msg += "<span class='info'>*---------*</span>"
msg += "<br><span class='info'>*---------*</span>"
user << msg
return
return
@@ -128,8 +128,8 @@
var/datum/plant_gene/trait/slip/S = seed.get_gene(/datum/plant_gene/trait/slip)
if(S && !ispath(trash, /obj/item/weapon/grown) && iscarbon(AM))
var/mob/living/carbon/M = AM
var/stun = min(seed.potency * S.rate * 2, 1)
var/weaken = min(seed.potency * S.rate, 0.5)
var/stun = max(seed.potency * S.rate * 2, 1)
var/weaken = max(seed.potency * S.rate, 0.5)
if(M.slip(stun, weaken, src))
for(var/datum/plant_gene/trait/T in seed.genes)
T.on_slip(src, M)
+1 -1
View File
@@ -30,7 +30,7 @@
// Orange
/obj/item/seeds/orange
name = "pack of orange seed"
name = "pack of orange seeds"
desc = "Sour seeds."
icon_state = "seed-orange"
species = "orange"
+3 -3
View File
@@ -17,7 +17,7 @@
else if(ispath(seed))
// This is for adminspawn or map-placed growns. They get the default stats of their seed type.
seed = new seed()
seed.potency = 50
seed.adjust_potency(50-seed.potency)
else // Something is terribly wrong
qdel(src)
return
@@ -53,8 +53,8 @@
var/datum/plant_gene/trait/slip/S = seed.get_gene(/datum/plant_gene/trait/slip)
if(S && iscarbon(AM))
var/mob/living/carbon/M = AM
var/stun = min(seed.potency * S.rate * 2, 1)
var/weaken = min(seed.potency * S.rate, 0.5)
var/stun = max(seed.potency * S.rate * 2, 1)
var/weaken = max(seed.potency * S.rate, 0.5)
if(M.slip(stun, weaken, src))
for(var/datum/plant_gene/trait/T in seed.genes)
T.on_slip(src, M)
+42
View File
@@ -4,11 +4,15 @@
/datum/plant_gene/proc/get_name() // Used for manipulator display and gene disk name.
return name
/datum/plant_gene/proc/can_add(obj/item/seeds/S)
return TRUE
/datum/plant_gene/proc/Copy()
return new type
// Core plant genes store 5 main variables: lifespan, endurance, production, yield, potency
/datum/plant_gene/core
var/value
@@ -16,6 +20,9 @@
/datum/plant_gene/core/get_name()
return "[name] [value]"
/datum/plant_gene/core/proc/apply_stat(obj/item/seeds/S)
return
/datum/plant_gene/core/New(var/i = null)
..()
if(!isnull(i))
@@ -26,27 +33,47 @@
C.value = value
return C
/datum/plant_gene/core/can_add(obj/item/seeds/S)
return S.get_gene(src.type)
/datum/plant_gene/core/lifespan
name = "Lifespan"
value = 25
/datum/plant_gene/core/lifespan/apply_stat(obj/item/seeds/S)
S.lifespan = value
/datum/plant_gene/core/endurance
name = "Endurance"
value = 15
/datum/plant_gene/core/endurance/apply_stat(obj/item/seeds/S)
S.endurance = value
/datum/plant_gene/core/production
name = "Production Speed"
value = 6
/datum/plant_gene/core/production/apply_stat(obj/item/seeds/S)
S.production = value
/datum/plant_gene/core/yield
name = "Yield"
value = 3
/datum/plant_gene/core/yield/apply_stat(obj/item/seeds/S)
S.yield = value
/datum/plant_gene/core/potency
name = "Potency"
value = 10
/datum/plant_gene/core/potency/apply_stat(obj/item/seeds/S)
S.potency = value
// Reagent genes store reagent ID and reagent ratio. Amount of reagent in the plant = 1 + (potency * rate)
@@ -79,6 +106,11 @@
G.rate = rate
return G
/datum/plant_gene/reagent/can_add(obj/item/seeds/S)
for(var/datum/plant_gene/reagent/R in S.genes)
if(R.reagent_id == reagent_id)
return FALSE
return TRUE
// Various traits affecting the product. Each must be somehow useful.
@@ -86,12 +118,21 @@
var/rate = 0.05
var/examine_line = ""
var/list/origin_tech = null
var/trait_id // must be set and equal for any two traits of the same type
/datum/plant_gene/trait/Copy()
var/datum/plant_gene/trait/G = ..()
G.rate = rate
return G
/datum/plant_gene/trait/can_add(obj/item/seeds/S)
for(var/datum/plant_gene/trait/R in S.genes)
if(trait_id && R.trait_id == trait_id)
return FALSE
if(type == R.type)
return FALSE
return TRUE
/datum/plant_gene/trait/proc/on_new(obj/item/weapon/reagent_containers/food/snacks/grown/G, newloc)
if(origin_tech) // This ugly code segment adds RnD tech levels to resulting plants.
if(G.origin_tech)
@@ -179,6 +220,7 @@
name = "Bioluminescence"
rate = 0.1
examine_line = "<span class='info'>It emits a soft glow.</span>"
trait_id = "glow"
/datum/plant_gene/trait/glow/proc/get_lum(obj/item/seeds/S)
return round(S.potency*rate)
+3 -2
View File
@@ -78,6 +78,7 @@
for(var/g in genes)
var/datum/plant_gene/G = g
S.genes += G.Copy()
S.reagents_add = reagents_add.Copy() // Faster than grabbing the list from genes.
return S
/obj/item/seeds/proc/get_gene(typepath)
@@ -141,10 +142,10 @@
if(T.reagents)
for(var/reagent_id in reagents_add)
if(reagent_id == "blood") // Hack to make blood in plants always O-
T.reagents.add_reagent(reagent_id, 1 + round(potency * reagents_add[reagent_id]), list("blood_type"="O-"))
T.reagents.add_reagent(reagent_id, 1 + round(potency * reagents_add[reagent_id], 1), list("blood_type"="O-"))
continue
T.reagents.add_reagent(reagent_id, 1 + round(potency * reagents_add[reagent_id]))
T.reagents.add_reagent(reagent_id, 1 + round(potency * reagents_add[reagent_id]), 1)
return 1