From ce6b574d6712b1608bd761d093cd5ac7891bfb89 Mon Sep 17 00:00:00 2001 From: Datraen Date: Wed, 18 May 2016 13:42:09 -0400 Subject: [PATCH] Status as of 05-18-2016 --- .../telecomms/machine_interactions.dm | 2 +- code/game/objects/items/devices/multitool.dm | 12 +- code/modules/xenobio2/_xeno_setup.dm | 102 +++++- code/modules/xenobio2/controller.dm | 44 +++ .../xenobio2/machinery/core_extractor.dm | 12 +- .../xenobio2/machinery/gene_manipulators.dm | 317 ++++++++++++++++++ code/modules/xenobio2/machinery/injector.dm | 133 ++++++++ .../xenobio2/machinery/injector_computer.dm | 87 +++++ .../xenobio2/machinery/slime_replicator.dm | 22 +- code/modules/xenobio2/mob/slime/slime_core.dm | 13 +- code/modules/xenobio2/mob/xeno.dm | 4 + code/modules/xenobio2/mob/xeno_product.dm | 12 + nano/templates/xenobio_computer.tmpl | 29 ++ nano/templates/xenobio_editor.tmpl | 57 ++++ nano/templates/xenobio_isolator.tmpl | 74 ++++ polaris.dme | 4 + 16 files changed, 906 insertions(+), 18 deletions(-) create mode 100644 code/modules/xenobio2/controller.dm create mode 100644 code/modules/xenobio2/machinery/gene_manipulators.dm create mode 100644 code/modules/xenobio2/machinery/injector.dm create mode 100644 code/modules/xenobio2/machinery/injector_computer.dm create mode 100644 code/modules/xenobio2/mob/xeno_product.dm create mode 100644 nano/templates/xenobio_computer.tmpl create mode 100644 nano/templates/xenobio_editor.tmpl create mode 100644 nano/templates/xenobio_isolator.tmpl diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 2b3561395f..002da7bc53 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -196,7 +196,7 @@ // Returns a multitool from a user depending on their mobtype. -/obj/machinery/telecomms/proc/get_multitool(mob/user as mob) +/obj/machinery/proc/get_multitool(mob/user as mob) //No need to have this being a telecomms specific proc. var/obj/item/device/multitool/P = null // Let's double check diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 867e64f446..cbc60670e7 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -20,4 +20,14 @@ origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1) var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage - var/obj/machinery/clonepod/connecting //same for cryopod linkage \ No newline at end of file + var/obj/machinery/clonepod/connecting //same for cryopod linkage + var/obj/machinery/connectable //Used to connect machinery, currently only used by Xenobio2. + +/obj/item/device/multitool/attack_self(mob/user) + var/clear = alert("Do you want to clear the buffers on the [src]?",, "Yes", "No",) + if(clear == "Yes") + buffer = null + connecting = null + connectable = null + else + ..() \ No newline at end of file diff --git a/code/modules/xenobio2/_xeno_setup.dm b/code/modules/xenobio2/_xeno_setup.dm index 720f1bec3e..c958256777 100644 --- a/code/modules/xenobio2/_xeno_setup.dm +++ b/code/modules/xenobio2/_xeno_setup.dm @@ -6,11 +6,14 @@ #define GENE_XENO_RESISTANCES "resistances" #define GENE_XENO_INTERNAL "internal" #define GENE_XENO_COLOR "color" +#define GENE_XENO_GLOW "glow" #define GENE_XENO_LEARN "learn" #define GENE_XENO_SPEAK "speak" #define GENE_XENO_SPEED "speed" #define GENE_XENO_SPECIAL "special" +#define ALL_XENO_GENES list(GENE_XENO_BIOCHEMISTRY, GENE_XENO_HEALTH, GENE_XENO_RESISTANCES, GENE_XENO_INTERNAL, GENE_XENO_COLOR, GENE_XENO_LEARN, GENE_XENO_SPEAK, GENE_XENO_SPEED, GENE_XENO_SPECIAL) + //Definitions for traits. #define TRAIT_XENO_COLOR "color" @@ -79,6 +82,7 @@ var/global/list/xenoChemList = list("mutationtoxin", var/list/traits = list() var/list/chemlist = list() var/obj/chems + var/source = "unknown" /datum/xeno/traits/proc/set_trait(var/trait, var/newval) traits["[trait]"] = newval @@ -112,4 +116,100 @@ var/global/list/xenoChemList = list("mutationtoxin", set_trait(TRAIT_XENO_STRENGTH, 0) set_trait(TRAIT_XENO_STR_RANGE, 0) chems = new() - chems.create_reagents(traits[TRAIT_XENO_CHEMVOL]) \ No newline at end of file + chems.create_reagents(traits[TRAIT_XENO_CHEMVOL]) + +/datum/xeno/traits/proc/get_gene(var/genetype) + + if(!genetype) return 0 + + var/datum/xeno/genes/G = new() + G.genetype = genetype + G.values = list() + + switch(genetype) + if(GENE_XENO_BIOCHEMISTRY) + G.values["[TRAIT_XENO_CHEMVOL]"] = get_trait(TRAIT_XENO_CHEMVOL) + G.chems = chems + if(GENE_XENO_HEALTH) + G.values["[TRAIT_XENO_HEALTH]"] = get_trait(TRAIT_XENO_HEALTH) + G.values["[TRAIT_XENO_STRENGTH]"] = get_trait(TRAIT_XENO_STRENGTH) + G.values["[TRAIT_XENO_STR_RANGE]"] = get_trait(TRAIT_XENO_STR_RANGE) + if(GENE_XENO_RESISTANCES) + G.values["[TRAIT_XENO_COLDRES]"] = get_trait(TRAIT_XENO_HEALTH) + G.values["[TRAIT_XENO_HEATRES]"] = get_trait(TRAIT_XENO_STRENGTH) + if(GENE_XENO_INTERNAL) + G.values["[TRAIT_XENO_NUTRITIONAL_CHEMS]"] = get_trait(TRAIT_XENO_NUTRITIONAL_CHEMS) + G.values["[TRAIT_XENO_HEALING_CHEMS]"] = get_trait(TRAIT_XENO_HEALING_CHEMS) + G.values["[TRAIT_XENO_TOXIC_CHEMS]"] = get_trait(TRAIT_XENO_TOXIC_CHEMS) + G.values["[TRAIT_XENO_MUTATING_CHEMS]"] = get_trait(TRAIT_XENO_MUTATING_CHEMS) + if(GENE_XENO_COLOR) + G.values["[TRAIT_XENO_COLOR]"] = get_trait(TRAIT_XENO_COLOR) + G.values["[TRAIT_XENO_BIO_COLOR]"] = get_trait(TRAIT_XENO_BIO_COLOR) + if(GENE_XENO_GLOW) + G.values["[TRAIT_XENO_BIOLUMESCENT]"] = get_trait(TRAIT_XENO_BIOLUMESCENT) + G.values["[TRAIT_XENO_GLOW_RANGE]"] = get_trait(TRAIT_XENO_GLOW_RANGE) + G.values["[TRAIT_XENO_GLOW_STRENGTH]"] = get_trait(TRAIT_XENO_GLOW_STRENGTH) + if(GENE_XENO_LEARN) + G.values["[TRAIT_XENO_LEARNCHANCE]"] = get_trait(TRAIT_XENO_LEARNCHANCE) + G.values["[TRAIT_XENO_CANLEARN]"] = get_trait(TRAIT_XENO_CANLEARN) + if(GENE_XENO_SPEAK) + G.values["[TRAIT_XENO_SPEAKCHANCE]"] = get_trait(TRAIT_XENO_SPEAKCHANCE) + G.values["[TRAIT_XENO_CANSPEAK]"] = get_trait(TRAIT_XENO_CANSPEAK) + if(GENE_XENO_SPEED) + G.values["[TRAIT_XENO_SPEED]"] = get_trait(TRAIT_XENO_SPEED) + if(GENE_XENO_SPECIAL) + G.values["[TRAIT_XENO_HOSTILE]"] = get_trait(TRAIT_XENO_HOSTILE) + G.values["[TRAIT_XENO_CHROMATIC]"] = get_trait(TRAIT_XENO_CHROMATIC) + +/datum/xeno/traits/proc/apply_gene(var/datum/xeno/genes/genes) + if(!genes.genetype) return 0 + + switch(genes.genetype) + if(GENE_XENO_BIOCHEMISTRY) + set_trait(TRAIT_XENO_CHEMVOL, genes.values["[TRAIT_XENO_CHEMVOL]"]) + chems.reagents.maximum_volume = genes.values["[TRAIT_XENO_CHEMVOL]"] + for(var/reagent in genes.chems.reagents) + var/amount = genes.chems.reagents[reagent] + chems.reagents.add_reagent(reagent, amount) + + if(GENE_XENO_HEALTH) + set_trait(TRAIT_XENO_HEALTH, genes.values["[TRAIT_XENO_HEALTH]"]) + set_trait(TRAIT_XENO_STRENGTH, genes.values["[TRAIT_XENO_STRENGTH]"]) + set_trait(TRAIT_XENO_STR_RANGE, genes.values["[TRAIT_XENO_STR_RANGE]"]) + if(GENE_XENO_RESISTANCES) + set_trait(TRAIT_XENO_COLDRES, genes.values["[TRAIT_XENO_COLDRES]"]) + set_trait(TRAIT_XENO_HEATRES, genes.values["[TRAIT_XENO_HEATRES]"]) + if(GENE_XENO_INTERNAL) + set_trait(TRAIT_XENO_NUTRITIONAL_CHEMS, genes.values["[TRAIT_XENO_NUTRITIONAL_CHEMS]"]) + set_trait(TRAIT_XENO_HEALING_CHEMS, genes.values["[TRAIT_XENO_HEALING_CHEMS]"]) + set_trait(TRAIT_XENO_TOXIC_CHEMS, genes.values["[TRAIT_XENO_TOXIC_CHEMS]"]) + set_trait(TRAIT_XENO_MUTATING_CHEMS, genes.values["[TRAIT_XENO_MUTATING_CHEMS]"]) + if(GENE_XENO_COLOR) + set_trait(TRAIT_XENO_COLOR, genes.values["[TRAIT_XENO_COLOR]"]) + set_trait(TRAIT_XENO_BIO_COLOR, genes.values["[TRAIT_XENO_BIO_COLOR]"]) + if(GENE_XENO_GLOW) + set_trait(TRAIT_XENO_BIOLUMESCENT, genes.values["[TRAIT_XENO_BIOLUMESCENT]"]) + set_trait(TRAIT_XENO_GLOW_RANGE, genes.values["[TRAIT_XENO_GLOW_RANGE]"]) + set_trait(TRAIT_XENO_GLOW_STRENGTH, genes.values["[TRAIT_XENO_GLOW_STRENGTH]"]) + if(GENE_XENO_LEARN) + set_trait(TRAIT_XENO_LEARNCHANCE, genes.values["[TRAIT_XENO_LEARNCHANCE]"]) + set_trait(TRAIT_XENO_CANLEARN, genes.values["[TRAIT_XENO_CANLEARN]"]) + if(GENE_XENO_SPEAK) + set_trait(TRAIT_XENO_SPEAKCHANCE, genes.values["[TRAIT_XENO_SPEAKCHANCE]"]) + set_trait(TRAIT_XENO_CANSPEAK, genes.values["[TRAIT_XENO_CANSPEAK]"]) + if(GENE_XENO_SPEED) + set_trait(TRAIT_XENO_SPEED ,genes.values["[TRAIT_XENO_SPEED]"]) + if(GENE_XENO_SPECIAL) + set_trait(TRAIT_XENO_HOSTILE, genes.values["[TRAIT_XENO_HOSTILE]"]) + set_trait(TRAIT_XENO_CHROMATIC, genes.values["[TRAIT_XENO_CHROMATIC]"]) + +/datum/xeno/genes + var/genetype //Label for specifying what gene is used. + var/list/values //What's going to be put into specific traits + var/obj/chems + +/datum/xeno/genes/New() + ..() + chems = new() + chems.create_reagents(20) + \ No newline at end of file diff --git a/code/modules/xenobio2/controller.dm b/code/modules/xenobio2/controller.dm new file mode 100644 index 0000000000..ecc550dcde --- /dev/null +++ b/code/modules/xenobio2/controller.dm @@ -0,0 +1,44 @@ +//Used to create the gene mask. Shamelessly stolen from the plant controller and cut down. + +/client/proc/show_xenobio_genes() + set category = "Debug" + set name = "Show Xenobio Genes" + set desc = "Prints the round's plant xenobio masks." + + if(!holder) return + + if(!xenobio_controller || !xenobio_controller.gene_tag_masks) + usr << "Gene masks not set." + return + + for(var/mask in xenobio_controller.gene_tag_masks) + usr << "[mask]: [xenobio_controller.gene_tag_masks[mask]]" + +var/global/datum/controller/plants/xenobio_controller // Set in New(). + +/datum/controller/xenobio + + var/list/gene_tag_masks = list() // Gene obfuscation for delicious trial and error goodness. + +/datum/controller/xenobio/New() + if(xenobio_controller && xenobio_controller != src) + log_debug("Rebuilding xenobio controller.") + qdel(xenobio_controller) + xenobio_controller = src + setup() + + +/datum/controller/xenobio/proc/setup() + + var/list/used_masks = list() + var/list/xenobio_traits = ALL_XENO_GENES + while(xenobio_traits && xenobio_traits.len) + var/gene_tag = pick(xenobio_traits) + var/gene_mask = "[uppertext(num2hex(rand(0,255)))]" + + while(gene_mask in used_masks) + gene_mask = "[uppertext(num2hex(rand(0,255)))]" + + used_masks += gene_mask + xenobio_traits -= gene_tag + gene_tag_masks[gene_tag] = gene_mask \ No newline at end of file diff --git a/code/modules/xenobio2/machinery/core_extractor.dm b/code/modules/xenobio2/machinery/core_extractor.dm index eedd631692..d9219a7e61 100644 --- a/code/modules/xenobio2/machinery/core_extractor.dm +++ b/code/modules/xenobio2/machinery/core_extractor.dm @@ -6,6 +6,8 @@ /obj/machinery/slime/extractor name = "Slime extractor" desc = "A machine for cutting up slimes to get to their cores." + icon = 'icons/obj/xenoarchaeology.dmi' + icon_state = "scanner_0old" density = 1 anchored = 1 circuit = /obj/item/weapon/circuitboard/slimeextractor @@ -94,18 +96,20 @@ inuse = 1 update_light_color() spawn(30) + icon_state = "scanner_1old" for(var/i=1 to occupant.cores) - var/obj/item/slime/core/C = new(src) - C.slimetraits = occupant.traitdat + var/obj/item/xenoproduct/slime/core/C = new(src) + C.traits = occupant.traitdat - C.create_reagents(C.slimetraits.traits[TRAIT_XENO_CHEMVOL]) + C.create_reagents(C.traits.traits[TRAIT_XENO_CHEMVOL]) for(var/reagent in occupant.traitdat.chems.reagents) var/amount = occupant.traitdat.chems.reagents[reagent] C.reagents.add_reagent(reagent, amount) - C.color = C.slimetraits.traits[TRAIT_XENO_COLOR] + C.color = C.traits.traits[TRAIT_XENO_COLOR] spawn(30) + icon_state = "scanner_0old" qdel(occupant) inuse = 0 eject_contents() diff --git a/code/modules/xenobio2/machinery/gene_manipulators.dm b/code/modules/xenobio2/machinery/gene_manipulators.dm new file mode 100644 index 0000000000..2b453051f8 --- /dev/null +++ b/code/modules/xenobio2/machinery/gene_manipulators.dm @@ -0,0 +1,317 @@ +/* + This file contains: + + Xenobiological disk: + Holds traits that can be taken from cores and transplanted into slimes. + + Biological Product Destructive Analyzer: + Takes certain traits in gene grouping from a core and places them into a disk. + + Biological genetic bombarder: + Takes traits from a disk and replaces/adds to the genes in a xenobiological creature. +*/ +/obj/item/weapon/disk/xenobio + name = "biological data disk" + desc = "A small disk used for carrying data on genetics." + icon = 'icons/obj/hydroponics_machines.dmi' + icon_state = "disk" + w_class = 1.0 + + var/list/genes = list() + var/genesource = "unknown" + +/obj/item/weapon/disk/xenobio/attack_self(var/mob/user as mob) + if(genes.len) + var/choice = alert(user, "Are you sure you want to wipe the disk?", "Xenobiological Data", "No", "Yes") + if(src && user && genes && choice && choice == "Yes" && user.Adjacent(get_turf(src))) + user << "You wipe the disk data." + name = initial(name) + desc = initial(name) + genes = list() + genesource = "unknown" + +/obj/item/weapon/storage/box/xenobiodisk + name = "biological disk box" + desc = "A box of biological data disks, apparently." + +/obj/item/weapon/storage/box/xenobiodisk/New() + ..() + for(var/i = 0 to 7) + new /obj/item/weapon/disk/xenobio(src) + +/obj/machinery/xenobio + density = 1 + anchored = 1 + use_power = 1 + + var/obj/item/weapon/disk/xenobio/loaded_disk //Currently loaded data disk. + + var/open = 0 + var/active = 0 + var/action_time = 5 + var/last_action = 0 + var/eject_disk = 0 + var/failed_task = 0 + var/disk_needs_genes = 0 + +/obj/machinery/xenobio/process() + + ..() + if(!active) return + + if(world.time > last_action + action_time) + finished_task() + +/obj/machinery/xenobio/proc/finished_task() + active = 0 + if(failed_task) + failed_task = 0 + visible_message("\icon[src] [src] pings unhappily, flashing a red warning light.") + else + visible_message("\icon[src] [src] pings happily.") + + if(eject_disk) + eject_disk = 0 + if(loaded_disk) + loaded_disk.forceMove(get_turf(src)) + visible_message("\icon[src] [src] beeps and spits out [loaded_disk].") + loaded_disk = null + +/obj/machinery/xenobio/extractor + name = "biological product destructive analyzer" + icon = 'icons/obj/hydroponics_machines.dmi' + icon_state = "traitcopier" + circuit = /obj/item/weapon/circuitboard/bioproddestanalyzer + + var/obj/item/xenoproduct/product + var/datum/xeno/traits/genetics // Currently scanned xeno genetic structure. + var/degradation = 0 // Increments with each scan, stops allowing gene mods after a certain point. + +/obj/machinery/xenobio/extractor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + + if(!user) + return + + var/list/data = list() + + var/list/geneMasks[0] + for(var/gene_tag in xenobio_controller.gene_tag_masks) + geneMasks.Add(list(list("tag" = gene_tag, "mask" = xenobio_controller.gene_tag_masks[gene_tag]))) + data["geneMasks"] = geneMasks + + data["activity"] = active + data["degradation"] = degradation + + if(loaded_disk) + data["disk"] = 1 + else + data["disk"] = 0 + + if(product) + data["loaded"] = "[product.source] [product.product]" + else + data["loaded"] = 0 + + if(genetics) + data["hasGenetics"] = 1 + data["sourceName"] = genetics.source + else + data["hasGenetics"] = 0 + data["sourceName"] = 0 + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "xenobio_isolator.tmpl", "Biological Product Destructive Analyzer UI", 470, 450) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/xenobio/extractor/Topic(href, href_list) + + if(..()) + return 1 + + if(href_list["eject_product"]) + if(!product) return + + product.forceMove(get_turf(src)) + visible_message("\icon[src] [src] beeps and spits out [product].") + product = null + + if(href_list["eject_disk"]) + if(!loaded_disk) return + + loaded_disk.forceMove(get_turf(src)) + visible_message("\icon[src] [src] beeps and spits out [loaded_disk].") + loaded_disk = null + + if(href_list["scan_genome"]) + + if(!product) return + + last_action = world.time + active = 1 + + if(product && product.product) + genetics = product.traits + degradation = 0 + + qdel(product) + product = null + + if(href_list["get_gene"]) + + if(!genetics || !loaded_disk) return + + last_action = world.time + active = 1 + + var/datum/xeno/genes/G = genetics.get_gene(href_list["get_gene"]) + if(!G) return + loaded_disk.genes += G + + loaded_disk.genesource = "[genetics.source]" + + loaded_disk.name += " ([xenobio_controller.gene_tag_masks[href_list["get_gene"]]], [genetics.source]" + loaded_disk.desc += " The label reads \'gene [xenobio_controller.gene_tag_masks[href_list["get_gene"]]], sampled from [genetics.source]\'." + eject_disk = 1 + + degradation += rand(20,60) + if(degradation >= 100) + failed_task = 1 + genetics = null + degradation = 0 + + if(href_list["clear_buffer"]) + if(!genetics) return + genetics = null + degradation = 0 + + usr.set_machine(src) + src.add_fingerprint(usr) + + src.updateUsrDialog() + return + +/obj/machinery/xenobio/editor + name = "biological genetic bombarder" + icon = 'icons/obj/cryogenics.dmi' + icon_state = "cellold0" + disk_needs_genes = 1 + circuit = /obj/item/weapon/circuitboard/biobombarder + + var/mob/living/simple_animal/xeno/slime/occupant + +/obj/machinery/xenobio/editor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + + if(!user) + return + + var/list/data = list() + + data["activity"] = active + + if(occupant) + data["degradation"] = occupant.stability + else + data["degradation"] = 0 + + if(loaded_disk && loaded_disk.genes.len) + data["disk"] = 1 + data["sourceName"] = loaded_disk.genesource + data["locus"] = "" + + for(var/datum/xeno/genes/X in loaded_disk.genes) + if(data["locus"] != "") data["locus"] += ", " + data["locus"] += "[xenobio_controller.gene_tag_masks[X.genetype]]" + + else + data["disk"] = 0 + data["sourceName"] = 0 + data["locus"] = 0 + + if(occupant) + data["loaded"] = "[occupant]" + else + data["loaded"] = 0 + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "xenobio_editor.tmpl", "Biological Genetic Bombarder UI", 470, 450) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/xenobio/editor/Topic(href, href_list) + + if(..()) + return 1 + + if(href_list["apply_gene"]) + if(!loaded_disk || !occupant) return + + last_action = world.time + active = 1 + + if(prob(occupant.stability)) + failed_task = 1 + occupant.stability = 101 + + for(var/datum/plantgene/gene in loaded_disk.genes) + occupant.traitdat.apply_gene(gene) + occupant.stability += rand(5,10) + occupant.ProcessTraits() + + usr.set_machine(src) + src.add_fingerprint(usr) + +/obj/machinery/xenobio/editor/MouseDrop_T(mob/target, mob/user) + if(user.stat || user.restrained()) + return + move_into_editor(user,target) + +/obj/machinery/xenobio/editor/proc/move_into_editor(var/mob/user,var/mob/living/victim) + + if(src.occupant) + user << "The biological genetic bombarder is full, empty it first!" + return + + if(in_use) + user << "The biological genetic bombarder is locked and running, wait for it to finish." + return + + if(!(istype(victim, /mob/living/simple_animal/xeno/slime)) ) + user << "This is not a suitable subject for the biological genetic bombarder!" + return + + user.visible_message("[user] starts to put [victim] into the biological genetic bombarder!") + src.add_fingerprint(user) + if(do_after(user, 30) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant) + user.visible_message("[user] stuffs [victim] into the biological genetic bombarder!") + if(victim.client) + victim.client.perspective = EYE_PERSPECTIVE + victim.client.eye = src + victim.forceMove(src) + occupant = victim + +/obj/machinery/xenobio/editor/proc/eject_contents() + for(var/obj/thing in (contents - component_parts - circuit)) + thing.forceMove(loc) + if(occupant) + occupant.forceMove(loc) + occupant = null + +/obj/item/weapon/circuitboard/bioproddestanalyzer + name = T_BOARD("biological product destructive analyzer") + build_path = "/obj/machinery/xenobio/extractor" + board_type = "machine" + origin_tech = list() //To be filled, + req_components = list() //To be filled, + +/obj/item/weapon/circuitboard/biobombarder + name = T_BOARD("biological genetic bombarder") + build_path = "/obj/machinery/xenobio/editor" + board_type = "machine" + origin_tech = list() //To be filled, + req_components = list() //To be filled, + \ No newline at end of file diff --git a/code/modules/xenobio2/machinery/injector.dm b/code/modules/xenobio2/machinery/injector.dm new file mode 100644 index 0000000000..8af7aea495 --- /dev/null +++ b/code/modules/xenobio2/machinery/injector.dm @@ -0,0 +1,133 @@ +/* + This file contains: + + Manual Injector: + Manually injects chemicals into a xenobiological creature from a linked machine. + +*/ +/obj/machinery/xenobio2/manualinjector + name = "biological injector" + desc = "Injects biological organisms that are inserted with the contents of an inserted beaker at the command of a remote computer." + density = 1 + anchored = 1 + use_power = 1 + icon = 'icons/obj/biogenerator.dmi' + icon_state = "biogen-work" + var/mob/living/occupant + var/obj/item/weapon/reagent_containers/glass/beaker + var/obj/machinery/computer/xenobio2/computer + + circuit = /obj/item/weapon/circuitboard/xenobioinjectormachine + +/obj/machinery/xenobio2/manualinjector/New() + ..() + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + +/obj/machinery/xenobio2/manualinjector/map/New() + ..() + beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src) + circuit = new circuit(src) + component_parts = list() + component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) + component_parts += new /obj/item/weapon/stock_parts/manipulator(src) + component_parts += new /obj/item/weapon/stock_parts/manipulator(src) + RefreshParts() + +/obj/machinery/xenobio2/manualinjector/update_icon() + if(beaker) + if(occupant) + icon_state = "biogen-stand" + else + icon_state = "biogen-work" + else + icon_state = "biogen-empty" + +/obj/machinery/xenobio2/manualinjector/MouseDrop_T(mob/target, mob/user) + if(user.stat || user.restrained()) + return + move_into_injector(user,target) + +/obj/machinery/xenobio2/manualinjector/proc/move_into_injector(var/mob/user,var/mob/living/victim) + if(src.occupant) + user << "The injector is full, empty it first!" + return + + if(!(istype(victim, /mob/living/simple_animal/xeno)) && !emagged) + user << "This is not a suitable subject for the injector!" + return + + user.visible_message("[user] starts to put [victim] into the injector!") + src.add_fingerprint(user) + if(do_after(user, 30) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant) + user.visible_message("[user] stuffs [victim] into the injector!") + if(victim.client) + victim.client.perspective = EYE_PERSPECTIVE + victim.client.eye = src + victim.forceMove(src) + src.occupant = victim + +/obj/machinery/xenobio2/manualinjector/proc/eject_contents() + for(var/obj/thing in (contents - component_parts - circuit)) + thing.forceMove(loc) + if(occupant) + occupant.forceMove(loc) + occupant = null + +/obj/machinery/xenobio2/manualinjector/proc/inject_reagents() + if(!occupant) + return + if(isxeno(occupant)) + var/mob/living/simple_animal/xeno/X = occupant + beaker.reagents.trans_to_holder(X.reagents, computer.transfer_amount, 1, 0) + else + beaker.reagents.trans_to_mob(occupant, computer.transfer_amount) + +/obj/machinery/xenobio2/manualinjector/attackby(var/obj/item/W, var/mob/user) + + //Let's try to deconstruct first. + if(istype(W, /obj/item/weapon/screwdriver)) + default_deconstruction_screwdriver(user, W) + return + + if(istype(W, /obj/item/weapon/crowbar) && !occupant) + default_deconstruction_crowbar(user, W) + return + + //Did you want to link it? + if(istype(W, /obj/item/device/multitool)) + var/obj/item/device/multitool/P = W + if(P.connectable) + if(istype(P.connectable, /obj/machinery/computer/xenobio2)) + var/obj/machinery/computer/xenobio2/C = P.connectable + computer = C + C.injector = src + user << " You link the [src] to the [P.connectable]!" + else + user << " You store the [src] in the [P]'s buffer!" + P.connectable = src + return + + if(panel_open) + user << "Close the panel first!" + + var/obj/item/weapon/grab/G = W + + if(!istype(G)) + return ..() + + if(G.state < 2) + user << "You need a better grip to do that!" + return + + move_into_injector(user,G.affecting) + + +/obj/item/weapon/circuitboard/xenobioinjectormachine + name = T_BOARD("biological injector") + build_path = "/obj/machinery/xenobio2/manualinjector" + board_type = "machine" + origin_tech = list() //To be filled, + req_components = list() //To be filled, \ No newline at end of file diff --git a/code/modules/xenobio2/machinery/injector_computer.dm b/code/modules/xenobio2/machinery/injector_computer.dm new file mode 100644 index 0000000000..0460131dd1 --- /dev/null +++ b/code/modules/xenobio2/machinery/injector_computer.dm @@ -0,0 +1,87 @@ +/* + This file contains: + + Manual Injector: + Manually injects chemicals into a xenobiological creature from a linked machine. + +*/ +/obj/machinery/computer/xenobio2 + name = "injector control console" + desc = "Used to control mechanized biological injectors." + icon_keyboard = "med_key" + icon_screen = "dna" + light_color = "#315ab4" + use_power = 1 + idle_power_usage = 250 + active_power_usage = 500 + circuit = /obj/item/weapon/circuitboard/xenobio2computer + var/obj/machinery/xenobio2/manualinjector/injector + var/transfer_amount + +/obj/machinery/computer/xenobio2/Destroy() + ..() + injector.computer = null + +/obj/machinery/computer/xenobio2/attackby(var/obj/item/W, var/mob/user) + + //Did you want to link it? + if(istype(W, /obj/item/device/multitool)) + var/obj/item/device/multitool/P = W + if(P.connectable) + if(istype(P.connectable, /obj/machinery/xenobio2/manualinjector)) + var/obj/machinery/xenobio2/manualinjector/I = P.connectable + injector = I + I.computer = src + user << " You link the [src] to the [P.connectable]!" + else + user << " You store the [src] in the [P]'s buffer!" + P.connectable = src + return + + ..() + +/obj/machinery/computer/xenobio2/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + if(!user) + return + + var/list/data = list() + + data["activity"] = active + if(isxeno(occupant)) + var/mob/living/simple_animal/xeno/X = occupant + data["instability"] = (X.mut_level / X.mut_max) + else + data["instability"] = null + + data["reagentamount"] = beaker.reagents.total_volume + data["reagentmax"] = beaker.reagents.max_volume + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "xenobio_computer.tmpl", "Injector Control Console UI", 470, 450) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/computer/xenobio2/Topic(href, href_list) + + if(..()) + return 1 + + if(href_list["inject_target"]) + active = 1 + spawn(5) + injector.inject_reagents() + active = 0 + if(href_list["eject"]) + injector.eject_contents() + + usr.set_machine(src) + src.add_fingerprint(usr) + +/obj/item/weapon/circuitboard/xenobio2computer + name = T_BOARD("injector control console") + build_path = "/obj/item/weapon/circuitboard/xenobio2computer" + board_type = "computer" + origin_tech = list() //To be filled, + \ No newline at end of file diff --git a/code/modules/xenobio2/machinery/slime_replicator.dm b/code/modules/xenobio2/machinery/slime_replicator.dm index 85a9524739..c191e856ed 100644 --- a/code/modules/xenobio2/machinery/slime_replicator.dm +++ b/code/modules/xenobio2/machinery/slime_replicator.dm @@ -4,12 +4,14 @@ To create more of these cores, stick the slime core in the extractor. */ /obj/machinery/slime/replicator - name = "Slime replicator" + name = "slime core growth apparatus" desc = "A machine for creating slimes from cores. Amazing!" + icon = 'icons/obj/xenoarchaeology.dmi' + icon_state = "restruct_0" density = 1 anchored = 1 circuit = /obj/item/weapon/circuitboard/slimereplicator - var/obj/item/slime/core/core = null + var/obj/item/xenoproduct/slime/core/core = null var/inuse var/occupiedcolor = "#22FF22" var/emptycolor = "#FF2222" @@ -31,7 +33,7 @@ default_deconstruction_crowbar(user, W) return - var/obj/item/slime/core/G = W + var/obj/item/xenoproduct/slime/core/G = W if(!istype(G)) return ..() @@ -53,7 +55,7 @@ else set_light(4, 4, emptycolor) -/obj/machinery/slime/replicator/proc/extract_cores() +/obj/machinery/slime/replicator/proc/replicate_slime() if(!src.core) src.visible_message("\icon[src] [src] pings unhappily.") else if(inuse) @@ -61,14 +63,15 @@ inuse = 1 update_light_color() + icon_state = "restruct_1" spawn(30) - var/mob/living/simple_animal/xeno/slime/S = new() - S.traitdat = core.slimetraits - S.forceMove(src) + var/mob/living/simple_animal/xeno/slime/S = new(src) + S.traitdat = core.traits + qdel(core) spawn(30) - qdel(core) inuse = 0 eject_contents() + icon_state = "restruct_0" update_light_color() /obj/machinery/slime/replicator/proc/eject_contents() @@ -77,6 +80,9 @@ if(core) core.forceMove(loc) core = null + +//Here lies the UI + //Circuit board below, /obj/item/weapon/circuitboard/slimereplicator diff --git a/code/modules/xenobio2/mob/slime/slime_core.dm b/code/modules/xenobio2/mob/slime/slime_core.dm index bb6bde65b7..3e6fddf722 100644 --- a/code/modules/xenobio2/mob/slime/slime_core.dm +++ b/code/modules/xenobio2/mob/slime/slime_core.dm @@ -1,10 +1,17 @@ /* -Slime core lives here, and related procs. +Slime core lives here. */ -/obj/item/slime/core +/obj/item/xenoproduct/slime/core name = "slime core" desc = "Gooey." icon = 'icons/mob/slime2.dmi' icon_state = "slime extract" - var/datum/xeno/traits/slimetraits + source = "Slime" + product = "core" + +/obj/item/xenoproduct/slime/core/New() + ..() + color = traits.get_trait(TRAIT_XENO_COLOR) + if(traits.get_trait(TRAIT_XENO_BIOLUMESCENT)) + set_light(traits.get_trait(TRAIT_XENO_GLOW_STRENGTH),traits.get_trait(TRAIT_XENO_GLOW_RANGE),traits.get_trait(TRAIT_XENO_BIO_COLOR)) \ No newline at end of file diff --git a/code/modules/xenobio2/mob/xeno.dm b/code/modules/xenobio2/mob/xeno.dm index a3ef1b09ad..be0191f71a 100644 --- a/code/modules/xenobio2/mob/xeno.dm +++ b/code/modules/xenobio2/mob/xeno.dm @@ -30,6 +30,7 @@ Also includes Life and New var/mut_max = 100000 var/colored = 1 var/maleable = MIN_MALEABLE //How easy is it to manipulate traitdat.traits after it's alive. + var/stability = 0 //Used in gene manipulation //Traits that might not be maleable. var/list/chemreact = list() @@ -87,6 +88,9 @@ Also includes Life and New nutrition = 350 for(var/R in default_chems) traitdat.chems.reagents.add_reagent("[R]", default_chems[R]) + + traitdat.source = name + if(!health) stat = DEAD \ No newline at end of file diff --git a/code/modules/xenobio2/mob/xeno_product.dm b/code/modules/xenobio2/mob/xeno_product.dm new file mode 100644 index 0000000000..2ea970c89f --- /dev/null +++ b/code/modules/xenobio2/mob/xeno_product.dm @@ -0,0 +1,12 @@ +/* +Xenobiological product lives here as a basic type. +*/ +/obj/item/xenoproduct + name = "Xenobiological product" + desc = "How did this get here?." + icon = 'icons/mob/slime2.dmi' + icon_state = "slime extract" + var/datum/xeno/traits/traits + var/source = "Unknown" + var/product = "mess" + \ No newline at end of file diff --git a/nano/templates/xenobio_computer.tmpl b/nano/templates/xenobio_computer.tmpl new file mode 100644 index 0000000000..3b75fe32a5 --- /dev/null +++ b/nano/templates/xenobio_computer.tmpl @@ -0,0 +1,29 @@ + + +{{if data.activity}} + Scanning... +{{else}} +

Injector Sensor Readings:

+
+ {{if data.instability}} +
+
+ Instability:
+ {{:data.instability}}% +
+
+ {{else}} +
+
+ Instability:
+ ERRR%
Please contact your local technician for assistance. +
+

+ {{/if}} +
+

Controls

+
+{{/if}} \ No newline at end of file diff --git a/nano/templates/xenobio_editor.tmpl b/nano/templates/xenobio_editor.tmpl new file mode 100644 index 0000000000..2ee83488f0 --- /dev/null +++ b/nano/templates/xenobio_editor.tmpl @@ -0,0 +1,57 @@ + + +{{if data.activity}} + Scanning... +{{else}} +

Buffered Genetic Data

+ {{if data.disk}} +
+
+ Source: +
+
+ {{:data.sourceName}} +
+
+ Gene decay: +
+
+ {{if data.degradation <= 100}} + {{:data.degradation}}% + {{else}} + FURTHER AMENDMENTS NONVIABLE + {{/if}} +
+
+ Locus: +
+
+ {{:data.locus}} +
+ {{:helper.link('Eject Disk', 'circle-arrow-e', {'eject_disk' : 1}, null)}} +
+ {{else}} +
No disk loaded.
+ {{/if}} +

Loaded Material

+ {{if data.loaded}} +
+
+ Target: +
+
+ {{:data.loaded}} +
+ {{if data.degradation <= 100}} + {{:helper.link('Apply Gene Mods', 'gear', {'apply_gene' : 1}, null)}} + {{/if}} + {{:helper.link('Eject Target', 'circle-arrow-e', {'eject_packet' : 1}, null)}} +
+ {{else}} +
No target organism loaded
+ {{/if}} +{{/if}} \ No newline at end of file diff --git a/nano/templates/xenobio_isolator.tmpl b/nano/templates/xenobio_isolator.tmpl new file mode 100644 index 0000000000..630828eb4c --- /dev/null +++ b/nano/templates/xenobio_isolator.tmpl @@ -0,0 +1,74 @@ + + +{{if data.activity}} + Scanning... +{{else}} +

Buffered Genetic Data

+ {{if data.hasGenetics}} +
+
+ Source: +
+
+ {{:data.sourceName}} +
+
+ Gene decay: +
+
+ {{:data.degradation}}% +
+
+ {{if data.disk}} + {{for data.geneMasks}} +
+
+ {{:value.mask}} +
+
+ {{:helper.link('Extract', 'circle-arrow-s', {'get_gene' : value.tag}, null)}} +
+
+ {{empty}} +
Data error. Genetic record corrupt.
+ {{/for}} +
+
+ {{:helper.link('Eject Loaded Disk', 'circle-arrow-e', {'eject_disk' : 1}, null)}} + {{:helper.link('Clear Genetic Buffer', 'gear', {'clear_buffer' : 1}, null)}} +
+ {{else}} +
No disk inserted.
+ {{/if}} + {{else}} +
No data buffered.
+ {{if data.disk}} +
+
+ {{:helper.link('Eject Loaded Disk', 'circle-arrow-e', {'eject_disk' : 1}, null)}} +
+ {{else}} +
No disk inserted.
+ {{/if}} + {{/if}} +

Loaded Material

+ {{if data.loaded}} +
+
+ Product loaded: +
+
+ {{:data.loaded}} +
+
+ {{:helper.link('Process Genome', 'gear', {'scan_genome' : 1}, null)}}{{:helper.link('Eject Product', 'circle-arrow-e', {'eject_product' : 1}, null)}} +
+
+ {{else}} +
No seeds loaded.
+ {{/if}} +{{/if}} \ No newline at end of file diff --git a/polaris.dme b/polaris.dme index ed416e048b..6b24fb3816 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1874,10 +1874,14 @@ #include "code\modules\virus2\isolator.dm" #include "code\modules\virus2\items_devices.dm" #include "code\modules\xenobio2\_xeno_setup.dm" +#include "code\modules\xenobio2\controller.dm" #include "code\modules\xenobio2\machinery\core_extractor.dm" +#include "code\modules\xenobio2\machinery\gene_manipulators.dm" +#include "code\modules\xenobio2\machinery\injector.dm" #include "code\modules\xenobio2\machinery\slime_replicator.dm" #include "code\modules\xenobio2\mob\xeno procs.dm" #include "code\modules\xenobio2\mob\xeno.dm" +#include "code\modules\xenobio2\mob\xeno_product.dm" #include "code\modules\xenobio2\mob\slime\slime life.dm" #include "code\modules\xenobio2\mob\slime\slime procs.dm" #include "code\modules\xenobio2\mob\slime\slime.dm"