/obj/machinery/r_n_d/protolathe name = "Protolathe" icon_state = "protolathe" flags = OPENCONTAINER use_power = 1 idle_power_usage = 30 active_power_usage = 5000 var/list/materials = list("metal" = 0, "glass" = 0, "gold" = 0, "silver" = 0, "phoron" = 0, "uranium" = 0, "diamond" = 0) var/list/datum/design/queue = list() var/progress = 0 var/max_material_storage = 100000 // All this could probably be done better with a list but meh. var/mat_efficiency = 1 var/speed = 1 var/datum/design/chassis/current_chassis = null var/list/datum/design/current_components = list() /obj/machinery/r_n_d/protolathe/New() ..() component_parts = list() component_parts += new /obj/item/weapon/circuitboard/protolathe(src) 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) component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) RefreshParts() /obj/machinery/r_n_d/protolathe/process() ..() if(stat) update_icon() return if(queue.len == 0) busy = 0 update_icon() return var/datum/design/D = queue[1] if(canBuild(D)) busy = 1 progress += speed if(progress >= D.time) build(D) progress = 0 removeFromQueue(1) if(linked_console) linked_console.updateUsrDialog() update_icon() else if(busy) visible_message("\icon [src] flashes: insufficient materials: [getLackingMaterials(D)].") busy = 0 update_icon() /obj/machinery/r_n_d/protolathe/proc/TotalMaterials() //returns the total of all the stored materials. Makes code neater. var/t = 0 for(var/f in materials) t += materials[f] return t /obj/machinery/r_n_d/protolathe/RefreshParts() var/T = 0 for(var/obj/item/weapon/reagent_containers/glass/G in component_parts) T += G.reagents.maximum_volume create_reagents(T) max_material_storage = 0 for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) max_material_storage += M.rating * 75000 T = 0 for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) T += M.rating mat_efficiency = 1 - (T - 2) / 8 speed = T / 2 /obj/machinery/r_n_d/protolathe/dismantle() for(var/obj/I in component_parts) if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker)) reagents.trans_to(I, reagents.total_volume) for(var/f in materials) if(materials[f] >= SHEET_MATERIAL_AMOUNT) var/path = getMaterialType(f) if(path) var/obj/item/stack/S = new f(loc) S.amount = round(materials[f] / SHEET_MATERIAL_AMOUNT) ..() /obj/machinery/r_n_d/protolathe/update_icon() if(panel_open) icon_state = "protolathe_t" else if(busy) icon_state = "protolathe_n" else icon_state = "protolathe" /obj/machinery/r_n_d/protolathe/attackby(var/obj/item/O as obj, var/mob/user as mob) if(busy) user << "\The [src] is busy. Please wait for completion of previous operation." return 1 if(default_deconstruction_screwdriver(user, O)) if(linked_console) linked_console.linked_lathe = null linked_console = null return if(default_deconstruction_crowbar(user, O)) return if(default_part_replacement(user, O)) return if(O.is_open_container()) return 1 if(panel_open) user << "You can't load \the [src] while it's opened." return 1 if(!linked_console) user << "\The [src] must be linked to an R&D console first!" return 1 if(!istype(O, /obj/item/stack/sheet)) user << "You cannot insert this item into \the [src]!" return 1 if(stat) return 1 if(TotalMaterials() + SHEET_MATERIAL_AMOUNT > max_material_storage) user << "\The [src]'s material bin is full. Please remove material before adding more." return 1 var/obj/item/stack/sheet/stack = O var/amount = round(input("How many sheets do you want to add?") as num)//No decimals if(!O) return if(amount <= 0)//No negative numbers return if(amount > stack.get_amount()) amount = stack.get_amount() if(max_material_storage - TotalMaterials() < (amount * SHEET_MATERIAL_AMOUNT)) //Can't overfill amount = min(stack.get_amount(), round((max_material_storage - TotalMaterials()) / SHEET_MATERIAL_AMOUNT)) var/stacktype = stack.type var/t = getMaterialName(stacktype) overlays += "protolathe_[t]" spawn(10) overlays -= "protolathe_[t]" busy = 1 use_power(max(1000, (SHEET_MATERIAL_AMOUNT * amount / 10))) if(t) if(do_after(user, 16)) if(stack.use(amount)) user << "You add [amount] sheets to \the [src]." materials[t] += amount * SHEET_MATERIAL_AMOUNT busy = 0 updateUsrDialog() return /obj/machinery/r_n_d/protolathe/proc/getMaterialType(var/name) // TODO: make not copypasted to CI switch(name) if("metal") return /obj/item/stack/sheet/metal if("glass") return /obj/item/stack/sheet/glass if("gold") return /obj/item/stack/sheet/mineral/gold if("silver") return /obj/item/stack/sheet/mineral/silver if("phoron") return /obj/item/stack/sheet/mineral/phoron if("uranium") return /obj/item/stack/sheet/mineral/uranium if("diamond") return /obj/item/stack/sheet/mineral/diamond return null /obj/machinery/r_n_d/protolathe/proc/getMaterialName(var/type) switch(type) if(/obj/item/stack/sheet/metal) return "metal" if(/obj/item/stack/sheet/glass) return "glass" if(/obj/item/stack/sheet/mineral/gold) return "gold" if(/obj/item/stack/sheet/mineral/silver) return "silver" if(/obj/item/stack/sheet/mineral/phoron) return "phoron" if(/obj/item/stack/sheet/mineral/uranium) return "uranium" if(/obj/item/stack/sheet/mineral/diamond) return "diamond" /obj/machinery/r_n_d/protolathe/proc/addToQueue(var/datum/design/D) queue += D return /obj/machinery/r_n_d/protolathe/proc/removeFromQueue(var/index) queue.Cut(index, index + 1) return /obj/machinery/r_n_d/protolathe/proc/canBuild(var/datum/design/D) for(var/M in D.materials) if(materials[M] < D.materials[M]) return 0 for(var/C in D.chemicals) if(!reagents.has_reagent(C, D.chemicals[C])) return 0 return 1 /obj/machinery/r_n_d/protolathe/proc/getLackingMaterials(var/datum/design/D) var/ret = "" for(var/M in D.materials) if(materials[M] < D.materials[M]) if(ret != "") ret += ", " ret += "[D.materials[M] - materials[M]] [M]" for(var/C in D.chemicals) if(!reagents.has_reagent(C, D.chemicals[C])) if(ret != "") ret += ", " ret += C return ret /obj/machinery/r_n_d/protolathe/proc/build(var/datum/design/D) var/power = active_power_usage for(var/M in D.materials) power += round(D.materials[M] / 5) power = max(active_power_usage, power) use_power(power) for(var/M in D.materials) materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency) for(var/C in D.chemicals) reagents.remove_reagent(C, D.chemicals[C] * mat_efficiency) if(D.build_path) var/obj/new_item = new D.build_path(src) new_item.loc = loc if(mat_efficiency != 1) // No matter out of nowhere if(new_item.matter && new_item.matter.len > 0) for(var/i in new_item.matter) new_item.matter[i] = new_item.matter[i] * mat_efficiency /obj/machinery/r_n_d/protolathe/proc/choosePart(var/name, var/datum/design/D) current_components[name] = D /obj/machinery/r_n_d/protolathe/proc/buildChassis() var/obj/item/I = new current_chassis.build_path(loc) for(var/t in current_components) var/datum/design/D = current_components[t] var/obj/item/O = new D.build_path(I) world << I world << I.type current_chassis.setup(I, O, t) current_components.Cut() current_chassis = null