mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-29 11:02:05 +00:00
## About The Pull Request
1. **Qol Stuff**
- Screentips & examines for screwdriver, crowbar acts, multiool &
wirecutter Also for Alt click
- Techfabs can now also use the Mouse drag functionality to set drop
target for items
- Lathe printing animation now plays on loop instead of just flicking
once till printing is finished for more visual feedback
2. **Code Improvements**
- Merged `start_making()` with `do_make_item()`. That proc was like only
3 lines long and used only in 1 place so let's just move that code to
`ui_act()`
- Merged `user_print_item_id()` with `ui_act()`. Again was used only in
1 place so let's just move that code in to save some proc overhead
- Sets `processing_flags` for autolathe to `NONE` cause we don't use
`process()`
- Autodocs vars such as `hacked` , `shocked` etc & procs
- `maxmult` is now computed client side saving backend bandwidth,
`construction_time` is removed from lathes which did not use it
- Removed all usages of lathe taxes and their related vars, removed
engineering lathe no tax from ice moon, replaced with normal engineering
lathe
3. **Fixes**
- Lathe sheet insertion animations are now linked & work again for all
material types inserted via remote silo/local storage,
silver/titanium/plastic all play the same animation(that is
`protolathe_shiny` overlay). Other materials have their own respective
overlays
- Fixes #81243. Calling `update_static_data_for_all_viewers()` is too
expensive for the UI. We should instead use `SStgui.update_uis(src)`
which will report the `busy` status to the UI more immediatly
- Fixes #81236. Some problems with the params passed to the timer
callback. It should now print the correct number of requested items
- Fixes #81192. `design.materials` would runtime for custom material
items as they were list of texts not materials. We have to pass our
manually parsed list of materials for an specific item to ensure they
are set & used correctly. Same fixes apply for techfabs as well
## Changelog
🆑
qol: adds screentips & examines for screwdriver & crowbar acts & alt
click.
qol: techfabs can now use the mouse drop functionality to set drop
target.
qol: lathe printing animation plays on loop while printing rather than
flicking once for more visual feedback
fix: lathe sheet insertion animations are now linked & work again for
all material types inserted via remote silo/local storage
fix: printing custom materials items from autolathe works again.
fix: printing multiple items from lathes will actually print that
correct quantity of items requested.
fix: printing items the 2nd time around from lathes won't cause the UI
to reload each time.
code: autodoc for some vars & procs, merges procs.
refactor: Optimized code for autolathe & techfabs in general. Report
bugs on github
/🆑
---------
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
508 lines
17 KiB
Plaintext
508 lines
17 KiB
Plaintext
/// Component printer, creates components for integrated circuits.
|
|
/obj/machinery/component_printer
|
|
name = "component printer"
|
|
desc = "Produces components for the creation of integrated circuits."
|
|
icon = 'icons/obj/machines/wiremod_fab.dmi'
|
|
icon_state = "fab-idle"
|
|
circuit = /obj/item/circuitboard/machine/component_printer
|
|
|
|
/// The internal material bus
|
|
var/datum/component/remote_materials/materials
|
|
|
|
density = TRUE
|
|
|
|
/// The techweb the printer will get researched designs from
|
|
var/datum/techweb/techweb
|
|
|
|
/// The current unlocked circuit component designs. Used by integrated circuits to print off circuit components remotely.
|
|
var/list/current_unlocked_designs = list()
|
|
|
|
/// The efficiency of this machine
|
|
var/efficiency_coeff = 1
|
|
|
|
/obj/machinery/component_printer/Initialize(mapload)
|
|
. = ..()
|
|
materials = AddComponent(/datum/component/remote_materials, mapload)
|
|
|
|
/obj/machinery/component_printer/LateInitialize()
|
|
. = ..()
|
|
if(!CONFIG_GET(flag/no_default_techweb_link) && !techweb)
|
|
CONNECT_TO_RND_SERVER_ROUNDSTART(techweb, src)
|
|
if(techweb)
|
|
on_connected_techweb()
|
|
|
|
/obj/machinery/component_printer/proc/connect_techweb(datum/techweb/new_techweb)
|
|
if(techweb)
|
|
UnregisterSignal(techweb, list(COMSIG_TECHWEB_ADD_DESIGN, COMSIG_TECHWEB_REMOVE_DESIGN))
|
|
techweb = new_techweb
|
|
if(!isnull(techweb))
|
|
on_connected_techweb()
|
|
|
|
/obj/machinery/component_printer/proc/on_connected_techweb()
|
|
for (var/researched_design_id in techweb.researched_designs)
|
|
var/datum/design/design = SSresearch.techweb_design_by_id(researched_design_id)
|
|
if (!(design.build_type & COMPONENT_PRINTER) || !ispath(design.build_path, /obj/item/circuit_component))
|
|
continue
|
|
|
|
current_unlocked_designs[design.build_path] = design.id
|
|
|
|
RegisterSignal(techweb, COMSIG_TECHWEB_ADD_DESIGN, PROC_REF(on_research))
|
|
RegisterSignal(techweb, COMSIG_TECHWEB_REMOVE_DESIGN, PROC_REF(on_removed))
|
|
|
|
/obj/machinery/component_printer/multitool_act(mob/living/user, obj/item/multitool/tool)
|
|
if(!QDELETED(tool.buffer) && istype(tool.buffer, /datum/techweb))
|
|
connect_techweb(tool.buffer)
|
|
return TRUE
|
|
|
|
/obj/machinery/component_printer/proc/on_research(datum/source, datum/design/added_design, custom)
|
|
SIGNAL_HANDLER
|
|
if (!(added_design.build_type & COMPONENT_PRINTER) || !ispath(added_design.build_path, /obj/item/circuit_component))
|
|
return
|
|
current_unlocked_designs[added_design.build_path] = added_design.id
|
|
|
|
/obj/machinery/component_printer/proc/on_removed(datum/source, datum/design/added_design, custom)
|
|
SIGNAL_HANDLER
|
|
if (!(added_design.build_type & COMPONENT_PRINTER) || !ispath(added_design.build_path, /obj/item/circuit_component))
|
|
return
|
|
current_unlocked_designs -= added_design.build_path
|
|
|
|
|
|
/obj/machinery/component_printer/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "ComponentPrinter", name)
|
|
ui.open()
|
|
|
|
/obj/machinery/component_printer/ui_assets(mob/user)
|
|
return list(
|
|
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
|
|
)
|
|
|
|
/obj/machinery/component_printer/RefreshParts()
|
|
. = ..()
|
|
|
|
if(materials)
|
|
var/total_storage = 0
|
|
|
|
for(var/datum/stock_part/matter_bin/bin in component_parts)
|
|
total_storage += bin.tier * (37.5*SHEET_MATERIAL_AMOUNT)
|
|
|
|
materials.set_local_size(total_storage)
|
|
|
|
efficiency_coeff = 0
|
|
|
|
for(var/datum/stock_part/servo/servo in component_parts)
|
|
///we do -1 because normal manipulators rating of 1 gives us 1-1=0 i.e no decrement in cost
|
|
efficiency_coeff += servo.tier-1
|
|
|
|
///linear interpolation between full cost i.e 1 & 1/8th the cost i.e 0.125
|
|
///we do it in 6 steps because maximum rating of 2 manipulators is 8 but -1 gives us 6
|
|
efficiency_coeff = 1.0+((0.125-1.0)*(efficiency_coeff / 6))
|
|
|
|
update_static_data_for_all_viewers()
|
|
|
|
/obj/machinery/component_printer/proc/print_component(typepath)
|
|
var/design_id = current_unlocked_designs[typepath]
|
|
|
|
var/datum/design/design = SSresearch.techweb_design_by_id(design_id)
|
|
if (!(design.build_type & COMPONENT_PRINTER))
|
|
return
|
|
|
|
if (materials.on_hold())
|
|
return
|
|
|
|
if (!materials.mat_container.has_materials(design.materials, efficiency_coeff))
|
|
return
|
|
|
|
materials.use_materials(design.materials, efficiency_coeff, 1, "printed", "[design.name]")
|
|
return new design.build_path(drop_location())
|
|
|
|
/obj/machinery/component_printer/ui_act(action, list/params)
|
|
. = ..()
|
|
if (.)
|
|
return
|
|
|
|
switch (action)
|
|
if ("print")
|
|
var/design_id = params["designId"]
|
|
if (!techweb.researched_designs[design_id])
|
|
return TRUE
|
|
|
|
var/datum/design/design = SSresearch.techweb_design_by_id(design_id)
|
|
if (!(design.build_type & COMPONENT_PRINTER))
|
|
return TRUE
|
|
|
|
if (materials.on_hold())
|
|
say("Mineral access is on hold, please contact the quartermaster.")
|
|
return TRUE
|
|
|
|
if (!materials.mat_container.has_materials(design.materials, efficiency_coeff))
|
|
say("Not enough materials.")
|
|
return TRUE
|
|
|
|
balloon_alert_to_viewers("printed [design.name]")
|
|
|
|
materials.use_materials(design.materials, efficiency_coeff, 1, "printed", "[design.name]")
|
|
var/atom/printed_design = new design.build_path(drop_location())
|
|
printed_design.pixel_x = printed_design.base_pixel_x + rand(-5, 5)
|
|
printed_design.pixel_y = printed_design.base_pixel_y + rand(-5, 5)
|
|
if ("remove_mat")
|
|
var/datum/material/material = locate(params["ref"])
|
|
var/amount = text2num(params["amount"])
|
|
// SAFETY: eject_sheets checks for valid mats
|
|
materials.eject_sheets(material, amount)
|
|
|
|
return TRUE
|
|
|
|
/obj/machinery/component_printer/ui_data(mob/user)
|
|
var/list/data = list()
|
|
data["materials"] = materials.mat_container.ui_data()
|
|
return data
|
|
|
|
/obj/machinery/component_printer/ui_static_data(mob/user)
|
|
var/list/data = materials.mat_container.ui_static_data()
|
|
|
|
var/list/designs = list()
|
|
|
|
var/datum/asset/spritesheet/research_designs/spritesheet = get_asset_datum(/datum/asset/spritesheet/research_designs)
|
|
var/size32x32 = "[spritesheet.name]32x32"
|
|
|
|
// for (var/datum/design/component/component_design_type as anything in subtypesof(/datum/design/component))
|
|
for (var/researched_design_id in techweb.researched_designs)
|
|
var/datum/design/design = SSresearch.techweb_design_by_id(researched_design_id)
|
|
if (!(design.build_type & COMPONENT_PRINTER))
|
|
continue
|
|
|
|
var/list/cost = list()
|
|
for(var/datum/material/mat in design.materials)
|
|
cost[mat.name] = OPTIMAL_COST(design.materials[mat] * efficiency_coeff)
|
|
|
|
var/icon_size = spritesheet.icon_size_id(design.id)
|
|
designs[researched_design_id] = list(
|
|
"name" = design.name,
|
|
"desc" = design.desc,
|
|
"cost" = cost,
|
|
"id" = researched_design_id,
|
|
"categories" = design.category,
|
|
"icon" = "[icon_size == size32x32 ? "" : "[icon_size] "][design.id]"
|
|
)
|
|
|
|
data["designs"] = designs
|
|
|
|
return data
|
|
|
|
/obj/machinery/component_printer/attackby(obj/item/weapon, mob/living/user, params)
|
|
if(istype(weapon, /obj/item/integrated_circuit) && !user.combat_mode)
|
|
var/obj/item/integrated_circuit/circuit = weapon
|
|
circuit.linked_component_printer = WEAKREF(src)
|
|
circuit.update_static_data_for_all_viewers()
|
|
balloon_alert(user, "successfully linked to the integrated circuit")
|
|
return
|
|
return ..()
|
|
|
|
/obj/machinery/component_printer/crowbar_act(mob/living/user, obj/item/tool)
|
|
if(..())
|
|
return TRUE
|
|
return default_deconstruction_crowbar(tool)
|
|
|
|
/obj/machinery/component_printer/screwdriver_act(mob/living/user, obj/item/tool)
|
|
if(..())
|
|
return TRUE
|
|
return default_deconstruction_screwdriver(user, "fab-o", "fab-idle", tool)
|
|
|
|
/obj/machinery/component_printer/proc/get_material_cost_data(list/materials, efficiency_coeff)
|
|
var/list/data = list()
|
|
|
|
for (var/datum/material/material_type as anything in materials)
|
|
data[initial(material_type.name)] = materials[material_type] * efficiency_coeff
|
|
|
|
return data
|
|
|
|
/obj/machinery/debug_component_printer
|
|
name = "debug component printer"
|
|
desc = "Produces components for the creation of integrated circuits."
|
|
icon = 'icons/obj/machines/wiremod_fab.dmi'
|
|
icon_state = "fab-idle"
|
|
|
|
/// All of the possible circuit designs stored by this debug printer
|
|
var/list/all_circuit_designs
|
|
|
|
density = TRUE
|
|
|
|
/obj/machinery/debug_component_printer/Initialize(mapload)
|
|
. = ..()
|
|
all_circuit_designs = list()
|
|
|
|
for(var/id in SSresearch.techweb_designs)
|
|
var/datum/design/design = SSresearch.techweb_design_by_id(id)
|
|
if((design.build_type & COMPONENT_PRINTER) && design.build_path)
|
|
all_circuit_designs[design.build_path] = list(
|
|
"name" = design.name,
|
|
"description" = design.desc,
|
|
"materials" = design.materials,
|
|
"categories" = design.category
|
|
)
|
|
|
|
for(var/obj/item/circuit_component/component as anything in subtypesof(/obj/item/circuit_component))
|
|
var/categories = list("Inaccessible")
|
|
if(initial(component.circuit_flags) & CIRCUIT_FLAG_ADMIN)
|
|
categories = list("Admin")
|
|
if(!(component in all_circuit_designs))
|
|
all_circuit_designs[component] = list(
|
|
"name" = initial(component.display_name),
|
|
"description" = initial(component.desc),
|
|
"materials" = list(),
|
|
"categories" = categories,
|
|
)
|
|
|
|
/obj/machinery/debug_component_printer/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "ComponentPrinter", name)
|
|
ui.open()
|
|
|
|
/obj/machinery/debug_component_printer/ui_assets(mob/user)
|
|
return list(
|
|
get_asset_datum(/datum/asset/spritesheet/sheetmaterials),
|
|
get_asset_datum(/datum/asset/spritesheet/research_designs)
|
|
)
|
|
|
|
/obj/machinery/debug_component_printer/ui_act(action, list/params)
|
|
. = ..()
|
|
if (.)
|
|
return
|
|
|
|
switch (action)
|
|
if ("print")
|
|
var/build_path = text2path(params["designId"])
|
|
if (!build_path)
|
|
return TRUE
|
|
|
|
var/list/design = all_circuit_designs[build_path]
|
|
if(!design)
|
|
return TRUE
|
|
|
|
balloon_alert_to_viewers("printed [design["name"]]")
|
|
var/atom/printed_design = new build_path(drop_location())
|
|
printed_design.pixel_x = printed_design.base_pixel_x + rand(-5, 5)
|
|
printed_design.pixel_y = printed_design.base_pixel_y + rand(-5, 5)
|
|
|
|
return TRUE
|
|
|
|
/obj/machinery/debug_component_printer/ui_static_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
data["materials"] = list()
|
|
data["designs"] = all_circuit_designs
|
|
|
|
return data
|
|
|
|
/// Module duplicator, allows you to save and recreate module components.
|
|
/obj/machinery/module_duplicator
|
|
name = "module duplicator"
|
|
desc = "Allows you to duplicate module components so that you don't have to recreate them. Scan a module component over this machine to add it as an entry."
|
|
icon = 'icons/obj/machines/wiremod_fab.dmi'
|
|
icon_state = "module-fab-idle"
|
|
circuit = /obj/item/circuitboard/machine/module_duplicator
|
|
density = TRUE
|
|
|
|
///The internal material bus
|
|
var/datum/component/remote_materials/materials
|
|
///List of designs scanned and saved
|
|
var/list/scanned_designs = list()
|
|
///Constant material cost per component
|
|
var/cost_per_component = SHEET_MATERIAL_AMOUNT / 10
|
|
///Cost efficiency of this machine
|
|
var/efficiency_coeff = 1
|
|
|
|
/obj/machinery/module_duplicator/Initialize(mapload)
|
|
. = ..()
|
|
|
|
materials = AddComponent(/datum/component/remote_materials, mapload)
|
|
|
|
/obj/machinery/module_duplicator/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "ComponentPrinter", name)
|
|
ui.open()
|
|
|
|
/obj/machinery/module_duplicator/ui_assets(mob/user)
|
|
return list(
|
|
get_asset_datum(/datum/asset/spritesheet/sheetmaterials),
|
|
get_asset_datum(/datum/asset/spritesheet/research_designs)
|
|
)
|
|
|
|
/obj/machinery/module_duplicator/RefreshParts()
|
|
. = ..()
|
|
|
|
if(materials)
|
|
var/total_storage = 0
|
|
|
|
for(var/datum/stock_part/matter_bin/bin in component_parts)
|
|
total_storage += bin.tier * (37.5*SHEET_MATERIAL_AMOUNT)
|
|
|
|
materials.set_local_size(total_storage)
|
|
|
|
efficiency_coeff = 0
|
|
|
|
for(var/datum/stock_part/servo/servo in component_parts)
|
|
///we do -1 because normal manipulators rating of 1 gives us 1-1=0 i.e no decrement in cost
|
|
efficiency_coeff += servo.tier - 1
|
|
|
|
///linear interpolation between full cost i.e 1 & 1/8th the cost i.e 0.125
|
|
///we do it in 6 steps because maximum rating of 2 manipulators is 8 but -1 gives us 6
|
|
efficiency_coeff = 1.0 + ((0.125 - 1.0) * (efficiency_coeff / 6))
|
|
|
|
update_static_data_for_all_viewers()
|
|
|
|
/obj/machinery/module_duplicator/ui_act(action, list/params)
|
|
. = ..()
|
|
if (.)
|
|
return
|
|
|
|
switch (action)
|
|
if ("print")
|
|
var/design_id = text2num(params["designId"])
|
|
|
|
if (design_id < 1 || design_id > length(scanned_designs))
|
|
return TRUE
|
|
|
|
var/list/design = scanned_designs[design_id]
|
|
|
|
if (materials.on_hold())
|
|
say("Mineral access is on hold, please contact the quartermaster.")
|
|
return TRUE
|
|
|
|
if (!materials.mat_container.has_materials(design["materials"], efficiency_coeff))
|
|
say("Not enough materials.")
|
|
return TRUE
|
|
|
|
materials.use_materials(design["materials"], efficiency_coeff, 1, design["name"], design["materials"])
|
|
print_module(design)
|
|
balloon_alert_to_viewers("printed [design["name"]]")
|
|
if ("remove_mat")
|
|
var/datum/material/material = locate(params["ref"])
|
|
var/amount = text2num(params["amount"])
|
|
// SAFETY: eject_sheets checks for valid mats
|
|
materials.eject_sheets(material, amount)
|
|
|
|
return TRUE
|
|
|
|
/obj/machinery/module_duplicator/proc/print_module(list/design)
|
|
flick("module-fab-print", src)
|
|
addtimer(CALLBACK(src, PROC_REF(finish_module_print), design), 1.6 SECONDS)
|
|
|
|
/obj/machinery/module_duplicator/proc/finish_module_print(list/design)
|
|
var/atom/movable/created_atom
|
|
if(design["integrated_circuit"])
|
|
var/obj/item/integrated_circuit/circuit = new(drop_location())
|
|
var/list/errors = list()
|
|
circuit.load_circuit_data(design["dupe_data"], errors)
|
|
if(length(errors))
|
|
stack_trace("Error loading user saved circuit [errors.Join(", ")].")
|
|
created_atom = circuit
|
|
else
|
|
var/obj/item/circuit_component/module/module = new(drop_location())
|
|
module.load_data_from_list(design["dupe_data"])
|
|
created_atom = module
|
|
created_atom.pixel_x = created_atom.base_pixel_x + rand(-5, 5)
|
|
created_atom.pixel_y = created_atom.base_pixel_y + rand(-5, 5)
|
|
|
|
/obj/machinery/module_duplicator/attackby(obj/item/weapon, mob/user, params)
|
|
var/list/data = list()
|
|
|
|
if(istype(weapon, /obj/item/circuit_component/module))
|
|
var/obj/item/circuit_component/module/module = weapon
|
|
if(HAS_TRAIT(module, TRAIT_CIRCUIT_UNDUPABLE))
|
|
balloon_alert(user, "integrated circuit cannot be saved!")
|
|
return ..()
|
|
|
|
data["dupe_data"] = list()
|
|
module.save_data_to_list(data["dupe_data"])
|
|
|
|
data["name"] = module.display_name
|
|
data["desc"] = "A module that has been loaded in by [user]."
|
|
data["materials"] = list(GET_MATERIAL_REF(/datum/material/glass) = module.circuit_size * cost_per_component)
|
|
else if(istype(weapon, /obj/item/integrated_circuit))
|
|
var/obj/item/integrated_circuit/integrated_circuit = weapon
|
|
if(HAS_TRAIT(integrated_circuit, TRAIT_CIRCUIT_UNDUPABLE))
|
|
balloon_alert(user, "integrated circuit cannot be saved!")
|
|
return ..()
|
|
data["dupe_data"] = integrated_circuit.convert_to_json()
|
|
|
|
data["name"] = integrated_circuit.display_name
|
|
data["desc"] = "An integrated circuit that has been loaded in by [user]."
|
|
|
|
var/datum/design/integrated_circuit/circuit_design = SSresearch.techweb_design_by_id("integrated_circuit")
|
|
var/materials = list(GET_MATERIAL_REF(/datum/material/glass) = integrated_circuit.current_size * cost_per_component)
|
|
for(var/material_type in circuit_design.materials)
|
|
materials[material_type] += circuit_design.materials[material_type]
|
|
|
|
data["materials"] = materials
|
|
data["integrated_circuit"] = TRUE
|
|
|
|
if(!length(data))
|
|
return ..()
|
|
|
|
if(!data["name"])
|
|
balloon_alert(user, "it needs a name!")
|
|
return ..()
|
|
|
|
for(var/list/component_data as anything in scanned_designs)
|
|
if(component_data["name"] == data["name"])
|
|
balloon_alert(user, "name already exists!")
|
|
return ..()
|
|
|
|
flick("module-fab-scan", src)
|
|
addtimer(CALLBACK(src, PROC_REF(finish_module_scan), user, data), 1.4 SECONDS)
|
|
|
|
/obj/machinery/module_duplicator/proc/finish_module_scan(mob/user, data)
|
|
scanned_designs += list(data)
|
|
|
|
balloon_alert(user, "module has been saved.")
|
|
playsound(src, 'sound/machines/ping.ogg', 50)
|
|
|
|
update_static_data_for_all_viewers()
|
|
|
|
/obj/machinery/module_duplicator/ui_data(mob/user)
|
|
var/list/data = list()
|
|
data["materials"] = materials.mat_container.ui_data()
|
|
return data
|
|
|
|
/obj/machinery/module_duplicator/ui_static_data(mob/user)
|
|
var/list/data = materials.mat_container.ui_static_data()
|
|
|
|
var/list/designs = list()
|
|
|
|
var/index = 1
|
|
for (var/list/design as anything in scanned_designs)
|
|
|
|
var/list/cost = list()
|
|
var/list/materials = design["materials"]
|
|
for(var/datum/material/mat in materials)
|
|
cost[mat.name] = OPTIMAL_COST(materials[mat] * efficiency_coeff)
|
|
|
|
designs["[index]"] = list(
|
|
"name" = design["name"],
|
|
"desc" = design["desc"],
|
|
"cost" = cost,
|
|
"id" = "[index]",
|
|
"icon" = "integrated_circuit",
|
|
"categories" = list("/Saved Circuits"),
|
|
)
|
|
index++
|
|
|
|
data["designs"] = designs
|
|
|
|
return data
|
|
|
|
/obj/machinery/module_duplicator/crowbar_act(mob/living/user, obj/item/tool)
|
|
if(..())
|
|
return TRUE
|
|
return default_deconstruction_crowbar(tool)
|
|
|
|
/obj/machinery/module_duplicator/screwdriver_act(mob/living/user, obj/item/tool)
|
|
if(..())
|
|
return TRUE
|
|
return default_deconstruction_screwdriver(user, "module-fab-o", "module-fab-idle", tool)
|