From a56d3ac51b2e0b00fe3464aa21389063658e1a3f Mon Sep 17 00:00:00 2001 From: MrCastmer <125900379+MrCastmer@users.noreply.github.com> Date: Thu, 22 Feb 2024 17:50:22 +0300 Subject: [PATCH] Spacepod Fabricator (#16) * Spacepod Fabricator * Update protolathe.dm --------- Co-authored-by: Blundir <100090741+Blundir@users.noreply.github.com> --- code/modules/research/machinery/protolathe.dm | 2 +- code/modules/research/machinery/techfab.dm | 2 +- .../code/game/machinery/pod_fabricator.dm | 756 ++++++++++++++++++ .../modules/research/techweb/all_nodes.dm | 5 + modular_dripstation/includes.dm | 2 + .../tgui/interfaces/ExosuitFabricator.js | 2 +- .../research/designs/spacepod_designs.dm | 28 +- 7 files changed, 793 insertions(+), 4 deletions(-) create mode 100644 modular_dripstation/code/game/machinery/pod_fabricator.dm create mode 100644 modular_dripstation/code/modules/research/techweb/all_nodes.dm diff --git a/code/modules/research/machinery/protolathe.dm b/code/modules/research/machinery/protolathe.dm index 5f5847cc2a5c..ff2327ff62bd 100644 --- a/code/modules/research/machinery/protolathe.dm +++ b/code/modules/research/machinery/protolathe.dm @@ -16,7 +16,7 @@ "Ammo", "Firing Pins", "Computer Parts", - "Spacepod Designs", // yoggers + //"Spacepod Designs", // dripstation spacepod move to new fab "Service", "Assemblies" ) diff --git a/code/modules/research/machinery/techfab.dm b/code/modules/research/machinery/techfab.dm index 1289ebcde85e..ed5a8c105eef 100644 --- a/code/modules/research/machinery/techfab.dm +++ b/code/modules/research/machinery/techfab.dm @@ -27,7 +27,7 @@ "Research Machinery", "Misc. Machinery", "Computer Parts", - "Spacepod Designs", // yogs + //"Spacepod Designs", // dripstation edit "Service" //yogs ) console_link = FALSE diff --git a/modular_dripstation/code/game/machinery/pod_fabricator.dm b/modular_dripstation/code/game/machinery/pod_fabricator.dm new file mode 100644 index 000000000000..e6c9bd0f4154 --- /dev/null +++ b/modular_dripstation/code/game/machinery/pod_fabricator.dm @@ -0,0 +1,756 @@ +/obj/item/circuitboard/machine/pod_fab + name = "Space Pod Fabricator (Machine Board)" + icon_state = "science" + build_path = /obj/machinery/pod_fabricator + req_components = list( + /obj/item/stock_parts/matter_bin = 2, + /obj/item/stock_parts/manipulator = 1, + /obj/item/stock_parts/micro_laser = 1, + /obj/item/stack/sheet/glass = 1) + +/datum/design/board/podfab + name = "Machine Design (Space Pod Fabricator Board)" + desc = "The circuit board for an Space Pod Fabricator." + id = "podfab" + build_path = /obj/machinery/pod_fabricator + category = list("Research Machinery") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE + +/datum/wires/tesla_coil + proper_name = "Spacepod Fabricator" + randomize = TRUE //Only one wire don't need blueprints + holder_type = /obj/machinery/pod_fabricator + +/obj/machinery/pod_fabricator + icon = 'icons/obj/robotics.dmi' + icon_state = "fab-idle" + name = "spacepod fabricator" + desc = "Nothing is being built." + density = TRUE + use_power = IDLE_POWER_USE + idle_power_usage = 20 + active_power_usage = 5000 + + req_access = list(ACCESS_SECURE_TECH_STORAGE) //place mechanic access here + var/hacked = FALSE + ///World ticks the machine is electified for + var/seconds_electrified = MACHINE_NOT_ELECTRIFIED + + + circuit = /obj/item/circuitboard/machine/pod_fab + subsystem_type = /datum/controller/subsystem/processing/fastprocess + /// Controls whether or not the more dangerous designs have been unlocked by a head's id manually, rather than alert level unlocks + var/authorization_override = FALSE + /// ID card of the person using the machine for the purpose of tracking access + var/obj/item/card/id/id_card = new() + /// Current items in the build queue. + var/list/queue = list() + /// Whether or not the machine is building the entire queue automagically. + var/process_queue = FALSE + + /// The current design datum that the machine is building. + var/datum/design/being_built + /// World time when the build will finish. + var/build_finish = 0 + /// World time when the build started. + var/build_start = 0 + /// Reference to all materials used in the creation of the item being_built. + var/list/build_materials + /// Part currently stored in the Exofab. + var/obj/item/stored_part + + /// Coefficient for the speed of item building. Based on the installed parts. + var/time_coeff = 1 + /// Coefficient for the efficiency of material usage in item building. Based on the installed parts. + var/component_coeff = 1 + + /// Reference to the techweb. + var/datum/techweb/stored_research + + /// Whether the Exofab links to the ore silo on init. Special derelict or maintanance variants should set this to FALSE. + var/link_on_init = TRUE + + /// Reference to a remote material inventory, such as an ore silo. + var/datum/component/remote_materials/rmat + + /// A list of categories that valid pod fab design datums will broadly categorise themselves under. + var/list/part_sets = list( + "Spacepod Designs", + "Shuttle Machinery", + "Misc" + ) + +/obj/machinery/pod_fabricator/Initialize(mapload) + stored_research = SSresearch.science_tech + rmat = AddComponent(/datum/component/remote_materials, "mechfab", mapload && link_on_init) + RefreshParts() //Recalculating local material sizes if the fab isn't linked + wires = new /datum/wires/mecha_part_fabricator(src) + return ..() + +/obj/machinery/pod_fabricator/Destroy() + QDEL_NULL(wires) + return ..() + +/obj/machinery/pod_fabricator/RefreshParts() + var/T = 0 + + //maximum stocking amount (default 300000, 600000 at T4) + for(var/obj/item/stock_parts/matter_bin/M in component_parts) + T += M.rating + rmat.set_local_size((200000 + (T*50000))) + + //resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55) + T = 1.15 + for(var/obj/item/stock_parts/micro_laser/Ma in component_parts) + T -= Ma.rating*0.15 + component_coeff = T + + //building time adjustment coefficient (1 -> 0.8 -> 0.6) + T = -1 + for(var/obj/item/stock_parts/manipulator/Ml in component_parts) + T += Ml.rating + time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) + + // Adjust the build time of any item currently being built. + if(being_built) + var/last_const_time = build_finish - build_start + var/new_const_time = get_construction_time_w_coeff(initial(being_built.construction_time)) + var/const_time_left = build_finish - world.time + var/new_build_time = (new_const_time / last_const_time) * const_time_left + build_finish = world.time + new_build_time + + update_static_data(usr) + +/obj/machinery/pod_fabricator/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += span_notice("The status display reads: Storing up to [rmat.local_size] material units.
Material consumption at [component_coeff*100]%.
Build time reduced by [100-time_coeff*100]%.") + +/obj/machinery/pod_fabricator/attackby(obj/item/I, mob/living/user, params) + if(panel_open && is_wire_tool(I)) + wires.interact(user) + return TRUE + if(I.GetID()) + var/obj/item/card/id/C = I.GetID() + if(obj_flags & EMAGGED) + to_chat(user, span_warning("The authentication slot spits sparks at you and the display reads scrambled text!")) + do_sparks(1, FALSE, src) + authorization_override = TRUE //just in case it wasn't already for some reason. keycard reader is busted. + return + if(ACCESS_HEADS in C.access) + if(!authorization_override) + authorization_override = TRUE + to_chat(user, span_warning("You override the safety protocols on the [src], removing access restrictions from this terminal.")) + else + authorization_override = FALSE + to_chat(user, span_notice("You reengage the safety protocols on the [src], restoring access restrictions to this terminal.")) + update_static_data(user) + return + return ..() +/** + * All the negative wire effects + * Break wire breaks one limb (Because pain is to be had) +*/ +/obj/machinery/pod_fabricator/_try_interact(mob/user) + if(seconds_electrified && !(stat & NOPOWER)) + if(shock(user, 100)) + return + return ..() + +/obj/machinery/pod_fabricator/proc/wire_break(mob/user) + if(stat & (BROKEN|NOPOWER)) + return FALSE + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(5, 1, src) + s.start() + var/mob/living/carbon/C = user + var/datum/wound/blunt/severe/break_it = new + ///Picks limb to break. People with less limbs have a chance of it grapping at air + var/obj/item/bodypart/bone = C.get_bodypart(pick(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) + if(bone && Adjacent(user)) + to_chat(C,span_userdanger("The manipulator arms grapple after your [bone.name], attempting to break its bone!")) + break_it.apply_wound(bone) + bone.receive_damage(brute=50, updating_health=TRUE) + else + to_chat(C,span_userdanger("The manipulator arms attempt to grab one of your limbs, but grapple air instead!")) + qdel(break_it) + +/obj/machinery/pod_fabricator/proc/reset(wire) + switch(wire) + if(WIRE_HACK) + if(!wires.is_cut(wire)) + hacked = FALSE +/** + * Shock the passed in user + * + * This checks we have power and that the passed in prob is passed, then generates some sparks + * and calls electrocute_mob on the user + * + * Arguments: + * * user - the user to shock + * * prb - probability the shock happens + */ +/obj/machinery/pod_fabricator/proc/shock(mob/user, prb) + if(stat & (BROKEN|NOPOWER)) // unpowered, no shock + return FALSE + if(!prob(prb)) + return FALSE + do_sparks(5, TRUE, src) + var/check_range = TRUE + if(electrocute_mob(user, get_area(src), src, 0.7, check_range)) + return TRUE + else + return FALSE +/** + * Generates an info list for a given part. + * + * Returns a list of part information. + * * D - Design datum to get information on. + * * categories - Boolean, whether or not to parse snowflake categories into the part information list. + */ + +/obj/machinery/pod_fabricator/proc/output_part_info(datum/design/D, categories = FALSE) + var/cost = list() + for(var/c in D.materials) + var/datum/material/M = c + cost[M.name] = get_resource_cost_w_coeff(D, M) + + var/obj/built_item = D.build_path + + var/list/sub_category = null + + if(categories) + var/module_types = D.departmental_flags + sub_category = list() + if(D.category == "Spacepod Designs" && module_types) + if(module_types & DEPARTMENTAL_FLAG_SECURITY) + sub_category += "Security" + if(module_types & DEPARTMENTAL_FLAG_CARGO) + sub_category += "Cargo" + if(module_types & DEPARTMENTAL_FLAG_SCIENCE) + sub_category += "Science" + if(module_types & DEPARTMENTAL_FLAG_ALL) + sub_category += "Civilian" + else + sub_category = "Equipment" + + var/list/part = list( + "name" = D.name, + "desc" = initial(built_item.desc), + "printTime" = get_construction_time_w_coeff(initial(D.construction_time))/10, + "cost" = cost, + "id" = D.id, + "subCategory" = sub_category, + "searchMeta" = D.search_metadata + ) + + return part + +/** + * Generates a list of resources / materials available to this Exosuit Fab + * + * Returns null if there is no material container available. + * List format is list(material_name = list(amount = ..., ref = ..., etc.)) + */ +/obj/machinery/pod_fabricator/proc/output_available_resources() + var/datum/component/material_container/materials = rmat.mat_container + + var/list/material_data = list() + + if(materials) + for(var/mat_id in materials.materials) + var/datum/material/M = mat_id + var/list/material_info = list() + var/amount = materials.materials[mat_id] + + material_info = list( + "name" = M.name, + "ref" = REF(M), + "amount" = amount, + "sheets" = round(amount / MINERAL_MATERIAL_AMOUNT), + "removable" = amount >= MINERAL_MATERIAL_AMOUNT + ) + + material_data += list(material_info) + + return material_data + + return null + +/** + * Intended to be called when an item starts printing. + * + * Adds the overlay to show the fab working and sets active power usage settings. + */ +/obj/machinery/pod_fabricator/proc/on_start_printing() + add_overlay("fab-active") + use_power = ACTIVE_POWER_USE + +/** + * Intended to be called when the exofab has stopped working and is no longer printing items. + * + * Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing. + */ +/obj/machinery/pod_fabricator/proc/on_finish_printing() + cut_overlay("fab-active") + use_power = IDLE_POWER_USE + desc = initial(desc) + process_queue = FALSE + +/** + * Calculates resource/material costs for printing an item based on the machine's resource coefficient. + * + * Returns a list of k,v resources with their amounts. + * * D - Design datum to calculate the modified resource cost of. + */ +/obj/machinery/pod_fabricator/proc/get_resources_w_coeff(datum/design/D) + var/list/resources = list() + for(var/R in D.materials) + var/datum/material/M = R + resources[M] = get_resource_cost_w_coeff(D, M) + return resources + +/** + * Checks if the Exofab has enough resources to print a given item. + * + * Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources. + * Returns TRUE if there are sufficient resources to print the item. + * * D - Design datum to calculate the modified resource cost of. + */ +/obj/machinery/pod_fabricator/proc/check_resources(datum/design/D) + if(length(D.reagents_list)) // No reagents storage - no reagent designs. + return FALSE + var/datum/component/material_container/materials = rmat.mat_container + if(materials.has_materials(get_resources_w_coeff(D))) + return TRUE + return FALSE + +/** + * Attempts to build the next item in the build queue. + * + * Returns FALSE if either there are no more parts to build or the next part is not buildable. + * Returns TRUE if the next part has started building. + * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. + */ +/obj/machinery/pod_fabricator/proc/build_next_in_queue(verbose = TRUE) + if(!length(queue)) + return FALSE + + var/datum/design/D = queue[1] + if(build_part(D, verbose)) + remove_from_queue(1) + return TRUE + + return FALSE + +/** + * Starts the build process for a given design datum. + * + * Returns FALSE if the procedure fails. Returns TRUE when being_built is set. + * Uses materials. + * * D - Design datum to attempt to print. + * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. + */ +/obj/machinery/pod_fabricator/proc/build_part(datum/design/D, verbose = TRUE) + if(!D) + return FALSE + + var/datum/component/material_container/materials = rmat.mat_container + if (!materials) + if(verbose) + say("No access to material storage, please contact the quartermaster.") + return FALSE + if (rmat.on_hold()) + if(verbose) + say("Mineral access is on hold, please contact the quartermaster.") + return FALSE + if(!check_resources(D)) + if(verbose) + say("Not enough resources. Processing stopped.") + return FALSE + + build_materials = get_resources_w_coeff(D) + + materials.use_materials(build_materials) + being_built = D + build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time)) + build_start = world.time + desc = "It's building \a [D.name]." + + rmat.silo_log(src, "built", -1, "[D.name]", build_materials) + + return TRUE + +/obj/machinery/pod_fabricator/process() + // Deelectrifies the machine + if(seconds_electrified > MACHINE_NOT_ELECTRIFIED) + seconds_electrified-- + + // If there's a stored part to dispense due to an obstruction, try to dispense it. + if(stored_part) + var/turf/exit = get_step(src,(dir)) + if(exit.density) + return TRUE + + say("Obstruction cleared. \The [stored_part] is complete.") + stored_part.forceMove(exit) + stored_part = null + + // If there's nothing being built, try to build something + if(!being_built) + // If we're not processing the queue anymore or there's nothing to build, end processing. + if(!process_queue || !build_next_in_queue()) + on_finish_printing() + end_processing() + return TRUE + on_start_printing() + + // If there's an item being built, check if it is complete. + if(being_built && (build_finish < world.time)) + // Then attempt to dispense it and if appropriate build the next item. + dispense_built_part(being_built) + if(process_queue) + build_next_in_queue(FALSE) + return TRUE + + +/** + * Dispenses a part to the tile infront of the Exosuit Fab. + * + * Returns FALSE is the machine cannot dispense the part on the appropriate turf. + * Return TRUE if the part was successfully dispensed. + * * D - Design datum to attempt to dispense. + */ +/obj/machinery/pod_fabricator/proc/dispense_built_part(datum/design/D) + var/obj/item/I = new D.build_path(src) + //I.set_custom_materials(build_materials) + being_built = null + + var/turf/exit = get_step(src,(dir)) + if(exit.density) + say("Error! Part outlet is obstructed.") + desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed." + stored_part = I + return FALSE + + say("\The [I] is complete.") + I.forceMove(exit) + return TRUE + +/** + * Adds a list of datum designs to the build queue. + * + * Will only add designs that are in this machine's stored techweb. + * Does final checks for datum IDs and makes sure this machine can build the designs. + * * part_list - List of datum design ids for designs to add to the queue. + */ +/obj/machinery/pod_fabricator/proc/add_part_set_to_queue(list/part_list, mob/user) + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if((D.id in part_list) && (!D.combat_design || combat_parts_allowed(user))) + add_to_queue(D, user) + +/** + * Adds a datum design to the build queue. + * + * Returns TRUE if successful and FALSE if the design was not added to the queue. + * * D - Datum design to add to the queue. + */ +/obj/machinery/pod_fabricator/proc/add_to_queue(datum/design/D, mob/user) + if(D.combat_design && !combat_parts_allowed(user)) + return FALSE + if(!istype(queue)) + queue = list() + if(D) + queue[++queue.len] = D + return TRUE + return FALSE + +/** + * Removes datum design from the build queue based on index. + * + * Returns TRUE if successful and FALSE if a design was not removed from the queue. + * * index - Index in the build queue of the element to remove. + */ +/obj/machinery/pod_fabricator/proc/remove_from_queue(index) + if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue))) + return FALSE + queue.Cut(index,++index) + return TRUE + +/** + * Generates a list of parts formatted for tgui based on the current build queue. + * + * Returns a formatted list of lists containing formatted part information for every part in the build queue. + */ +/obj/machinery/pod_fabricator/proc/list_queue() + if(!istype(queue) || !length(queue)) + return null + + var/list/queued_parts = list() + for(var/datum/design/D in queue) + var/list/part = output_part_info(D) + queued_parts += list(part) + return queued_parts + +/** + * Calculates the coefficient-modified resource cost of a single material component of a design's recipe. + * + * Returns coefficient-modified resource cost for the given material component. + * * D - Design datum to pull the resource cost from. + * * resource - Material datum reference to the resource to calculate the cost of. + * * roundto - Rounding value for round() proc + */ +/obj/machinery/pod_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, datum/material/resource, roundto = 1) + return round(D.materials[resource]*component_coeff, roundto) + +/** + * Calculates the coefficient-modified build time of a design. + * + * Returns coefficient-modified build time of a given design. + * * D - Design datum to calculate the modified build time of. + * * roundto - Rounding value for round() proc + */ +/obj/machinery/pod_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran + return round(construction_time*time_coeff, roundto) + +/obj/machinery/pod_fabricator/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/sheetmaterials) + ) + +/obj/machinery/pod_fabricator/ui_status(mob/user) + if(stat & BROKEN || panel_open) + return UI_CLOSE + return ..() + +/obj/machinery/pod_fabricator/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ExosuitFabricator") + ui.open() + +/obj/machinery/pod_fabricator/ui_static_data(mob/user) + var/list/data = list() + + var/list/final_sets = part_sets.Copy() + var/list/buildable_parts = list() + + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if(D.combat_design && !combat_parts_allowed(user)) // Yogs -- ID swiping for combat parts + continue + // This is for us. + var/list/part = output_part_info(D, TRUE) + for(var/cat in part_sets) + // Find all matching categories. + if(!(cat in D.category)) + continue + buildable_parts[cat] += list(part) + data["partSets"] = final_sets + data["buildableParts"] = buildable_parts + + return data + +/obj/machinery/pod_fabricator/ui_data(mob/user) + var/list/data = list() + data["materials"] = output_available_resources() + + if(being_built) + var/list/part = list( + "name" = being_built.name, + "duration" = build_finish - world.time, + "printTime" = get_construction_time_w_coeff(initial(being_built.construction_time)) + ) + data["buildingPart"] = part + else + data["buildingPart"] = null + + data["queue"] = list_queue() + + if(stored_part) + data["storedPart"] = stored_part.name + else + data["storedPart"] = null + + data["isProcessingQueue"] = process_queue + data["authorization"] = authorization_override + data["user_clearance"] = head_or_silicon(user) + data["alert_level"] = GLOB.security_level + data["combat_parts_allowed"] = combat_parts_allowed(user) + data["emagged"] = (obj_flags & EMAGGED) + data["silicon_user"] = issilicon(user) + + return data + +/// Updates the various authorization checks used to determine if combat parts are available to the current user +/obj/machinery/pod_fabricator/proc/combat_parts_allowed(mob/user) + return authorization_override || GLOB.security_level >= SEC_LEVEL_RED || head_or_silicon(user) + +/// made as a lazy check to allow silicons full access always +/obj/machinery/pod_fabricator/proc/head_or_silicon(mob/user) + if(issilicon(user)) + return TRUE + id_card = user.get_idcard(hand_first = TRUE) + return ACCESS_HEADS in id_card?.access + +/obj/machinery/pod_fabricator/ui_act(action, list/params) + . = ..() + if(.) + return + + . = TRUE + + add_fingerprint(usr) + usr.set_machine(src) + + switch(action) + if("sync_rnd") + // Syncronises designs on interface with R&D techweb. + update_static_data(usr) + say("Successfully synchronized with R&D server.") + return + if("add_queue_set") + // Add all parts of a set to queue + var/part_list = params["part_list"] + add_part_set_to_queue(part_list, usr) + return + if("add_queue_part") + // Add a specific part to queue + var/T = params["id"] + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if((D.id == T)) + add_to_queue(D, usr) + break + return + if("del_queue_part") + // Delete a specific from from the queue + var/index = text2num(params["index"]) + remove_from_queue(index) + return + if("clear_queue") + // Delete everything from queue + queue.Cut() + return + if("build_queue") + // Build everything in queue + if(process_queue) + return + process_queue = TRUE + + if(!being_built) + begin_processing() + return + if("stop_queue") + // Pause queue building. Also known as stop. + process_queue = FALSE + return + if("build_part") + // Build a single part + if(being_built || process_queue) + return + + var/id = params["id"] + var/datum/design/D = SSresearch.techweb_design_by_id(id) + + if(!(D.id == id)) + return + + if(build_part(D)) + on_start_printing() + begin_processing() + + return + if("move_queue_part") + // Moves a part up or down in the queue. + var/index = text2num(params["index"]) + var/new_index = index + text2num(params["newindex"]) + if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index)) + if(ISINRANGE(new_index,1,length(queue))) + queue.Swap(index,new_index) + return + if("remove_mat") + // Remove a material from the fab + var/mat_ref = params["ref"] + var/amount = text2num(params["amount"]) + var/datum/material/mat = locate(mat_ref) + eject_sheets(mat, amount) + return + + return FALSE + +/** + * Eject material sheets. + * + * Returns the number of sheets successfully ejected. + * eject_sheet - Byond REF of the material to eject. + * eject_amt - Number of sheets to attempt to eject. + */ +/obj/machinery/pod_fabricator/proc/eject_sheets(eject_sheet, eject_amt) + var/datum/component/material_container/mat_container = rmat.mat_container + if (!mat_container) + say("No access to material storage, please contact the quartermaster.") + return 0 + if (rmat.on_hold()) + say("Mineral access is on hold, please contact the quartermaster.") + return 0 + var/count = mat_container.retrieve_sheets(text2num(eject_amt), eject_sheet, drop_location()) + var/list/matlist = list() + matlist[eject_sheet] = text2num(eject_amt) + rmat.silo_log(src, "ejected", -count, "sheets", matlist) + return count + +/obj/machinery/pod_fabricator/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted) + var/datum/material/M = id_inserted + add_overlay("fab-load-[M.name]") + addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[M.name]"), 10) + +/obj/machinery/pod_fabricator/screwdriver_act(mob/living/user, obj/item/I) + if(..()) + return TRUE + if(being_built) + to_chat(user, span_warning("\The [src] is currently processing! Please wait until completion.")) + return FALSE + return default_deconstruction_screwdriver(user, "fab-o", "fab-idle", I) + +/obj/machinery/pod_fabricator/crowbar_act(mob/living/user, obj/item/I) + if(..()) + return TRUE + if(being_built) + to_chat(user, span_warning("\The [src] is currently processing! Please wait until completion.")) + return FALSE + return default_deconstruction_crowbar(I) + +/obj/machinery/pod_fabricator/proc/is_insertion_ready(mob/user) + if(panel_open) + to_chat(user, span_warning("You can't load [src] while it's panel is opened!")) + return FALSE + if(being_built) + to_chat(user, span_warning("\The [src] is currently processing! Please wait until completion.")) + return FALSE + return TRUE + +/obj/machinery/pod_fabricator/emag_act(mob/user, obj/item/card/emag/emag_card) + if(obj_flags & EMAGGED) + to_chat(user, span_warning("[src] has no functional safeties to emag.")) + return FALSE + do_sparks(1, FALSE, src) + to_chat(user, span_notice("You short out [src]'s safeties.")) + authorization_override = TRUE + obj_flags |= EMAGGED + update_static_data(user) + return TRUE + + +/obj/machinery/pod_fabricator/maint + link_on_init = FALSE + +/obj/machinery/pod_fabricator/ruin + link_on_init = FALSE + authorization_override = TRUE + hacked = TRUE + +/obj/machinery/pod_fabricator/ruin/Initialize(mapload) + . = ..() + stored_research = SSresearch.ruin_tech diff --git a/modular_dripstation/code/modules/research/techweb/all_nodes.dm b/modular_dripstation/code/modules/research/techweb/all_nodes.dm new file mode 100644 index 000000000000..af3fe10c67c6 --- /dev/null +++ b/modular_dripstation/code/modules/research/techweb/all_nodes.dm @@ -0,0 +1,5 @@ +/datum/techweb_node/base //BASE NODES OVERRIDE! + design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", "desttagger", "handlabel", "packagewrap", + "destructive_analyzer", "circuit_imprinter", "rack_creator", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "podfab", "paystand", "ticket_machine", "ticket_remote", "light_tube", "light_bulb", + "space_heater", "beaker", "large_beaker", "vial", "bucket", "fork", "tray","plate", "bowl", "mixing_bowl", "drinking_glass", "shot_glass", "shaker", "xlarge_beaker", "sec_rshot", "sec_beanbag_slug", "sec_bshot", "sec_slug", "sec_Islug", "sec_Brslug", "sec_38", "sec_38_lethal", "apc_control", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "blastdoorcontroller", "aac_electronics", "mousetrap", + "rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass","wallframe/flasher", "rsf", "rls", "oven_tray", "bounced_radio", "signaler", "signalbutton", "inspector_booth", "intercom_frame", "infrared_emitter", "health_sensor", "timer", "voice_analyser", "camera_assembly", "newscaster_frame", "prox_sensor", "flashlight", "extinguisher", "pocketfireextinguisher") diff --git a/modular_dripstation/includes.dm b/modular_dripstation/includes.dm index 6bcd39c21a97..e4964aa060fb 100644 --- a/modular_dripstation/includes.dm +++ b/modular_dripstation/includes.dm @@ -106,6 +106,8 @@ #include "code\game\turfs\simulated\floor.dm" #include "code\game\turfs\open.dm" #include "code\game\mecha\mech_bay.dm" +#include "code\modules\research\techweb\all_nodes.dm" +#include "code\game\machinery\pod_fabricator.dm" #include "code\game\objects\effects\contraband.dm" #include "code\game\objects\structures\artstuff.dm" #include "code\game\objects\structures\bedsheet_bin.dm" diff --git a/tgui/packages/tgui/interfaces/ExosuitFabricator.js b/tgui/packages/tgui/interfaces/ExosuitFabricator.js index a9c55184145c..8d37e53e4822 100644 --- a/tgui/packages/tgui/interfaces/ExosuitFabricator.js +++ b/tgui/packages/tgui/interfaces/ExosuitFabricator.js @@ -146,7 +146,7 @@ export const ExosuitFabricator = (props, context) => { return (