mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-28 23:51:17 +01:00
Upgrades the research console to TGUI and adds the material silo (#22987)
This updates the research console to be a TGUI and fixes several bugs with it. It now uses a material silo for materials, while the acid for the circuit imprinter is still given directly to the machine. Mech fabricators now also need to be linked to a research console. It is also capable of connecting to multiple fabricators and distribute tasks between them. The sprite originates from TG station. Unit tests were also made to ensure there is no fabricators missing consoles and no console missing material silos. <img width="1200" height="800" alt="image" src="https://github.com/user-attachments/assets/b2076036-18e5-4518-9af1-3ac3698b3924" /> <img width="1200" height="800" alt="image" src="https://github.com/user-attachments/assets/e954e1e4-cf2d-4472-8386-10d8993ac375" /> <img width="1200" height="800" alt="image" src="https://github.com/user-attachments/assets/df690b93-c7ff-49a3-a1b3-002f6807981b" /> <img width="1200" height="800" alt="image" src="https://github.com/user-attachments/assets/ff10ef88-e1d9-4b6f-9643-309d919a601f" />
This commit is contained in:
@@ -315,9 +315,9 @@
|
||||
else if(istype(input_device,/obj/structure/machinery/r_n_d/server))
|
||||
var/obj/structure/machinery/r_n_d/server/input_machine = input_device
|
||||
incoming_files = input_machine.files
|
||||
else if(istype(input_device,/obj/structure/machinery/mecha_part_fabricator))
|
||||
var/obj/structure/machinery/mecha_part_fabricator/input_machine = input_device
|
||||
incoming_files = input_machine.files
|
||||
else if(istype(input_device, /obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator))
|
||||
var/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/input_mechfab = input_device
|
||||
incoming_files = input_mechfab.linked_console?.files
|
||||
|
||||
if(!incoming_files || !incoming_files.known_tech || !incoming_files.known_tech.len)
|
||||
to_chat(user, SPAN_WARNING("Memory failure. There is nothing accessible stored on this terminal."))
|
||||
|
||||
@@ -752,7 +752,7 @@ var/list/worths = list(
|
||||
/obj/structure/machinery/conveyor_switch = 10,
|
||||
/obj/structure/machinery/disposal = 50,
|
||||
/obj/structure/machinery/blackbox_recorder = -950,
|
||||
/obj/structure/machinery/r_n_d/protolathe = -1500,
|
||||
/obj/structure/machinery/r_n_d/fabricator/protolathe = -1500,
|
||||
/obj/structure/machinery/r_n_d/server = -2000,
|
||||
/obj/structure/machinery/r_n_d = -100,
|
||||
/obj/structure/machinery/auto_cloner = -1300,
|
||||
|
||||
@@ -1,82 +1,47 @@
|
||||
/*///////////////Circuit Imprinter (By Darem)////////////////////////
|
||||
Used to print new circuit boards (for computers and similar systems) and AI modules. Each circuit board pattern are stored in
|
||||
a /datum/desgin on the linked R&D console. You can then print them out in a fasion similar to a regular lathe. However, instead of
|
||||
using metal and glass, it uses glass and reagents (usually sulphuric acid).
|
||||
Used to print new circuit boards (for computers and similar systems) and AI modules.
|
||||
*/
|
||||
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter
|
||||
/obj/structure/machinery/r_n_d/fabricator/circuit_imprinter
|
||||
name = "circuit imprinter"
|
||||
desc = "An advanced device that can only be operated via a nearby RnD console, it can print any circuitboard the user requests, provided it has the correct materials to do so."
|
||||
icon_state = "circuit_imprinter"
|
||||
atom_flags = ATOM_FLAG_OPEN_CONTAINER
|
||||
|
||||
idle_power_usage = 30
|
||||
active_power_usage = 2500
|
||||
|
||||
build_type = IMPRINTER
|
||||
uses_reagents = TRUE
|
||||
fabrication_loop_type = /datum/looping_sound/synth_fab
|
||||
component_types = list(
|
||||
/obj/item/circuitboard/circuit_imprinter,
|
||||
/obj/item/stock_parts/matter_bin,
|
||||
/obj/item/stock_parts/manipulator,
|
||||
/obj/item/reagent_containers/glass/beaker = 2
|
||||
)
|
||||
|
||||
var/max_material_storage = 75000
|
||||
var/list/materials = list(MATERIAL_STEEL = 0, MATERIAL_GLASS = 0, MATERIAL_GOLD = 0, MATERIAL_SILVER = 0, MATERIAL_PHORON = 0, MATERIAL_URANIUM = 0, MATERIAL_DIAMOND = 0)
|
||||
|
||||
/**
|
||||
* A `/list` of enqueued `/datum/design` to be printed, processed in the queue
|
||||
*/
|
||||
var/list/datum/design/queue = list()
|
||||
|
||||
/**
|
||||
* How much efficient (or inefficient) the circuit imprinter is at manufacturing circuit boards
|
||||
*/
|
||||
var/mat_efficiency = 1
|
||||
|
||||
/**
|
||||
* The production speed of this specific circuit imprinter, a factor
|
||||
*/
|
||||
var/production_speed = 1
|
||||
|
||||
///Boolean, if to make the printer spawn its product in a neighboring turf dictated by dir
|
||||
var/product_offset = FALSE
|
||||
|
||||
///The timer id for the build callback, if we're building something
|
||||
var/build_callback_timer
|
||||
|
||||
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/upgrade_hints(mob/user, distance, is_adjacent)
|
||||
/obj/structure/machinery/r_n_d/fabricator/circuit_imprinter/upgrade_hints(mob/user, distance, is_adjacent)
|
||||
. += ..()
|
||||
. += "- Upgraded <b>matter bins</b> will increase material storage capacity."
|
||||
. += SPAN_NOTICE(" - The current storage capacity is <b>[max_material_storage / 2000]</b> sheets")
|
||||
. += "- Materials are drawn from the research material silo linked to the same R&D console."
|
||||
. += "- Upgraded <b>manipulators</b> will improve material use efficiency and increase fabrication speed."
|
||||
. += SPAN_NOTICE(" - The current speed increase is <b>[round((1 - (1 / production_speed)) * 100)]%</b>")
|
||||
. += SPAN_NOTICE(" - The current cost reduction is <b>[round((1 - mat_efficiency) * 100)]%</b>")
|
||||
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/RefreshParts()
|
||||
/obj/structure/machinery/r_n_d/fabricator/circuit_imprinter/RefreshParts()
|
||||
..()
|
||||
// Adjust reagent container volume to match combined volume of the inserted beakers
|
||||
var/T = 0
|
||||
for(var/obj/item/reagent_containers/glass/G in component_parts)
|
||||
T += G.reagents.maximum_volume
|
||||
create_reagents(T)
|
||||
// Transfer all reagents from the beakers to internal reagent container
|
||||
for(var/obj/item/reagent_containers/glass/G in component_parts)
|
||||
G.reagents.trans_to_obj(src, G.reagents.total_volume)
|
||||
var/total_volume = 0
|
||||
for(var/obj/item/reagent_containers/glass/beaker in component_parts)
|
||||
total_volume += beaker.reagents.maximum_volume
|
||||
create_reagents(total_volume)
|
||||
for(var/obj/item/reagent_containers/glass/beaker in component_parts)
|
||||
beaker.reagents.trans_to_obj(src, beaker.reagents.total_volume)
|
||||
|
||||
// Adjust material storage capacity to scale with matter bin rating
|
||||
max_material_storage = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
|
||||
max_material_storage += M.rating * 75000
|
||||
var/manipulator_rating = 0
|
||||
for(var/obj/item/stock_parts/manipulator/manipulator in component_parts)
|
||||
manipulator_rating += manipulator.rating
|
||||
mat_efficiency = 1 - (manipulator_rating - 1) / 8
|
||||
production_speed = manipulator_rating
|
||||
update_icon()
|
||||
|
||||
// Adjust production speed to increase with manipulator rating
|
||||
T = 0
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
T += M.rating
|
||||
mat_efficiency = 1 - (T - 1) / 4
|
||||
production_speed = T
|
||||
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/update_icon()
|
||||
/obj/structure/machinery/r_n_d/fabricator/circuit_imprinter/update_icon()
|
||||
if(panel_open)
|
||||
icon_state = "circuit_imprinter_t"
|
||||
else if(build_callback_timer)
|
||||
@@ -84,240 +49,11 @@ using metal and glass, it uses glass and reagents (usually sulphuric acid).
|
||||
else
|
||||
icon_state = "circuit_imprinter"
|
||||
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/proc/TotalMaterials()
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
var/t = 0
|
||||
for(var/f in materials)
|
||||
t += materials[f]
|
||||
return t
|
||||
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/dismantle()
|
||||
for(var/obj/I in component_parts)
|
||||
// This will distribute all reagents amongst the contained beakers
|
||||
if(istype(I, /obj/item/reagent_containers/glass/beaker))
|
||||
reagents.trans_to_obj(I, reagents.total_volume)
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/f in materials)
|
||||
if(materials[f] >= SHEET_MATERIAL_AMOUNT)
|
||||
var/path = getMaterialType(f)
|
||||
if(path)
|
||||
var/obj/item/stack/S = new path(loc)
|
||||
S.amount = round(materials[f] / SHEET_MATERIAL_AMOUNT)
|
||||
/obj/structure/machinery/r_n_d/fabricator/circuit_imprinter/dismantle()
|
||||
for(var/obj/item/reagent_containers/glass/beaker in component_parts)
|
||||
reagents.trans_to_obj(beaker, reagents.total_volume)
|
||||
..()
|
||||
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/attackby(obj/item/attacking_item, mob/user)
|
||||
//No touch the machine while it's working!
|
||||
if(build_callback_timer)
|
||||
to_chat(user, SPAN_NOTICE("\The [src] is busy. Please wait for completion of previous operation."))
|
||||
return 1
|
||||
|
||||
if(default_deconstruction_screwdriver(user, attacking_item))
|
||||
if(linked_console)
|
||||
linked_console.linked_imprinter = null
|
||||
linked_console = null
|
||||
return
|
||||
|
||||
if(default_deconstruction_crowbar(user, attacking_item))
|
||||
return
|
||||
|
||||
if(default_part_replacement(user, attacking_item))
|
||||
return
|
||||
|
||||
if(panel_open)
|
||||
to_chat(user, SPAN_NOTICE("You can't load \the [src] while it's opened."))
|
||||
return 1
|
||||
|
||||
if(!linked_console)
|
||||
to_chat(user, "\The [src] must be linked to an R&D console first.")
|
||||
return 1
|
||||
|
||||
if(attacking_item.is_open_container())
|
||||
return 0
|
||||
|
||||
if(!istype(attacking_item, /obj/item/stack/material))
|
||||
to_chat(user, SPAN_NOTICE("You cannot insert this item into \the [src]!"))
|
||||
return 1
|
||||
|
||||
if(stat)
|
||||
return 1
|
||||
|
||||
|
||||
if(TotalMaterials() + SHEET_MATERIAL_AMOUNT > max_material_storage)
|
||||
to_chat(user, SPAN_NOTICE("\The [src]'s material bin is full. Please remove material before adding more."))
|
||||
return 1
|
||||
|
||||
var/obj/item/stack/material/stack = attacking_item
|
||||
if(!stack.default_type)
|
||||
to_chat(user, SPAN_WARNING("This stack cannot be used!"))
|
||||
return
|
||||
|
||||
var/max_value = min(stack.get_amount(), round((max_material_storage - TotalMaterials()) / SHEET_MATERIAL_AMOUNT))
|
||||
var/amount = tgui_input_number(user, "How many sheets do you want to add?", "Add sheets", min(10, max_value), max_value = max_value, min_value = 1, round_value = TRUE)
|
||||
|
||||
if(!attacking_item)
|
||||
return
|
||||
if(!Adjacent(user))
|
||||
to_chat(user, SPAN_NOTICE("\The [src] is too far away for you to insert this."))
|
||||
return
|
||||
if(amount <= 0)//No negative numbers
|
||||
return
|
||||
|
||||
use_power_oneoff(max(1000, (SHEET_MATERIAL_AMOUNT * amount / 10)))
|
||||
if(do_after(user, 16))
|
||||
if(stack.use(amount))
|
||||
to_chat(user, SPAN_NOTICE("You add [amount] sheets to \the [src]."))
|
||||
SSmaterials.add_material_amount(materials, stack.default_type, amount * SHEET_MATERIAL_AMOUNT)
|
||||
|
||||
//In case there's things queued up, we run the queue handler
|
||||
handle_queue()
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
/**
|
||||
* Adds a design to the queue
|
||||
*
|
||||
* * design_to_add: The design to add
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/proc/addToQueue(datum/design/design_to_add)
|
||||
queue += design_to_add
|
||||
|
||||
//Wake up, we have things to do
|
||||
handle_queue()
|
||||
|
||||
|
||||
/**
|
||||
* Removes a design from the queue
|
||||
*
|
||||
* * index: The index of the design to remove
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/proc/removeFromQueue(index)
|
||||
queue.Cut(index, index + 1)
|
||||
|
||||
//Wake up, we have things to do
|
||||
handle_queue()
|
||||
|
||||
|
||||
/**
|
||||
* Handle the construction queue
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/proc/handle_queue()
|
||||
//No work to do or already busy, stop
|
||||
if(!length(queue) || build_callback_timer)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
//If there's no power, there's no building
|
||||
if(stat & NOPOWER)
|
||||
queue = list()
|
||||
return
|
||||
|
||||
//Get the first design in the queue
|
||||
var/datum/design/D = queue[1]
|
||||
|
||||
//If we can build it, process the request
|
||||
if(canBuild(D))
|
||||
build_callback_timer = addtimer(CALLBACK(src, PROC_REF(build), D), (D.time / production_speed), TIMER_UNIQUE)
|
||||
removeFromQueue(1)
|
||||
|
||||
else
|
||||
visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] flashes: insufficient materials: [getLackingMaterials(D)]."))
|
||||
if(linked_console)
|
||||
linked_console.updateUsrDialog()
|
||||
|
||||
update_icon()
|
||||
|
||||
/**
|
||||
* Checks if the protolathe can build the given design
|
||||
*
|
||||
* * design_to_check: The design to check
|
||||
*
|
||||
* Returns `TRUE` if the design can be built, `FALSE` otherwise
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/proc/canBuild(datum/design/design_to_check)
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/M in design_to_check.materials)
|
||||
var/material = SSmaterials.material_to_path(M, FALSE)
|
||||
if(!material)
|
||||
material = M
|
||||
if((materials[material] || 0) < design_to_check.materials[M])
|
||||
return FALSE
|
||||
|
||||
for(var/C in design_to_check.chemicals)
|
||||
if(!reagents.has_reagent(C, design_to_check.chemicals[C]))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Get what materials (chemicals included) are lacking from being able to build the given design
|
||||
*
|
||||
* * design_to_check: The design to check
|
||||
*
|
||||
* Returns a string of the materials that are missing
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/proc/getLackingMaterials(datum/design/design_to_check)
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
var/ret = ""
|
||||
|
||||
for(var/M in design_to_check.materials)
|
||||
var/amount = SSmaterials.get_material_amount(materials, M)
|
||||
if(amount < design_to_check.materials[M])
|
||||
if(ret != "")
|
||||
ret += ", "
|
||||
ret += "[design_to_check.materials[M] - amount] [SSmaterials.material_display_name(M)]"
|
||||
|
||||
for(var/C in design_to_check.chemicals)
|
||||
if(!reagents.has_reagent(C, design_to_check.chemicals[C]))
|
||||
var/singleton/reagent/R = GET_SINGLETON(C)
|
||||
if(ret != "")
|
||||
ret += ", "
|
||||
ret += "[R.name]"
|
||||
|
||||
return ret
|
||||
|
||||
/**
|
||||
* Builds the given design, assuming all the necessary conditions are met
|
||||
*
|
||||
* * design_to_build: The design to build
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/proc/build(datum/design/design_to_build)
|
||||
//Consume some power
|
||||
var/power = active_power_usage
|
||||
for(var/M in design_to_build.materials)
|
||||
power += round(design_to_build.materials[M] / 5)
|
||||
power = max(active_power_usage, power)
|
||||
use_power_oneoff(power)
|
||||
|
||||
//Consume the materials
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/M in design_to_build.materials)
|
||||
SSmaterials.remove_material_amount(materials, M, design_to_build.materials[M] * mat_efficiency)
|
||||
|
||||
for(var/C in design_to_build.chemicals)
|
||||
reagents.remove_reagent(C, design_to_build.chemicals[C] * mat_efficiency)
|
||||
|
||||
if(design_to_build.build_path)
|
||||
var/obj/new_item = design_to_build.Fabricate(src, src)
|
||||
if(product_offset)
|
||||
new_item.forceMove(get_step(src, dir))
|
||||
else
|
||||
new_item.forceMove(src.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
|
||||
|
||||
//We finished building, clear the timer
|
||||
build_callback_timer = null
|
||||
|
||||
//Do the queue handling for the next item, or to stop
|
||||
handle_queue()
|
||||
|
||||
|
||||
/obj/structure/machinery/r_n_d/circuit_imprinter/is_open_container()
|
||||
/obj/structure/machinery/r_n_d/fabricator/circuit_imprinter/is_open_container()
|
||||
. = ..()
|
||||
|
||||
//This is to recheck the queue when acid is added to the reagent container that we have
|
||||
//yes this should be done with signals, we don't have those signals yet
|
||||
//cope
|
||||
addtimer(CALLBACK(src, PROC_REF(handle_queue)), 1 SECOND, TIMER_UNIQUE)
|
||||
linked_console?.dispatch_fabrication_jobs()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
if(ispath(build_path, /obj/item/circuitboard))
|
||||
var/obj/item/circuitboard/CB = build_path
|
||||
var/atom/machine = initial(CB.build_path)
|
||||
desc = "Used in the construction of a: <b>[capitalize_first_letters(initial(machine.name))]</b>, [initial(machine.desc)]"
|
||||
desc = "Used in the construction of a: [capitalize_first_letters(initial(machine.name))], [initial(machine.desc)]"
|
||||
else
|
||||
var/atom/A = build_path
|
||||
desc = initial(A.desc)
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
|
||||
/datum/design/circuit/machine/aicore
|
||||
name = "AI Core"
|
||||
desc = "Used in the construction of an: <b>AI core</b>, Secure housing for an AI, it provides power and protection to its inhabitant."
|
||||
desc = "Used in the construction of an: AI core, Secure housing for an AI, it provides power and protection to its inhabitant."
|
||||
req_tech = list(TECH_DATA = 4, TECH_BIO = 3)
|
||||
build_path = /obj/item/circuitboard/aicore
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
//if the fabricator is a mech fab we need to construct the proper typepath for the manufacturer
|
||||
/datum/design/item/mechfab/prosthetic/Fabricate(var/newloc, var/fabricator)
|
||||
if(istype(fabricator, /obj/structure/machinery/mecha_part_fabricator))
|
||||
if(istype(fabricator, /obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator))
|
||||
if(!use_direct_buildpath)
|
||||
var/obj/structure/machinery/mecha_part_fabricator/mechfab = fabricator
|
||||
var/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/mechfab = fabricator
|
||||
for(var/model_path in subtypesof(build_path))
|
||||
var/obj/item/organ/external/E = new model_path
|
||||
if(E.robotize_type == mechfab.limb_manufacturer)
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
//if the fabricator is a mech fab pass the manufacturer info over to the robot part constructor
|
||||
/datum/design/item/mechfab/robot/Fabricate(var/newloc, var/fabricator)
|
||||
if(istype(fabricator, /obj/structure/machinery/mecha_part_fabricator))
|
||||
var/obj/structure/machinery/mecha_part_fabricator/mechfab = fabricator
|
||||
if(istype(fabricator, /obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator))
|
||||
var/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/mechfab = fabricator
|
||||
return new build_path(newloc, mechfab.manufacturer)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
/obj/structure/machinery/r_n_d/material_silo
|
||||
name = "material silo"
|
||||
desc = "A centralized material store used by linked research fabricators."
|
||||
icon_state = "silo"
|
||||
|
||||
idle_power_usage = 30 WATTS
|
||||
|
||||
/// Total material capacity, measured in material units.
|
||||
var/max_material_storage = 800000
|
||||
|
||||
/// Materials shared by every fabricator connected to the same R&D console.
|
||||
var/list/materials = list(
|
||||
MATERIAL_STEEL = 0,
|
||||
MATERIAL_GLASS = 0,
|
||||
MATERIAL_GOLD = 0,
|
||||
MATERIAL_SILVER = 0,
|
||||
MATERIAL_PHORON = 0,
|
||||
MATERIAL_URANIUM = 0,
|
||||
MATERIAL_DIAMOND = 0,
|
||||
MATERIAL_PLASTEEL = 0,
|
||||
MATERIAL_ALUMINIUM = 0,
|
||||
MATERIAL_LEAD = 0
|
||||
)
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/upgrade_hints(mob/user, distance, is_adjacent)
|
||||
. += ..()
|
||||
. += SPAN_NOTICE("\t- The shared storage capacity is <b>[max_material_storage / SHEET_MATERIAL_AMOUNT]</b> sheets.")
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/Initialize(mapload, d, populate_components, is_internal)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/update_icon()
|
||||
. = ..()
|
||||
ClearOverlays()
|
||||
if(!(stat & (NOPOWER | BROKEN)))
|
||||
AddOverlays(emissive_appearance(icon, "[icon_state]_lights"))
|
||||
AddOverlays("[icon_state]_lights")
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/TotalMaterials()
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
var/total = 0
|
||||
for(var/material in materials)
|
||||
total += materials[material]
|
||||
return total
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/get_material_amount(material_id)
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
var/material = SSmaterials.material_to_path(material_id, FALSE)
|
||||
if(!material)
|
||||
material = material_id
|
||||
return materials[material] || 0
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/has_material(material_id, amount)
|
||||
return get_material_amount(material_id) >= amount
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/add_material(material_id, amount)
|
||||
if(amount <= 0)
|
||||
return 0
|
||||
var/material = SSmaterials.material_to_path(material_id, FALSE)
|
||||
if(!material)
|
||||
material = material_id
|
||||
if(!(material in materials))
|
||||
return 0
|
||||
var/accepted = min(amount, max_material_storage - TotalMaterials())
|
||||
if(accepted <= 0)
|
||||
return 0
|
||||
SSmaterials.add_material_amount(materials, material, accepted)
|
||||
update_linked_uis()
|
||||
return accepted
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/remove_material(material_id, amount)
|
||||
if(amount <= 0)
|
||||
return TRUE
|
||||
var/material = SSmaterials.material_to_path(material_id, FALSE)
|
||||
if(!material)
|
||||
material = material_id
|
||||
if(!has_material(material, amount))
|
||||
return FALSE
|
||||
SSmaterials.remove_material_amount(materials, material, amount)
|
||||
update_linked_uis()
|
||||
return TRUE
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/eject_material(material_id, requested_sheets)
|
||||
if(requested_sheets < 1)
|
||||
return FALSE
|
||||
var/material = SSmaterials.material_to_path(material_id, FALSE)
|
||||
if(!material)
|
||||
return FALSE
|
||||
var/available = round(get_material_amount(material) / SHEET_MATERIAL_AMOUNT)
|
||||
var/amount = min(requested_sheets, available)
|
||||
if(amount < 1)
|
||||
return FALSE
|
||||
var/stack_type = SSmaterials.material_stack_type(material)
|
||||
if(!stack_type)
|
||||
return FALSE
|
||||
var/obj/item/stack/material/stack = new stack_type(loc, amount)
|
||||
stack.update_icon()
|
||||
SSmaterials.remove_material_amount(materials, material, amount * SHEET_MATERIAL_AMOUNT)
|
||||
update_linked_uis()
|
||||
return TRUE
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/wake_linked_fabricators()
|
||||
linked_console?.dispatch_fabrication_jobs()
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/update_linked_uis()
|
||||
if(!linked_console)
|
||||
return
|
||||
SStgui.update_uis(linked_console)
|
||||
for(var/obj/structure/machinery/r_n_d/fabricator/fabricator as anything in linked_console.linked_fabricators)
|
||||
SStgui.update_uis(fabricator)
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/attackby(obj/item/attacking_item, mob/user)
|
||||
if(user.a_intent == I_HURT)
|
||||
return ..()
|
||||
if(default_deconstruction_screwdriver(user, attacking_item))
|
||||
disconnect_console()
|
||||
return TRUE
|
||||
if(default_deconstruction_crowbar(user, attacking_item))
|
||||
return TRUE
|
||||
if(default_part_replacement(user, attacking_item))
|
||||
return TRUE
|
||||
if(panel_open)
|
||||
to_chat(user, SPAN_NOTICE("You can't load \the [src] while it's opened."))
|
||||
return TRUE
|
||||
if(!istype(attacking_item, /obj/item/stack/material))
|
||||
return ..()
|
||||
if(stat)
|
||||
return TRUE
|
||||
|
||||
var/obj/item/stack/material/stack = attacking_item
|
||||
if(!stack.default_type || !stack.material)
|
||||
to_chat(user, SPAN_WARNING("This stack cannot be stored."))
|
||||
return TRUE
|
||||
|
||||
var/material = SSmaterials.material_to_path(stack.default_type, FALSE)
|
||||
if(!material)
|
||||
material = stack.default_type
|
||||
if(!(material in materials))
|
||||
to_chat(user, SPAN_WARNING("\The [src] cannot hold [stack.material.name]."))
|
||||
return TRUE
|
||||
|
||||
var/max_value = min(stack.get_amount(), round((max_material_storage - TotalMaterials()) / SHEET_MATERIAL_AMOUNT))
|
||||
if(max_value < 1)
|
||||
to_chat(user, SPAN_NOTICE("\The [src] is full."))
|
||||
return TRUE
|
||||
|
||||
var/amount = tgui_input_number(user, "How many sheets do you want to add?", "Add sheets", min(10, max_value), max_value = max_value, min_value = 1, round_value = TRUE)
|
||||
if(!amount || !Adjacent(user))
|
||||
return TRUE
|
||||
|
||||
use_power_oneoff(max(1000, SHEET_MATERIAL_AMOUNT * amount / 10))
|
||||
if(do_after(user, 1.6 SECONDS) && stack.use(amount))
|
||||
SSmaterials.add_material_amount(materials, material, amount * SHEET_MATERIAL_AMOUNT)
|
||||
to_chat(user, SPAN_NOTICE("You add [amount] sheet\s of [stack.material.name] to \the [src]."))
|
||||
update_linked_uis()
|
||||
wake_linked_fabricators()
|
||||
return TRUE
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/dismantle()
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/material in materials)
|
||||
var/sheets = round(materials[material] / SHEET_MATERIAL_AMOUNT)
|
||||
if(sheets < 1)
|
||||
continue
|
||||
var/stack_type = SSmaterials.material_stack_type(material)
|
||||
if(!stack_type)
|
||||
continue
|
||||
var/obj/item/stack/material/stack = new stack_type(loc, sheets)
|
||||
stack.update_icon()
|
||||
..()
|
||||
|
||||
/obj/structure/machinery/r_n_d/material_silo/proc/disconnect_console()
|
||||
if(linked_console)
|
||||
linked_console.linked_silo = null
|
||||
linked_console = null
|
||||
@@ -0,0 +1,156 @@
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator
|
||||
name = "synthetic fabricator"
|
||||
desc = "A general purpose fabricator that can be used to fabricate equipment for synthetics or exosuits."
|
||||
icon = 'icons/obj/machinery/robotics_fabricator.dmi'
|
||||
icon_state = "fab"
|
||||
idle_power_usage = 20
|
||||
active_power_usage = 5000
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
component_types = list(
|
||||
/obj/item/circuitboard/mechfab,
|
||||
/obj/item/stock_parts/manipulator,
|
||||
/obj/item/stock_parts/micro_laser,
|
||||
/obj/item/stock_parts/console_screen
|
||||
)
|
||||
manufacturer = "hephaestus"
|
||||
build_type = MECHFAB
|
||||
product_offset = TRUE
|
||||
|
||||
fabrication_loop_type = /datum/looping_sound/synth_fab
|
||||
|
||||
/// Manufacturer used for the currently assigned prosthetic job.
|
||||
var/limb_manufacturer = PROSTHETIC_IND
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/LateInitialize()
|
||||
. = ..()
|
||||
if(!linked_console)
|
||||
for(var/obj/structure/machinery/computer/rdconsole/console in range(3, src))
|
||||
console.SyncRDevices()
|
||||
if(linked_console)
|
||||
break
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/upgrade_hints(mob/user, distance, is_adjacent)
|
||||
. += ..()
|
||||
. += "- Materials are drawn from the research material silo linked to the same R&D console."
|
||||
. += "- Upgraded <b>micro-lasers</b> will increase fabrication speed."
|
||||
. += SPAN_NOTICE(" - The current speed increase is <b>[round((1 - (1 / production_speed)) * 100)]%</b>")
|
||||
. += "- Upgraded <b>manipulators</b> will improve material use efficiency."
|
||||
. += SPAN_NOTICE(" - The current cost reduction is <b>[round((1 - mat_efficiency) * 100)]%</b>")
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/antagonist_hints(mob/user, distance, is_adjacent)
|
||||
. += ..()
|
||||
. += "Click-drag someone with long hair onto this machine to start feeding it their hair! This will hurt and piss them off!"
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/Initialize()
|
||||
. = ..()
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/update_icon()
|
||||
ClearOverlays()
|
||||
if(panel_open)
|
||||
AddOverlays("[icon_state]_panel")
|
||||
if(!(stat & (NOPOWER | BROKEN)))
|
||||
AddOverlays(emissive_appearance(icon, "[icon_state]_lights"))
|
||||
AddOverlays("[icon_state]_lights")
|
||||
if(build_callback_timer)
|
||||
AddOverlays("[icon_state]_working")
|
||||
AddOverlays(emissive_appearance(icon, "[icon_state]_lights_working"))
|
||||
AddOverlays("[icon_state]_lights_working")
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/RefreshParts()
|
||||
..()
|
||||
var/manipulator_rating = 0
|
||||
for(var/obj/item/stock_parts/manipulator/manipulator in component_parts)
|
||||
manipulator_rating += manipulator.rating
|
||||
mat_efficiency = 1 - (manipulator_rating - 1) / 4
|
||||
|
||||
var/laser_rating = 0
|
||||
for(var/obj/item/stock_parts/micro_laser/laser in component_parts)
|
||||
laser_rating += laser.rating
|
||||
production_speed = max(1, laser_rating)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
if(!allowed(user))
|
||||
to_chat(user, SPAN_WARNING("Access denied."))
|
||||
return
|
||||
do_hair_pull(user)
|
||||
|
||||
var/cancelled = FALSE
|
||||
SEND_SIGNAL(user, COMSIG_USE_MECH_FAB, &cancelled)
|
||||
if(cancelled)
|
||||
return
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/on_product_completed(obj/new_item, datum/design/design_to_build, datum/research_fabrication_job/job)
|
||||
visible_message("\The <b>[src]</b> pings, indicating that \the [new_item] is complete.", "You hear a ping.", intent_message = PING_SOUND)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/mouse_drop_receive(atom/dropped, mob/user, params)
|
||||
var/mob/living/carbon/human/target = dropped
|
||||
if (!istype(target) || target.buckled_to || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai))
|
||||
return
|
||||
if(target == user)
|
||||
return
|
||||
src.add_fingerprint(user)
|
||||
var/target_loc = target.loc
|
||||
|
||||
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
|
||||
if(isskrell(target) || isunathi(target))
|
||||
return
|
||||
|
||||
for(var/obj/item/protection in list(target.head))
|
||||
if(protection && (protection.flags_inv & BLOCKHAIR))
|
||||
return
|
||||
|
||||
var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_list[target.h_style]
|
||||
if(hair_style.length < 4)
|
||||
return
|
||||
|
||||
user.visible_message(SPAN_WARNING("[user] starts feeding [target]'s hair into \the [src]!"), SPAN_WARNING("You start feeding [target]'s hair into \the [src]!"))
|
||||
if(!do_after(user, 5 SECONDS, target, DO_UNIQUE))
|
||||
return
|
||||
if(target_loc != target.loc)
|
||||
return
|
||||
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
|
||||
user.visible_message(SPAN_WARNING("[user] feeds the [target]'s hair into the [src] and flicks it on!"), SPAN_ALERT("You turn the [src] on!"))
|
||||
do_hair_pull(target)
|
||||
user.attack_log += "\[[time_stamp()]\] <span class='warning'>Has fed [target.name]'s ([target.ckey]) hair into a [src].</span>"
|
||||
target.attack_log += "\[[time_stamp()]\] <font color='orange'>Has had their hair fed into [src] by [user.name] ([user.ckey])</font>"
|
||||
msg_admin_attack("[key_name_admin(user)] fed [key_name_admin(target)] in a [src]. (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",ckey=key_name(user),ckey_target=key_name(target))
|
||||
else
|
||||
return
|
||||
if(!do_after(user, 3.5 SECONDS, target, DO_UNIQUE))
|
||||
return
|
||||
if(target_loc != target.loc)
|
||||
return
|
||||
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
|
||||
user.visible_message(SPAN_ALERT("[user] starts tugging on [target]'s head as the [src] keeps running!"), SPAN_ALERT("You start tugging on [target]'s head!"))
|
||||
do_hair_pull(target)
|
||||
spawn(10)
|
||||
user.visible_message(SPAN_ALERT("[user] stops the [src] and leaves [target] resting as they are."), SPAN_ALERT("You turn the [src] off and let go of [target]."))
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/emag_act(var/remaining_charges, var/mob/user)
|
||||
switch(emagged)
|
||||
if(0)
|
||||
emagged = 0.5
|
||||
visible_message("[icon2html(src, viewers(get_turf(src)))] <b>[src]</b> beeps: \"DB error \[Code 0x00F1\]\"")
|
||||
sleep(10)
|
||||
visible_message("[icon2html(src, viewers(get_turf(src)))] <b>[src]</b> beeps: \"Attempting auto-repair\"")
|
||||
sleep(15)
|
||||
visible_message("[icon2html(src, viewers(get_turf(src)))] <b>[src]</b> beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
|
||||
sleep(30)
|
||||
visible_message("[icon2html(src, viewers(get_turf(src)))] <b>[src]</b> beeps: \"User DB truncated. Please contact your [SSatlas.current_map.company_name] system operator for future assistance.\"")
|
||||
req_access = null
|
||||
emagged = 1
|
||||
return 1
|
||||
if(0.5)
|
||||
visible_message("[icon2html(src, viewers(get_turf(src)))] <b>[src]</b> beeps: \"DB not responding \[Code 0x0003\]...\"")
|
||||
if(1)
|
||||
visible_message("[icon2html(src, viewers(get_turf(src)))] <b>[src]</b> beeps: \"No records in User DB\"")
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/on_job_started(datum/research_fabrication_job/job)
|
||||
limb_manufacturer = job?.manufacturer
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/mecha_part_fabricator/on_job_cleared()
|
||||
limb_manufacturer = PROSTHETIC_IND
|
||||
@@ -1,102 +1,56 @@
|
||||
/obj/structure/machinery/r_n_d/protolathe
|
||||
/obj/structure/machinery/r_n_d/fabricator/protolathe
|
||||
name = "protolathe"
|
||||
desc = "An upgraded variant of a common Autolathe, this can only be operated via a nearby RnD console, but can manufacture cutting edge technology, provided it has the design and the correct materials."
|
||||
icon_state = "protolathe"
|
||||
atom_flags = ATOM_FLAG_OPEN_CONTAINER
|
||||
|
||||
idle_power_usage = 30 WATTS
|
||||
active_power_usage = 25 KILO WATTS
|
||||
|
||||
var/max_material_storage = 100000
|
||||
var/list/materials = list(MATERIAL_STEEL = 0, MATERIAL_GLASS = 0, MATERIAL_GOLD = 0, MATERIAL_SILVER = 0, MATERIAL_PHORON = 0, MATERIAL_URANIUM = 0, MATERIAL_DIAMOND = 0)
|
||||
|
||||
/**
|
||||
* A `/list` of enqueued `/datum/design` to be printed, processed in the queue
|
||||
*/
|
||||
var/list/datum/design/queue = list()
|
||||
|
||||
/**
|
||||
* How much efficient (or inefficient) the protolathe is at manufacturing things
|
||||
*/
|
||||
var/mat_efficiency = 1
|
||||
|
||||
/**
|
||||
* The production speed of this specific protolathe, a factor
|
||||
*/
|
||||
var/production_speed = 1
|
||||
|
||||
///The timer id for the build callback, if we're building something
|
||||
var/build_callback_timer
|
||||
|
||||
build_type = PROTOLATHE
|
||||
uses_reagents = TRUE
|
||||
fabrication_loop_type = /datum/looping_sound/synth_fab
|
||||
component_types = list(
|
||||
/obj/item/circuitboard/protolathe,
|
||||
/obj/item/stock_parts/matter_bin = 2,
|
||||
/obj/item/stock_parts/manipulator = 2,
|
||||
/obj/item/reagent_containers/glass/beaker = 2
|
||||
)
|
||||
|
||||
/obj/structure/machinery/r_n_d/protolathe/upgrade_hints(mob/user, distance, is_adjacent)
|
||||
/obj/structure/machinery/r_n_d/fabricator/protolathe/upgrade_hints(mob/user, distance, is_adjacent)
|
||||
. += ..()
|
||||
. += "- Upgraded <b>matter bins</b> will increase material storage capacity."
|
||||
. += SPAN_NOTICE(" - The current storage capacity is <b>[max_material_storage / 2000]</b> sheets")
|
||||
. += "- Materials are drawn from the research material silo linked to the same R&D console."
|
||||
. += "- Upgraded <b>manipulators</b> will improve material use efficiency and increase fabrication speed."
|
||||
. += SPAN_NOTICE(" - The current speed increase is <b>[round((1 - (1 / production_speed)) * 100)]%</b>")
|
||||
. += SPAN_NOTICE(" - The current cost reduction is <b>[round((1 - mat_efficiency) * 100)]%</b>")
|
||||
|
||||
///Returns the total of all the stored materials
|
||||
/obj/structure/machinery/r_n_d/protolathe/proc/TotalMaterials()
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
var/t = 0
|
||||
for(var/f in materials)
|
||||
t += materials[f]
|
||||
return t
|
||||
|
||||
/obj/structure/machinery/r_n_d/protolathe/RefreshParts()
|
||||
/obj/structure/machinery/r_n_d/fabricator/protolathe/RefreshParts()
|
||||
..()
|
||||
// Adjust reagent container volume to match combined volume of the inserted beakers
|
||||
var/T = 0
|
||||
for(var/obj/item/reagent_containers/glass/G in component_parts)
|
||||
T += G.reagents.maximum_volume
|
||||
create_reagents(T)
|
||||
// Transfer all reagents from the beakers to internal reagent container
|
||||
for(var/obj/item/reagent_containers/glass/G in component_parts)
|
||||
G.reagents.trans_to_obj(src, G.reagents.total_volume)
|
||||
var/total_volume = 0
|
||||
for(var/obj/item/reagent_containers/glass/beaker in component_parts)
|
||||
total_volume += beaker.reagents.maximum_volume
|
||||
create_reagents(total_volume)
|
||||
for(var/obj/item/reagent_containers/glass/beaker in component_parts)
|
||||
beaker.reagents.trans_to_obj(src, beaker.reagents.total_volume)
|
||||
|
||||
// Adjust material storage capacity to scale with matter bin rating
|
||||
max_material_storage = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
|
||||
max_material_storage += M.rating * 75000
|
||||
|
||||
// Adjust production speed to increase with manipulator rating
|
||||
T = 0
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
T += M.rating
|
||||
mat_efficiency = 1 - (T - 2) / 8
|
||||
production_speed = T / 2
|
||||
var/manipulator_rating = 0
|
||||
for(var/obj/item/stock_parts/manipulator/manipulator in component_parts)
|
||||
manipulator_rating += manipulator.rating
|
||||
mat_efficiency = 1 - (manipulator_rating - 2) / 8
|
||||
production_speed = manipulator_rating / 2
|
||||
update_icon()
|
||||
|
||||
/obj/structure/machinery/r_n_d/protolathe/dismantle()
|
||||
for(var/obj/I in component_parts)
|
||||
if(istype(I, /obj/item/reagent_containers/glass/beaker))
|
||||
reagents.trans_to_obj(I, reagents.total_volume)
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/f in materials)
|
||||
if(materials[f] >= SHEET_MATERIAL_AMOUNT)
|
||||
var/path = getMaterialType(f)
|
||||
if(path)
|
||||
var/obj/item/stack/S = new path(loc)
|
||||
S.amount = round(materials[f] / SHEET_MATERIAL_AMOUNT)
|
||||
/obj/structure/machinery/r_n_d/fabricator/protolathe/dismantle()
|
||||
for(var/obj/item/reagent_containers/glass/beaker in component_parts)
|
||||
reagents.trans_to_obj(beaker, reagents.total_volume)
|
||||
..()
|
||||
|
||||
/obj/structure/machinery/r_n_d/protolathe/power_change()
|
||||
/obj/structure/machinery/r_n_d/fabricator/protolathe/power_change()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/structure/machinery/r_n_d/protolathe/update_icon()
|
||||
/obj/structure/machinery/r_n_d/fabricator/protolathe/update_icon()
|
||||
ClearOverlays()
|
||||
if(panel_open)
|
||||
AddOverlays("[icon_state]_panel")
|
||||
if(!(stat & (NOPOWER|BROKEN)))
|
||||
if(!(stat & (NOPOWER | BROKEN)))
|
||||
AddOverlays(emissive_appearance(icon, "[icon_state]_lights"))
|
||||
AddOverlays("[icon_state]_lights")
|
||||
if(build_callback_timer)
|
||||
@@ -104,214 +58,6 @@
|
||||
AddOverlays(emissive_appearance(icon, "[icon_state]_lights_working"))
|
||||
AddOverlays("[icon_state]_lights_working")
|
||||
|
||||
/obj/structure/machinery/r_n_d/protolathe/attackby(obj/item/attacking_item, mob/user)
|
||||
if(user.a_intent == I_HURT)
|
||||
return ..()
|
||||
|
||||
if(build_callback_timer)
|
||||
to_chat(user, SPAN_NOTICE("\The [src] is busy. Please wait for completion of previous operation."))
|
||||
return TRUE
|
||||
if(default_deconstruction_screwdriver(user, attacking_item))
|
||||
if(linked_console)
|
||||
linked_console.linked_lathe = null
|
||||
linked_console = null
|
||||
return TRUE
|
||||
if(default_deconstruction_crowbar(user, attacking_item))
|
||||
return TRUE
|
||||
if(default_part_replacement(user, attacking_item))
|
||||
return TRUE
|
||||
if(attacking_item.is_open_container())
|
||||
return TRUE
|
||||
if(panel_open)
|
||||
to_chat(user, SPAN_NOTICE("You can't load \the [src] while it's opened."))
|
||||
return TRUE
|
||||
if(!linked_console)
|
||||
to_chat(user, SPAN_NOTICE("The [src] must be linked to an R&D console first!"))
|
||||
return TRUE
|
||||
if(!istype(attacking_item, /obj/item/stack/material))
|
||||
to_chat(user, SPAN_NOTICE("You cannot insert this item into \the [src]!"))
|
||||
return TRUE
|
||||
if(stat)
|
||||
return TRUE
|
||||
|
||||
if(TotalMaterials() + SHEET_MATERIAL_AMOUNT > max_material_storage)
|
||||
to_chat(user, SPAN_NOTICE("The [src]'s material bin is full. Please remove material before adding more."))
|
||||
return TRUE
|
||||
|
||||
var/obj/item/stack/material/stack = attacking_item
|
||||
if(!stack.default_type)
|
||||
to_chat(user, SPAN_WARNING("This stack cannot be used!"))
|
||||
return
|
||||
|
||||
var/max_value = min(stack.get_amount(), round((max_material_storage - TotalMaterials()) / SHEET_MATERIAL_AMOUNT))
|
||||
var/amount = tgui_input_number(user, "How many sheets do you want to add?", "Add sheets", min(10, max_value), max_value = max_value, min_value = 1, round_value = TRUE)
|
||||
|
||||
if(!attacking_item)
|
||||
return
|
||||
if(!Adjacent(user))
|
||||
to_chat(user, SPAN_NOTICE("The [src] is too far away for you to insert this."))
|
||||
return
|
||||
if(amount <= 0)//No negative numbers, no nulls
|
||||
return
|
||||
|
||||
var/mutable_appearance/M = mutable_appearance(icon, "material_insertion")
|
||||
M.color = stack.material.icon_colour
|
||||
//first play the insertion animation
|
||||
flick_overlay_view(M, 1 SECONDS)
|
||||
|
||||
//now play the progress bar animation
|
||||
flick_overlay_view(mutable_appearance(icon, "protolathe_progress"), 1 SECONDS)
|
||||
|
||||
//Use some power and add the materials
|
||||
use_power_oneoff(max(1000, (SHEET_MATERIAL_AMOUNT * amount / 10)))
|
||||
if(do_after(user, 1.6 SECONDS))
|
||||
if(stack.use(amount))
|
||||
if(amount>1)
|
||||
to_chat(user, SPAN_NOTICE("You add [amount] [stack.material.sheet_plural_name] of [stack.material.name] to \the [src]."))
|
||||
else
|
||||
to_chat(user, SPAN_NOTICE("You add [amount] [stack.material.sheet_singular_name] of [stack.material.name] to \the [src]."))
|
||||
SSmaterials.add_material_amount(materials, stack.default_type, amount * SHEET_MATERIAL_AMOUNT)
|
||||
|
||||
//In case there's things queued up, we run the queue handler
|
||||
handle_queue()
|
||||
|
||||
//Give an update on the UIs
|
||||
updateUsrDialog()
|
||||
if(linked_console)
|
||||
linked_console.updateUsrDialog()
|
||||
|
||||
/**
|
||||
* Adds a design to the queue
|
||||
*
|
||||
* * design_to_add: The design to add
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/protolathe/proc/addToQueue(datum/design/design_to_add)
|
||||
queue += design_to_add
|
||||
|
||||
//Wake up, we have things to do
|
||||
handle_queue()
|
||||
|
||||
/**
|
||||
* Removes a design from the queue
|
||||
*
|
||||
* * index: The index of the design to remove
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/protolathe/proc/removeFromQueue(index)
|
||||
queue.Cut(index, index + 1)
|
||||
|
||||
//Wake up, we have things to do
|
||||
handle_queue()
|
||||
|
||||
/**
|
||||
* Handle the construction queue
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/protolathe/proc/handle_queue()
|
||||
|
||||
//No work to do or already busy, stop
|
||||
if(!length(queue) || build_callback_timer)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
//If there's no power, there's no building
|
||||
if(stat & NOPOWER)
|
||||
queue = list()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
//Get the first design in the queue
|
||||
var/datum/design/D = queue[1]
|
||||
|
||||
//If we can build it, process the request
|
||||
if(canBuild(D))
|
||||
build_callback_timer = addtimer(CALLBACK(src, PROC_REF(build), D), (D.time / production_speed), TIMER_UNIQUE)
|
||||
removeFromQueue(1)
|
||||
|
||||
else
|
||||
visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] flashes: Insufficient materials: [getLackingMaterials(D)]."))
|
||||
if(linked_console)
|
||||
linked_console.updateUsrDialog()
|
||||
|
||||
update_icon()
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the protolathe can build the given design
|
||||
*
|
||||
* * design_to_check: The design to check
|
||||
*
|
||||
* Returns `TRUE` if the design can be built, `FALSE` otherwise
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/protolathe/proc/canBuild(datum/design/design_to_check)
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/M in design_to_check.materials)
|
||||
var/material = SSmaterials.material_to_path(M, FALSE)
|
||||
if(!material)
|
||||
material = M
|
||||
if((materials[material] || 0) < design_to_check.materials[M])
|
||||
return FALSE
|
||||
|
||||
for(var/C in design_to_check.chemicals)
|
||||
if(!reagents.has_reagent(C, design_to_check.chemicals[C]))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Get what materials (chemicals included) are lacking from being able to build the given design
|
||||
*
|
||||
* * design_to_check: The design to check
|
||||
*
|
||||
* Returns a string of the materials that are missing
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/protolathe/proc/getLackingMaterials(var/datum/design/design_to_check)
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
var/ret = ""
|
||||
for(var/M in design_to_check.materials)
|
||||
var/amount = SSmaterials.get_material_amount(materials, M)
|
||||
if(amount < design_to_check.materials[M])
|
||||
if(ret != "")
|
||||
ret += ", "
|
||||
ret += "[design_to_check.materials[M] - amount] [SSmaterials.material_display_name(M)]"
|
||||
for(var/C in design_to_check.chemicals)
|
||||
if(!reagents.has_reagent(C, design_to_check.chemicals[C]))
|
||||
var/singleton/reagent/R = GET_SINGLETON(C)
|
||||
if(ret != "")
|
||||
ret += ", "
|
||||
ret += "[R.name]"
|
||||
return ret
|
||||
|
||||
/**
|
||||
* Builds the given design, assuming all the necessary conditions are met
|
||||
*
|
||||
* * design_to_build: The design to build
|
||||
*/
|
||||
/obj/structure/machinery/r_n_d/protolathe/proc/build(datum/design/design_to_build)
|
||||
//Consume some power
|
||||
var/power = active_power_usage
|
||||
for(var/M in design_to_build.materials)
|
||||
power += round(design_to_build.materials[M] / 2)
|
||||
power = max(active_power_usage, power)
|
||||
use_power_oneoff(power)
|
||||
|
||||
//Consume the materials
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/M in design_to_build.materials)
|
||||
SSmaterials.remove_material_amount(materials, M, design_to_build.materials[M] * mat_efficiency)
|
||||
for(var/C in design_to_build.chemicals)
|
||||
reagents.remove_reagent(C, design_to_build.chemicals[C] * mat_efficiency)
|
||||
|
||||
intent_message(MACHINE_SOUND)
|
||||
|
||||
if(design_to_build.build_path)
|
||||
var/obj/new_item = design_to_build.Fabricate(src, src)
|
||||
new_item.forceMove(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
|
||||
|
||||
//We finished building, clear the timer
|
||||
build_callback_timer = null
|
||||
|
||||
//Do the queue handling for the next item, or to stop
|
||||
handle_queue()
|
||||
/obj/structure/machinery/r_n_d/fabricator/protolathe/is_open_container()
|
||||
. = ..()
|
||||
linked_console?.dispatch_fabrication_jobs()
|
||||
|
||||
+786
-709
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
|
||||
|
||||
//All devices that link into the R&D console fall into thise type for easy identification and some shared procs.
|
||||
//All devices that link into the R&D console fall into this type for easy identification and shared procs.
|
||||
|
||||
/obj/structure/machinery/r_n_d
|
||||
name = "R&D device"
|
||||
@@ -15,3 +15,351 @@
|
||||
|
||||
/obj/structure/machinery/r_n_d/proc/getMaterialType(var/name)
|
||||
return SSmaterials.material_stack_type(name)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator
|
||||
/// The design build flag accepted by this machine.
|
||||
var/build_type
|
||||
|
||||
/// Whether this machine checks and consumes design chemicals.
|
||||
var/uses_reagents = FALSE
|
||||
|
||||
/// Whether completed products are placed one tile in front of the machine.
|
||||
var/product_offset = FALSE
|
||||
|
||||
/// Material cost multiplier.
|
||||
var/mat_efficiency = 1
|
||||
|
||||
/// Fabrication speed multiplier.
|
||||
var/production_speed = 1
|
||||
|
||||
/// Job currently assigned by the research console.
|
||||
var/datum/research_fabrication_job/assigned_job
|
||||
|
||||
/// Design currently being fabricated.
|
||||
var/datum/design/current_design
|
||||
|
||||
/// Timer ID for the active fabrication.
|
||||
var/build_callback_timer
|
||||
|
||||
/// Looping-sound datum selected by this machine type.
|
||||
var/fabrication_loop_type
|
||||
|
||||
/// Active looping-sound controller for this machine.
|
||||
var/datum/looping_sound/fabrication_loop
|
||||
|
||||
/// Whether this fabricator's construction loop is currently playing.
|
||||
var/fabrication_audio_playing = FALSE
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/Initialize(mapload, d, populate_components, is_internal)
|
||||
. = ..()
|
||||
|
||||
if(fabrication_loop_type)
|
||||
fabrication_loop = new fabrication_loop_type(src)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/start_fabrication_audio()
|
||||
if(!fabrication_loop || fabrication_audio_playing)
|
||||
return
|
||||
|
||||
fabrication_loop.start()
|
||||
fabrication_audio_playing = TRUE
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/stop_fabrication_audio()
|
||||
if(!fabrication_loop || !fabrication_audio_playing)
|
||||
return
|
||||
|
||||
fabrication_loop.stop()
|
||||
fabrication_audio_playing = FALSE
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/power_change()
|
||||
. = ..()
|
||||
if((stat & NOPOWER) && build_callback_timer)
|
||||
if(build_callback_timer)
|
||||
deltimer(build_callback_timer)
|
||||
pause_console_job()
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/is_available()
|
||||
return !assigned_job && !build_callback_timer && !(stat & (NOPOWER | BROKEN)) && !panel_open
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/get_material_silo()
|
||||
return linked_console?.linked_silo
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/get_required_material_amount(datum/design/design_to_check, material_id)
|
||||
return round(design_to_check.materials[material_id] * mat_efficiency)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/get_required_reagent_amount(datum/design/design_to_check, reagent_id)
|
||||
return round(design_to_check.chemicals[reagent_id] * mat_efficiency)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/has_required_materials(datum/design/design_to_check)
|
||||
if(!design_to_check)
|
||||
return FALSE
|
||||
|
||||
var/obj/structure/machinery/r_n_d/material_silo/silo = get_material_silo()
|
||||
if(!silo)
|
||||
return FALSE
|
||||
|
||||
for(var/material_id in design_to_check.materials)
|
||||
if(!silo.has_material(material_id, get_required_material_amount(design_to_check, material_id)))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/has_required_reagents(datum/design/design_to_check)
|
||||
if(!design_to_check)
|
||||
return FALSE
|
||||
if(!uses_reagents)
|
||||
return TRUE
|
||||
|
||||
for(var/reagent_id in design_to_check.chemicals)
|
||||
if(!reagents?.has_reagent(reagent_id, get_required_reagent_amount(design_to_check, reagent_id)))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/can_build(datum/design/design_to_check)
|
||||
return has_required_materials(design_to_check) && has_required_reagents(design_to_check)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/canBuild(datum/design/design_to_check)
|
||||
return can_build(design_to_check)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/getLackingMaterials(datum/design/design_to_check)
|
||||
var/obj/structure/machinery/r_n_d/material_silo/silo = get_material_silo()
|
||||
var/list/missing = list()
|
||||
|
||||
for(var/material_id in design_to_check.materials)
|
||||
var/required_amount = get_required_material_amount(design_to_check, material_id)
|
||||
var/stored_amount = silo?.get_material_amount(material_id) || 0
|
||||
if(stored_amount < required_amount)
|
||||
missing += "[required_amount - stored_amount] [SSmaterials.material_display_name(material_id)]"
|
||||
|
||||
if(uses_reagents)
|
||||
for(var/reagent_id in design_to_check.chemicals)
|
||||
var/required_amount = get_required_reagent_amount(design_to_check, reagent_id)
|
||||
if(!reagents?.has_reagent(reagent_id, required_amount))
|
||||
var/singleton/reagent/reagent = GET_SINGLETON(reagent_id)
|
||||
missing += reagent?.name || "unknown reagent"
|
||||
|
||||
return english_list(missing)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/can_produce_job(datum/research_fabrication_job/job)
|
||||
if(!job?.design)
|
||||
return FALSE
|
||||
if(!(job.design.build_type & build_type))
|
||||
return FALSE
|
||||
if(!has_required_reagents(job.design))
|
||||
return FALSE
|
||||
if(length(job.reserved_materials))
|
||||
return TRUE
|
||||
return has_required_materials(job.design)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/reserve_job_materials(datum/research_fabrication_job/job)
|
||||
if(!job?.design)
|
||||
return FALSE
|
||||
if(length(job.reserved_materials))
|
||||
return TRUE
|
||||
|
||||
var/obj/structure/machinery/r_n_d/material_silo/silo = get_material_silo()
|
||||
if(!silo)
|
||||
return FALSE
|
||||
|
||||
for(var/material_id in job.design.materials)
|
||||
var/required_amount = get_required_material_amount(job.design, material_id)
|
||||
if(!silo.has_material(material_id, required_amount))
|
||||
return FALSE
|
||||
|
||||
for(var/material_id in job.design.materials)
|
||||
var/required_amount = get_required_material_amount(job.design, material_id)
|
||||
var/material = SSmaterials.material_to_path(material_id, FALSE)
|
||||
if(!material)
|
||||
material = material_id
|
||||
SSmaterials.remove_material_amount(silo.materials, material, required_amount)
|
||||
job.reserved_materials[material] = required_amount
|
||||
|
||||
silo.update_linked_uis()
|
||||
return TRUE
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/begin_console_job(datum/research_fabrication_job/job)
|
||||
if(!job || !is_available() || !can_produce_job(job))
|
||||
return FALSE
|
||||
if(!reserve_job_materials(job))
|
||||
return FALSE
|
||||
|
||||
assigned_job = job
|
||||
current_design = job.design
|
||||
job.assigned_machine = src
|
||||
on_job_started(job)
|
||||
update_use_power(POWER_USE_ACTIVE)
|
||||
build_callback_timer = addtimer(CALLBACK(src, PROC_REF(complete_console_job)), current_design.time / production_speed, TIMER_UNIQUE | TIMER_STOPPABLE)
|
||||
start_fabrication_audio()
|
||||
update_icon()
|
||||
SStgui.update_uis(linked_console)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/on_job_started(datum/research_fabrication_job/job)
|
||||
return
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/complete_console_job()
|
||||
build_callback_timer = null
|
||||
|
||||
var/datum/research_fabrication_job/job = assigned_job
|
||||
var/datum/design/design_to_build = job?.design
|
||||
if(!job || !design_to_build)
|
||||
clear_console_job()
|
||||
return
|
||||
|
||||
if(!has_required_reagents(design_to_build))
|
||||
visible_message(SPAN_WARNING("\The [src] stops because the required reagents are no longer available."))
|
||||
pause_console_job()
|
||||
return
|
||||
|
||||
consume_reagents(design_to_build)
|
||||
use_fabrication_power(design_to_build)
|
||||
fabricate_design(design_to_build, job)
|
||||
job.reserved_materials.Cut()
|
||||
|
||||
var/obj/structure/machinery/computer/rdconsole/console = linked_console
|
||||
console?.finish_fabrication_job(job)
|
||||
|
||||
/*
|
||||
* Keep construction audio running while the console attempts to assign
|
||||
* another job. This prevents the end and startup sounds from playing
|
||||
* between consecutive items.
|
||||
*/
|
||||
clear_console_job(FALSE, FALSE)
|
||||
console?.dispatch_fabrication_jobs()
|
||||
|
||||
/*
|
||||
* If dispatch did not assign another job to this machine, construction
|
||||
* has actually ended and the loop can now stop.
|
||||
*/
|
||||
if(!assigned_job)
|
||||
stop_fabrication_audio()
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/pause_console_job()
|
||||
var/datum/research_fabrication_job/job = assigned_job
|
||||
if(job)
|
||||
job.assigned_machine = null
|
||||
|
||||
assigned_job = null
|
||||
current_design = null
|
||||
build_callback_timer = null
|
||||
stop_fabrication_audio()
|
||||
update_use_power(POWER_USE_IDLE)
|
||||
update_icon()
|
||||
on_job_cleared()
|
||||
|
||||
if(linked_console)
|
||||
SStgui.update_uis(linked_console)
|
||||
linked_console.dispatch_fabrication_jobs()
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/clear_console_job(clear_assignment = TRUE, stop_audio = TRUE)
|
||||
if(clear_assignment && assigned_job)
|
||||
assigned_job.assigned_machine = null
|
||||
|
||||
assigned_job = null
|
||||
current_design = null
|
||||
build_callback_timer = null
|
||||
|
||||
if(stop_audio)
|
||||
stop_fabrication_audio()
|
||||
|
||||
update_use_power(POWER_USE_IDLE)
|
||||
update_icon()
|
||||
on_job_cleared()
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/consume_reagents(datum/design/design_to_build)
|
||||
if(!uses_reagents)
|
||||
return
|
||||
|
||||
for(var/reagent_id in design_to_build.chemicals)
|
||||
reagents.remove_reagent(reagent_id, get_required_reagent_amount(design_to_build, reagent_id))
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/use_fabrication_power(datum/design/design_to_build)
|
||||
var/power_cost = active_power_usage
|
||||
for(var/material_id in design_to_build.materials)
|
||||
power_cost += round(design_to_build.materials[material_id] / 2)
|
||||
use_power_oneoff(max(active_power_usage, power_cost))
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/fabricate_design(datum/design/design_to_build, datum/research_fabrication_job/job)
|
||||
intent_message(MACHINE_SOUND)
|
||||
if(!design_to_build.build_path)
|
||||
return
|
||||
|
||||
var/atom/product_location = product_offset ? get_step(src, dir) : src
|
||||
var/obj/new_item = design_to_build.Fabricate(product_location, src)
|
||||
if(!new_item)
|
||||
return
|
||||
|
||||
if(!product_offset)
|
||||
new_item.forceMove(loc)
|
||||
|
||||
if(mat_efficiency != 1 && new_item.matter?.len)
|
||||
for(var/material_id in new_item.matter)
|
||||
new_item.matter[material_id] *= mat_efficiency
|
||||
|
||||
apply_product_data(new_item, design_to_build, job)
|
||||
on_product_completed(new_item, design_to_build, job)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/apply_product_data(obj/new_item, datum/design/design_to_build, datum/research_fabrication_job/job)
|
||||
return
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/on_product_completed(obj/new_item, datum/design/design_to_build, datum/research_fabrication_job/job)
|
||||
return
|
||||
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/wake_console_dispatch()
|
||||
linked_console?.dispatch_fabrication_jobs()
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/disconnect_console()
|
||||
if(!linked_console)
|
||||
return
|
||||
var/obj/structure/machinery/computer/rdconsole/console = linked_console
|
||||
if(build_callback_timer)
|
||||
deltimer(build_callback_timer)
|
||||
if(assigned_job)
|
||||
assigned_job.assigned_machine = null
|
||||
assigned_job = null
|
||||
current_design = null
|
||||
build_callback_timer = null
|
||||
stop_fabrication_audio()
|
||||
update_use_power(POWER_USE_IDLE)
|
||||
update_icon()
|
||||
linked_console = null
|
||||
console.remove_fabricator(src)
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/attackby(obj/item/attacking_item, mob/user)
|
||||
if(user.a_intent == I_HURT)
|
||||
return ..()
|
||||
if(build_callback_timer)
|
||||
to_chat(user, SPAN_NOTICE("\The [src] is busy. Please wait for the current operation to finish."))
|
||||
return TRUE
|
||||
if(default_deconstruction_screwdriver(user, attacking_item))
|
||||
disconnect_console()
|
||||
return TRUE
|
||||
if(default_deconstruction_crowbar(user, attacking_item))
|
||||
return TRUE
|
||||
if(default_part_replacement(user, attacking_item))
|
||||
return TRUE
|
||||
if(istype(attacking_item, /obj/item/stack/material))
|
||||
to_chat(user, SPAN_NOTICE("Materials must be inserted into the linked research material silo."))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/Destroy()
|
||||
if(build_callback_timer)
|
||||
deltimer(build_callback_timer)
|
||||
|
||||
stop_fabrication_audio()
|
||||
QDEL_NULL(fabrication_loop)
|
||||
|
||||
if(assigned_job)
|
||||
assigned_job.assigned_machine = null
|
||||
|
||||
if(linked_console)
|
||||
linked_console.remove_fabricator(src)
|
||||
|
||||
assigned_job = null
|
||||
current_design = null
|
||||
return ..()
|
||||
|
||||
/obj/structure/machinery/r_n_d/fabricator/proc/on_job_cleared()
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user