Files
CHOMPStation2/code/game/mecha/mech_fabricator.dm
Gamerofthegame 33b9d19df1 Commit repair
2014-09-28 17:13:42 -04:00

842 lines
31 KiB
Plaintext

/////////////////////////////
///// Part Fabricator ///////
/////////////////////////////
/obj/machinery/mecha_part_fabricator
icon = 'icons/obj/robotics.dmi'
icon_state = "fab-idle"
name = "Exosuit Fabricator"
desc = "Nothing is being built."
density = 1
anchored = 1
use_power = 1
idle_power_usage = 20
active_power_usage = 5000
req_access = list(access_robotics)
var/time_coeff = 1.5 //can be upgraded with research
var/resource_coeff = 1.5 //can be upgraded with research
var/list/resources = list(
"metal"=0,
"glass"=0,
"gold"=0,
"silver"=0,
"diamond"=0,
"phoron"=0,
"uranium"=0,
)
var/res_max_amount = 200000
var/datum/research/files
var/id
var/sync = 0
var/part_set
var/obj/being_built
var/list/queue = list()
var/processing_queue = 0
var/screen = "main"
var/opened = 0
var/temp
var/output_dir = SOUTH //the direction relative to the fabber at which completed parts appear.
var/list/part_sets = list( //set names must be unique
"Robot"=list(
/obj/item/robot_parts/robot_suit,
/obj/item/robot_parts/chest,
/obj/item/robot_parts/head,
/obj/item/robot_parts/l_arm,
/obj/item/robot_parts/r_arm,
/obj/item/robot_parts/l_leg,
/obj/item/robot_parts/r_leg,
/obj/item/robot_parts/robot_component/binary_communication_device,
/obj/item/robot_parts/robot_component/radio,
/obj/item/robot_parts/robot_component/actuator,
/obj/item/robot_parts/robot_component/diagnosis_unit,
/obj/item/robot_parts/robot_component/camera,
/obj/item/robot_parts/robot_component/armour
),
"Ripley"=list(
/obj/item/mecha_parts/chassis/ripley,
/obj/item/mecha_parts/part/ripley_torso,
/obj/item/mecha_parts/part/ripley_left_arm,
/obj/item/mecha_parts/part/ripley_right_arm,
/obj/item/mecha_parts/part/ripley_left_leg,
/obj/item/mecha_parts/part/ripley_right_leg
),
// "Hoverpod"=list(
// /obj/structure/largecrate/hoverpod // Doesn't work, even with required vars. Why? - Gamerofthegame
// ),
"Odysseus"=list(
/obj/item/mecha_parts/chassis/odysseus,
/obj/item/mecha_parts/part/odysseus_torso,
/obj/item/mecha_parts/part/odysseus_head,
/obj/item/mecha_parts/part/odysseus_left_arm,
/obj/item/mecha_parts/part/odysseus_right_arm,
/obj/item/mecha_parts/part/odysseus_left_leg,
/obj/item/mecha_parts/part/odysseus_right_leg
),
"Gygax"=list(
/obj/item/mecha_parts/chassis/gygax,
/obj/item/mecha_parts/part/gygax_torso,
/obj/item/mecha_parts/part/gygax_head,
/obj/item/mecha_parts/part/gygax_left_arm,
/obj/item/mecha_parts/part/gygax_right_arm,
/obj/item/mecha_parts/part/gygax_left_leg,
/obj/item/mecha_parts/part/gygax_right_leg,
/obj/item/mecha_parts/part/gygax_armour
),
"Durand"=list(
/obj/item/mecha_parts/chassis/durand,
/obj/item/mecha_parts/part/durand_torso,
/obj/item/mecha_parts/part/durand_head,
/obj/item/mecha_parts/part/durand_left_arm,
/obj/item/mecha_parts/part/durand_right_arm,
/obj/item/mecha_parts/part/durand_left_leg,
/obj/item/mecha_parts/part/durand_right_leg,
/obj/item/mecha_parts/part/durand_armour
),
/*"H.O.N.K"=list(
/obj/item/mecha_parts/chassis/honker,
/obj/item/mecha_parts/part/honker_torso,
/obj/item/mecha_parts/part/honker_head,
/obj/item/mecha_parts/part/honker_left_arm,
/obj/item/mecha_parts/part/honker_right_arm,
/obj/item/mecha_parts/part/honker_left_leg,
/obj/item/mecha_parts/part/honker_right_leg
), No need for HONK stuff*/
"Exosuit Equipment"=list(
/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,
/obj/item/mecha_parts/mecha_equipment/tool/drill,
/obj/item/mecha_parts/mecha_equipment/tool/extinguisher,
/obj/item/mecha_parts/mecha_equipment/tool/cable_layer,
/obj/item/mecha_parts/mecha_equipment/tool/sleeper,
/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun,
/obj/item/mecha_parts/mecha_equipment/tool/passenger,
/obj/item/mecha_parts/chassis/firefighter,
///obj/item/mecha_parts/mecha_equipment/repair_droid,
/obj/item/mecha_parts/mecha_equipment/generator,
///obj/item/mecha_parts/mecha_equipment/jetpack, //TODO MECHA JETPACK SPRITE MISSING
/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser,
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg,
///obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/mousetrap_mortar, HONK-related mech part
///obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar, Also HONK-related
///obj/item/mecha_parts/mecha_equipment/weapon/honker Thirdly HONK-related
),
"Robotic Upgrade Modules" = list(
/obj/item/borg/upgrade/reset,
/obj/item/borg/upgrade/rename,
/obj/item/borg/upgrade/restart,
/obj/item/borg/upgrade/vtec,
/obj/item/borg/upgrade/tasercooler,
/obj/item/borg/upgrade/jetpack
),
"Misc"=list(/obj/item/mecha_parts/mecha_tracking)
)
/obj/machinery/mecha_part_fabricator/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/mechfab(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
RefreshParts()
// part_sets["Cyborg Upgrade Modules"] = typesof(/obj/item/borg/upgrade/) - /obj/item/borg/upgrade/ // Eh. This does it dymaically, but to support having the items referenced otherwhere in the code but not being constructable, going to do it manaully.
for(var/part_set in part_sets)
convert_part_set(part_set)
files = new /datum/research(src) //Setup the research data holder.
/*
if(!id)
for(var/obj/machinery/r_n_d/server/centcom/S in world)
S.initialize()
break
*/
return
/obj/machinery/mecha_part_fabricator/RefreshParts()
var/T = 0
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
T += M.rating
res_max_amount = (187500+(T * 37500))
T = 0
for(var/obj/item/weapon/stock_parts/micro_laser/Ma in component_parts)
T += Ma.rating
if(T >= 1)
T -= 1
var/diff
diff = round(initial(resource_coeff) - (initial(resource_coeff)*(T))/25,0.01)
if(resource_coeff!=diff)
resource_coeff = diff
T = 0
for(var/obj/item/weapon/stock_parts/manipulator/Ml in component_parts)
T += Ml.rating
if(T>= 1)
T -= 1
diff = round(initial(time_coeff) - (initial(time_coeff)*(T))/25,0.01)
if(time_coeff!=diff)
time_coeff = diff
/obj/machinery/mecha_part_fabricator/Del()
for(var/atom/A in src)
del A
..()
return
/obj/machinery/mecha_part_fabricator/proc/operation_allowed(mob/M)
if(isrobot(M) || isAI(M))
return 1
if(!istype(req_access) || !req_access.len)
return 1
else if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
for(var/ID in list(H.get_active_hand(), H.wear_id, H.belt))
if(src.check_access(ID))
return 1
M << "<font color='red'>You don't have required permissions to use [src]</font>"
return 0
/obj/machinery/mecha_part_fabricator/proc/emag()
sleep()
switch(emagged)
if(0)
emagged = 0.5
src.visible_message("\icon[src] <b>[src]</b> beeps: \"DB error \[Code 0x00F1\]\"")
sleep(10)
src.visible_message("\icon[src] <b>[src]</b> beeps: \"Attempting auto-repair\"")
sleep(15)
src.visible_message("\icon[src] <b>[src]</b> beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
sleep(30)
src.visible_message("\icon[src] <b>[src]</b> beeps: \"User DB truncated. Please contact your Nanotrasen system operator for future assistance.\"")
req_access = null
emagged = 1
if(0.5)
src.visible_message("\icon[src] <b>[src]</b> beeps: \"DB not responding \[Code 0x0003\]...\"")
if(1)
src.visible_message("\icon[src] <b>[src]</b> beeps: \"No records in User DB\"")
return
/obj/machinery/mecha_part_fabricator/proc/convert_part_set(set_name as text)
var/list/parts = part_sets[set_name]
if(istype(parts, /list))
for(var/i=1;i<=parts.len;i++)
var/path = parts[i]
var/part = new path(src)
if(part)
parts[i] = part
//debug below
if(!istype(parts[i],/obj/item)) return 0
return
/obj/machinery/mecha_part_fabricator/proc/add_part_set(set_name as text,parts=null)
if(set_name in part_sets)//attempt to create duplicate set
return 0
if(isnull(parts))
part_sets[set_name] = list()
else
part_sets[set_name] = parts
convert_part_set(set_name)
return 1
/obj/machinery/mecha_part_fabricator/proc/add_part_to_set(set_name as text,part)
if(!part) return 0
src.add_part_set(set_name)//if no "set_name" set exists, create
var/list/part_set = part_sets[set_name]
var/atom/apart
if(ispath(part))
apart = new part(src)
else
apart = part
if(!istype(apart)) return 0
for(var/obj/O in part_set)
if(O.type == apart.type)
del apart
return 0
part_set[++part_set.len] = apart
return 1
/obj/machinery/mecha_part_fabricator/proc/remove_part_set(set_name as text)
for(var/i=1,i<=part_sets.len,i++)
if(part_sets[i]==set_name)
part_sets.Cut(i,++i)
return
/*
proc/sanity_check()
for(var/p in resources)
var/index = resources.Find(p)
index = resources.Find(p, ++index)
if(index) //duplicate resource
world << "Duplicate resource definition for [src](\ref[src])"
return 0
for(var/set_name in part_sets)
var/index = part_sets.Find(set_name)
index = part_sets.Find(set_name, ++index)
if(index) //duplicate part set
world << "Duplicate part set definition for [src](\ref[src])"
return 0
return 1
*/
/*
New()
..()
src.add_part_to_set("Test",list("result"="/obj/item/mecha_parts/part/gygax_armour","time"=600,"metal"=75000,"diamond"=10000))
src.add_part_to_set("Test",list("result"="/obj/item/mecha_parts/part/ripley_left_arm","time"=200,"metal"=25000))
src.remove_part_set("Gygax")
return
*/
/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name)
var/output = ""
var/list/part_set = listgetindex(part_sets, set_name)
if(istype(part_set))
for(var/obj/item/part in part_set)
var/resources_available = check_resources(part)
output += "<div class='part'>[output_part_info(part)]<br>\[[resources_available?"<a href='?src=\ref[src];part=\ref[part]'>Build</a> | ":null]<a href='?src=\ref[src];add_to_queue=\ref[part]'>Add to queue</a>\]\[<a href='?src=\ref[src];part_desc=\ref[part]'>?</a>\]</div>"
return output
/obj/machinery/mecha_part_fabricator/proc/output_part_info(var/obj/item/part)
var/output = "[part.name] (Cost: [output_part_cost(part)]) [get_construction_time_w_coeff(part)/10]sec"
return output
/obj/machinery/mecha_part_fabricator/proc/output_part_cost(var/obj/item/part)
var/i = 0
var/output
if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))//The most efficient way to go about this. Not all objects have these vars, but if they don't then they CANNOT be made by the mech fab. Doing it this way reduces a major amount of typecasting and switches, while cutting down maintenece for them as well -Sieve
for(var/c in part:construction_cost)//The check should ensure that anything without the var doesn't make it to this point
if(c in resources)
output += "[i?" | ":null][get_resource_cost_w_coeff(part,c)] [c]"
i++
return output
else
return 0
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/output
for(var/resource in resources)
var/amount = min(res_max_amount, resources[resource])
output += "<span class=\"res_name\">[resource]: </span>[amount] cm&sup3;"
if(amount>0)
output += "<span style='font-size:80%;'> - Remove \[<a href='?src=\ref[src];remove_mat=1;material=[resource]'>1</a>\] | \[<a href='?src=\ref[src];remove_mat=10;material=[resource]'>10</a>\] | \[<a href='?src=\ref[src];remove_mat=[res_max_amount];material=[resource]'>All</a>\]</span>"
output += "<br/>"
return output
/obj/machinery/mecha_part_fabricator/proc/remove_resources(var/obj/item/part)
//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects
if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
for(var/resource in part:construction_cost)
if(resource in src.resources)
src.resources[resource] -= get_resource_cost_w_coeff(part,resource)
else
return
/obj/machinery/mecha_part_fabricator/proc/check_resources(var/obj/item/part)
// if(istype(part, /obj/item/robot_parts) || istype(part, /obj/item/mecha_parts) || istype(part,/obj/item/borg/upgrade))
//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects
if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
for(var/resource in part:construction_cost)
if(resource in src.resources)
if(src.resources[resource] < get_resource_cost_w_coeff(part,resource))
return 0
return 1
else
return 0
/obj/machinery/mecha_part_fabricator/proc/build_part(var/obj/item/part)
if(!part) return
// critical exploit prevention, do not remove unless you replace it -walter0o
if( !(locate(part, src.contents)) || !(part.vars.Find("construction_time")) || !(part.vars.Find("construction_cost")) ) // these 3 are the current requirements for an object being buildable by the mech_fabricator
return
src.being_built = new part.type(src)
src.desc = "It's building [src.being_built]."
src.remove_resources(part)
src.overlays += "fab-active"
src.use_power = 2
src.updateUsrDialog()
sleep(get_construction_time_w_coeff(part))
src.use_power = 1
src.overlays -= "fab-active"
src.desc = initial(src.desc)
if(being_built)
src.being_built.Move(get_step(src,output_dir))
src.visible_message("\icon[src] <b>[src]</b> beeps, \"The following has been completed: [src.being_built] is built\".")
src.being_built = null
src.updateUsrDialog()
return 1
/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page()
send_byjax(usr,"mecha_fabricator.browser","queue",src.list_queue())
return
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name)
if(set_name in part_sets)
var/list/part_set = part_sets[set_name]
if(islist(part_set))
for(var/obj/item/part in part_set)
add_to_queue(part)
return
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(part)
if(!istype(queue))
queue = list()
if(part)
queue[++queue.len] = part
return queue.len
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index)
if(!isnum(index) || !istype(queue) || (index<1 || index>queue.len))
return 0
queue.Cut(index,++index)
return 1
/obj/machinery/mecha_part_fabricator/proc/process_queue()
var/obj/item/part = listgetindex(src.queue, 1)
if(!part)
remove_from_queue(1)
if(src.queue.len)
return process_queue()
else
return
if(!(part.vars.Find("construction_time")) || !(part.vars.Find("construction_cost")))//If it shouldn't be printed
remove_from_queue(1)//Take it out of the quene
return process_queue()//Then reprocess it
temp = null
while(part)
if(stat&(NOPOWER|BROKEN))
return 0
if(!check_resources(part))
src.visible_message("\icon[src] <b>[src]</b> beeps, \"Not enough resources. Queue processing stopped\".")
temp = {"<font color='red'>Not enough resources to build next part.</font><br>
<a href='?src=\ref[src];process_queue=1'>Try again</a> | <a href='?src=\ref[src];clear_temp=1'>Return</a><a>"}
return 0
remove_from_queue(1)
build_part(part)
part = listgetindex(src.queue, 1)
src.visible_message("\icon[src] <b>[src]</b> beeps, \"Queue processing finished successfully\".")
return 1
/obj/machinery/mecha_part_fabricator/proc/list_queue()
var/output = "<b>Queue contains:</b>"
if(!istype(queue) || !queue.len)
output += "<br>Nothing"
else
output += "<ol>"
for(var/i=1;i<=queue.len;i++)
var/obj/item/part = listgetindex(src.queue, i)
if(istype(part))
if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
output += "<li[!check_resources(part)?" style='color: #f00;'":null]>[part.name] - [i>1?"<a href='?src=\ref[src];queue_move=-1;index=[i]' class='arrow'>&uarr;</a>":null] [i<queue.len?"<a href='?src=\ref[src];queue_move=+1;index=[i]' class='arrow'>&darr;</a>":null] <a href='?src=\ref[src];remove_from_queue=[i]'>Remove</a></li>"
else//Prevents junk items from even appearing in the list, and they will be silently removed when the fab processes
remove_from_queue(i)//Trash it
return list_queue()//Rebuild it
output += "</ol>"
output += "\[<a href='?src=\ref[src];process_queue=1'>Process queue</a> | <a href='?src=\ref[src];clear_queue=1'>Clear queue</a>\]"
return output
/obj/machinery/mecha_part_fabricator/proc/convert_designs()
if(!files) return
var/i = 0
for(var/datum/design/D in files.known_designs)
if(D.build_type&16)
if(D.category in part_sets)//Checks if it's a valid category
if(add_part_to_set(D.category, text2path(D.build_path)))//Adds it to said category
i++
else
if(add_part_to_set("Misc", text2path(D.build_path)))//If in doubt, chunk it into the Misc
i++
return i
/obj/machinery/mecha_part_fabricator/proc/update_tech()
if(!files) return
var/output
for(var/datum/tech/T in files.known_tech)
if(T && T.level > 1)
var/diff
switch(T.id) //bad, bad formulas
if("materials")
var/pmat = 0//Calculations to make up for the fact that these parts and tech modify the same thing
for(var/obj/item/weapon/stock_parts/micro_laser/Ml in component_parts)
pmat += Ml.rating
if(pmat >= 1)
pmat -= 1//So the equations don't have to be reworked, upgrading a single part from T1 to T2 is == to 1 tech level
diff = round(initial(resource_coeff) - (initial(resource_coeff)*(T.level+pmat))/25,0.01)
if(resource_coeff!=diff)
resource_coeff = diff
output+="Production efficiency increased.<br>"
if("programming")
var/ptime = 0
for(var/obj/item/weapon/stock_parts/manipulator/Ma in component_parts)
ptime += Ma.rating
if(ptime >= 2)
ptime -= 2
diff = round(initial(time_coeff) - (initial(time_coeff)*(T.level+ptime))/25,0.1)
if(time_coeff!=diff)
time_coeff = diff
output+="Production routines updated.<br>"
return output
/obj/machinery/mecha_part_fabricator/proc/sync(silent=null)
/* if(queue.len)
if(!silent)
temp = "Error. Please clear processing queue before updating!"
src.updateUsrDialog()
return
*/
if(!silent)
temp = "Updating local R&D database..."
src.updateUsrDialog()
sleep(30) //only sleep if called by user
var/found = 0
for(var/obj/machinery/computer/rdconsole/RDC in get_area(src))
if(!RDC.sync)
continue
found++
for(var/datum/tech/T in RDC.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in RDC.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
var/i = src.convert_designs()
var/tech_output = update_tech()
if(!silent)
temp = "Processed [i] equipment designs.<br>"
temp += tech_output
temp += "<a href='?src=\ref[src];clear_temp=1'>Return</a>"
src.updateUsrDialog()
if(i || tech_output)
src.visible_message("\icon[src] <b>[src]</b> beeps, \"Successfully synchronized with R&D server. New data processed.\"")
if(found == 0)
temp = "Couldn't contact R&D server.<br>"
temp += "<a href='?src=\ref[src];clear_temp=1'>Return</a>"
src.updateUsrDialog()
src.visible_message("\icon[src] <b>[src]</b> beeps, \"Error! Couldn't connect to R&D server.\"")
return
/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(var/obj/item/part as obj,var/resource as text, var/roundto=1)
//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects
if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
return round(part:construction_cost[resource]*resource_coeff, roundto)
else
return 0
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(var/obj/item/part as obj, var/roundto=1)
//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects
if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))
return round(part:construction_time*time_coeff, roundto)
else
return 0
/obj/machinery/mecha_part_fabricator/attack_hand(mob/user as mob)
var/dat, left_part
if (..())
return
if(!operation_allowed(user))
return
user.set_machine(src)
var/turf/exit = get_step(src,SOUTH)
if(exit.density)
src.visible_message("\icon[src] <b>[src]</b> beeps, \"Error! Part outlet is obstructed\".")
return
if(temp)
left_part = temp
else if(src.being_built)
left_part = {"<TT>Building [src.being_built.name].<BR>
Please wait until completion...</TT>"}
else
switch(screen)
if("main")
left_part = output_available_resources()+"<hr>"
left_part += "<a href='?src=\ref[src];sync=1'>Sync with R&D servers</a><hr>"
for(var/part_set in part_sets)
left_part += "<a href='?src=\ref[src];part_set=[part_set]'>[part_set]</a> - \[<a href='?src=\ref[src];partset_to_queue=[part_set]'>Add all parts to queue\]<br>"
if("parts")
left_part += output_parts_list(part_set)
left_part += "<hr><a href='?src=\ref[src];screen=main'>Return</a>"
dat = {"<html>
<head>
<title>[src.name]</title>
<style>
.res_name {font-weight: bold; text-transform: capitalize;}
.red {color: #f00;}
.part {margin-bottom: 10px;}
.arrow {text-decoration: none; font-size: 10px;}
body, table {height: 100%;}
td {vertical-align: top; padding: 5px;}
html, body {padding: 0px; margin: 0px;}
h1 {font-size: 18px; margin: 5px 0px;}
</style>
<script language='javascript' type='text/javascript'>
[js_byjax]
</script>
</head><body>
<body>
<table style='width: 100%;'>
<tr>
<td style='width: 70%; padding-right: 10px;'>
[left_part]
</td>
<td style='width: 30%; background: #ccc;' id='queue'>
[list_queue()]
</td>
<tr>
</table>
</body>
</html>"}
user << browse(dat, "window=mecha_fabricator;size=1000x400")
onclose(user, "mecha_fabricator")
return
/obj/machinery/mecha_part_fabricator/proc/exploit_prevention(var/obj/Part, mob/user as mob, var/desc_exploit)
// critical exploit prevention, feel free to improve or replace this, but do not remove it -walter0o
if(!Part || !user || !istype(Part) || !istype(user)) // sanity
return 1
if( !(locate(Part, src.contents)) || !(Part.vars.Find("construction_time")) || !(Part.vars.Find("construction_cost")) ) // these 3 are the current requirements for an object being buildable by the mech_fabricator
var/turf/LOC = get_turf(user)
message_admins("[key_name_admin(user)] tried to exploit an Exosuit Fabricator to [desc_exploit ? "get the desc of" : "duplicate"] <a href='?_src_=vars;Vars=\ref[Part]'>[Part]</a> ! ([LOC ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[LOC.x];Y=[LOC.y];Z=[LOC.z]'>JMP</a>" : "null"])", 0)
log_admin("EXPLOIT : [key_name(user)] tried to exploit an Exosuit Fabricator to [desc_exploit ? "get the desc of" : "duplicate"] [Part] !")
return 1
return null
/obj/machinery/mecha_part_fabricator/Topic(href, href_list)
if(..()) // critical exploit prevention, do not remove unless you replace it -walter0o
return
var/datum/topic_input/filter = new /datum/topic_input(href,href_list)
if(href_list["part_set"])
var/tpart_set = filter.getStr("part_set")
if(tpart_set)
if(tpart_set=="clear")
src.part_set = null
else
src.part_set = tpart_set
screen = "parts"
if(href_list["part"])
var/obj/part = filter.getObj("part")
// critical exploit prevention, do not remove unless you replace it -walter0o
if(src.exploit_prevention(part, usr))
return
if(!processing_queue)
build_part(part)
else
add_to_queue(part)
if(href_list["add_to_queue"])
var/obj/part = filter.getObj("add_to_queue")
// critical exploit prevention, do not remove unless you replace it -walter0o
if(src.exploit_prevention(part, usr))
return
add_to_queue(part)
return update_queue_on_page()
if(href_list["remove_from_queue"])
remove_from_queue(filter.getNum("remove_from_queue"))
return update_queue_on_page()
if(href_list["partset_to_queue"])
add_part_set_to_queue(filter.get("partset_to_queue"))
return update_queue_on_page()
if(href_list["process_queue"])
spawn(-1)
if(processing_queue || being_built)
return 0
processing_queue = 1
process_queue()
processing_queue = 0
/*
if(href_list["list_queue"])
list_queue()
*/
if(href_list["clear_temp"])
temp = null
if(href_list["screen"])
src.screen = href_list["screen"]
if(href_list["queue_move"] && href_list["index"])
var/index = filter.getNum("index")
var/new_index = index + filter.getNum("queue_move")
if(isnum(index) && isnum(new_index))
if(InRange(new_index,1,queue.len))
queue.Swap(index,new_index)
return update_queue_on_page()
if(href_list["clear_queue"])
queue = list()
return update_queue_on_page()
if(href_list["sync"])
queue = list()
src.sync()
return update_queue_on_page()
if(href_list["part_desc"])
var/obj/part = filter.getObj("part_desc")
// critical exploit prevention, do not remove unless you replace it -walter0o
if(src.exploit_prevention(part, usr, 1))
return
if(part)
temp = {"<h1>[part] description:</h1>
[part.desc]<br>
<a href='?src=\ref[src];clear_temp=1'>Return</a>
"}
if(href_list["remove_mat"] && href_list["material"])
temp = "Ejected [remove_material(href_list["material"],text2num(href_list["remove_mat"]))] of [href_list["material"]]<br><a href='?src=\ref[src];clear_temp=1'>Return</a>"
src.updateUsrDialog()
return
/obj/machinery/mecha_part_fabricator/proc/remove_material(var/mat_string, var/amount)
var/type
switch(mat_string)
if("metal")
type = /obj/item/stack/sheet/metal
if("glass")
type = /obj/item/stack/sheet/glass
if("gold")
type = /obj/item/stack/sheet/mineral/gold
if("silver")
type = /obj/item/stack/sheet/mineral/silver
if("diamond")
type = /obj/item/stack/sheet/mineral/diamond
if("phoron")
type = /obj/item/stack/sheet/mineral/phoron
if("uranium")
type = /obj/item/stack/sheet/mineral/uranium
else
return 0
var/result = 0
var/obj/item/stack/sheet/res = new type(src)
// amount available to take out
var/total_amount = round(resources[mat_string]/res.perunit)
// number of stacks we're going to take out
res.amount = round(min(total_amount,amount))
if(res.amount>0)
resources[mat_string] -= res.amount*res.perunit
res.Move(src.loc)
result = res.amount
else
del res
return result
/obj/machinery/mecha_part_fabricator/attackby(obj/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/screwdriver))
if (!opened)
opened = 1
icon_state = "fab-o"
user << "You open the maintenance hatch of [src]."
else
opened = 0
icon_state = "fab-idle"
user << "You close the maintenance hatch of [src]."
return
if (opened)
if(istype(W, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc)
M.state = 2
M.icon_state = "box_1"
for(var/obj/I in component_parts)
if(I.reliability != 100 && crit_fail)
I.crit_fail = 1
I.loc = src.loc
if(src.resources["metal"] >= 3750)
var/obj/item/stack/sheet/metal/G = new /obj/item/stack/sheet/metal(src.loc)
G.amount = round(src.resources["metal"] / G.perunit)
if(src.resources["glass"] >= 3750)
var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc)
G.amount = round(src.resources["glass"] / G.perunit)
if(src.resources["phoron"] >= 2000)
var/obj/item/stack/sheet/mineral/phoron/G = new /obj/item/stack/sheet/mineral/phoron(src.loc)
G.amount = round(src.resources["phoron"] / G.perunit)
if(src.resources["silver"] >= 2000)
var/obj/item/stack/sheet/mineral/silver/G = new /obj/item/stack/sheet/mineral/silver(src.loc)
G.amount = round(src.resources["silver"] / G.perunit)
if(src.resources["gold"] >= 2000)
var/obj/item/stack/sheet/mineral/gold/G = new /obj/item/stack/sheet/mineral/gold(src.loc)
G.amount = round(src.resources["gold"] / G.perunit)
if(src.resources["uranium"] >= 2000)
var/obj/item/stack/sheet/mineral/uranium/G = new /obj/item/stack/sheet/mineral/uranium(src.loc)
G.amount = round(src.resources["uranium"] / G.perunit)
if(src.resources["diamond"] >= 2000)
var/obj/item/stack/sheet/mineral/diamond/G = new /obj/item/stack/sheet/mineral/diamond(src.loc)
G.amount = round(src.resources["diamond"] / G.perunit)
del(src)
return 1
else
user << "\red You can't load the [src.name] while it's opened."
return 1
if(istype(W, /obj/item/weapon/card/emag))
emag()
return
var/material
switch(W.type)
if(/obj/item/stack/sheet/mineral/gold)
material = "gold"
if(/obj/item/stack/sheet/mineral/silver)
material = "silver"
if(/obj/item/stack/sheet/mineral/diamond)
material = "diamond"
if(/obj/item/stack/sheet/mineral/phoron)
material = "phoron"
if(/obj/item/stack/sheet/metal)
material = "metal"
if(/obj/item/stack/sheet/glass)
material = "glass"
if(/obj/item/stack/sheet/mineral/uranium)
material = "uranium"
else
return ..()
if(src.being_built)
user << "The fabricator is currently processing. Please wait until completion."
return
var/obj/item/stack/sheet/stack = W
var/sname = "[stack.name]"
var/amnt = stack.perunit
if(src.resources[material] < res_max_amount)
if(stack && stack.amount >= 1)
var/count = 0
src.overlays += "fab-load-[material]"//loading animation is now an overlay based on material type. No more spontaneous conversion of all ores to metal. -vey
sleep(10)
while(src.resources[material] < res_max_amount && stack)
src.resources[material] += amnt
stack.use(1)
count++
src.overlays -= "fab-load-[material]"
user << "You insert [count] [sname] into the fabricator."
src.updateUsrDialog()
else
user << "The fabricator can only accept full sheets of [sname]."
return
else
user << "The fabricator cannot hold more [sname]."
return