Files
CHOMPStation2/code/game/machinery/autolathe.dm
2025-11-18 01:18:14 +01:00

286 lines
8.2 KiB
Plaintext

/obj/machinery/autolathe
name = "autolathe"
desc = "It produces items using metal and glass."
icon_state = "autolathe"
density = TRUE
anchored = TRUE
use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 2000
clicksound = "keyboard"
clickvol = 30
circuit = /obj/item/circuitboard/autolathe
var/static/datum/category_collection/autolathe/autolathe_recipes
var/hacked = 0
var/disabled = 0
var/shocked = 0
var/busy = 0
var/mat_efficiency = 1
var/build_time = 50
var/datum/wires/autolathe/wires = null
var/mb_rating = 0
var/man_rating = 0
var/filtertext
/// Reference to a remote material inventory, such as an ore silo.
var/datum/component/remote_materials/rmat
/obj/machinery/autolathe/Initialize(mapload)
rmat = AddComponent( \
/datum/component/remote_materials, \
mapload, \
mat_container_signals = list( \
COMSIG_MATCONTAINER_ITEM_CONSUMED = TYPE_PROC_REF(/obj/machinery/autolathe, AfterMaterialInsert) \
))
. = ..()
if(!autolathe_recipes)
autolathe_recipes = new()
wires = new(src)
default_apply_parts()
RefreshParts()
/obj/machinery/autolathe/Destroy()
qdel(wires)
wires = null
return ..()
/obj/machinery/autolathe/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Autolathe", name)
ui.open()
/obj/machinery/autolathe/tgui_status(mob/user)
if(disabled)
return STATUS_CLOSE
return ..()
/obj/machinery/autolathe/tgui_static_data(mob/user)
var/list/data = ..()
var/list/categories = list()
var/list/recipes = list()
for(var/datum/category_group/autolathe/A in autolathe_recipes.categories)
categories += A.name
for(var/datum/category_item/autolathe/M in A.items)
if(M.hidden && !hacked)
continue
if(M.man_rating > man_rating)
continue
recipes.Add(list(list(
"category" = A.name,
"name" = M.name,
"ref" = REF(M),
"requirements" = M.resources,
"hidden" = M.hidden,
"coeff_applies" = !M.no_scale,
"is_stack" = M.is_stack,
)))
data["recipes"] = recipes
data["categories"] = categories
var/list/material_data = rmat.mat_container?.tgui_static_data(user)
if(material_data)
data += material_data
return data
/obj/machinery/autolathe/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet_batched/sheetmaterials)
)
/obj/machinery/autolathe/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["busy"] = busy
var/list/material_data = rmat.mat_container?.tgui_data(user, TRUE)
if(material_data)
data["materials"] = material_data
data["mat_efficiency"] = mat_efficiency
return data
/obj/machinery/autolathe/interact(mob/user)
if(panel_open)
return wires.Interact(user)
if(disabled)
to_chat(user, span_danger("\The [src] is disabled!"))
return
if(shocked)
shock(user, 50)
tgui_interact(user)
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(busy)
to_chat(user, span_notice("\The [src] is busy. Please wait for completion of previous operation."))
return
if(default_deconstruction_screwdriver(user, O))
interact(user)
return
if(default_deconstruction_crowbar(user, O))
return
if(default_part_replacement(user, O))
return
if(stat)
return
if(panel_open)
//Don't eat multitools or wirecutters used on an open lathe.
if(O.has_tool_quality(TOOL_MULTITOOL) || O.has_tool_quality(TOOL_WIRECUTTER))
wires.Interact(user)
return
if(is_robot_module(O))
return 0
if(istype(O,/obj/item/ammo_magazine/clip) || istype(O,/obj/item/ammo_magazine/s357) || istype(O,/obj/item/ammo_magazine/s38) || istype (O,/obj/item/ammo_magazine/s44)/* VOREstation Edit*/) // Prevents ammo recycling exploit with speedloaders.
to_chat(user, "\The [O] is too hazardous to recycle with the autolathe!")
return
return ..()
/obj/machinery/autolathe/attack_hand(mob/user as mob)
interact(user)
/obj/machinery/autolathe/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
add_fingerprint(ui.user)
if(busy)
to_chat(ui.user, span_notice("The autolathe is busy. Please wait for completion of previous operation."))
return
switch(action)
if("make")
var/datum/category_item/autolathe/making = locate(params["make"])
if(!istype(making))
return
if(making.hidden && !hacked)
return
var/multiplier = (params["multiplier"] || 1)
if(making.is_stack)
var/max_sheets
for(var/material in making.resources)
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
var/sheets = round(rmat.mat_container.get_material_amount(material) / round(making.resources[material] * coeff))
if(isnull(max_sheets) || max_sheets > sheets)
max_sheets = sheets
if(!isnull(rmat.mat_container.get_material_amount(material)) && rmat.mat_container.get_material_amount(material) < round(making.resources[material] * coeff))
max_sheets = 0
//Build list of multipliers for sheets.
multiplier = tgui_input_number(ui.user, "How many do you want to print? (0-[max_sheets])", null, null, max_sheets, 0)
if(!multiplier || multiplier <= 0 || (multiplier != round(multiplier)) || multiplier > max_sheets || tgui_status(ui.user, state) != STATUS_INTERACTIVE)
return FALSE
//Check if we still have the materials.
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
if(!rmat.can_use_resource())
return
if(LAZYLEN(making.resources))
if(!rmat.mat_container.has_materials(making.resources, coeff, multiplier))
return
rmat.use_materials(making.resources, coeff, multiplier)
busy = making.name
update_use_power(USE_POWER_ACTIVE)
update_icon() // So lid closes
sleep(build_time)
busy = 0
update_use_power(USE_POWER_IDLE)
update_icon() // So lid opens
//Sanity check.
if(!making || !src)
return
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
if(LAZYLEN(I.matter)) // Sadly we must obey the laws of equivalent exchange.
I.matter.Cut()
else
I.matter = list()
for(var/material in making.resources) // Handle the datum's autoscaling for waste, so we're properly wasting material, but not so much if we have efficiency.
I.matter[material] = round(making.resources[material] / (making.no_scale ? 1 : 1.25)) * (making.no_scale ? 1 : mat_efficiency)
flick("[initial(icon_state)]_finish", src)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
S.set_amount(multiplier)
else
for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack.
I = new making.path(src.loc)
// We've already deducted the cost of multiple items. Process the matter the same.
if(LAZYLEN(I.matter))
I.matter.Cut()
else
I.matter = list()
for(var/material in making.resources)
I.matter[material] = round(making.resources[material] / (making.no_scale ? 1 : 1.25)) * (making.no_scale ? 1 : mat_efficiency)
return TRUE
return FALSE
/obj/machinery/autolathe/update_icon()
cut_overlays()
icon_state = initial(icon_state)
if(panel_open)
add_overlay("[icon_state]_panel")
if(stat & NOPOWER)
return
if(busy)
icon_state = "[icon_state]_work"
//Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts()
..()
mb_rating = 0
man_rating = 0
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
mb_rating += MB.rating
for(var/obj/item/stock_parts/manipulator/M in component_parts)
man_rating += M.rating
rmat.set_local_size(mb_rating * 75000)
build_time = 50 / man_rating
mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5
update_tgui_static_data(usr)
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
flick("autolathe_loading", src)//plays metal insertion animation
// use_power(min(1000, amount_inserted / 100))
SStgui.update_uis(src)
/obj/machinery/autolathe/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
. += span_notice("The status display reads: Storing up to <b>[rmat.local_size]</b> material units.<br>Material consumption at <b>[mat_efficiency*100]%</b>.")