mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 01:49:19 +00:00
480 lines
15 KiB
Plaintext
480 lines
15 KiB
Plaintext
/obj/machinery/autolathe
|
|
name = "autolathe"
|
|
desc = "It produces items using metal and glass."
|
|
icon_state = "autolathe"
|
|
density = TRUE
|
|
use_power = IDLE_POWER_USE
|
|
idle_power_usage = 10
|
|
active_power_usage = 100
|
|
circuit = /obj/item/circuitboard/machine/autolathe
|
|
layer = BELOW_OBJ_LAYER
|
|
|
|
var/operating = FALSE
|
|
var/list/L = list()
|
|
var/list/LL = list()
|
|
var/hacked = FALSE
|
|
var/disabled = FALSE
|
|
var/shocked = FALSE
|
|
var/hack_wire
|
|
var/disable_wire
|
|
var/shock_wire
|
|
|
|
var/busy = FALSE
|
|
|
|
///the multiplier for how much materials the created object takes from this machines stored materials
|
|
var/creation_efficiency = 1.6
|
|
|
|
var/datum/design/being_built
|
|
var/datum/techweb/stored_research
|
|
var/list/datum/design/matching_designs
|
|
var/selected_category = "None"
|
|
var/base_price = 25
|
|
var/hacked_price = 50
|
|
|
|
var/list/categories = list(
|
|
"Tools",
|
|
"Electronics",
|
|
"Construction",
|
|
"T-Comm",
|
|
"Security",
|
|
"Machinery",
|
|
"Medical",
|
|
"Misc",
|
|
"Dinnerware",
|
|
"Imported"
|
|
)
|
|
|
|
/obj/machinery/autolathe/Initialize(mapload)
|
|
. = ..()
|
|
wires = new /datum/wires/autolathe(src)
|
|
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
|
|
matching_designs = list()
|
|
|
|
/obj/machinery/autolathe/ComponentInitialize()
|
|
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID], 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
|
|
|
/obj/machinery/autolathe/Destroy()
|
|
QDEL_NULL(wires)
|
|
return ..()
|
|
|
|
/obj/machinery/autolathe/ui_interact(mob/user, datum/tgui/ui)
|
|
. = ..()
|
|
if(!is_operational())
|
|
return
|
|
|
|
if(shocked && !(stat & NOPOWER))
|
|
shock(user,50)
|
|
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "Autolathe", capitalize(src.name))
|
|
ui.open()
|
|
|
|
/obj/machinery/autolathe/ui_data(mob/user)
|
|
var/list/data = list()
|
|
data["materials"] = list()
|
|
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
|
data["materialtotal"] = materials.total_amount
|
|
data["materialsmax"] = materials.max_amount
|
|
data["categories"] = categories
|
|
data["designs"] = list()
|
|
data["active"] = busy
|
|
|
|
for(var/mat_id in materials.materials)
|
|
var/datum/material/M = mat_id
|
|
var/mineral_count = materials.materials[mat_id]
|
|
var/list/material_data = list(
|
|
name = M.name,
|
|
mineral_amount = mineral_count,
|
|
matcolour = M.color,
|
|
)
|
|
data["materials"] += list(material_data)
|
|
if(selected_category != "None" && !length(matching_designs))
|
|
data["designs"] = handle_designs(stored_research.researched_designs, TRUE)
|
|
else
|
|
data["designs"] = handle_designs(matching_designs, FALSE)
|
|
return data
|
|
|
|
/obj/machinery/autolathe/proc/handle_designs(list/designs, categorycheck)
|
|
var/list/output = list()
|
|
for(var/v in designs)
|
|
var/datum/design/D = categorycheck ? SSresearch.techweb_design_by_id(v) : v
|
|
if(categorycheck)
|
|
if(!(selected_category in D.category))
|
|
continue
|
|
var/unbuildable = FALSE // we can't build the design currently
|
|
var/m10 = FALSE // 10x mult
|
|
var/m25 = FALSE // 25x mult
|
|
var/m50 = FALSE // 50x mult
|
|
var/m5 = FALSE // 5x mult
|
|
var/sheets = FALSE // sheets or no?
|
|
if(disabled || !can_build(D))
|
|
unbuildable = TRUE
|
|
var/max_multiplier = unbuildable ? 0 : 1
|
|
if(ispath(D.build_path, /obj/item/stack))
|
|
sheets = TRUE
|
|
if(!unbuildable)
|
|
var/datum/component/material_container/mats = GetComponent(/datum/component/material_container)
|
|
for(var/datum/material/mat in D.materials)
|
|
max_multiplier = min(D.maxstack, round(mats.get_material_amount(mat)/D.materials[mat]))
|
|
if (max_multiplier>10 && !disabled)
|
|
m10 = TRUE
|
|
if (max_multiplier>25 && !disabled)
|
|
m25 = TRUE
|
|
else
|
|
if(!unbuildable)
|
|
if(!disabled && can_build(D, 5))
|
|
m5 = TRUE
|
|
if(!disabled && can_build(D, 10))
|
|
m10 = TRUE
|
|
var/datum/component/material_container/mats = GetComponent(/datum/component/material_container)
|
|
for(var/datum/material/mat in D.materials)
|
|
max_multiplier = min(50, round(mats.get_material_amount(mat)/(D.materials[mat] * creation_efficiency)))
|
|
|
|
var/list/design = list(
|
|
name = D.name,
|
|
id = D.id,
|
|
ref = REF(src),
|
|
cost = get_design_cost(D),
|
|
buildable = unbuildable,
|
|
mult5 = m5,
|
|
mult10 = m10,
|
|
mult25 = m25,
|
|
mult50 = m50,
|
|
sheet = sheets,
|
|
maxmult = max_multiplier,
|
|
)
|
|
output += list(design)
|
|
return output
|
|
|
|
/obj/machinery/autolathe/ui_act(action, params)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
if(action == "menu")
|
|
selected_category = null
|
|
matching_designs.Cut()
|
|
. = TRUE
|
|
|
|
if(action == "category")
|
|
selected_category = params["selectedCategory"]
|
|
matching_designs.Cut()
|
|
. = TRUE
|
|
|
|
if(action == "search")
|
|
matching_designs.Cut()
|
|
|
|
for(var/v in stored_research.researched_designs)
|
|
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
|
if(findtext(D.name,params["to_search"]))
|
|
matching_designs.Add(D)
|
|
. = TRUE
|
|
|
|
if(action == "make")
|
|
if (!busy)
|
|
/////////////////
|
|
//href protection
|
|
being_built = stored_research.isDesignResearchedID(params["id"])
|
|
if(!being_built)
|
|
return
|
|
|
|
var/multiplier = text2num(params["multiplier"])
|
|
if(!multiplier)
|
|
to_chat(usr, span_alert("[src] only accepts a numerical multiplier!"))
|
|
return
|
|
var/is_stack = ispath(being_built.build_path, /obj/item/stack)
|
|
multiplier = clamp(round(multiplier),1,50)
|
|
|
|
/////////////////
|
|
|
|
var/coeff = (is_stack ? 1 : creation_efficiency) //stacks are unaffected by production coefficient
|
|
var/total_amount = 0
|
|
|
|
for(var/MAT in being_built.materials)
|
|
total_amount += being_built.materials[MAT]
|
|
|
|
var/power = max(2000, (total_amount)*multiplier/5) //Change this to use all materials
|
|
|
|
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
|
|
|
var/list/materials_used = list()
|
|
var/list/custom_materials = list() //These will apply their material effect, This should usually only be one.
|
|
|
|
for(var/MAT in being_built.materials)
|
|
var/datum/material/used_material = MAT
|
|
var/amount_needed = being_built.materials[MAT] * coeff * multiplier
|
|
if(istext(used_material)) //This means its a category
|
|
var/list/list_to_show = list()
|
|
for(var/i in SSmaterials.materials_by_category[used_material])
|
|
if(materials.materials[i] > 0)
|
|
list_to_show += i
|
|
|
|
used_material = tgui_input_list(usr, "Choose [used_material]", "Custom Material", sortList(list_to_show, /proc/cmp_typepaths_asc))
|
|
if(isnull(used_material))
|
|
return //Didn't pick any material, so you can't build shit either.
|
|
custom_materials[used_material] += amount_needed
|
|
|
|
materials_used[used_material] = amount_needed
|
|
|
|
if(materials.has_materials(materials_used))
|
|
busy = TRUE
|
|
to_chat(usr, span_notice("You print [multiplier] item(s) from the [src]"))
|
|
use_power(power)
|
|
icon_state = "autolathe_n"
|
|
var/time = is_stack ? 32 : (32 * coeff * multiplier) ** 0.8
|
|
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack, usr), time)
|
|
. = TRUE
|
|
else
|
|
to_chat(usr, span_alert("Not enough materials for this operation."))
|
|
else
|
|
to_chat(usr, span_alert("The autolathe is busy. Please wait for completion of previous operation."))
|
|
|
|
/obj/machinery/autolathe/on_deconstruction()
|
|
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
|
materials.retrieve_all()
|
|
|
|
/obj/machinery/autolathe/attackby(obj/item/O, mob/living/user, params)
|
|
if(busy)
|
|
balloon_alert(user, "it's busy!")
|
|
return TRUE
|
|
|
|
if(user.a_intent == INTENT_HARM) //so we can hit the machine
|
|
return ..()
|
|
|
|
if(stat)
|
|
return TRUE
|
|
|
|
if(istype(O, /obj/item/disk/design_disk))
|
|
user.visible_message(span_notice("[user] begins to load \the [O] in \the [src]..."),
|
|
balloon_alert(user, "uploading design..."),
|
|
span_hear("You hear the chatter of a floppy drive."))
|
|
busy = TRUE
|
|
if(do_after(user, 14.4, target = src))
|
|
var/obj/item/disk/design_disk/disky = O
|
|
var/list/not_imported
|
|
for(var/datum/design/blueprint as anything in disky.blueprints)
|
|
if(!blueprint)
|
|
continue
|
|
if(blueprint.build_type & AUTOLATHE)
|
|
stored_research.add_design(blueprint)
|
|
else
|
|
LAZYADD(not_imported, blueprint.name)
|
|
if(not_imported)
|
|
to_chat(user, span_warning("The following design[length(not_imported) > 1 ? "s" : ""] couldn't be imported: [english_list(not_imported)]"))
|
|
busy = FALSE
|
|
return TRUE
|
|
|
|
if(panel_open)
|
|
balloon_alert(user, "close the panel first!")
|
|
return FALSE
|
|
|
|
return ..()
|
|
|
|
/obj/machinery/autolathe/screwdriver_act(mob/living/user, obj/item/I)
|
|
. = ..()
|
|
if(busy)
|
|
balloon_alert(user, "it's busy!")
|
|
return STOP_ATTACK_PROC_CHAIN
|
|
|
|
if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", I))
|
|
return STOP_ATTACK_PROC_CHAIN
|
|
|
|
/obj/machinery/autolathe/crowbar_act(mob/living/user, obj/item/I)
|
|
. = ..()
|
|
if(busy)
|
|
balloon_alert(user, "it's busy!")
|
|
return STOP_ATTACK_PROC_CHAIN
|
|
|
|
if(default_deconstruction_crowbar(I))
|
|
return STOP_ATTACK_PROC_CHAIN
|
|
|
|
/obj/machinery/autolathe/multitool_act(mob/living/user, obj/item/I)
|
|
. = ..()
|
|
if(busy)
|
|
balloon_alert(user, "it's busy!")
|
|
return STOP_ATTACK_PROC_CHAIN
|
|
|
|
if(panel_open)
|
|
wires.interact(user)
|
|
return STOP_ATTACK_PROC_CHAIN
|
|
|
|
/obj/machinery/autolathe/wirecutter_act(mob/living/user, obj/item/I)
|
|
. = ..()
|
|
if(busy)
|
|
balloon_alert(user, "it's busy!")
|
|
return STOP_ATTACK_PROC_CHAIN
|
|
|
|
if(panel_open)
|
|
wires.interact(user)
|
|
return STOP_ATTACK_PROC_CHAIN
|
|
|
|
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
|
|
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
|
|
use_power(MINERAL_MATERIAL_AMOUNT / 10)
|
|
else if(custom_materials && custom_materials.len && custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
|
|
flick("autolathe_r", src)//plays glass insertion animation by default otherwise
|
|
else
|
|
flick("autolathe_o", src)//plays metal insertion animation
|
|
|
|
use_power(min(1000, amount_inserted / 100))
|
|
|
|
/obj/machinery/autolathe/proc/make_item(power, list/materials_used, list/picked_materials, multiplier, coeff, is_stack, mob/user)
|
|
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
|
var/atom/A = drop_location()
|
|
use_power(power)
|
|
|
|
materials.use_materials(materials_used)
|
|
|
|
if(is_stack)
|
|
var/obj/item/stack/N = new being_built.build_path(A, multiplier, FALSE)
|
|
N.update_appearance()
|
|
N.autolathe_crafted(src)
|
|
else
|
|
for(var/i in 1 to multiplier)
|
|
var/obj/item/new_item = new being_built.build_path(A)
|
|
new_item.autolathe_crafted(src)
|
|
|
|
if(length(picked_materials))
|
|
new_item.set_custom_materials(picked_materials, 1 / multiplier) //Ensure we get the non multiplied amount
|
|
for(var/x in picked_materials)
|
|
var/datum/material/M = x
|
|
if(!istype(M, /datum/material/glass) && !istype(M, /datum/material/iron))
|
|
user.client.give_award(/datum/award/achievement/misc/getting_an_upgrade, user)
|
|
|
|
|
|
icon_state = "autolathe"
|
|
busy = FALSE
|
|
|
|
/obj/machinery/autolathe/RefreshParts()
|
|
var/mat_capacity = 0
|
|
for(var/obj/item/stock_parts/matter_bin/new_matter_bin in component_parts)
|
|
mat_capacity += new_matter_bin.rating*75000
|
|
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
|
materials.max_amount = mat_capacity
|
|
|
|
var/efficiency=1.2
|
|
for(var/obj/item/stock_parts/manipulator/new_manipulator in component_parts)
|
|
efficiency -= new_manipulator.rating*0.2
|
|
creation_efficiency = max(1,efficiency) // creation_efficiency goes 1 -> 0,8 -> 0,6 -> 0,4 per level of manipulator efficiency
|
|
|
|
/obj/machinery/autolathe/examine(mob/user)
|
|
. += ..()
|
|
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
|
if(in_range(user, src) || isobserver(user))
|
|
. += span_notice("The status display reads: Storing up to <b>[materials.max_amount]</b> material units.<br>Material consumption at <b>[creation_efficiency*100]%</b>.")
|
|
|
|
/obj/machinery/autolathe/proc/can_build(datum/design/D, amount = 1)
|
|
if(length(D.make_reagents))
|
|
return FALSE
|
|
|
|
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : creation_efficiency)
|
|
|
|
var/list/required_materials = list()
|
|
|
|
for(var/i in D.materials)
|
|
required_materials[i] = D.materials[i] * coeff * amount
|
|
|
|
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
|
|
|
return materials.has_materials(required_materials)
|
|
|
|
|
|
/obj/machinery/autolathe/proc/get_design_cost(datum/design/D)
|
|
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : creation_efficiency)
|
|
var/dat
|
|
for(var/i in D.materials)
|
|
if(istext(i)) //Category handling
|
|
dat += "[D.materials[i] * coeff] [i]"
|
|
else
|
|
var/datum/material/M = i
|
|
dat += "[D.materials[i] * coeff] [M.name] "
|
|
return dat
|
|
|
|
/obj/machinery/autolathe/proc/reset(wire)
|
|
switch(wire)
|
|
if(WIRE_HACK)
|
|
if(!wires.is_cut(wire))
|
|
adjust_hacked(FALSE)
|
|
if(WIRE_SHOCK)
|
|
if(!wires.is_cut(wire))
|
|
shocked = FALSE
|
|
if(WIRE_DISABLE)
|
|
if(!wires.is_cut(wire))
|
|
disabled = FALSE
|
|
|
|
/obj/machinery/autolathe/proc/shock(mob/user, prb)
|
|
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
|
|
return FALSE
|
|
if(!prob(prb))
|
|
return FALSE
|
|
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
|
s.set_up(5, 1, src)
|
|
s.start()
|
|
if (electrocute_mob(user, get_area(src), src, 0.7, TRUE))
|
|
return TRUE
|
|
else
|
|
return FALSE
|
|
|
|
/obj/machinery/autolathe/proc/adjust_hacked(state)
|
|
hacked = state
|
|
for(var/id in SSresearch.techweb_designs)
|
|
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
|
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
|
|
if(hacked)
|
|
stored_research.add_design(D)
|
|
else
|
|
stored_research.remove_design(D)
|
|
|
|
/obj/machinery/autolathe/hacked/Initialize(mapload)
|
|
. = ..()
|
|
adjust_hacked(TRUE)
|
|
|
|
//Called when the object is constructed by an autolathe
|
|
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
|
|
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
|
|
return
|
|
|
|
/obj/machinery/autolathe/secure
|
|
name = "secured autolathe"
|
|
desc = "It produces items using metal and glass. This model was reprogrammed without some of the more hazardous designs."
|
|
circuit = /obj/item/circuitboard/machine/autolathe/secure
|
|
|
|
/obj/machinery/autolathe/secure/Initialize(mapload)
|
|
. = ..()
|
|
// let's not leave the parent datum floating, right?
|
|
if(stored_research)
|
|
QDEL_NULL(stored_research)
|
|
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/public
|
|
|
|
/obj/machinery/autolathe/toy
|
|
name = "autoylathe"
|
|
desc = "It produces toys using plastic, metal and glass."
|
|
circuit = /obj/item/circuitboard/machine/autolathe/toy
|
|
categories = list(
|
|
"Toys",
|
|
"Figurines",
|
|
"Pistols",
|
|
"Rifles",
|
|
"Heavy",
|
|
"Melee",
|
|
"Armor",
|
|
"Adult",
|
|
"Misc",
|
|
"Imported"
|
|
)
|
|
/obj/machinery/autolathe/toy/Initialize(mapload)
|
|
. = ..()
|
|
// let's not leave the parent datum floating, right?
|
|
if(stored_research)
|
|
QDEL_NULL(stored_research)
|
|
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/toy
|
|
|
|
/obj/machinery/autolathe/toy/hacked/Initialize(mapload)
|
|
. = ..()
|
|
adjust_hacked(TRUE)
|
|
|
|
// override the base to allow plastics
|
|
/obj/machinery/autolathe/ComponentInitialize()
|
|
var/list/extra_mats = list(/datum/material/plastic)
|
|
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID] + extra_mats, 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|