/* Research and Development (R&D) Console This is the main work horse of the R&D system. It contains the menus/controls for the Destructive Analyzer, Protolathe, and Circuit imprinter. It also contains the /datum/research holder with all the known/possible technology paths and device designs. Basic use: When it first is created, it will attempt to link up to related devices within 3 squares. It'll only link up if they aren't already linked to another console. Any consoles it cannot link up with (either because all of a certain type are already linked or there aren't any in range), you'll just not have access to that menu. In the settings menu, there are menu options that allow a player to attempt to re-sync with nearby consoles. You can also force it to disconnect from a specific console. The imprinting and construction menus do NOT require toxins access to access but all the other menus do. However, if you leave it on a menu, nothing is to stop the person from using the options on that menu (although they won't be able to change to a different one). You can also lock the console on the settings menu if you're feeling paranoid and you don't want anyone messing with it who doesn't have toxins access. When a R&D console is destroyed or even partially disassembled, you lose all research data on it. However, there are two ways around this dire fate: - The easiest way is to go to the settings menu and select "Sync Database with Network." That causes it to upload (but not download) it's data to every other device in the game. Each console has a "disconnect from network" option that'll will cause data base sync operations to skip that console. This is useful if you want to make a "public" R&D console or, for example, give the engineers a circuit imprinter with certain designs on it and don't want it accidentally updating. The downside of this method is that you have to have physical access to the other console to send data back. Note: An R&D console is on CentCom so if a random griffan happens to cause a ton of data to be lost, an admin can go send it back. - The second method is with Technology Disks and Design Disks. Each of these disks can hold a single technology or design datum in it's entirety. You can then take the disk to any R&D console and upload it's data to it. This method is a lot more secure (since it won't update every console in existence) but it's more of a hassle to do. Also, the disks can be stolen. */ /obj/structure/machinery/computer/rdconsole name = "R&D control console" icon_screen = "rdcomp" icon_keyboard = "purple_key" icon_keyboard_emis = "purple_key_mask" light_color = LIGHT_COLOR_PURPLE manufacturer = "nanotrasen" circuit = /obj/item/circuitboard/rdconsole //Stores all the collected research data. var/datum/research/files //Stores the technology disk. var/obj/item/disk/tech_disk/t_disk = null //Stores the design disk. var/obj/item/disk/design_disk/d_disk = null /// All fabrication machinery connected to this console. var/list/obj/structure/machinery/r_n_d/fabricator/linked_fabricators = list() /// Console-owned production queues. var/list/datum/research_fabrication_job/protolathe_queue = list() var/list/datum/research_fabrication_job/imprinter_queue = list() var/list/datum/research_fabrication_job/mechfab_queue = list() //Linked Destructive Analyzer var/obj/structure/machinery/r_n_d/destructive_analyzer/linked_destroy = null //Shared material storage var/obj/structure/machinery/r_n_d/material_silo/linked_silo = null var/selected_mech_manufacturer var/device_sync_range = 7 var/allow_analyzer = TRUE var/allow_lathe = TRUE var/allow_imprinter = TRUE var/allow_mechfab = TRUE var/allow_silo = TRUE //Which screen is currently showing. var/screen = 1.0 //ID of the computer (for server restrictions). var/id = 0 //If sync = 0, it doesn't show up on Server Control Console var/sync = 1 /// Number of copies to queue when adding a design. var/queue_amount = 1 /// Message displayed while a delayed console action is processing. var/busy_message = "Processing request. Please wait." var/protolathe_category = "All" var/imprinter_category = "All" var/ref_for_ui //Data and setting manipulation requires scientist access. req_access = list(ACCESS_TOX) /datum/research_fabrication_job /// Design being produced. var/datum/design/design /// Machine currently producing this job. var/obj/structure/machinery/assigned_machine /// Manufacturer selected for mech-fabricator products. var/manufacturer /// Materials removed from the silo and reserved for this job. var/list/reserved_materials = list() /datum/research_fabrication_job/New(datum/design/new_design, new_manufacturer) . = ..() design = new_design manufacturer = new_manufacturer /datum/research_fabrication_job/Destroy() design = null assigned_machine = null reserved_materials = null return ..() /obj/structure/machinery/computer/rdconsole/proc/CallMaterialName(var/ID) return SSmaterials.material_display_name(ID) /obj/structure/machinery/computer/rdconsole/proc/CallReagentName(ID) var/singleton/reagent/R = GET_SINGLETON(ID) return R ? R.name : "(none)" /obj/structure/machinery/computer/rdconsole/proc/SyncRDevices() linked_fabricators ||= list() for(var/obj/structure/machinery/r_n_d/device in range(device_sync_range, src)) if(device.panel_open) continue if(istype(device, /obj/structure/machinery/r_n_d/destructive_analyzer) && allow_analyzer) if(!linked_destroy && !device.linked_console) linked_destroy = device device.linked_console = src else if(istype(device, /obj/structure/machinery/r_n_d/material_silo) && allow_silo) if(!linked_silo && !device.linked_console) linked_silo = device device.linked_console = src else if(istype(device, /obj/structure/machinery/r_n_d/fabricator)) var/obj/structure/machinery/r_n_d/fabricator/fabricator = device if(!fabricator_type_allowed(fabricator)) continue if(fabricator.linked_console && fabricator.linked_console != src) continue fabricator.linked_console = src linked_fabricators |= fabricator cleanup_fabricators() dispatch_fabrication_jobs() return /obj/structure/machinery/computer/rdconsole/proc/fabricator_type_allowed(obj/structure/machinery/r_n_d/fabricator/fabricator) if(fabricator.build_type & PROTOLATHE) return allow_lathe if(fabricator.build_type & IMPRINTER) return allow_imprinter if(fabricator.build_type & MECHFAB) return allow_mechfab return FALSE /obj/structure/machinery/computer/rdconsole/proc/cleanup_fabricators() for(var/obj/structure/machinery/r_n_d/fabricator/fabricator as anything in linked_fabricators.Copy()) if(QDELETED(fabricator) || fabricator.linked_console != src) linked_fabricators -= fabricator /obj/structure/machinery/computer/rdconsole/proc/remove_fabricator(obj/structure/machinery/r_n_d/fabricator/fabricator) if(!fabricator) return linked_fabricators -= fabricator if(fabricator.assigned_job) fabricator.assigned_job.assigned_machine = null fabricator.assigned_job = null fabricator.current_design = null SStgui.update_uis(src) dispatch_fabrication_jobs() /obj/structure/machinery/computer/rdconsole/proc/get_fabricators(build_flag) var/list/result = list() for(var/obj/structure/machinery/r_n_d/fabricator/fabricator as anything in linked_fabricators) if(fabricator.build_type & build_flag) result += fabricator return result /obj/structure/machinery/computer/rdconsole/proc/get_primary_fabricator(build_flag) for(var/obj/structure/machinery/r_n_d/fabricator/fabricator as anything in linked_fabricators) if(fabricator.build_type & build_flag) return fabricator return null /obj/structure/machinery/computer/rdconsole/proc/disconnect_fabricators(build_flag) for(var/obj/structure/machinery/r_n_d/fabricator/fabricator as anything in linked_fabricators.Copy()) if(fabricator.build_type & build_flag) fabricator.disconnect_console() /obj/structure/machinery/computer/rdconsole/proc/SyncTechs() var/turf/turf = get_turf(src) for(var/obj/structure/machinery/r_n_d/server/S in SSmachinery.machinery) var/turf/ST = get_turf(S) if(ST && !AreConnectedZLevels(ST.z, turf.z)) continue var/server_processed = 0 if((id in S.id_with_upload) || istype(S, /obj/structure/machinery/r_n_d/server/centcom)) for(var/tech_id in files.known_tech) var/datum/tech/T = files.known_tech[tech_id] S.files.AddTech2Known(T) S.files.RefreshResearch() server_processed = 1 files.known_tech = S.files.known_tech.Copy() if(!istype(S, /obj/structure/machinery/r_n_d/server/centcom) && server_processed) S.produce_heat() screen = 1.6 updateUsrDialog() //Have it automatically push research to the centcomm server so wild griffins can't fuck up R&D's work /obj/structure/machinery/computer/rdconsole/proc/griefProtection() for(var/obj/structure/machinery/r_n_d/server/centcom/C in SSmachinery.machinery) for(var/tech_id in files.known_tech) var/datum/tech/T = files.known_tech[tech_id] C.files.AddTech2Known(files.known_tech[T]) C.files.RefreshResearch() /obj/structure/machinery/computer/rdconsole/proc/dispatch_fabrication_jobs() cleanup_fabricators() dispatch_queue_to_machines(protolathe_queue, PROTOLATHE) dispatch_queue_to_machines(imprinter_queue, IMPRINTER) dispatch_queue_to_machines(mechfab_queue, MECHFAB) SStgui.update_uis(src) /obj/structure/machinery/computer/rdconsole/proc/dispatch_queue_to_machines(list/job_queue, build_flag) if(!length(job_queue)) return for(var/datum/research_fabrication_job/job as anything in job_queue) if(job.assigned_machine) continue for(var/obj/structure/machinery/r_n_d/fabricator/fabricator as anything in linked_fabricators) if(!(fabricator.build_type & build_flag) || !fabricator.is_available()) continue if(!fabricator.can_produce_job(job)) continue if(fabricator.begin_console_job(job)) break /obj/structure/machinery/computer/rdconsole/proc/get_job_queue(build_flag) if(build_flag & PROTOLATHE) return protolathe_queue if(build_flag & IMPRINTER) return imprinter_queue if(build_flag & MECHFAB) return mechfab_queue return null /obj/structure/machinery/computer/rdconsole/proc/refund_job_materials(datum/research_fabrication_job/job) if(!job || !length(job.reserved_materials) || !linked_silo) return for(var/material_id in job.reserved_materials) SSmaterials.add_material_amount(linked_silo.materials, material_id, job.reserved_materials[material_id]) job.reserved_materials.Cut() linked_silo.update_linked_uis() /obj/structure/machinery/computer/rdconsole/proc/refund_all_queued_materials() for(var/datum/research_fabrication_job/job as anything in protolathe_queue) refund_job_materials(job) for(var/datum/research_fabrication_job/job as anything in imprinter_queue) refund_job_materials(job) for(var/datum/research_fabrication_job/job as anything in mechfab_queue) refund_job_materials(job) /obj/structure/machinery/computer/rdconsole/proc/remove_fabrication_job(list/job_queue, index) if(index < 1 || index > length(job_queue)) return FALSE var/datum/research_fabrication_job/job = job_queue[index] if(job.assigned_machine) return FALSE refund_job_materials(job) job_queue.Cut(index, index + 1) qdel(job) dispatch_fabrication_jobs() return TRUE /obj/structure/machinery/computer/rdconsole/proc/finish_fabrication_job(datum/research_fabrication_job/job) if(!job) return if(job in protolathe_queue) protolathe_queue -= job else if(job in imprinter_queue) imprinter_queue -= job else if(job in mechfab_queue) mechfab_queue -= job qdel(job) SStgui.update_uis(src) /obj/structure/machinery/computer/rdconsole/Initialize() ..() files = new /datum/research(src) //Setup the research data holder. selected_mech_manufacturer = GLOB.basic_robolimb.company if(!id) for(var/obj/structure/machinery/r_n_d/server/centcom/S in SSmachinery.machinery) S.setup() break SyncRDevices() ref_for_ui = "[REF(src)]" return INITIALIZE_HINT_LATELOAD /obj/structure/machinery/computer/rdconsole/LateInitialize() . = ..() SyncTechs() screen = 1.0 /obj/structure/machinery/computer/rdconsole/Destroy() refund_all_queued_materials() if(linked_destroy) linked_destroy.linked_console = null if(linked_silo) linked_silo.linked_console = null for(var/obj/structure/machinery/r_n_d/fabricator/fabricator as anything in linked_fabricators.Copy()) fabricator.linked_console = null linked_fabricators.Cut() return ..() /obj/structure/machinery/computer/rdconsole/attackby(obj/item/attacking_item, mob/user) //Loading a disk into it. if(istype(attacking_item, /obj/item/disk)) if(t_disk || d_disk) to_chat(user, "A disk is already loaded into the machine.") return if(istype(attacking_item, /obj/item/disk/tech_disk)) t_disk = attacking_item else if (istype(attacking_item, /obj/item/disk/design_disk)) d_disk = attacking_item else to_chat(user, SPAN_NOTICE("Machine cannot accept disks in that format.")) return user.drop_from_inventory(attacking_item, src) to_chat(user, SPAN_NOTICE("You add \the [attacking_item] to the machine.")) else //The construction/deconstruction of the console code. ..() SStgui.update_uis(src) return /obj/structure/machinery/computer/rdconsole/emag_act(remaining_charges, mob/user, emag_source) . = ..() if(!emagged) playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1) emagged = 1 to_chat(usr, SPAN_NOTICE("You disable the security protocols.")) return 1 /obj/structure/machinery/computer/rdconsole/proc/GetResearchLevelsInfo() var/dat dat += "