diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm index aab0560fe1..b9373e1818 100644 --- a/code/game/machinery/bioprinter.dm +++ b/code/game/machinery/bioprinter.dm @@ -1,84 +1,266 @@ -//These machines are mostly just here for debugging/spawning. Skeletons of the feature to come. +// GENERIC PRINTER - DO NOT USE THIS OBJECT. +// Flesh and robot printers are defined below this object. -/obj/machinery/bioprinter - name = "organ bioprinter" - desc = "It's a machine that grows replacement organs." +/obj/machinery/organ_printer + name = "organ printer" + desc = "It's a machine that prints organs." icon = 'icons/obj/surgery.dmi' + icon_state = "bioprinter" anchored = 1 density = 1 use_power = 1 idle_power_usage = 40 + active_power_usage = 300 - icon_state = "bioprinter" - - var/prints_prosthetics - var/stored_matter = 200 + var/stored_matter = 0 + var/max_stored_matter = 0 + var/print_delay = 100 + var/printing var/loaded_dna //Blood sample for DNA hashing. + + // These should be subtypes of /obj/item/organ var/list/products = list( - O_HEART = list(/obj/item/organ/internal/heart, 50), - O_LUNGS = list(/obj/item/organ/internal/lungs, 40), - O_KIDNEYS = list(/obj/item/organ/internal/kidneys,20), - O_EYES = list(/obj/item/organ/internal/eyes, 30), - O_LIVER = list(/obj/item/organ/internal/liver, 50) + "Heart" = list(/obj/item/organ/internal/heart, 25), + "Lungs" = list(/obj/item/organ/internal/lungs, 25), + "Kidneys" = list(/obj/item/organ/internal/kidneys,20), + "Eyes" = list(/obj/item/organ/internal/eyes, 20), + "Liver" = list(/obj/item/organ/internal/liver, 25), + "Arm, Left" = list(/obj/item/organ/external/arm, 65), + "Arm, Right" = list(/obj/item/organ/external/arm/right, 65), + "Leg, Left" = list(/obj/item/organ/external/leg, 65), + "Leg, Right" = list(/obj/item/organ/external/leg/right, 65), + "Foot, Left" = list(/obj/item/organ/external/foot, 40), + "Foot, Right" = list(/obj/item/organ/external/foot/right, 40), + "Hand, Left" = list(/obj/item/organ/external/hand, 40), + "Hand, Right" = list(/obj/item/organ/external/hand/right, 40) ) -/obj/machinery/bioprinter/prosthetics - name = "prosthetics fabricator" - desc = "It's a machine that prints prosthetic organs." - prints_prosthetics = 1 +/obj/machinery/organ_printer/attackby(var/obj/item/O, var/mob/user) + if(default_deconstruction_screwdriver(user, O)) + updateUsrDialog() + return + if(default_deconstruction_crowbar(user, O)) + return + if(default_part_replacement(user, O)) + return + return ..() -/obj/machinery/bioprinter/attack_hand(mob/user) +/obj/machinery/organ_printer/update_icon() + overlays.Cut() + if(panel_open) + overlays += "bioprinter_panel_open" + if(printing) + overlays += "bioprinter_working" - var/choice = input("What would you like to print?") as null|anything in products - if(!choice) +/obj/machinery/organ_printer/New() + ..() + 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/organ_printer/examine(var/mob/user) + . = ..() + to_chat(user, "It is loaded with [stored_matter]/[max_stored_matter] matter units.") + +/obj/machinery/organ_printer/RefreshParts() + print_delay = initial(print_delay) + max_stored_matter = 0 + for(var/obj/item/weapon/stock_parts/matter_bin/bin in component_parts) + max_stored_matter += bin.rating * 100 + for(var/obj/item/weapon/stock_parts/manipulator/manip in component_parts) + print_delay -= (manip.rating-1)*10 + print_delay = max(0,print_delay) + . = ..() + +/obj/machinery/organ_printer/attack_hand(mob/user) + + if(stat & (BROKEN|NOPOWER)) return - if(stored_matter >= products[choice][2]) + if(panel_open) + to_chat(user, "Close the panel first!") + return - stored_matter -= products[choice][2] - var/new_organ = products[choice][1] - var/obj/item/organ/O = new new_organ(get_turf(src)) + if(printing) + to_chat(user, "\The [src] is busy!") + return - if(prints_prosthetics) - O.robotize() - else if(loaded_dna) - visible_message("The printer injects the stored DNA into the biomass..") - O.transplant_data = list() - var/mob/living/carbon/C = loaded_dna["donor"] - O.transplant_data["species"] = C.species.name - O.transplant_data["blood_type"] = loaded_dna["blood_type"] - O.transplant_data["blood_DNA"] = loaded_dna["blood_DNA"] + var/choice = input("What would you like to print?") as null|anything in products - visible_message("The bioprinter spits out a new organ.") + if(!choice || printing || (stat & (BROKEN|NOPOWER))) + return - else - user << "There is not enough matter in the printer." + if(!can_print(choice)) + return -/obj/machinery/bioprinter/attackby(obj/item/weapon/W, mob/user) + stored_matter -= products[choice][2] - // DNA sample from syringe. - if(!prints_prosthetics && istype(W,/obj/item/weapon/reagent_containers/syringe)) + use_power = 2 + printing = 1 + update_icon() + + visible_message("\The [src] begins churning.") + + sleep(print_delay) + + use_power = 1 + printing = 0 + update_icon() + + if(!choice || !src || (stat & (BROKEN|NOPOWER))) + return + + print_organ(choice) + +/obj/machinery/organ_printer/proc/can_print(var/choice) + if(stored_matter < products[choice][2]) + visible_message("\The [src] displays a warning: 'Not enough matter. [stored_matter] stored and [products[choice][2]] needed.'") + return 0 + + if(!loaded_dna || !loaded_dna["donor"]) + visible_message("\The [src] displays a warning: 'No DNA saved. Insert a blood sample.'") + return 0 + + return 1 + +/obj/machinery/organ_printer/proc/print_organ(var/choice) + var/new_organ = products[choice][1] + var/obj/item/organ/O = new new_organ(get_turf(src)) + O.status |= ORGAN_CUT_AWAY + var/mob/living/carbon/C = loaded_dna["donor"] + O.set_dna(C.dna) + + if(O.species) + // This is a very hacky way of doing of what organ/New() does if it has an owner + O.w_class = max(O.w_class + mob_size_difference(O.species.mob_size, MOB_MEDIUM), 1) + + return O +// END GENERIC PRINTER + +// CIRCUITS +/obj/item/weapon/circuitboard/bioprinter + name = "bioprinter circuit" + build_path = /obj/machinery/organ_printer/flesh + board_type = new /datum/frame/frame_types/machine + origin_tech = list(TECH_DATA = 3, TECH_BIO = 3) + req_components = list( + /obj/item/stack/cable_coil = 2, + /obj/item/weapon/stock_parts/matter_bin = 2, + /obj/item/weapon/stock_parts/manipulator = 2) + +/obj/item/weapon/circuitboard/roboprinter + name = "roboprinter circuit" + build_path = /obj/machinery/organ_printer/robot + board_type = new /datum/frame/frame_types/machine + origin_tech = list(TECH_DATA = 3, TECH_BIO = 3) + req_components = list( + /obj/item/stack/cable_coil = 2, + /obj/item/weapon/stock_parts/matter_bin = 2, + /obj/item/weapon/stock_parts/manipulator = 2) + +// ROBOT ORGAN PRINTER +// Still Requires DNA, /obj/machinery/pros_fab is better for limbs +/obj/machinery/organ_printer/robot + name = "prosthetic organ fabricator" + desc = "It's a machine that prints prosthetic organs." + icon_state = "roboprinter" + circuit = /obj/item/weapon/circuitboard/roboprinter + + var/matter_amount_per_sheet = 10 + var/matter_type = DEFAULT_WALL_MATERIAL + +/obj/machinery/organ_printer/robot/full/New() + . = ..() + stored_matter = max_stored_matter + +/obj/machinery/organ_printer/robot/dismantle() + if(stored_matter >= matter_amount_per_sheet) + new /obj/item/stack/material/steel(get_turf(src), Floor(stored_matter/matter_amount_per_sheet)) + return ..() + +/obj/machinery/organ_printer/robot/print_organ(var/choice) + var/obj/item/organ/O = ..() + O.robotize() + O.status |= ORGAN_CUT_AWAY // robotize() resets status to 0 + playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) + audible_message("\The [src] dings, then spits out \a [O].") + return O + +/obj/machinery/organ_printer/robot/attackby(var/obj/item/weapon/W, var/mob/user) + if(istype(W, /obj/item/stack/material) && W.get_material_name() == matter_type) + if((max_stored_matter-stored_matter) < matter_amount_per_sheet) + to_chat(user, "\The [src] is too full.") + return + var/obj/item/stack/S = W + var/space_left = max_stored_matter - stored_matter + var/sheets_to_take = min(S.amount, Floor(space_left/matter_amount_per_sheet)) + if(sheets_to_take <= 0) + to_chat(user, "\The [src] is too full.") + return + stored_matter = min(max_stored_matter, stored_matter + (sheets_to_take*matter_amount_per_sheet)) + to_chat(user, "\The [src] processes \the [W]. Levels of stored matter now: [stored_matter]") + S.use(sheets_to_take) + return + else if(istype(W,/obj/item/weapon/reagent_containers/syringe)) //TODO: Make this actuall empty the syringe var/obj/item/weapon/reagent_containers/syringe/S = W var/datum/reagent/blood/injected = locate() in S.reagents.reagent_list //Grab some blood if(injected && injected.data) loaded_dna = injected.data - user << "You inject the blood sample into the bioprinter." - return - // Meat for biomass. - if(!prints_prosthetics && istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) - stored_matter += 50 - user.drop_item() - user << "\The [src] processes \the [W]. Levels of stored biomass now: [stored_matter]" - qdel(W) - return - // Steel for matter. - if(prints_prosthetics && istype(W, /obj/item/stack/material) && W.get_material_name() == DEFAULT_WALL_MATERIAL) - var/obj/item/stack/S = W - stored_matter += S.amount * 10 - user.drop_item() - user << "\The [src] processes \the [W]. Levels of stored matter now: [stored_matter]" - qdel(W) + to_chat(user, "You scan the blood sample into the bioprinter.") return + return ..() +// END ROBOT ORGAN PRINTER - return..() \ No newline at end of file +// FLESH ORGAN PRINTER +/obj/machinery/organ_printer/flesh + name = "bioprinter" + desc = "It's a machine that prints replacement organs." + icon_state = "bioprinter" + circuit = /obj/item/weapon/circuitboard/bioprinter + + var/amount_per_slab = 50 + +/obj/machinery/organ_printer/flesh/full/New() + . = ..() + stored_matter = max_stored_matter + +/obj/machinery/organ_printer/flesh/dismantle() + var/turf/T = get_turf(src) + if(T) + while(stored_matter >= amount_per_slab) + stored_matter -= amount_per_slab + new /obj/item/weapon/reagent_containers/food/snacks/meat(T) + return ..() + +/obj/machinery/organ_printer/flesh/print_organ(var/choice) + var/obj/item/organ/O = ..() + + playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) + visible_message("\The [src] dings, then spits out \a [O].") + return O + +/obj/machinery/organ_printer/flesh/attackby(obj/item/weapon/W, mob/user) + // Load with matter for printing. + if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) + if((max_stored_matter - stored_matter) < amount_per_slab) + to_chat(user, "\The [src] is too full.") + return + stored_matter += amount_per_slab + user.drop_item() + to_chat(user, "\The [src] processes \the [W]. Levels of stored biomass now: [stored_matter]") + qdel(W) + return + // DNA sample from syringe. + else if(istype(W,/obj/item/weapon/reagent_containers/syringe)) //TODO: Make this actually empty the syringe + var/obj/item/weapon/reagent_containers/syringe/S = W + var/datum/reagent/blood/injected = locate() in S.reagents.reagent_list //Grab some blood + if(injected && injected.data) + loaded_dna = injected.data + to_chat(user, "You scan the blood sample into the bioprinter.") + return + return ..() +// END FLESH ORGAN PRINTER \ No newline at end of file diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 02450c2c5c..cdf5893d3c 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -78,8 +78,9 @@ var/list/organ_cache = list() /obj/item/organ/proc/set_dna(var/datum/dna/new_dna) if(new_dna) dna = new_dna.Clone() - blood_DNA.Cut() - blood_DNA[dna.unique_enzymes] = dna.b_type + if(blood_DNA) + blood_DNA.Cut() + blood_DNA[dna.unique_enzymes] = dna.b_type /obj/item/organ/proc/die() if(robotic >= ORGAN_ROBOT) diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index a933bc6a2f..15ef72276f 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ