mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-28 15:39:57 +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:
@@ -797,3 +797,8 @@
|
||||
new /obj/item/storage/box/unique/tea/messa(src)
|
||||
new /obj/item/reagent_containers/toothpaste(src)
|
||||
new /obj/item/reagent_containers/food/drinks/flask/vacuumflask/mouthwash(src)
|
||||
|
||||
/obj/structure/closet/crate/tool/machinist/fill()
|
||||
new /obj/item/reagent_containers/weldpack(src)
|
||||
new /obj/item/portable_whiteboard(src)
|
||||
new /obj/item/paint_sprayer(src)
|
||||
|
||||
@@ -1,506 +0,0 @@
|
||||
/obj/structure/machinery/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"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
idle_power_usage = 20
|
||||
active_power_usage = 5000
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
component_types = list(
|
||||
/obj/item/circuitboard/mechfab,
|
||||
/obj/item/stock_parts/matter_bin = 2,
|
||||
/obj/item/stock_parts/manipulator,
|
||||
/obj/item/stock_parts/micro_laser,
|
||||
/obj/item/stock_parts/console_screen
|
||||
)
|
||||
manufacturer = "hephaestus"
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
var/list/materials = list(MATERIAL_STEEL = 0, MATERIAL_GLASS = 0, MATERIAL_GOLD = 0, MATERIAL_SILVER = 0, MATERIAL_DIAMOND = 0, MATERIAL_PHORON = 0, MATERIAL_URANIUM = 0, MATERIAL_PLASTEEL = 0, MATERIAL_ALUMINIUM = 0, MATERIAL_LEAD = 0)
|
||||
var/res_max_amount = 200000
|
||||
|
||||
var/datum/research/files
|
||||
|
||||
/// The looping sound for production.
|
||||
var/datum/looping_sound/synth_fab/fab_loop
|
||||
|
||||
var/list/categories = list()
|
||||
var/category = null
|
||||
var/sync_message = ""
|
||||
var/limb_manufacturer
|
||||
|
||||
///The timer id for the build callback, if we're building something
|
||||
var/build_callback_timer
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/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>[res_max_amount / 2000]</b> sheets")
|
||||
. += "- 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/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/mecha_part_fabricator/Initialize()
|
||||
. = ..()
|
||||
|
||||
files = new /datum/research(src) //Setup the research data holder.
|
||||
fab_loop = new(src)
|
||||
limb_manufacturer = GLOB.basic_robolimb.company
|
||||
update_categories()
|
||||
update_icon()
|
||||
|
||||
/// Make sure the machine starts the round properly synced.
|
||||
/obj/structure/machinery/mecha_part_fabricator/LateInitialize()
|
||||
. = ..()
|
||||
sync()
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/update_icon()
|
||||
ClearOverlays()
|
||||
update_fab_audio()
|
||||
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")
|
||||
|
||||
/// Starts and stops the necessary audio.
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/update_fab_audio()
|
||||
if(!fab_loop)
|
||||
return
|
||||
|
||||
if(build_callback_timer)
|
||||
fab_loop.start()
|
||||
else
|
||||
fab_loop.stop()
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/dismantle()
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/f in materials.Copy())
|
||||
eject_materials(f, materials[f])
|
||||
|
||||
//Stop the queue building if you're dismantling
|
||||
deltimer(build_callback_timer)
|
||||
|
||||
..()
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/RefreshParts()
|
||||
..()
|
||||
res_max_amount = 0
|
||||
|
||||
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
|
||||
res_max_amount += M.rating * 100000 // 200k -> 600k
|
||||
var/T = 0
|
||||
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
T += M.rating
|
||||
mat_efficiency = 1 - (T - 1) / 4 // 1 -> 0.5
|
||||
|
||||
for(var/obj/item/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both
|
||||
T += M.rating
|
||||
production_speed = T / 2 // 1 -> 3
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/attack_hand(var/mob/user)
|
||||
if(..())
|
||||
return
|
||||
if(!allowed(user))
|
||||
to_chat(user, SPAN_WARNING("Access denied."))
|
||||
return
|
||||
do_hair_pull(user)
|
||||
|
||||
// Yes I'm doing this after do_hair_pull() intentionally, you can totally fail the skill check and still get your hair stuck in a blender.
|
||||
var/cancelled = FALSE
|
||||
SEND_SIGNAL(user, COMSIG_USE_MECH_FAB, &cancelled)
|
||||
if (cancelled)
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "SyntheticFabricator", "Synthetic Fabricator", 1200, 800)
|
||||
ui.open()
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["manufacturer"] = manufacturer
|
||||
var/datum/design/current = queue.len ? queue[1] : null
|
||||
if(current)
|
||||
data["current"] = current.name
|
||||
data["queue"] = get_queue_names()
|
||||
data["buildable"] = get_build_options()
|
||||
data["category"] = category
|
||||
data["available_categories"] = list()
|
||||
for(var/possible_category in categories)
|
||||
data["available_categories"] += list(list("name" = possible_category))
|
||||
|
||||
if(GLOB.fabricator_robolimbs)
|
||||
var/list/T = list()
|
||||
for(var/A in GLOB.fabricator_robolimbs)
|
||||
var/datum/robolimb/R = GLOB.fabricator_robolimbs[A]
|
||||
T += list(list("name" = R.company, "type" = A))
|
||||
data["manufacturers"] = T
|
||||
data["selected_manufacturer"] = limb_manufacturer
|
||||
|
||||
data["materials"] = get_materials()
|
||||
data["maximum_resource_amount"] = res_max_amount
|
||||
data["sync"] = sync_message
|
||||
|
||||
//If we have something in the queue that we're trying to build, show the time left if the build is undergoing, otherwise null
|
||||
//the logic of displaying it is handled client-side
|
||||
if(current)
|
||||
if(build_callback_timer)
|
||||
data["timeleft"] = round(timeleft(build_callback_timer))
|
||||
else
|
||||
data["timeleft"] = null
|
||||
return data
|
||||
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("build")
|
||||
var/path = text2path(params["build"])
|
||||
add_to_queue(path)
|
||||
. = TRUE
|
||||
|
||||
if("remove")
|
||||
remove_from_queue(text2num(params["remove"]))
|
||||
. = TRUE
|
||||
|
||||
if("category")
|
||||
if(params["category"] in categories)
|
||||
category = params["category"]
|
||||
. = TRUE
|
||||
|
||||
if("manufacturer")
|
||||
if(params["manufacturer"] in GLOB.fabricator_robolimbs)
|
||||
limb_manufacturer = params["manufacturer"]
|
||||
. = TRUE
|
||||
|
||||
if("eject")
|
||||
eject_materials(params["eject"], text2num(params["amount"]))
|
||||
. = TRUE
|
||||
|
||||
if("sync")
|
||||
sync()
|
||||
. = TRUE
|
||||
else
|
||||
sync_message = ""
|
||||
|
||||
if(.)
|
||||
playsound(src, 'sound/machines/synthfab/synthfab_button.ogg', 50)
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/attackby(obj/item/attacking_item, mob/user)
|
||||
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))
|
||||
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))
|
||||
return ..()
|
||||
|
||||
var/obj/item/stack/material/M = attacking_item
|
||||
if(!M.material)
|
||||
return ..()
|
||||
var/material = SSmaterials.material_to_path(M.material, FALSE)
|
||||
if(!(material in list(MATERIAL_STEEL, MATERIAL_GLASS, MATERIAL_GOLD, MATERIAL_SILVER, MATERIAL_DIAMOND, MATERIAL_PHORON, MATERIAL_URANIUM, MATERIAL_PLASTEEL, MATERIAL_ALUMINIUM, MATERIAL_LEAD)))
|
||||
to_chat(user, SPAN_WARNING("\The [src] cannot hold [M.material.name]."))
|
||||
return TRUE
|
||||
|
||||
var/sname = "[M.name]"
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
if((materials[material] || 0) + SHEET_MATERIAL_AMOUNT <= res_max_amount)
|
||||
if(M.amount >= 1)
|
||||
var/count = 0
|
||||
var/mutable_appearance/MA = mutable_appearance(icon, "material_insertion")
|
||||
MA.color = M.material.icon_colour
|
||||
//first play the insertion animation
|
||||
flick_overlay_view(MA, 1 SECONDS)
|
||||
|
||||
//now play the progress bar animation
|
||||
flick_overlay_view(mutable_appearance(icon, "fab_progress"), 1 SECONDS)
|
||||
|
||||
while((materials[material] || 0) + SHEET_MATERIAL_AMOUNT <= res_max_amount && M.amount >= 1)
|
||||
SSmaterials.add_material_amount(materials, material, M.perunit)
|
||||
M.use(1)
|
||||
count++
|
||||
to_chat(user, SPAN_NOTICE("You insert [count] [sname] into \the [src]."))
|
||||
|
||||
//Wake up, we have things to do (maybe)
|
||||
handle_queue()
|
||||
|
||||
else
|
||||
to_chat(user, SPAN_NOTICE("\The [src] cannot hold more [sname]."))
|
||||
return TRUE
|
||||
|
||||
/obj/structure/machinery/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/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\"")
|
||||
|
||||
/**
|
||||
* Adds a design to the queue
|
||||
*
|
||||
* * path: The path of the design to add
|
||||
*/
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/add_to_queue(path)
|
||||
var/datum/design/D = files.known_designs[path]
|
||||
if(!D)
|
||||
return
|
||||
queue += D
|
||||
|
||||
//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/mecha_part_fabricator/proc/remove_from_queue(index)
|
||||
queue.Cut(index, index + 1)
|
||||
|
||||
//If we're removing the first thing in the queue, stop the build timer
|
||||
if(index == 1)
|
||||
deltimer(build_callback_timer)
|
||||
build_callback_timer = null
|
||||
|
||||
//Wake up, we have things to do
|
||||
handle_queue()
|
||||
|
||||
/**
|
||||
* Handle the construction queue
|
||||
*/
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/handle_queue()
|
||||
|
||||
//No work to do or already busy, stop
|
||||
if(!length(queue) || build_callback_timer)
|
||||
//If we don't have a build in progress, revert to idle power usage
|
||||
if(!build_callback_timer)
|
||||
update_use_power(POWER_USE_IDLE)
|
||||
|
||||
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(can_build(D))
|
||||
update_use_power(POWER_USE_ACTIVE)
|
||||
|
||||
//Add the callback timer for printing, and remove the design from the queue
|
||||
build_callback_timer = addtimer(CALLBACK(src, PROC_REF(build), D), (D.time / production_speed), TIMER_UNIQUE|TIMER_STOPPABLE)
|
||||
//No queue removal here because we show how long it takes to build in the UI
|
||||
|
||||
else
|
||||
visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] flashes: Insufficient materials to complete build: [D.name]."))
|
||||
remove_from_queue(1)
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/can_build(var/datum/design/D)
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/M in D.materials)
|
||||
var/material = SSmaterials.material_to_path(M, FALSE)
|
||||
if(!material)
|
||||
material = M
|
||||
if((materials[material] || 0) < D.materials[M] * mat_efficiency)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Builds the given design, assuming all the necessary conditions are met
|
||||
*
|
||||
* * design_to_build: The design to build
|
||||
*/
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/build(datum/design/design_to_build)
|
||||
//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)
|
||||
|
||||
intent_message(MACHINE_SOUND)
|
||||
|
||||
if(design_to_build.build_path)
|
||||
var/loc_offset = get_step(src, dir)
|
||||
var/obj/new_item = design_to_build.Fabricate(loc_offset, src)
|
||||
visible_message("\The <b>[src]</b> pings, indicating that \the [new_item] is complete.", "You hear a ping.", intent_message = PING_SOUND)
|
||||
if(mat_efficiency != 1)
|
||||
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 and remove the thing from the queue
|
||||
build_callback_timer = null
|
||||
remove_from_queue(1)
|
||||
|
||||
//Do the queue handling for the next item, or to stop
|
||||
handle_queue()
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/get_queue_names()
|
||||
. = list()
|
||||
for(var/i = 1 to queue.len)
|
||||
var/datum/design/D = queue[i]
|
||||
. += list(list("name" = D.name, "time" = get_design_time(D), "index" = i))
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/get_build_options()
|
||||
. = list()
|
||||
for(var/path in files.known_designs)
|
||||
var/datum/design/D = files.known_designs[path]
|
||||
if(!D.build_path || !(D.build_type & MECHFAB) || !D.category || (D.category != category))
|
||||
continue
|
||||
. += list(list("name" = D.name, "desc" = D.desc, "type" = D.type, "category" = D.category, "resources" = get_design_resourses(D), "time" = get_design_time(D)))
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/get_design_resourses(var/datum/design/D)
|
||||
var/list/F = list()
|
||||
for(var/T in D.materials)
|
||||
F += "[SSmaterials.material_display_name(T)]: [D.materials[T] * mat_efficiency]"
|
||||
return english_list(F, and_text = ", ")
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/get_design_time(var/datum/design/D)
|
||||
return time2text(round(10 * D.time / production_speed), "mm:ss")
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/update_categories()
|
||||
categories = list()
|
||||
for(var/path in files.known_designs)
|
||||
var/datum/design/D = files.known_designs[path]
|
||||
if(!D.build_path || !(D.build_type & MECHFAB) || !D.category)
|
||||
continue
|
||||
categories |= D.category
|
||||
if(!category || !(category in categories))
|
||||
category = categories[1]
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/get_materials()
|
||||
. = list()
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
for(var/T in materials)
|
||||
. += list(list("name" = SSmaterials.material_display_name(T), "amount" = materials[T]))
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/eject_materials(var/material, var/amount)
|
||||
if(!amount)
|
||||
return
|
||||
SSmaterials.normalize_material_amounts(materials)
|
||||
material = SSmaterials.material_to_path(material, FALSE)
|
||||
if(!material)
|
||||
return
|
||||
var/stack_type = SSmaterials.material_stack_type(material)
|
||||
if(!stack_type)
|
||||
return
|
||||
|
||||
var/real_amount = min(round(amount / SHEET_MATERIAL_AMOUNT), round((materials[material] || 0) / SHEET_MATERIAL_AMOUNT))
|
||||
if(real_amount < 1)
|
||||
return
|
||||
var/obj/item/stack/material/S = new stack_type(loc, real_amount)
|
||||
S.update_icon()
|
||||
SSmaterials.remove_material_amount(materials, material, real_amount * SHEET_MATERIAL_AMOUNT)
|
||||
|
||||
/obj/structure/machinery/mecha_part_fabricator/proc/sync()
|
||||
sync_message = "Error: no console found."
|
||||
for(var/obj/structure/machinery/computer/rdconsole/RDC in get_area(src))
|
||||
if(!RDC.sync)
|
||||
continue
|
||||
for(var/id in RDC.files.known_tech)
|
||||
var/datum/tech/T = RDC.files.known_tech[id]
|
||||
files.AddTech2Known(T)
|
||||
files.RefreshResearch()
|
||||
sync_message = "Sync complete."
|
||||
update_categories()
|
||||
Reference in New Issue
Block a user