mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
Moved the files into a module.
This commit is contained in:
35
code/modules/research/mechanic/blueprint.dm
Normal file
35
code/modules/research/mechanic/blueprint.dm
Normal file
@@ -0,0 +1,35 @@
|
||||
/obj/item/research_blueprint //These are NOT the engineer blueprints
|
||||
name = "blueprint"
|
||||
desc = "An electromagnetic blueprint design, used by mechanics. The white lines and doodles are just for show."
|
||||
icon = 'icons/obj/machines/mechanic.dmi'
|
||||
icon_state = "blueprint"
|
||||
var/datum/design/mechanic_design/stored_design = null
|
||||
var/design_type = "" //istype is 2longafunction4me
|
||||
var/delete_on_use = 1 //whether the blueprint is used up on use
|
||||
var/change_design_count = 1
|
||||
|
||||
/obj/item/research_blueprint/nano //nano kind
|
||||
name = "nanoprint"
|
||||
icon_state = "nanoprint"
|
||||
desc = "An electromagnetic nanoprint design, used by mechanics. This nanopaper variant is more advanced than the normal version."
|
||||
change_design_count = 0
|
||||
|
||||
/obj/item/research_blueprint/New(var/new_loc, var/datum/design/mechanic_design/printed_design, var/maxuses = 0 as num)
|
||||
..(new_loc)
|
||||
|
||||
if(!istype(printed_design))
|
||||
return
|
||||
|
||||
stored_design = printed_design
|
||||
design_type = stored_design.design_type
|
||||
|
||||
if(stored_design) //if it doesn't have a source (like a printer), a blueprint can have no design
|
||||
name = "[design_type] " + name + " ([printed_design.name])"
|
||||
|
||||
if(change_design_count && maxuses > 0) //can't change nano uses
|
||||
printed_design.uses = maxuses
|
||||
else
|
||||
printed_design.uses = -1
|
||||
|
||||
pixel_x = rand(-3, 3)
|
||||
pixel_y = rand(-5, 6)
|
||||
112
code/modules/research/mechanic/blueprinter.dm
Normal file
112
code/modules/research/mechanic/blueprinter.dm
Normal file
@@ -0,0 +1,112 @@
|
||||
//Makes blueprint items from device analyzers and PDAs with the device analyser setting
|
||||
//Can be loaded with both paper and nanopaper
|
||||
|
||||
/obj/machinery/r_n_d/blueprinter
|
||||
name = "Blueprint Printer"
|
||||
icon = 'icons/obj/machines/mechanic.dmi'
|
||||
icon_state = "blueprinter"
|
||||
desc = "An old-fashioned roller printer, capable of producing highly-detailed design blueprints using the special properties of nano-paper, as well as the regular properties of normal paper."
|
||||
var/paper_loaded = 0
|
||||
var/nano_loaded = 0
|
||||
var/max_paper = 10
|
||||
var/max_nano = 10
|
||||
var/max_paperprint_uses = 1 //how many uses you get out of a paper blueprint
|
||||
|
||||
research_flags = HASOUTPUT
|
||||
|
||||
/obj/machinery/r_n_d/blueprinter/New()
|
||||
..()
|
||||
|
||||
component_parts = newlist(
|
||||
/obj/item/weapon/circuitboard/blueprinter,
|
||||
/obj/item/weapon/stock_parts/matter_bin,
|
||||
/obj/item/weapon/stock_parts/matter_bin,
|
||||
/obj/item/weapon/stock_parts/manipulator,
|
||||
/obj/item/weapon/stock_parts/scanning_module
|
||||
)
|
||||
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/r_n_d/blueprinter/RefreshParts()
|
||||
var/list/bins = list()
|
||||
var/obj/item/weapon/stock_parts/manipulator/M
|
||||
if(!component_parts)
|
||||
return
|
||||
for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts)
|
||||
if(istype(MB))
|
||||
bins += MB.rating
|
||||
max_paper = 10 * bins[1]
|
||||
max_nano = 10 * bins[2]
|
||||
for(var/obj/item/weapon/stock_parts/SP in component_parts)
|
||||
if(istype(SP, /obj/item/weapon/stock_parts/manipulator))
|
||||
M = SP
|
||||
break
|
||||
if(M)
|
||||
max_paperprint_uses = 1 * M.rating
|
||||
else
|
||||
max_paperprint_uses = 1
|
||||
|
||||
/obj/machinery/r_n_d/blueprinter/attackby(var/atom/A, mob/user)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(istype(A, /obj/item/weapon/paper))
|
||||
var/obj/item/weapon/paper/P = A
|
||||
if(istype(P, /obj/item/weapon/paper/nano))
|
||||
if(max_nano > nano_loaded)
|
||||
nano_loaded++
|
||||
qdel(P)
|
||||
else
|
||||
user <<"<span class='notice'>\The [src] is full.</span>"
|
||||
else
|
||||
if(max_paper > paper_loaded)
|
||||
paper_loaded++
|
||||
qdel(P)
|
||||
else
|
||||
user <<"<span class='notice'>\The [src] is full.</span>"
|
||||
return
|
||||
|
||||
if(istype(A, /obj/item/weapon/paper_pack))
|
||||
var/obj/item/weapon/paper_pack/PP = A
|
||||
var/usingamount = 0
|
||||
if(!PP.amount)
|
||||
user <<"<span class='notice'>You have to have paper to load the [src]!</span>"
|
||||
else
|
||||
var/load_overlay = "[base_state][PP.pptype ? "nano" : "regular"]"
|
||||
if(PP.pptype == "nano")
|
||||
usingamount = min(max_nano - nano_loaded, PP.amount)
|
||||
nano_loaded += usingamount
|
||||
else
|
||||
usingamount = min(max_paper - paper_loaded, PP.amount)
|
||||
paper_loaded += usingamount
|
||||
overlays += load_overlay
|
||||
PP.usepaper(usingamount)
|
||||
user <<"<span class='notice'>You successfully load [usingamount] sheets into the [src].</span>"
|
||||
spawn(30)
|
||||
overlays -= load_overlay
|
||||
return
|
||||
|
||||
//Creates a blueprint of a given design datum
|
||||
//use_nano controls if the design is printed using nanopaper or regular paper
|
||||
//nanopaper designs are better, see blueprint.dm for the code details
|
||||
/obj/machinery/r_n_d/blueprinter/proc/PrintDesign(var/datum/design/mechanic_design/design, var/use_nano = 0)
|
||||
if(!istype(design)) //sanity checks yay
|
||||
return
|
||||
if((use_nano && nano_loaded == 0) || (!use_nano && paper_loaded == 0)) //material checks
|
||||
visible_message("\icon [src]<span class='notice'> \The [src] beeps: 'Out of [use_nano ? "nanopaper" : "paper"]!'</span>")
|
||||
return
|
||||
|
||||
busy = 1
|
||||
overlays += "[base_state]_ani"
|
||||
sleep(30)
|
||||
busy = 0
|
||||
if(use_nano)
|
||||
new/obj/item/research_blueprint/nano(output.loc, design)
|
||||
nano_loaded -= 1
|
||||
else
|
||||
new/obj/item/research_blueprint(output.loc, design, max_paperprint_uses)
|
||||
paper_loaded -= 1
|
||||
src.visible_message("\icon [src]<span class='notice'>\The [src] beeps: Successfully printed the [design.name] design.</span>")
|
||||
spawn(20)
|
||||
overlays -= "[base_state]_ani"
|
||||
return 1
|
||||
81
code/modules/research/mechanic/device_analyser.dm
Normal file
81
code/modules/research/mechanic/device_analyser.dm
Normal file
@@ -0,0 +1,81 @@
|
||||
//You use this to scan items and machines to recreate them in a fabricator or the flatpacker
|
||||
//You can scan syndicate items, but only with the syndicate version (might be overpowered, so I'll make it expensive)
|
||||
/datum
|
||||
|
||||
/obj/item/device/device_analyser
|
||||
name = "device analyzer"
|
||||
desc = "An electromagnetic scanner used by mechanics. Capable of storing objects and machines as portable designs."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "mechanic"
|
||||
gender = NEUTER
|
||||
var/list/loaded_designs = list() //the stored designs
|
||||
var/max_designs = 10
|
||||
var/syndi_filter = 1 //whether the scanner should filter traitor tech items. 1 is filtered, 0 is not filtered
|
||||
var/loadone = 0 //whether or not it should load just one at a time. 0 is all at once, 1 is one at a time
|
||||
flags = FPRINT | TABLEPASS
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = 2
|
||||
item_state = "electronic"
|
||||
m_amt = 300
|
||||
w_type = RECYK_ELECTRONIC
|
||||
origin_tech = "magnets=3;engineering=4;materials=4;programming=3"
|
||||
|
||||
/obj/item/device/device_analyser/attack_self()
|
||||
..()
|
||||
loadone = !loadone
|
||||
usr <<"<span class='notice'> You set the Device Analyzer to [loadone ? "transfer one design" : "transfer all designs"] on use.</span>"
|
||||
|
||||
/obj/item/device/device_analyser/afterattack(var/atom/A, var/mob/user) //Hurrah for after-attack
|
||||
if(istype(A, /obj)) //don't want to scan mobs or anything like that
|
||||
var/obj/O = A
|
||||
for(var/datum/design/mechanic_design/current_design in loaded_designs)
|
||||
if(current_design.build_path == O.type)
|
||||
user <<"<span class='rose'>You've already got a schematic of \the [O]!</span>"
|
||||
return
|
||||
|
||||
if(O.origin_tech || istype(O, /obj/machinery)) //two requirements: items have origin_tech, machines are checked in...
|
||||
if(CanCreateDesign(O)) //this proc. Checks to see if there's anything illegal in the thing before scanning it
|
||||
if(max_designs && !(max_designs <= loaded_designs.len))
|
||||
loaded_designs += new /datum/design/mechanic_design(O)
|
||||
user.visible_message("[user] scans \the [O].", "<span class='notice'>You successfully scan \the [O].</span>")
|
||||
return 1
|
||||
else
|
||||
user << "\icon [src] \The [src] flashes a message on-screen: \"Too many designs loaded.\""
|
||||
else
|
||||
user <<"<span class='rose'>\icon [src] \The [src]'s safety features prevent you from scanning that item.</span>"
|
||||
else //no origin_tech, no scans.
|
||||
user <<"<span class='rose'>\The [src] can't seem to scan \the [O]!</span>"
|
||||
else
|
||||
return
|
||||
|
||||
/obj/item/device/device_analyser/syndicate
|
||||
desc = "A suspicious-looking device anaylzer. A thorough examination reveals that it lacks the required Nanotrasen logo, and that the safety features have been disabled."
|
||||
syndi_filter = 0
|
||||
origin_tech = "magnets=3;engineering=4;materials=4;programming=3;syndicate=3"
|
||||
|
||||
/obj/item/device/device_analyser/proc/CanCreateDesign(var/obj/O)
|
||||
if(!istype(O))
|
||||
return 0
|
||||
|
||||
var/list/techlist
|
||||
if(istype(O, /obj/machinery))
|
||||
var/obj/machinery/M = O
|
||||
if(M.component_parts)
|
||||
for(var/obj/item/weapon/circuitboard/CB in M.component_parts) //fetching the circuit by looking in the parts
|
||||
if(istype(CB))
|
||||
techlist = ConvertReqString2List(CB.origin_tech)
|
||||
else if(istype(M, /obj/machinery/computer))
|
||||
var/obj/machinery/computer/C = M
|
||||
if(C.circuit)
|
||||
var/obj/item/weapon/circuitboard/comp_circuit = text2path(C.circuit)
|
||||
techlist = ConvertReqString2List(initial(comp_circuit.origin_tech))
|
||||
|
||||
else if(istype(O, /obj/item))
|
||||
var/obj/item/I = O
|
||||
techlist = ConvertReqString2List(I.origin_tech) //our tech is simply the item requirement
|
||||
|
||||
if(!techlist) //this don't fly
|
||||
return 0
|
||||
if(techlist && techlist["syndicate"] && src.syndi_filter)
|
||||
return 0
|
||||
return 1
|
||||
31
code/modules/research/mechanic/flatpack.dm
Normal file
31
code/modules/research/mechanic/flatpack.dm
Normal file
@@ -0,0 +1,31 @@
|
||||
/obj/structure/closet/crate/flatpack
|
||||
name = "flatpack"
|
||||
desc = "A ready-to-assemble machine flatpack produced in the space-Swedish style.<br>Crowbar the flatpack open and follow the obtuse instructions to make the resulting machine."
|
||||
icon = 'icons/obj/machines/flatpack.dmi'
|
||||
icon_state = "flatpack"
|
||||
density = 1
|
||||
anchored = 0
|
||||
var/obj/machinery/machine = null
|
||||
|
||||
/obj/structure/closet/crate/flatpack/New()
|
||||
..()
|
||||
icon_state = "flatpack" //it gets changed in the crate code, so we reset it here
|
||||
|
||||
/obj/structure/closet/crate/flatpack/attackby(var/atom/A, mob/user)
|
||||
if(istype(A, /obj/item/weapon/crowbar))
|
||||
user <<"<span class='notice'>You begin to open the flatpack...</span>"
|
||||
if(do_after(user, 40))
|
||||
if(machine)
|
||||
user <<"<span class='notice'>\icon [src]You successfully unpack \the [src]!</span>"
|
||||
machine.loc = get_turf(src)
|
||||
machine.RefreshParts()
|
||||
else
|
||||
user <<"<span class='notice'>\icon [src]It seems this [src] was empty...</span>"
|
||||
for(var/atom/movable/AM in src)
|
||||
AM.loc = get_turf(src)
|
||||
qdel(src)
|
||||
return 1
|
||||
return
|
||||
|
||||
/obj/structure/closet/crate/flatpack/attack_hand()
|
||||
return
|
||||
136
code/modules/research/mechanic/flatpacker.dm
Normal file
136
code/modules/research/mechanic/flatpacker.dm
Normal file
@@ -0,0 +1,136 @@
|
||||
#define FLA_FAB_WIDTH 1000
|
||||
#define FLA_FAB_HEIGHT 600
|
||||
|
||||
#define FLA_FAB_BASETIME 100
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker
|
||||
name = "Flatpack Fabricator"
|
||||
desc = "A machine used to produce flatpacks from blueprint designs."
|
||||
icon = 'icons/obj/machines/mechanic.dmi'
|
||||
icon_state = "flatpacker"
|
||||
|
||||
nano_file = "flatpacker.tmpl"
|
||||
|
||||
design_types = list("machine" = 1, "item" = 0)
|
||||
|
||||
var/build_parts = list(
|
||||
/obj/item/weapon/stock_parts/micro_laser = 1,
|
||||
/obj/item/weapon/stock_parts/manipulator = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 1,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1
|
||||
)
|
||||
|
||||
part_sets = list( "Machines" = list(),
|
||||
"Computers" = list(),
|
||||
"Misc" = list()
|
||||
)
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker/New()
|
||||
..()
|
||||
|
||||
component_parts = newlist(
|
||||
/obj/item/weapon/circuitboard/flatpacker,
|
||||
/obj/item/weapon/stock_parts/matter_bin,
|
||||
/obj/item/weapon/stock_parts/matter_bin,
|
||||
/obj/item/weapon/stock_parts/manipulator,
|
||||
/obj/item/weapon/stock_parts/manipulator,
|
||||
/obj/item/weapon/stock_parts/micro_laser,
|
||||
/obj/item/weapon/stock_parts/micro_laser,
|
||||
/obj/item/weapon/reagent_containers/glass/beaker,
|
||||
/obj/item/weapon/stock_parts/scanning_module,
|
||||
/obj/item/weapon/stock_parts/scanning_module
|
||||
)
|
||||
|
||||
RefreshParts()
|
||||
|
||||
obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker/build_part(var/datum/design/mechanic_design/part)
|
||||
if(!part)
|
||||
return
|
||||
|
||||
for(var/M in part.materials)
|
||||
if(!check_mat(part, M))
|
||||
src.visible_message("<font color='blue'>The [src.name] beeps, \"Not enough materials to complete item.\"</font>")
|
||||
stopped=1
|
||||
return 0
|
||||
if(copytext(M,1,2) == "$")
|
||||
var/matID=copytext(M,2)
|
||||
var/datum/material/material=materials[matID]
|
||||
material.stored = max(0, (material.stored-part.materials[M]))
|
||||
materials[matID]=material
|
||||
else
|
||||
reagents.remove_reagent(M, part.materials[M])
|
||||
|
||||
src.being_built = new part.build_path(src)
|
||||
|
||||
src.busy = 1
|
||||
src.overlays += "[base_state]_ani"
|
||||
src.use_power = 2
|
||||
src.updateUsrDialog()
|
||||
//message_admins("We're going building with [get_construction_time_w_coeff(part)]")
|
||||
sleep(get_construction_time_w_coeff(part))
|
||||
src.use_power = 1
|
||||
src.overlays -= "[base_state]_ani"
|
||||
if(being_built)
|
||||
var/obj/structure/closet/crate/flatpack/FP = new
|
||||
being_built.loc = FP
|
||||
FP.name += " ([being_built.name])"
|
||||
FP.machine = being_built
|
||||
FP.loc = get_turf(output)
|
||||
src.visible_message("\icon [src] \The [src] beeps: \"Succesfully completed \the [being_built.name].\"")
|
||||
src.being_built = null
|
||||
|
||||
//blueprint stuff
|
||||
part.uses--
|
||||
if(part.uses == 0)
|
||||
remove_part_from_set(part.category, part)
|
||||
src.updateUsrDialog()
|
||||
src.busy = 0
|
||||
return 1
|
||||
|
||||
//returns the required materials for the parts of a machine design
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker/Gen_Mat_Reqs(var/obj/machinery/machine, var/datum/design/mechanic_design/design)
|
||||
if(!machine)
|
||||
message_admins("We couldn't find something in part checking, how did this happen?")
|
||||
return
|
||||
|
||||
if(machine in typesof(/obj/machinery/computer)) //istype does not work. Since it's a path, this does
|
||||
design.materials["$iron"] += 15000
|
||||
var/datum/design/circuit_design = FindDesign(design.connected_circuit)
|
||||
if(circuit_design)
|
||||
//message_admins("Found the circuit design")
|
||||
circuit_design = new circuit_design
|
||||
for(var/matID in circuit_design.materials)
|
||||
if(copytext(matID,1,2) == "$")
|
||||
design.materials[matID] += circuit_design.materials[matID]
|
||||
del(circuit_design)
|
||||
else
|
||||
design.materials["$glass"] += 2000
|
||||
//message_admins("Couldn't find the board")
|
||||
return 1
|
||||
|
||||
var/obj/machinery/test_machine = new machine
|
||||
//why do we instance?
|
||||
//because components are generated in New()
|
||||
|
||||
design.materials["$iron"] += 15000 //base costs, the best costs
|
||||
for(var/obj/item/thispart in test_machine.component_parts)
|
||||
//message_admins("We're trying to find the design for [thispart]")
|
||||
var/datum/design/part_design = FindDesign(thispart)
|
||||
if(!part_design)
|
||||
design.materials["$iron"] += rand(50, 500)
|
||||
design.materials["$glass"] += rand(20, 300)
|
||||
continue
|
||||
//message_admins("We found the design!")
|
||||
part_design = new part_design
|
||||
var/list/fetched_materials = part_design.materials
|
||||
for(var/matID in fetched_materials)
|
||||
if(copytext(matID,1,2) == "$")
|
||||
design.materials[matID] += fetched_materials[matID]
|
||||
del(part_design)
|
||||
qdel(test_machine)
|
||||
return 1
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
..()
|
||||
if (O.is_open_container())
|
||||
return 1
|
||||
47
code/modules/research/mechanic/mechanic_designs.dm
Normal file
47
code/modules/research/mechanic/mechanic_designs.dm
Normal file
@@ -0,0 +1,47 @@
|
||||
/datum/design/mechanic_design //used to store the details of a scanned item or machine
|
||||
name = "" //the design name
|
||||
desc = ""
|
||||
|
||||
var/design_type = "" //this is "machine" or "item" (not to be confused with design, this is just an indicator of type)
|
||||
build_path = null //used to store the type of the design itself (not to be confused with design type, this is the class of the thing)
|
||||
|
||||
req_tech = list() //the origin tech of either the item, or the board in the machine
|
||||
var/obj/item/weapon/circuitboard/connected_circuit //used to store the type of the circuit in a scanned machine. Empty for items
|
||||
category = ""
|
||||
var/uses = 0 //counter of how many times you can make this design before it disappears!
|
||||
|
||||
/datum/design/mechanic_design/New(var/obj/O) //sets the name, type, design, origin_tech, and circuit, all by itself
|
||||
if(!istype(O))
|
||||
return
|
||||
name = O.name
|
||||
desc = initial(O.desc) //we use initial because some things edit the description
|
||||
build_path = O.type
|
||||
if(istype(O, /obj/machinery))
|
||||
var/obj/machinery/M = O
|
||||
design_type = "machine"
|
||||
if(M.component_parts && M.component_parts.len)
|
||||
category = "Machines"
|
||||
for(var/obj/item/weapon/circuitboard/CB in M.component_parts) //fetching the circuit by looking in the parts
|
||||
if(istype(CB))
|
||||
connected_circuit = CB.type
|
||||
break
|
||||
else if(istype(M, /obj/machinery/computer))
|
||||
category = "Computers"
|
||||
var/obj/machinery/computer/C = M
|
||||
if(C.circuit)
|
||||
connected_circuit = text2path(C.circuit)
|
||||
if(connected_circuit) //our tech is the circuit's requirement
|
||||
req_tech = ConvertReqString2List(initial(connected_circuit.origin_tech))
|
||||
else if(istype(O, /obj/item))
|
||||
var/obj/item/I = O
|
||||
category = "Items"
|
||||
design_type = "item"
|
||||
req_tech = ConvertReqString2List(I.origin_tech) //our tech is simply the item requirement
|
||||
if(!category)
|
||||
category = "Misc"
|
||||
|
||||
proc/ConvertReqString2List(var/list/source_list) //shamelessly ripped from the code for research machines. Shoot me - Comic
|
||||
var/list/temp_list = params2list(source_list)
|
||||
for(var/O in temp_list)
|
||||
temp_list[O] = text2num(temp_list[O])
|
||||
return temp_list
|
||||
155
code/modules/research/mechanic/mechanic_fabs.dm
Normal file
155
code/modules/research/mechanic/mechanic_fabs.dm
Normal file
@@ -0,0 +1,155 @@
|
||||
#define GEN_FAB_WIDTH 1000 //Gen fab stands for General Fabricator
|
||||
#define GEN_FAB_HEIGHT 600
|
||||
|
||||
#define GEN_FAB_BASETIME 100
|
||||
|
||||
#define GEN_FAB_BASESTORAGE 150000
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab
|
||||
name = "General Fabricator"
|
||||
desc = "A machine used to produce items from blueprint designs."
|
||||
icon = 'icons/obj/machines/mechanic.dmi'
|
||||
icon_state = "genfab"
|
||||
max_material_storage = 150000
|
||||
nano_file = "genfab.tmpl"
|
||||
var/list/design_types = list("machine" = 0, "item" = 1)
|
||||
|
||||
idle_power_usage = 20
|
||||
active_power_usage = 5000
|
||||
|
||||
research_flags = NANOTOUCH | TAKESMATIN | HASOUTPUT
|
||||
|
||||
part_sets = list("Items" = list())
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/New()
|
||||
..()
|
||||
|
||||
component_parts = newlist(
|
||||
/obj/item/weapon/circuitboard/generalfab,
|
||||
/obj/item/weapon/stock_parts/matter_bin,
|
||||
/obj/item/weapon/stock_parts/matter_bin,
|
||||
/obj/item/weapon/stock_parts/manipulator,
|
||||
/obj/item/weapon/stock_parts/manipulator,
|
||||
/obj/item/weapon/stock_parts/micro_laser,
|
||||
/obj/item/weapon/stock_parts/micro_laser
|
||||
)
|
||||
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/attackby(var/obj/O, var/mob/user)
|
||||
if(..())
|
||||
return 1
|
||||
if(istype(O, /obj/item/research_blueprint))
|
||||
var/obj/item/research_blueprint/RB = O
|
||||
if(!design_types[RB.design_type])
|
||||
user <<"<span class='warning'>This isn't the right machine for that kind of blueprint!</span>"
|
||||
return 0
|
||||
else if(RB.stored_design && design_types[RB.design_type])
|
||||
var/datum/design/mechanic_design/MD = RB.stored_design
|
||||
src.AddMechanicDesign(MD)
|
||||
overlays += "[base_state]-bp"
|
||||
user <<"<span class='notice'>You successfully load \the [MD.name] design into \the [src].</span>"
|
||||
qdel(RB)
|
||||
spawn(10)
|
||||
overlays -= "[base_state]-bp"
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
if((user.stat && !isobserver(user)) || user.restrained() || !allowed(user))
|
||||
return
|
||||
|
||||
var/data[0]
|
||||
var/queue_list[0]
|
||||
|
||||
for(var/i=1;i<=queue.len;i++)
|
||||
var/datum/design/part = queue[i]
|
||||
queue_list.Add(list(list("name" = part.name, "cost" = output_part_cost(part), "commands" = list("remove_from_queue" = i))))
|
||||
|
||||
data["queue"] = queue_list
|
||||
data["screen"]=screen
|
||||
var/materials_list[0]
|
||||
//Get the material names
|
||||
for(var/matID in materials)
|
||||
var/datum/material/material = materials[matID] // get the ID of the materials
|
||||
if(material && material.stored > 0)
|
||||
materials_list.Add(list(list("name" = material.processed_name, "storage" = material.stored, "commands" = list("eject" = matID)))) // get the amount of the materials
|
||||
data["materials"] = materials_list
|
||||
|
||||
var/parts_list[0] // setup a list to get all the information for parts
|
||||
|
||||
for(var/set_name in part_sets)
|
||||
//message_admins("Assiging parts to [set_name]")
|
||||
var/list/parts = part_sets[set_name]
|
||||
var/list/set_name_list = list()
|
||||
var/i = 0
|
||||
for(var/datum/design/mechanic_design/part in parts)
|
||||
//message_admins("Adding the [part.name] to the list")
|
||||
i++
|
||||
set_name_list.Add(list(list("name" = part.name, "uses" = part.uses, "cost" = output_part_cost(part), "time" = get_construction_time_w_coeff(part)/10, "command1" = list("add_to_queue" = "[i][set_name]"), "command2" = list("build" = "[i][set_name]"), "command3" = list("remove_design" = "[i][set_name]"))))
|
||||
parts_list[set_name] = set_name_list
|
||||
data["parts"] = parts_list // assigning the parts data to the data sent to UI
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, nano_file, name, FAB_SCREEN_WIDTH, FAB_SCREEN_HEIGHT)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/Topic(href, href_list)
|
||||
|
||||
if(..()) // critical exploit prevention, do not remove unless you replace it -walter0o
|
||||
return 1
|
||||
|
||||
if(href_list["remove_design"])
|
||||
var/datum/design/part = getTopicDesign(href_list["remove_design"])
|
||||
remove_part_from_set(copytext(href_list["remove_design"], 2), part)
|
||||
return 1
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/proc/AddMechanicDesign(var/datum/design/mechanic_design/design)
|
||||
if(istype(design))
|
||||
Gen_Mat_Reqs(design.build_path, design) //makes the material cost for the design. Weird to have here, I know, but it's the best place
|
||||
add_part_to_set(design.category, design)
|
||||
|
||||
//returns the required materials for the parts of a machine design
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/proc/Gen_Mat_Reqs(var/obj/O, var/datum/design/mechanic_design/design)
|
||||
if(!O)
|
||||
message_admins("We couldn't find something in part checking, how did this happen?")
|
||||
return
|
||||
|
||||
var/datum/design/part_design = FindDesign(O)
|
||||
if(part_design)
|
||||
part_design = new part_design
|
||||
design.materials = part_design.materials
|
||||
del(part_design)
|
||||
|
||||
if(!design.materials.len) //let's make something up! complain about the RNG some other time
|
||||
var/techtotal = TechTotal(design)
|
||||
design.materials["$iron"] = techtotal * round(rand(500, 1500), 100)
|
||||
design.materials["$glass"] = techtotal * round(rand(250, 1000), 50)
|
||||
if(prob(techtotal * 5)) //let's add an extra cost of some medium-rare material
|
||||
design.materials[pick("$plasma", "$uranium", "$gold", "$silver")] = techtotal * round(rand(100, 500), 10)
|
||||
if(prob(techtotal * 2)) //and another cost, because we can
|
||||
design.materials[pick("$plasma", "$uranium", "$gold", "$silver")] = techtotal * round(rand(50, 250), 10)
|
||||
if(techtotal >= 15 && prob(techtotal)) //let's add something REALLY rare
|
||||
design.materials[pick("$diamond", "$clown", "$phazon")] = techtotal * round(rand(10, 150), 10)
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
..()
|
||||
if (O.is_open_container())
|
||||
return 0
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/build_part(var/datum/design/mechanic_design/part)
|
||||
if(..())
|
||||
if(part.uses > 0)
|
||||
part.uses--
|
||||
if(part.uses == 0)
|
||||
remove_part_from_set(part.category, part)
|
||||
|
||||
/obj/machinery/r_n_d/fabricator/mechanic_fab/add_to_queue(var/datum/design/mechanic_design/part)
|
||||
. = ..()
|
||||
if(part.uses > 0)
|
||||
part.uses--
|
||||
if(part.uses == 0)
|
||||
remove_part_from_set(part.category, part)
|
||||
return .
|
||||
253
code/modules/research/mechanic/reverse_engine.dm
Normal file
253
code/modules/research/mechanic/reverse_engine.dm
Normal file
@@ -0,0 +1,253 @@
|
||||
#define REV_ENG_HEIGHT 400
|
||||
#define REV_ENG_WIDTH 1200
|
||||
|
||||
#define REV_ENG_RESEARCHBASE 150
|
||||
|
||||
/obj/machinery/r_n_d/reverse_engine
|
||||
name = "Reverse Engine"
|
||||
desc = ""
|
||||
icon = 'icons/obj/machines/mechanic.dmi'
|
||||
icon_state = "reverse-engine"
|
||||
|
||||
var/list/datum/design/mechanic_design/research_queue = list()//all the designs we are waiting to research
|
||||
var/list/datum/design/mechanic_design/ready_queue = list()//all the designs we HAVE researched, and are ready to print
|
||||
var/max_queue_len = 0 as num //maximum number of items in the research queue
|
||||
|
||||
var/scan_rating = 1 //the scanner rating
|
||||
var/cap_rating = 1 //the capacitor rating
|
||||
|
||||
research_flags = NANOTOUCH
|
||||
|
||||
/obj/machinery/r_n_d/reverse_engine/New()
|
||||
..()
|
||||
|
||||
component_parts = newlist(
|
||||
/obj/item/weapon/circuitboard/reverse_engine,
|
||||
/obj/item/weapon/stock_parts/scanning_module,
|
||||
/obj/item/weapon/stock_parts/scanning_module,
|
||||
/obj/item/weapon/stock_parts/capacitor,
|
||||
/obj/item/weapon/stock_parts/capacitor,
|
||||
/obj/item/weapon/stock_parts/manipulator,
|
||||
/obj/item/weapon/stock_parts/console_screen
|
||||
)
|
||||
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/r_n_d/reverse_engine/RefreshParts()
|
||||
var/i = 0
|
||||
for(var/obj/item/weapon/stock_parts/scanning_module/S in component_parts)
|
||||
i++
|
||||
scan_rating += S.rating //sum
|
||||
scan_rating = scan_rating / i //average
|
||||
|
||||
i = 0
|
||||
for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
|
||||
i++
|
||||
cap_rating += C.rating
|
||||
cap_rating = cap_rating / i
|
||||
|
||||
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
|
||||
max_queue_len = 10 * M.rating
|
||||
|
||||
/obj/machinery/r_n_d/reverse_engine/attackby(var/obj/O as obj, var/mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
if(busy)
|
||||
user <<"<span class='notice'>The [src] is currently busy, please wait until the current operation is finished.</span>"
|
||||
return
|
||||
if(istype(O, /obj/item/device/device_analyser))
|
||||
var/obj/item/device/device_analyser/DA = O
|
||||
if(DA.loaded_designs && DA.loaded_designs.len)
|
||||
if(DA.loadone)
|
||||
var/list/name_list = list()
|
||||
for(var/datum/design/mechanic_design/thisdesign in DA.loaded_designs)
|
||||
name_list[thisdesign.name] = thisdesign
|
||||
var/design_name = input(user, "Select a design to load", "Select Design", "") in name_list
|
||||
var/datum/design/mechanic_design/chosen_design = name_list[design_name]
|
||||
AddDesign(chosen_design, DA.loaded_designs, user)
|
||||
return 1
|
||||
else
|
||||
var/i = 0
|
||||
for(var/datum/design/mechanic_design/loop_design in DA.loaded_designs)
|
||||
if(!AddDesign(loop_design, DA.loaded_designs, user))
|
||||
break
|
||||
i++
|
||||
user << "Sucessfully transferred [i] design\s."
|
||||
return 1
|
||||
return
|
||||
if(istype(O, /obj/item/device/pda))
|
||||
var/obj/item/device/pda/PDA = O
|
||||
if(PDA.dev_analys)
|
||||
var/obj/item/device/device_analyser/DA = PDA.dev_analys
|
||||
for(var/datum/design/mechanic_design/loop_design in DA.loaded_designs)
|
||||
AddDesign(loop_design, DA.loaded_designs, user)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Loads a design from a list onto the machine to be researched
|
||||
//Pretty simple, just checks if the design is already present and then adds it and removes it from the parent list
|
||||
/obj/machinery/r_n_d/reverse_engine/proc/AddDesign(var/datum/design/mechanic_design/design, var/list/design_list, var/mob/user)
|
||||
if(!istype(design))
|
||||
design_list -= design //lets just brush that under the rug
|
||||
return
|
||||
if(design in research_queue || design in ready_queue) //if it's already loaded to be researched or has been researched
|
||||
user <<"<span class='notice'>The [design.name] is already loaded onto the [src]!</span>"
|
||||
return
|
||||
if(research_queue.len >= max_queue_len)
|
||||
user <<"<span class='notice'>The [src]'s research queue is full. Research some designs first before adding more.</span>"
|
||||
return
|
||||
if(design in design_list) //let's make sure, here
|
||||
research_queue += design
|
||||
design_list -= design
|
||||
user <<"<span class='notice'>The [design.name] was successfully loaded onto the [src].</span>"
|
||||
return 1
|
||||
return
|
||||
|
||||
//proc used to determine how quickly a design is researched.
|
||||
//given a design, it checks to see the difference between the tech levels of the design and of the rd console it is linked to.
|
||||
//returns the number of levels difference between the design and the console, if any at all ( no negatives )
|
||||
/obj/machinery/r_n_d/reverse_engine/proc/Tech_Difference(var/datum/design/mechanic_design/design)
|
||||
var/list/techlist = design.req_tech
|
||||
var/techdifference = 0
|
||||
if(techlist.len && linked_console)
|
||||
//message_admins("We have a techlist and a linked_console")
|
||||
var/obj/machinery/computer/rdconsole/console = src.linked_console
|
||||
var/list/possible_tech = console.files.possible_tech
|
||||
for(var/checktech in techlist)
|
||||
//message_admins("Looking at [checktech] with value of [techlist[checktech]]")
|
||||
for(var/datum/tech/pointed_tech in possible_tech) //if we find that technology
|
||||
if(pointed_tech.id == checktech)
|
||||
if(techlist[checktech] > pointed_tech.level) //if the machine board's research level is higher than the one on the console
|
||||
//message_admins("Found a difference of [techlist[checktech] - pointed_tech.level]")
|
||||
techdifference += techlist[checktech] - pointed_tech.level //then add this to the tech difference
|
||||
else if(techlist.len)
|
||||
//message_admins("We only have a techlist")
|
||||
for(var/checktech in techlist) //we have no console, so this is the worst case scenario
|
||||
techdifference += techlist[checktech] - 1 //maximum time possible
|
||||
//message_admins("Techdifference before adjust is [techdifference]")
|
||||
if(techdifference < 0) //I'm not sure how this could happen, but just for sanity
|
||||
techdifference = 0
|
||||
return techdifference
|
||||
|
||||
/obj/machinery/r_n_d/reverse_engine/proc/researchQueue()
|
||||
while(research_queue[1])
|
||||
if(stat&(NOPOWER|BROKEN))
|
||||
return 0
|
||||
var/datum/design/mechanic_design/current_design = research_queue[1]
|
||||
if(!researchDesign(current_design))
|
||||
break
|
||||
if(!research_queue.len)
|
||||
break
|
||||
else
|
||||
current_design = research_queue[1]
|
||||
if(!research_queue.len)
|
||||
src.visible_message("<span class='notice'>\icon [src] \The [src] beeps: 'Successfully researched all designs.'</span>")
|
||||
|
||||
/obj/machinery/r_n_d/reverse_engine/proc/researchDesign(var/datum/design/mechanic_design/design)
|
||||
//message_admins("This researchDesign got called with the [design.design_name].")
|
||||
if(busy)
|
||||
return
|
||||
if(!istype(design) || !(design in research_queue)) //sanity checking, always good
|
||||
return
|
||||
if(design in ready_queue)
|
||||
src.visible_message("<span class='notice'>\icon [src] \The [src] beeps:'The [design.name] is already researched.'</span>")
|
||||
research_queue -= design
|
||||
return
|
||||
var/researchtime = ( (REV_ENG_RESEARCHBASE * Tech_Difference(design)) / (scan_rating + cap_rating) )
|
||||
busy = 1
|
||||
overlays += "[base_state]_ani"
|
||||
sleep(researchtime) //we use sleep instead of spawn because code like the queue code has to hang on this proc
|
||||
research_queue -= design
|
||||
busy = 0
|
||||
overlays -= "[base_state]_ani"
|
||||
if(!(design in ready_queue))
|
||||
ready_queue += design
|
||||
src.visible_message("<span class='notice'>\icon [src] \The [src] beeps: 'Successfully researched \the [design.name].'</span>")
|
||||
return 1
|
||||
return
|
||||
|
||||
//finds a printer connected to the console, and use it to print our design
|
||||
/obj/machinery/r_n_d/reverse_engine/proc/PrintDesign(var/datum/design/mechanic_design/design, var/use_nano = 0)
|
||||
if(linked_console)
|
||||
//message_admins("Looking for machines...")
|
||||
for(var/obj/machinery/r_n_d/M in linked_console.linked_machines)
|
||||
if(istype(M, /obj/machinery/r_n_d/blueprinter))
|
||||
var/obj/machinery/r_n_d/blueprinter/BP = M
|
||||
//message_admins("Found the blueprinter!")
|
||||
BP.PrintDesign(design, use_nano)
|
||||
return 1
|
||||
else
|
||||
src.visible_message("You need to link this machine to a research console first!")
|
||||
|
||||
|
||||
/obj/machinery/r_n_d/reverse_engine/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
if(src.stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
if((user.stat && !isobserver(user)) || user.restrained() || !allowed(user))
|
||||
return
|
||||
|
||||
var/data[0]
|
||||
var/list/todo_queue = list()
|
||||
var/list/done_queue = list()
|
||||
|
||||
for(var/i=1;i<=research_queue.len;i++)
|
||||
var/datum/design/mechanic_design/research_item = research_queue[i]
|
||||
todo_queue.Add(list(list("name" = research_item.name, "command1" = list("research" = i), "command2" = list("remove_tosearch" = i))))
|
||||
|
||||
for(var/i=1;i<=ready_queue.len;i++)
|
||||
var/datum/design/mechanic_design/ready_item = ready_queue[i]
|
||||
done_queue.Add(list(list("name" = ready_item.name, "command1" = list("print_design" = i), "command2" = list("nanoprint_design" = i), "command3" = list("remove_researched" = i))))
|
||||
|
||||
data["research_queue"] = todo_queue
|
||||
data["ready_queue"] = done_queue
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "rev-engine.tmpl", name, REV_ENG_WIDTH, REV_ENG_HEIGHT)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/r_n_d/reverse_engine/Topic(href, href_list)
|
||||
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["remove_tosearch"])
|
||||
var/datum/design/mechanic_design/design = research_queue[text2num(href_list["remove_tosearch"])]
|
||||
if(design)
|
||||
research_queue -= design
|
||||
del(design)
|
||||
ui_interact(usr)
|
||||
return 1
|
||||
|
||||
if(href_list["remove_researched"])
|
||||
var/datum/design/mechanic_design/design = ready_queue[text2num(href_list["remove_researched"])]
|
||||
if(design)
|
||||
ready_queue -= design
|
||||
del(design)
|
||||
ui_interact(usr)
|
||||
return 1
|
||||
|
||||
if(href_list["research"])
|
||||
var/datum/design/mechanic_design/design = research_queue[text2num(href_list["research"])]
|
||||
if(design)
|
||||
researchDesign(design)
|
||||
ui_interact(usr)
|
||||
return 1
|
||||
|
||||
if(href_list["research_all"])
|
||||
researchQueue()
|
||||
ui_interact(usr)
|
||||
return 1
|
||||
|
||||
if(href_list["print_design"])
|
||||
var/datum/design/mechanic_design/design = ready_queue[text2num(href_list["print_design"])]
|
||||
if(design)
|
||||
PrintDesign(design, 0)
|
||||
return 1
|
||||
|
||||
if(href_list["nanoprint_design"])
|
||||
var/datum/design/mechanic_design/design = ready_queue[text2num(href_list["nanoprint_design"])]
|
||||
if(design)
|
||||
PrintDesign(design, 1)
|
||||
return 1
|
||||
Reference in New Issue
Block a user