#define MAX_CIRCUIT_CLONE_TIME 3 MINUTES //circuit slow-clones can only take up this amount of time to complete
/obj/item/integrated_circuit_printer
name = "integrated circuit printer"
desc = "A portable(ish) machine made to print tiny modular circuitry out of metal."
icon = 'icons/obj/assemblies/electronic_tools.dmi'
icon_state = "circuit_printer"
w_class = WEIGHT_CLASS_BULKY
var/upgraded = FALSE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits.
var/can_clone = TRUE // Allows the printer to clone circuits, either instantly or over time depending on upgrade. Set to FALSE to disable entirely.
var/fast_clone = FALSE // If this is false, then cloning will take an amount of deciseconds equal to the metal cost divided by 100.
var/debug = FALSE // If it's upgraded and can clone, even without config settings.
var/current_category = null
var/cloning = FALSE // If the printer is currently creating a circuit
var/clone_countdown = 0 // Timestamp for when to print the circuit
var/recycling = FALSE // If an assembly is being emptied into this printer
var/list/program // Currently loaded save, in form of list
/obj/item/integrated_circuit_printer/proc/check_interactivity(mob/user)
return user.canUseTopic(src, BE_CLOSE)
/obj/item/integrated_circuit_printer/upgraded
upgraded = TRUE
can_clone = TRUE
fast_clone = TRUE
/obj/item/integrated_circuit_printer/debug //translation: "integrated_circuit_printer/local_server"
name = "debug circuit printer"
debug = TRUE
upgraded = TRUE
can_clone = TRUE
w_class = WEIGHT_CLASS_TINY
/obj/item/integrated_circuit_printer/Initialize()
. = ..()
AddComponent(/datum/component/material_container, list(MAT_METAL), MINERAL_MATERIAL_AMOUNT * 25, TRUE, list(/obj/item/stack, /obj/item/integrated_circuit, /obj/item/electronic_assembly))
/obj/item/integrated_circuit_printer/Destroy()
STOP_PROCESSING(SSprocessing, src)
return ..()
/obj/item/integrated_circuit_printer/process()
if(!cloning)
STOP_PROCESSING(SSprocessing, src)
if(world.time >= clone_countdown || fast_clone)
var/turf/T = get_turf(src)
T.visible_message("[src] has finished printing its assembly!")
playsound(get_turf(T), 'sound/items/poster_being_created.ogg', 50, TRUE)
SScircuit.load_electronic_assembly(T, program)
cloning = FALSE
STOP_PROCESSING(SSprocessing, src)
/obj/item/integrated_circuit_printer/attackby(obj/item/O, mob/user)
if(istype(O, /obj/item/disk/integrated_circuit/upgrade/advanced))
if(upgraded)
to_chat(user, "[src] already has this upgrade. ")
return TRUE
to_chat(user, "You install [O] into [src]. ")
upgraded = TRUE
interact(user)
return TRUE
if(istype(O, /obj/item/disk/integrated_circuit/upgrade/clone))
if(fast_clone)
to_chat(user, "[src] already has this upgrade. ")
return TRUE
to_chat(user, "You install [O] into [src]. Circuit cloning will now be instant. ")
fast_clone = TRUE
interact(user)
return TRUE
if(istype(O, /obj/item/electronic_assembly))
var/obj/item/electronic_assembly/EA = O //microtransactions not included
if(EA.assembly_components.len)
if(recycling)
return
if(!EA.opened)
to_chat(user, "You can't reach [EA]'s components to remove them!")
return
if(EA.battery)
to_chat(user, "Remove [EA]'s power cell first!")
return
for(var/V in EA.assembly_components)
var/obj/item/integrated_circuit/IC = V
if(!IC.removable)
to_chat(user, "[EA] has irremovable components in the casing, preventing you from emptying it.")
return
to_chat(user, "You begin recycling [EA]'s components...")
playsound(src, 'sound/items/electronic_assembly_emptying.ogg', 50, TRUE)
if(!do_after(user, 30, target = src)) //short channel so you don't accidentally start emptying out a complex assembly
return
recycling = TRUE
var/datum/component/material_container/mats = GetComponent(/datum/component/material_container)
for(var/V in EA.assembly_components)
var/obj/item/integrated_circuit/IC = V
if(!mats.has_space(mats.get_item_material_amount(IC)))
to_chat(user, "[src] can't hold any more materials!")
break
if(!do_after(user, 5, target = user))
recycling = FALSE
return
playsound(src, 'sound/items/crowbar.ogg', 50, TRUE)
if(EA.try_remove_component(IC, user, TRUE))
mats.user_insert(IC, user)
to_chat(user, "You recycle all the components[EA.assembly_components.len ? " you could " : " "]from [EA]!")
playsound(src, 'sound/items/electronic_assembly_empty.ogg', 50, TRUE)
recycling = FALSE
return TRUE
return ..()
/obj/item/integrated_circuit_printer/attack_self(mob/user)
interact(user)
/obj/item/integrated_circuit_printer/interact(mob/user)
if(isnull(current_category))
current_category = SScircuit.circuit_fabricator_recipe_list[1]
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/HTML = "
Integrated Circuit Printer
"
if(debug)
HTML += "DEBUG PRINTER -- Infinite materials. Cloning available.
"
else
HTML += "Metal: [materials.total_amount]/[materials.max_amount].
"
if(CONFIG_GET(flag/ic_printing) || debug)
HTML += "Assembly cloning: [can_clone ? (fast_clone ? "Instant" : "Available") : "Unavailable"].
"
HTML += "Circuits available: [upgraded || debug ? "Advanced":"Regular"]."
if(!upgraded)
HTML += "
Crossed out circuits mean that the printer is not sufficiently upgraded to create that circuit."
HTML += "
"
if((can_clone && CONFIG_GET(flag/ic_printing)) || debug)
HTML += "Here you can load script for your assembly.
"
if(!cloning)
HTML += " {Load Program} "
else
HTML += " {Load Program}"
if(!program)
HTML += " {[fast_clone ? "Print" : "Begin Printing"] Assembly}"
else if(cloning)
HTML += " {Cancel Print} - [DisplayTimeText(max(0, clone_countdown - world.time))] remaining until completion"
else
HTML += " {[fast_clone ? "Print" : "Begin Printing"] Assembly}"
HTML += "
"
HTML += "Categories:"
for(var/category in SScircuit.circuit_fabricator_recipe_list)
if(category != current_category)
HTML += " \[[category]\] "
else // Bold the button if it's already selected.
HTML += " \[[category]\] "
HTML += "
"
HTML += "[current_category]
"
var/list/current_list = SScircuit.circuit_fabricator_recipe_list[current_category]
for(var/path in current_list)
var/obj/O = path
var/can_build = TRUE
if(ispath(path, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = path
if((initial(IC.spawn_flags) & IC_SPAWN_RESEARCH) && (!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT)) && !upgraded)
can_build = FALSE
if(can_build)
HTML += "\[[initial(O.name)]\]: [initial(O.desc)]
"
else
HTML += "\[[initial(O.name)]\]: [initial(O.desc)]
"
user << browse(HTML, "window=integrated_printer;size=600x500;border=1;can_resize=1;can_close=1;can_minimize=1")
/obj/item/integrated_circuit_printer/Topic(href, href_list)
if(!check_interactivity(usr))
return
if(..())
return TRUE
add_fingerprint(usr)
if(href_list["category"])
current_category = href_list["category"]
if(href_list["build"])
var/build_type = text2path(href_list["build"])
if(!build_type || !ispath(build_type))
return TRUE
var/cost = 400
if(ispath(build_type, /obj/item/electronic_assembly))
var/obj/item/electronic_assembly/E = SScircuit.cached_assemblies[build_type]
cost = E.materials[MAT_METAL]
else if(ispath(build_type, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = SScircuit.cached_components[build_type]
cost = IC.materials[MAT_METAL]
else if(!build_type in SScircuit.circuit_fabricator_recipe_list["Tools"])
return
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(!debug && !materials.use_amount_type(cost, MAT_METAL))
to_chat(usr, "You need [cost] metal to build that!")
return TRUE
var/obj/item/built = new build_type(drop_location())
usr.put_in_hands(built)
if(istype(built, /obj/item/electronic_assembly))
var/obj/item/electronic_assembly/E = built
E.opened = TRUE
E.update_icon()
//reupdate diagnostic hud because it was put_in_hands() and not pickup()'ed
E.diag_hud_set_circuithealth()
E.diag_hud_set_circuitcell()
E.diag_hud_set_circuitstat()
E.diag_hud_set_circuittracking()
to_chat(usr, "[capitalize(built.name)] printed.")
playsound(src, 'sound/items/jaws_pry.ogg', 50, TRUE)
if(href_list["print"])
if(!CONFIG_GET(flag/ic_printing) && !debug)
to_chat(usr, "CentCom has disabled printing of custom circuitry due to recent allegations of copyright infringement.")
return
if(!can_clone) // Copying and printing ICs is cloning
to_chat(usr, "This printer does not have the cloning upgrade.")
return
switch(href_list["print"])
if("load")
var/input = input("Put your code there:", "loading", null, null) as message | null
if(!check_interactivity(usr))
return
if(!input)
program = null
return
var/validation = SScircuit.validate_electronic_assembly(input)
// Validation error codes are returned as text.
if(istext(validation))
to_chat(usr, "Error: [validation]")
return
else if(islist(validation))
program = validation
to_chat(usr, "This is a valid program for [program["assembly"]["type"]].")
if(program["requires_upgrades"])
if(upgraded)
to_chat(usr, "It uses advanced component designs.")
else
to_chat(usr, "It uses unknown component designs. Printer upgrade is required to proceed.")
if(program["unsupported_circuit"])
to_chat(usr, "This program uses components not supported by the specified assembly. Please change the assembly type in the save file to a supported one.")
to_chat(usr, "Used space: [program["used_space"]]/[program["max_space"]].")
to_chat(usr, "Complexity: [program["complexity"]]/[program["max_complexity"]].")
to_chat(usr, "Metal cost: [program["metal_cost"]].")
if("print")
if(!program)
return
if(program["requires_upgrades"] && !upgraded && !debug)
to_chat(usr, "This program uses unknown component designs. Printer upgrade is required to proceed.")
if(program["unsupported_circuit"] && !debug)
to_chat(usr, "This program uses components not supported by the specified assembly. Please change the assembly type in the save file to a supported one.")
else if(fast_clone || debug)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(debug || materials.use_amount_type(program["metal_cost"], MAT_METAL))
var/obj/item/assembly = SScircuit.load_electronic_assembly(get_turf(src), program)
to_chat(usr, "[assembly] has been printed from the provided template!")
playsound(src, 'sound/items/poster_being_created.ogg', 50, TRUE)
else
to_chat(usr, "You need [program["metal_cost"]] metal to build that!")
else
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(!materials.use_amount_type(program["metal_cost"], MAT_METAL))
to_chat(usr, "You need [program["metal_cost"]] metal to build that!")
return
var/cloning_time = round(program["metal_cost"] / 15)
cloning_time = min(cloning_time, MAX_CIRCUIT_CLONE_TIME)
cloning = TRUE
clone_countdown = world.time + cloning_time
to_chat(usr, "You begin printing a custom assembly. This will take approximately [DisplayTimeText(cloning_time)]. You can still print \
off normal parts during this time.")
playsound(src, 'sound/items/poster_being_created.ogg', 50, TRUE)
START_PROCESSING(SSprocessing, src)
if("cancel")
if(!cloning || !program)
return
to_chat(usr, "Cloning has been canceled. Metal cost has been refunded.")
cloning = FALSE
clone_countdown = FALSE
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.use_amount_type(-program["metal_cost"], MAT_METAL) //use negative amount to regain the cost
interact(usr)
// FUKKEN UPGRADE DISKS
/obj/item/disk/integrated_circuit/upgrade
name = "integrated circuit printer upgrade disk"
desc = "Install this into your integrated circuit printer to enhance it."
icon = 'icons/obj/assemblies/electronic_tools.dmi'
icon_state = "upgrade_disk"
item_state = "card-id"
w_class = WEIGHT_CLASS_SMALL
/obj/item/disk/integrated_circuit/upgrade/advanced
name = "integrated circuit printer upgrade disk - advanced designs"
desc = "Install this into your integrated circuit printer to enhance it. This one adds new, advanced designs to the printer."
/obj/item/disk/integrated_circuit/upgrade/clone
name = "integrated circuit printer upgrade disk - instant cloner"
desc = "Install this into your integrated circuit printer to enhance it. This one allows the printer to duplicate assemblies instantaneously."
icon_state = "upgrade_disk_clone"