diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm
new file mode 100644
index 00000000000..9e0fa6039c8
--- /dev/null
+++ b/code/modules/integrated_electronics/_defines.dm
@@ -0,0 +1,356 @@
+#define DATA_CHANNEL "data channel"
+#define PULSE_CHANNEL "pulse channel"
+
+/obj/item/integrated_circuit
+ name = "integrated circuit"
+ desc = "It's a tiny chip! This one doesn't seem to do much, however."
+ icon = 'icons/obj/electronic_assemblies.dmi'
+ icon_state = "template"
+ w_class = 1
+ var/extended_desc = null
+ var/list/inputs = list()
+ var/list/outputs = list()
+ var/list/activators = list()
+ var/number_of_inputs = 0 //This is how many input pins are created
+ var/number_of_outputs = 0 //Likewise for output
+ var/number_of_activators = 0 //Guess
+ var/list/input_names = list()
+ var/list/output_names = list()
+ var/list/activator_names = list()
+ var/last_used = 0 //Uses world.time
+ var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
+ var/power_required = 5 //w
+
+/obj/item/integrated_circuit/examine(mob/user)
+ ..()
+ user << "This board has [inputs.len] input [inputs.len != 1 ? "pins" : "pin"] and \
+ [outputs.len] output [outputs.len != 1 ? "pins" : "pin"]."
+ for(var/datum/integrated_io/input/I in inputs)
+ if(I.linked.len)
+ user << "\The [I.name] is connected to [I.get_linked_to_desc()]."
+ for(var/datum/integrated_io/output/O in outputs)
+ if(O.linked.len)
+ user << "\The [O.name] is connected to [O.get_linked_to_desc()]."
+ for(var/datum/integrated_io/activate/A in activators)
+ if(A.linked.len)
+ user << "\The [A.name] is connected to [A.get_linked_to_desc()]."
+
+ interact(user)
+
+/obj/item/integrated_circuit/New()
+ ..()
+ var/i = 0
+ if(number_of_inputs)
+ for(i = number_of_inputs, i > 0, i--)
+ inputs.Add(new /datum/integrated_io/input(src))
+
+ if(number_of_outputs)
+ for(i = number_of_outputs, i > 0, i--)
+ outputs.Add(new /datum/integrated_io/output(src))
+
+ if(number_of_activators)
+ for(i = number_of_activators, i > 0, i--)
+ activators.Add(new /datum/integrated_io/activate(src))
+
+ apply_names_to_io()
+
+/obj/item/integrated_circuit/proc/apply_names_to_io()
+ var/i = 1
+ if(input_names.len)
+ for(var/datum/integrated_io/input/I in inputs)
+ I.name = "[input_names[i]]"
+ i++
+ i = 1
+ if(output_names.len)
+ for(var/datum/integrated_io/output/O in outputs)
+ O.name = "[output_names[i]]"
+ i++
+
+ i = 1
+ if(activator_names.len)
+ for(var/datum/integrated_io/activate/A in activators)
+ A.name = "[activator_names[i]]"
+ i++
+
+/obj/item/integrated_circuit/Destroy()
+ for(var/datum/integrated_io/I in inputs)
+ qdel(I)
+ for(var/datum/integrated_io/O in outputs)
+ qdel(O)
+ for(var/datum/integrated_io/A in activators)
+ qdel(A)
+ ..()
+
+/obj/item/integrated_circuit/emp_act(severity)
+ for(var/datum/integrated_io/io in inputs + outputs + activators)
+ io.scramble()
+
+/obj/item/integrated_circuit/verb/rename_component()
+ set name = "Rename Circuit"
+ set category = "Object"
+ set desc = "Rename your circuit, useful to stay organized."
+
+ var/mob/M = usr
+
+ var/input = sanitizeSafe(input("What do you want to name the circuit?", ,""), MAX_NAME_LEN)
+
+ if(src && input)
+ M << "The circuit '[src.name]' is now labeled '[input]'."
+ name = input
+
+/obj/item/integrated_circuit/proc/get_pin_ref(var/pin_type, var/pin_number)
+ switch(pin_type)
+ if("input")
+ if(pin_number > inputs.len)
+ return null
+ return inputs[pin_number]
+ if("output")
+ if(pin_number > outputs.len)
+ return null
+ return outputs[pin_number]
+ if("activator")
+ if(pin_number > activators.len)
+ return null
+ return activators[pin_number]
+ return null
+
+/obj/item/integrated_circuit/interact(mob/user)
+ if(get_dist(get_turf(src), user) > 1)
+ user.unset_machine(src)
+ return
+ var/HTML = "
[src.name]"
+ HTML += ""
+ HTML += "
"
+
+ HTML += "
\[Refresh\] | "
+ HTML += "\[Rename\]
"
+
+ HTML += ""
+ HTML += ""
+ HTML += ""
+ HTML += ""
+ HTML += ""
+
+ var/column_width = 3
+ var/row_height = max(inputs.len, outputs.len, 1)
+ var/i
+ var/j
+ for(i = 1, i < row_height+1, i++)
+ HTML += ""
+ for(j = 1, j < column_width+1, j++)
+ var/datum/integrated_io/io = null
+ var/words = null
+ var/height = 1
+ switch(j)
+ if(1)
+ io = get_pin_ref("input",i)
+ if(io)
+ if(io.linked.len)
+ words = "[io.name] [io.display_data()]
"
+ for(var/datum/integrated_io/linked in io.linked)
+ words += "\[[linked.name]\] \
+ @ [linked.holder]
"
+ else // "Click here!"
+ words = "[io.name] [io.display_data()]
"
+ for(var/datum/integrated_io/linked in io.linked)
+ words += "\[[linked.name]\] \
+ @ [linked.holder]
"
+ if(outputs.len > inputs.len)
+ height = Floor(outputs.len / inputs.len)
+ //world << "I wrote [words] at ([i],[j])."
+ if(2)
+ if(i == 1)
+ words = "[src.name]
[src.desc]"
+ height = row_height
+ //world << "I wrote the center piece because i was equal to 1, at ([i],[j])."
+ else
+ continue
+ if(3)
+ io = get_pin_ref("output",i)
+ if(io)
+ if(io.linked.len)
+ words = "[io.name] [io.display_data()]
"
+ for(var/datum/integrated_io/linked in io.linked)
+ words += "\[[linked.name]\] \
+ @ [linked.holder]
"
+ else
+ words = "[io.name] [io.display_data()]
"
+ for(var/datum/integrated_io/linked in io.linked)
+ words += "\[[linked.name]\] \
+ @ [linked.holder]
"
+ if(inputs.len > outputs.len)
+ height = Floor(inputs.len / outputs.len)
+ //world << "I wrote [words] at ([i],[j])."
+ HTML += "[words] | "
+ //HTML += "[words] | "
+ //world << "Writing to ([i],[j])."
+ HTML += "
"
+
+ if(activators.len)
+ for(i = 1, i < activators.len+1, i++)
+ var/datum/integrated_io/io = null
+ var/words = null
+ io = get_pin_ref("activator",i)
+ if(io)
+ if(io.linked.len)
+ words = "[io.name]
"
+ for(var/datum/integrated_io/linked in io.linked)
+ words += "\[[linked.name]\] \
+ @ [linked.holder]
"
+ else // "Click here!"
+ words = "[io.name]
"
+ for(var/datum/integrated_io/linked in io.linked)
+ words += "\[[linked.name]\] \
+ @ [linked.holder]
"
+ HTML += ""
+ HTML += "| [words] | "
+ HTML += "
"
+
+ HTML += "
"
+ HTML += "
"
+
+ HTML += "
[extended_desc]"
+
+ HTML += ""
+ user << browse(HTML, "window=circuit-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1")
+
+ user.set_machine(src)
+ onclose(user, "circuit-\ref[src]")
+
+/obj/item/integrated_circuit/Topic(href, href_list[])
+ var/mob/living/user = locate(href_list["user"]) in mob_list
+ var/pin = locate(href_list["pin"]) in inputs + outputs + activators
+
+ if(!user || !user.Adjacent(get_turf(src)) )
+ return 1
+
+ if(href_list["wire"])
+ if(ishuman(user) && Adjacent(user))
+ var/mob/living/carbon/human/H = user
+ var/obj/item/device/integrated_electronics/wirer/wirer = null
+ if(istype(H.r_hand, /obj/item/device/integrated_electronics/wirer))
+ wirer = H.r_hand
+ else if(istype(H.l_hand, /obj/item/device/integrated_electronics/wirer))
+ wirer = H.l_hand
+
+ if(wirer && pin)
+ wirer.wire(pin, user)
+ else
+ user << "You can't do a whole lot without tools."
+
+ if(href_list["examine"])
+ examine(user)
+
+ if(href_list["rename"])
+ rename_component(user)
+
+ interact(user) // To refresh the UI.
+
+/datum/integrated_io
+ var/name = "input/output"
+ var/obj/item/integrated_circuit/holder = null
+ var/data = null
+ var/list/linked = list()
+ var/io_type = DATA_CHANNEL
+
+/datum/integrated_io/New(var/newloc)
+ ..()
+ holder = newloc
+ if(!holder)
+ message_admins("ERROR: An integrated_io ([src.name]) spawned without a holder! This is a bug.")
+
+/datum/integrated_io/Destroy()
+ disconnect()
+ holder = null
+ ..()
+
+/datum/integrated_io/proc/display_data()
+ if(!data)
+ return "(null)" // Empty data means nothing to show.
+ if(istext(data))
+ return "(\"[data]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'.
+ if(istype(data, /atom))
+ var/atom/A = data
+ return "([A.name] \[Ref\])" // For refs, we want just the name displayed.
+ return "([data])" // Nothing special needed for numbers or other stuff.
+
+/datum/integrated_io/activate/display_data()
+ return "(\[pulse\])"
+
+/datum/integrated_io/proc/scramble()
+ if(isnull(data))
+ return
+ if(isnum(data))
+ data = rand(-10000, 10000)
+ if(istext(data))
+ data = "ERROR"
+ push_data()
+
+/datum/integrated_io/activate/scramble()
+ push_data()
+
+/datum/integrated_io/proc/push_data()
+ if(linked.len)
+ for(var/datum/integrated_io/io in linked)
+ io.data = data
+
+/datum/integrated_io/activate/push_data()
+ if(linked.len)
+ for(var/datum/integrated_io/io in linked)
+ io.holder.work()
+
+/datum/integrated_io/proc/pull_data()
+ if(linked.len)
+ for(var/datum/integrated_io/io in linked)
+ data = io.data
+
+/datum/integrated_io/proc/get_linked_to_desc()
+ if(linked.len)
+ var/result = english_list(linked)
+ return "the [result]"
+ return "nothing"
+
+/datum/integrated_io/proc/disconnect()
+ if(linked.len)
+ //First we iterate over everything we are linked to.
+ for(var/datum/integrated_io/their_io in linked)
+ //While doing that, we iterate them as well, and disconnect ourselves from them.
+ for(var/datum/integrated_io/their_linked_io in their_io.linked)
+ if(their_linked_io == src)
+ their_io.linked.Remove(src)
+ else
+ continue
+ //Now that we're removed from them, we gotta remove them from us.
+ src.linked.Remove(their_io)
+
+/datum/integrated_io/input
+ name = "input pin"
+
+/datum/integrated_io/output
+ name = "output pin"
+
+/datum/integrated_io/activate
+ name = "activation pin"
+ io_type = PULSE_CHANNEL
+
+/obj/item/integrated_circuit/proc/push_data()
+ for(var/datum/integrated_io/output/O in outputs)
+ O.push_data()
+
+/obj/item/integrated_circuit/proc/pull_data()
+ for(var/datum/integrated_io/input/I in inputs)
+ I.push_data()
+
+/obj/item/integrated_circuit/proc/work()
+ if(last_used + 2 SECONDS > world.time) // All intergrated circuits have an internal cooldown of two seconds to protect from spam.
+ return 0
+ last_used = world.time
+ return 1
+
+/obj/item/integrated_circuit/proc/disconnect_all()
+ for(var/datum/integrated_io/input/I in inputs)
+ I.disconnect()
+ for(var/datum/integrated_io/output/O in outputs)
+ O.disconnect()
+ for(var/datum/integrated_io/activate/A in activators)
+ A.disconnect()
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/arithmetic.dm b/code/modules/integrated_electronics/arithmetic.dm
new file mode 100644
index 00000000000..5f5a4f1d2e6
--- /dev/null
+++ b/code/modules/integrated_electronics/arithmetic.dm
@@ -0,0 +1,157 @@
+//These circuits do simple math.
+/obj/item/integrated_circuit/arithmetic
+ complexity = 1
+ number_of_inputs = 8
+ number_of_outputs = 1
+ number_of_activators = 1
+ input_names = list(
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H"
+ )
+ output_names = list(
+ "result"
+ )
+ activator_names = list(
+ "compute"
+ )
+
+// +Adding+ //
+
+/obj/item/integrated_circuit/arithmetic/addition
+ name = "addition circuit"
+ desc = "This circuit can add numbers together."
+ icon_state = "addition"
+
+/obj/item/integrated_circuit/arithmetic/addition/work()
+ if(..())
+ var/result = 0
+ for(var/datum/integrated_io/input/I in inputs)
+ I.pull_data()
+ if(isnum(I.data))
+ result = result + I.data
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = result
+ O.push_data()
+
+// -Subtracting- //
+
+/obj/item/integrated_circuit/arithmetic/subtraction
+ name = "subtraction circuit"
+ desc = "This circuit can subtract numbers."
+ icon_state = "subtraction"
+
+/obj/item/integrated_circuit/arithmetic/subtraction/work()
+ if(..())
+ var/result = 0
+ for(var/datum/integrated_io/input/I in inputs)
+ I.pull_data()
+ if(isnum(I.data))
+ result = result - I.data
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = result
+ O.push_data()
+
+// *Multiply* //
+
+/obj/item/integrated_circuit/arithmetic/multiplication
+ name = "multiplication circuit"
+ desc = "This circuit can multiply numbers."
+ icon_state = "multiplication"
+
+/obj/item/integrated_circuit/arithmetic/subtraction/work()
+ if(..())
+ var/result = 0
+ for(var/datum/integrated_io/input/I in inputs)
+ I.pull_data()
+ if(isnum(I.data))
+ result = result * I.data
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = result
+ O.push_data()
+
+// /Division/ //
+
+/obj/item/integrated_circuit/arithmetic/division
+ name = "division circuit"
+ desc = "This circuit can divide numbers, just don't think about trying to divide by zero!"
+ icon_state = "division"
+
+/obj/item/integrated_circuit/arithmetic/division/work()
+ if(..())
+ var/result = 0
+ for(var/datum/integrated_io/input/I in inputs)
+ I.pull_data()
+ if(isnum(I.data) && I.data != 0) //No runtimes here.
+ result = result / I.data
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = result
+ O.push_data()
+
+// Absolute //
+
+/obj/item/integrated_circuit/arithmetic/absolute
+ name = "absolute circuit"
+ desc = "This outputs a non-negative version of the number you put in. This may also be thought of as its distance from zero."
+ icon_state = "absolute"
+ number_of_inputs = 1
+ number_of_outputs = 1
+
+/obj/item/integrated_circuit/arithmetic/absolute/work()
+ if(..())
+ var/result = 0
+ for(var/datum/integrated_io/input/I in inputs)
+ I.pull_data()
+ if(isnum(I.data) && I.data != 0)
+ result = abs(result)
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = result
+ O.push_data()
+
+// Averaging //
+
+/obj/item/integrated_circuit/arithmetic/average
+ name = "average circuit"
+ desc = "This circuit is of average quality, however it will compute the average for numbers you give it."
+ icon_state = "average"
+
+/obj/item/integrated_circuit/arithmetic/average/work()
+ if(..())
+ var/result = 0
+ var/inputs_used = 0
+ for(var/datum/integrated_io/input/I in inputs)
+ I.pull_data()
+ if(isnum(I.data))
+ inputs_used++
+ result = result + I.data
+
+ if(inputs_used)
+ result = result / inputs_used
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = result
+ O.push_data()
+
+// Pi, because why the hell not? //
+/obj/item/integrated_circuit/arithmetic/pi
+ name = "pi constant circuit"
+ desc = "Not recommended for cooking. Outputs '3.14159' when it receives a pulse."
+ icon_state = "pi"
+ number_of_inputs = 0
+ number_of_outputs = 1
+
+/obj/item/integrated_circuit/arithmetic/pi/work()
+ if(..())
+ var/datum/integrated_io/output/O = outputs[1]
+ O.data = 3.14159
+ O.push_data()
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/assemblies.dm b/code/modules/integrated_electronics/assemblies.dm
new file mode 100644
index 00000000000..97690b977f8
--- /dev/null
+++ b/code/modules/integrated_electronics/assemblies.dm
@@ -0,0 +1,109 @@
+/obj/item/device/electronic_assembly
+ name = "electronic assembly"
+ desc = "It's a case, for building electronics with."
+ w_class = 2
+ icon = 'icons/obj/electronic_assemblies.dmi'
+ icon_state = "setup"
+ var/max_components = 10
+ var/max_complexity = 30
+ var/opened = 0
+
+/obj/item/device/electronic_assembly/medium
+ name = "electronic mechanism"
+ w_class = 3
+ max_components = 20
+ max_complexity = 50
+
+/obj/item/device/electronic_assembly/large
+ name = "electronic machine"
+ w_class = 4
+ max_components = 30
+ max_complexity = 60
+
+/*
+
+/obj/item/device/electronic_assembly/New()
+ ..()
+ processing_objects |= src
+
+/obj/item/device/electronic_assembly/Destroy()
+ processing_objects.Remove(src)
+ ..()
+
+/obj/item/device/electronic_assembly/process()
+ for(var/obj/item/integrated_circuit/IC in contents)
+ IC.work()
+*/
+
+/obj/item/device/electronic_assembly/examine(mob/user)
+ ..()
+ if(!opened)
+ for(var/obj/item/integrated_circuit/output/screen/S in contents)
+ if(S.stuff_to_display)
+ user << "There's a little screen labeled '[S.name]', which displays '[S.stuff_to_display]'."
+ else
+ var/obj/item/integrated_circuit/IC = input(user, "Which circuit do you want to examine?", "Examination") as null|anything in contents
+ if(IC)
+ IC.examine(user)
+
+/obj/item/device/electronic_assembly/attackby(var/obj/item/I, var/mob/user)
+ if(istype(I, /obj/item/integrated_circuit))
+ if(!opened)
+ user << "\The [src] isn't opened, so you can't put anything inside. Try using a crowbar."
+ return 0
+ var/obj/item/integrated_circuit/IC = I
+ var/total_parts = 0
+ var/total_complexity = 0
+ for(var/obj/item/integrated_circuit/part in contents)
+ total_parts++
+ total_complexity = total_complexity + part.complexity
+
+ if( (total_parts + 1) >= max_components)
+ user << "You can't seem to add this [IC.name], since there's no more room."
+ return 0
+ if( (total_complexity + IC.complexity) >= max_complexity)
+ user << "You can't seem to add this [IC.name], since this setup's too complicated for the case."
+ return 0
+
+ user << "You slide \the [IC] inside \the [src]."
+ user.drop_item()
+ IC.forceMove(src)
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(istype(I, /obj/item/weapon/screwdriver))
+ if(!opened)
+ user << "\The [src] isn't opened, so you can't remove anything inside. Try using a crowbar."
+ return 0
+ if(!contents.len)
+ user << "There's nothing inside this to remove!"
+ return 0
+ var/obj/item/integrated_circuit/option = input("What do you want to remove?", "Component Removal") as null|anything in contents
+ if(option)
+ option.disconnect_all()
+ option.forceMove(get_turf(src))
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ user << "You pop \the [option] out of the case, and slide it out."
+ if(istype(I, /obj/item/weapon/crowbar))
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ opened = !opened
+ user << "You [opened ? "opened" : "closed"] \the [src]."
+ if(istype(I, /obj/item/device/integrated_electronics/wirer))
+ if(opened)
+ var/obj/item/integrated_circuit/IC = input(user, "Which circuit do you want to examine?", "Examination") as null|anything in contents
+ if(IC)
+ IC.examine(user)
+ else
+ user << "\The [src] isn't opened, so you can't fiddle with the internal components. \
+ Try using a crowbar."
+
+/obj/item/device/electronic_assembly/attack_self(mob/user)
+ var/list/available_inputs = list()
+ for(var/obj/item/integrated_circuit/input/input in contents)
+ available_inputs.Add(input)
+ var/obj/item/integrated_circuit/input/choice = input(user, "What do you want to interact with?", "Interaction") as null|anything in available_inputs
+ if(choice)
+ choice.ask_for_input(user)
+
+/obj/item/device/electronic_assembly/emp_act(severity)
+ ..()
+ for(var/atom/movable/AM in contents)
+ AM.emp_act(severity)
diff --git a/code/modules/integrated_electronics/converters.dm b/code/modules/integrated_electronics/converters.dm
new file mode 100644
index 00000000000..0bd21664195
--- /dev/null
+++ b/code/modules/integrated_electronics/converters.dm
@@ -0,0 +1,96 @@
+//These circuits convert one variable to another.
+/obj/item/integrated_circuit/converter
+ complexity = 2
+ number_of_inputs = 1
+ number_of_outputs = 1
+ number_of_activators = 1
+ input_names = list(
+ "input",
+ )
+ output_names = list(
+ "result"
+ )
+ activator_names = list(
+ "convert"
+ )
+
+/obj/item/integrated_circuit/converter/num2text
+ name = "number to string"
+ desc = "This circuit can convert a number variable into a string."
+ icon_state = "addition"
+
+/obj/item/integrated_circuit/converter/num2text/work()
+ if(..())
+ var/result = null
+ var/datum/integrated_io/incoming = inputs[1]
+ var/datum/integrated_io/outgoing = outputs[1]
+ if(incoming.data && isnum(incoming.data))
+ result = num2text(incoming.data)
+
+ outgoing.data = result
+ outgoing.push_data()
+
+/obj/item/integrated_circuit/converter/text2num
+ name = "string to number"
+ desc = "This circuit can convert a string variable into a number."
+ icon_state = "addition"
+
+/obj/item/integrated_circuit/converter/text2num/work()
+ if(..())
+ var/result = null
+ var/datum/integrated_io/incoming = inputs[1]
+ var/datum/integrated_io/outgoing = outputs[1]
+ if(incoming.data && istext(incoming.data))
+ result = text2num(incoming.data)
+
+ outgoing.data = result
+ outgoing.push_data()
+
+/obj/item/integrated_circuit/converter/ref2text
+ name = "reference to string"
+ desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference."
+ icon_state = "addition"
+
+/obj/item/integrated_circuit/converter/ref2text/work()
+ if(..())
+ var/result = null
+ var/datum/integrated_io/incoming = inputs[1]
+ var/datum/integrated_io/outgoing = outputs[1]
+ if(incoming.data && istype(incoming.data, /atom/))
+ var/atom/A = incoming.data
+ result = A.name
+
+ outgoing.data = result
+ outgoing.push_data()
+
+/obj/item/integrated_circuit/converter/lowercase
+ name = "lowercase string converter"
+ desc = "this will cause a string to come out in all lowercase."
+ icon_state = "addition"
+
+/obj/item/integrated_circuit/converter/lowercase/work()
+ if(..())
+ var/result = null
+ var/datum/integrated_io/incoming = inputs[1]
+ var/datum/integrated_io/outgoing = outputs[1]
+ if(incoming.data && istext(incoming.data))
+ result = lowertext(incoming.data)
+
+ outgoing.data = result
+ outgoing.push_data()
+
+/obj/item/integrated_circuit/converter/uppercase
+ name = "uppercase string converter"
+ desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE."
+ icon_state = "addition"
+
+/obj/item/integrated_circuit/converter/uppercase/work()
+ if(..())
+ var/result = null
+ var/datum/integrated_io/incoming = inputs[1]
+ var/datum/integrated_io/outgoing = outputs[1]
+ if(incoming.data && istext(incoming.data))
+ result = uppertext(incoming.data)
+
+ outgoing.data = result
+ outgoing.push_data()
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/coordinate.dm b/code/modules/integrated_electronics/coordinate.dm
new file mode 100644
index 00000000000..04409907ac8
--- /dev/null
+++ b/code/modules/integrated_electronics/coordinate.dm
@@ -0,0 +1,74 @@
+//This circuit gives information on where the machine is.
+/obj/item/integrated_circuit/gps
+ name = "global positioning system"
+ desc = "This allows you to easily know the position of a machine containing this device."
+ complexity = 4
+ number_of_inputs = 0
+ number_of_outputs = 2
+ number_of_activators = 1
+ input_names = list(
+ )
+ output_names = list(
+ "X (abs)",
+ "Y (abs)"
+ )
+ activator_names = list(
+ "get coordinates"
+ )
+
+/obj/item/integrated_circuit/gps/work()
+ if(..())
+ var/turf/T = get_turf(src)
+ var/datum/integrated_io/result_x = outputs[1]
+ var/datum/integrated_io/result_y = outputs[2]
+
+ result_x.data = null
+ result_y.data = null
+ if(!T)
+ return
+
+ result_x.data = T.x
+ result_y.data = T.y
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.push_data()
+
+/obj/item/integrated_circuit/abs_to_rel_coords
+ name = "abs to rel coordinate converter"
+ desc = "Easily convert absolute coordinates to relative coordinates with this."
+ complexity = 4
+ number_of_inputs = 0
+ number_of_outputs = 4
+ number_of_activators = 1
+ input_names = list(
+ "X1 (abs)",
+ "Y1 (abs)",
+ "X2 (abs)",
+ "Y2 (abs)"
+ )
+ output_names = list(
+ "X (rel)",
+ "Y (rel)"
+ )
+ activator_names = list(
+ "compute rel coordinates"
+ )
+
+/obj/item/integrated_circuit/abs_to_rel_coords/work()
+ var/datum/integrated_io/x1 = inputs[1]
+ var/datum/integrated_io/y1 = inputs[2]
+
+ var/datum/integrated_io/x2 = inputs[3]
+ var/datum/integrated_io/y2 = inputs[4]
+
+ var/datum/integrated_io/result_x = outputs[1]
+ var/datum/integrated_io/result_y = outputs[2]
+
+ if(x1.data && y1.data && x2.data && y2.data)
+ result_x.data = x1.data - x2.data
+ result_y.data = y1.data - y2.data
+
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.push_data()
+ ..()
diff --git a/code/modules/integrated_electronics/data_transfer.dm b/code/modules/integrated_electronics/data_transfer.dm
new file mode 100644
index 00000000000..12380e9ccac
--- /dev/null
+++ b/code/modules/integrated_electronics/data_transfer.dm
@@ -0,0 +1,79 @@
+/obj/item/integrated_circuit/transfer/splitter
+ name = "splitter"
+ desc = "Splits incoming data into all of the output pins."
+ icon_state = "splitter"
+ complexity = 3
+ number_of_inputs = 1
+ number_of_outputs = 2
+ input_names = list(
+ "data to split"
+ )
+ output_names = list(
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H"
+ )
+
+/obj/item/integrated_circuit/transfer/splitter/medium
+ name = "four splitter"
+ icon_state = "splitter4"
+ complexity = 5
+ number_of_inputs = 1
+ number_of_outputs = 4
+
+/obj/item/integrated_circuit/transfer/splitter/large
+ name = "eight splitter"
+ icon_state = "splitter8"
+ complexity = 9
+ number_of_inputs = 1
+ number_of_outputs = 8
+
+/obj/item/integrated_circuit/transfer/splitter/work()
+ if(..())
+ var/datum/integrated_io/I = inputs[1]
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = I.data
+
+/obj/item/integrated_circuit/transfer/activator_splitter
+ name = "activator splitter"
+ desc = "Splits incoming activation pulses into all of the output pins."
+ icon_state = "splitter"
+ complexity = 3
+ number_of_activators = 3
+ activator_names = list(
+ "incoming pulse",
+ "outgoing pulse A",
+ "outgoing pulse B",
+ "outgoing pulse C",
+ "outgoing pulse D",
+ "outgoing pulse E",
+ "outgoing pulse F",
+ "outgoing pulse G",
+ "outgoing pulse H"
+ )
+
+/obj/item/integrated_circuit/transfer/activator_splitter/work()
+ if(..())
+ for(var/datum/integrated_io/activate/A in outputs)
+ if(A == activators[1])
+ continue
+ if(A.linked.len)
+ for(var/datum/integrated_io/activate/target in A.linked)
+ target.holder.work()
+
+/obj/item/integrated_circuit/transfer/activator_splitter/medium
+ name = "four activator splitter"
+ icon_state = "splitter4"
+ complexity = 5
+ number_of_activators = 5
+
+/obj/item/integrated_circuit/transfer/activator_splitter/large
+ name = "eight activator splitter"
+ icon_state = "splitter4"
+ complexity = 9
+ number_of_activators = 9
diff --git a/code/modules/integrated_electronics/input_output.dm b/code/modules/integrated_electronics/input_output.dm
new file mode 100644
index 00000000000..8f9c2cac040
--- /dev/null
+++ b/code/modules/integrated_electronics/input_output.dm
@@ -0,0 +1,91 @@
+/obj/item/integrated_circuit/input/proc/ask_for_input(mob/user)
+ return
+
+/obj/item/integrated_circuit/input/button
+ name = "button"
+ desc = "This tiny button must do something, right?"
+ icon_state = "button"
+ number_of_inputs = 0
+ number_of_outputs = 0
+ number_of_activators = 1
+ complexity = 1
+ activator_names = list(
+ "on pressed"
+ )
+
+/obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use.
+ var/datum/integrated_io/A = activators[1]
+ if(A.linked.len)
+ for(var/datum/integrated_io/activate/target in A.linked)
+ target.holder.work()
+ user << "You press the button labeled '[src.name]'."
+
+/obj/item/integrated_circuit/input/numberpad
+ name = "number pad"
+ desc = "This small number pad allows someone to input a number into the system."
+ icon_state = "numberpad"
+ number_of_inputs = 0
+ number_of_outputs = 1
+ number_of_activators = 1
+ complexity = 2
+ output_names = list(
+ "number entered"
+ )
+ activator_names = list(
+ "on entered"
+ )
+
+/obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user)
+ var/new_input = input(user, "Enter a number, please.","Number pad") as num
+ if(new_input && isnum(new_input))
+ var/datum/integrated_io/O = outputs[1]
+ O.data = new_input
+ O.push_data()
+ var/datum/integrated_io/A = activators[1]
+ if(A.linked)
+ A.holder.work()
+
+/obj/item/integrated_circuit/input/textpad
+ name = "text pad"
+ desc = "This small text pad allows someone to input a string into the system."
+ icon_state = "numberpad"
+ number_of_inputs = 0
+ number_of_outputs = 1
+ number_of_activators = 1
+ complexity = 2
+ output_names = list(
+ "string entered"
+ )
+ activator_names = list(
+ "on entered"
+ )
+
+/obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user)
+ var/new_input = input(user, "Enter some words, please.","Number pad") as text
+ if(new_input && istext(new_input))
+ var/datum/integrated_io/O = outputs[1]
+ O.data = new_input
+ O.push_data()
+ var/datum/integrated_io/A = activators[1]
+ if(A.linked)
+ A.holder.work()
+
+/obj/item/integrated_circuit/output/screen
+ name = "screen"
+ desc = "This small screen can display a single piece of data, when the machine is examined closely."
+ icon_state = "screen"
+ complexity = 4
+ number_of_inputs = 1
+ number_of_outputs = 0
+ number_of_activators = 1
+ input_names = list(
+ "displayed data"
+ )
+ activator_names = list(
+ "load data"
+ )
+ var/stuff_to_display = null
+
+/obj/item/integrated_circuit/output/screen/work()
+ var/datum/integrated_io/I = inputs[1]
+ stuff_to_display = I.data
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/logic.dm b/code/modules/integrated_electronics/logic.dm
new file mode 100644
index 00000000000..4d123c61d09
--- /dev/null
+++ b/code/modules/integrated_electronics/logic.dm
@@ -0,0 +1,172 @@
+/obj/item/integrated_circuit/logic
+ name = "logic gate"
+ desc = "This tiny chip will decide for you!"
+ complexity = 3
+ number_of_inputs = 2
+ number_of_outputs = 1
+ number_of_activators = 2
+ input_names = list(
+ "A",
+ "B"
+ )
+ output_names = list(
+ "result"
+ )
+ activator_names = list(
+ "compare",
+ "on true result"
+ )
+
+/obj/item/integrated_circuit/logic/equals
+ name = "equal gate"
+ desc = "This gate compares two values, and outputs the number one if both are the same."
+ icon_state = "equal"
+
+/obj/item/integrated_circuit/logic/equals/work()
+ if(..())
+ var/datum/integrated_io/A = inputs[1]
+ var/datum/integrated_io/B = inputs[2]
+ var/datum/integrated_io/O = outputs[1]
+ var/datum/integrated_io/P = activators[2]
+ if(A.data == B.data)
+ O.data = 1
+ O.push_data()
+ P.push_data()
+ else
+ O.data = 0
+
+/obj/item/integrated_circuit/logic/not
+ name = "not gate"
+ desc = "This gate inverts what's fed into it."
+ icon_state = "not"
+ number_of_inputs = 1
+ number_of_outputs = 1
+ number_of_activators = 1
+ output_names = list(
+ "invert"
+ )
+
+
+/obj/item/integrated_circuit/logic/not/work()
+ if(..())
+ var/datum/integrated_io/A = inputs[1]
+ var/datum/integrated_io/O = outputs[1]
+ if(A.data)
+ O.data = !A.data
+ O.push_data()
+ else
+ O.data = 0
+
+/obj/item/integrated_circuit/logic/and
+ name = "and gate"
+ desc = "This gate will output 'one' if both inputs evaluate to true."
+ icon_state = "and"
+
+/obj/item/integrated_circuit/logic/and/work()
+ if(..())
+ var/datum/integrated_io/A = inputs[1]
+ var/datum/integrated_io/B = inputs[2]
+ var/datum/integrated_io/O = outputs[1]
+ var/datum/integrated_io/P = activators[2]
+ if(A.data && B.data)
+ O.data = 1
+ O.push_data()
+ A.push_data()
+ P.push_data()
+ else
+ O.data = 0
+
+/obj/item/integrated_circuit/logic/or
+ name = "or gate"
+ desc = "This gate will output 'one' if one of the inputs evaluate to true."
+ icon_state = "or"
+
+/obj/item/integrated_circuit/logic/or/work()
+ if(..())
+ var/datum/integrated_io/A = inputs[1]
+ var/datum/integrated_io/B = inputs[2]
+ var/datum/integrated_io/O = outputs[1]
+ var/datum/integrated_io/P = activators[2]
+ if(A.data || B.data)
+ O.data = 1
+ O.push_data()
+ A.push_data()
+ P.push_data()
+ else
+ O.data = 0
+
+/obj/item/integrated_circuit/logic/less_than
+ name = "less than gate"
+ desc = "This will output 'one' if the first input is less than the second input."
+ icon_state = "less_than"
+
+/obj/item/integrated_circuit/logic/less_than/work()
+ if(..())
+ var/datum/integrated_io/A = inputs[1]
+ var/datum/integrated_io/B = inputs[2]
+ var/datum/integrated_io/O = outputs[1]
+ var/datum/integrated_io/P = activators[2]
+ if(A.data < B.data)
+ O.data = 1
+ O.push_data()
+ A.push_data()
+ P.push_data()
+ else
+ O.data = 0
+
+/obj/item/integrated_circuit/logic/less_than_or_equal
+ name = "less than or equal gate"
+ desc = "This will output 'one' if the first input is less than, or equal to the second input."
+ icon_state = "less_than_or_equal"
+
+/obj/item/integrated_circuit/logic/less_than_or_equal/work()
+ if(..())
+ var/datum/integrated_io/A = inputs[1]
+ var/datum/integrated_io/B = inputs[2]
+ var/datum/integrated_io/O = outputs[1]
+ var/datum/integrated_io/P = activators[2]
+ if(A.data <= B.data)
+ O.data = 1
+ O.push_data()
+ A.push_data()
+ P.push_data()
+ else
+ O.data = 0
+
+/obj/item/integrated_circuit/logic/greater_than
+ name = "greater than gate"
+ desc = "This will output 'one' if the first input is greater than the second input."
+ icon_state = "greater_than"
+
+/obj/item/integrated_circuit/logic/greater_than/work()
+ if(..())
+ var/datum/integrated_io/A = inputs[1]
+ var/datum/integrated_io/B = inputs[2]
+ var/datum/integrated_io/O = outputs[1]
+ var/datum/integrated_io/P = activators[2]
+ if(A.data > B.data)
+ O.data = 1
+ O.push_data()
+ A.push_data()
+ P.push_data()
+ else
+ O.data = 0
+
+/obj/item/integrated_circuit/logic/greater_than_or_equal
+ name = "greater_than or equal gate"
+ desc = "This will output 'one' if the first input is greater than, or equal to the second input."
+ icon_state = "greater_than_or_equal"
+
+/obj/item/integrated_circuit/logic/greater_than_or_equal/work()
+ if(..())
+ var/datum/integrated_io/A = inputs[1]
+ var/datum/integrated_io/B = inputs[2]
+ var/datum/integrated_io/O = outputs[1]
+ var/datum/integrated_io/P = activators[2]
+ if(A.data >= B.data)
+ O.data = 1
+ O.push_data()
+ A.push_data()
+ P.push_data()
+ else
+ O.data = 0
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/manipulation.dm b/code/modules/integrated_electronics/manipulation.dm
new file mode 100644
index 00000000000..422f793f5de
--- /dev/null
+++ b/code/modules/integrated_electronics/manipulation.dm
@@ -0,0 +1,116 @@
+/obj/item/integrated_circuit/manipulation/weapon_firing
+ name = "weapon firing mechanism"
+ desc = "This somewhat complicated system allows one to slot in a gun, direct it towards a position, and remotely fire it."
+ extended_desc = "The firing mechanism can slot in most ranged weapons, ballistic and energy. \
+ The first and second inputs need to be numbers. They are coordinates for the gun to fire at, relative to the machine itself. \
+ The 'fire' activator will cause the mechanism to attempt to fire the weapon at the coordinates, if possible. Note that the \
+ normal limitations to firearms, such as ammunition requirements and firing delays, still hold true if fired by the mechanism."
+ complexity = 20
+ number_of_inputs = 2
+ number_of_outputs = 0
+ number_of_activators = 1
+ input_names = list(
+ "target X rel",
+ "target Y rel"
+ )
+ activator_names = list(
+ "fire"
+ )
+ var/obj/item/weapon/gun/installed_gun = null
+
+/obj/item/integrated_circuit/manipulation/weapon_firing/Destroy()
+ qdel(installed_gun)
+ ..()
+
+/obj/item/integrated_circuit/manipulation/weapon_firing/attackby(var/obj/O, var/mob/user)
+ if(istype(O, /obj/item/weapon/gun))
+ var/obj/item/weapon/gun/gun = O
+ if(installed_gun)
+ user << "There's already a weapon installed."
+ return
+ user.drop_from_inventory(gun)
+ installed_gun = gun
+ gun.forceMove(src)
+ user << "You slide \the [gun] into the firing mechanism."
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ else
+ ..()
+
+/obj/item/integrated_circuit/manipulation/weapon_firing/attack_self(var/mob/user)
+ if(installed_gun)
+ installed_gun.forceMove(get_turf(src))
+ user << "You slide \the [installed_gun] out of the firing mechanism."
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ installed_gun = null
+ else
+ user << "There's no weapon to remove from the mechanism."
+
+/obj/item/integrated_circuit/manipulation/weapon_firing/work()
+ if(!installed_gun)
+ return
+
+ var/datum/integrated_io/target_x = inputs[1]
+ var/datum/integrated_io/target_y = inputs[2]
+
+ if(target_x.data && target_y.data && isnum(target_x.data) && isnum(target_y.data))
+ var/turf/T = get_turf(src)
+
+ if(target_x.data == 0 && target_y.data == 0) // Don't shoot ourselves.
+ return
+
+ // We need to do this in order to enable relative coordinates, as locate() only works for absolute coordinates.
+ var/i
+ if(target_x.data > 0)
+ i = abs(target_x.data)
+ while(i)
+ T = get_step(T, EAST)
+ i--
+ else if(target_x.data < 0)
+ i = abs(target_x.data)
+ while(i)
+ T = get_step(T, WEST)
+ i--
+
+ if(target_y.data > 0)
+ i = abs(target_y.data)
+ while(i)
+ T = get_step(T, NORTH)
+ i--
+ else if(target_y.data < 0)
+ i = abs(target_y.data)
+ while(i)
+ T = get_step(T, SOUTH)
+ i--
+
+ if(!T)
+ return
+ installed_gun.Fire_userless(T)
+
+/obj/item/integrated_circuit/manipulation/smoke
+ name = "smoke generator"
+ desc = "Unlike most electronics, creating smoke is completely intentional."
+ extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \
+ into the smoke clouds when activated."
+ flags = OPENCONTAINER
+ complexity = 20
+ number_of_inputs = 0
+ number_of_outputs = 0
+ number_of_activators = 1
+ input_names = list()
+ activator_names = list(
+ "create smoke"
+ )
+
+/obj/item/integrated_circuit/manipulation/smoke/New()
+ ..()
+ create_reagents(100)
+
+/obj/item/integrated_circuit/manipulation/smoke/work()
+ if(..())
+ playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
+ var/datum/effect/effect/system/smoke_spread/chem/smoke_system = new()
+ smoke_system.set_up(reagents, 10, 0, get_turf(src))
+ spawn(0)
+ for(var/i = 1 to 8)
+ smoke_system.start()
+ reagents.clear_reagents()
diff --git a/code/modules/integrated_electronics/memory.dm b/code/modules/integrated_electronics/memory.dm
new file mode 100644
index 00000000000..3305cf0a939
--- /dev/null
+++ b/code/modules/integrated_electronics/memory.dm
@@ -0,0 +1,83 @@
+/obj/item/integrated_circuit/memory
+ name = "memory chip"
+ desc = "This tiny chip can store one piece of data."
+ icon_state = "memory"
+ complexity = 1
+ number_of_inputs = 1
+ number_of_outputs = 1
+ number_of_activators = 1
+ activator_names = list(
+ "set"
+ )
+
+/obj/item/integrated_circuit/memory/examine(mob/user)
+ ..()
+ var/i
+ for(i = 1, i <= outputs.len, i++)
+ var/datum/integrated_io/O = outputs[i]
+ user << "\The [src] has [O.data ? "'O.data'" : "nothing"] saved to address [i]."
+
+/obj/item/integrated_circuit/memory/work()
+ if(..())
+ var/i
+ for(i = 1, i <= inputs.len, i++)
+ var/datum/integrated_io/I = inputs[i]
+ var/datum/integrated_io/O = outputs[i]
+ O.data = I.data
+
+/obj/item/integrated_circuit/memory/medium
+ name = "memory circuit"
+ desc = "This circuit can store four pieces of data."
+ icon_state = "memory4"
+ complexity = 4
+ number_of_inputs = 4
+ number_of_outputs = 4
+
+/obj/item/integrated_circuit/memory/large
+ name = "large memory circuit"
+ desc = "This big circuit can hold eight pieces of data."
+ icon_state = "memory8"
+ complexity = 8
+ number_of_inputs = 8
+ number_of_outputs = 8
+
+/obj/item/integrated_circuit/memory/huge
+ name = "large memory stick"
+ desc = "This stick of memory can hold up up to sixteen pieces of data."
+ icon_state = "memory16"
+ complexity = 16
+ number_of_inputs = 16
+ number_of_outputs = 16
+
+/obj/item/integrated_circuit/memory/constant
+ name = "constant chip"
+ desc = "This tiny chip can store one piece of data, which cannot be overwritten without disassembly."
+ icon_state = "memory"
+ complexity = 1
+ number_of_inputs = 0
+ number_of_outputs = 1
+ number_of_activators = 1
+ activator_names = list(
+ "trigger output"
+ )
+
+/obj/item/integrated_circuit/memory/constant/work()
+ if(..())
+ var/datum/integrated_io/O = outputs[1]
+ O.push_data()
+
+/obj/item/integrated_circuit/memory/constant/attack_hand(mob/user)
+ var/datum/integrated_io/O = outputs[1]
+ var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number")
+ var/new_data = null
+ switch(type_to_use)
+ if("string")
+ new_data = input("Now type in a string.","[src] string writing") as null|text
+ if(istext(new_data))
+ O.data = new_data
+ user << "You set \the [src]'s memory to '[new_data]'."
+ if("number")
+ new_data = input("Now type in a number.","[src] number writing") as null|num
+ if(isnum(new_data))
+ O.data = new_data
+ user << "You set \the [src]'s memory to '[new_data]'."
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/time.dm b/code/modules/integrated_electronics/time.dm
new file mode 100644
index 00000000000..99c8a42436e
--- /dev/null
+++ b/code/modules/integrated_electronics/time.dm
@@ -0,0 +1,120 @@
+/obj/item/integrated_circuit/time
+ name = "time circuit"
+ desc = "Now you can build your own clock!"
+ complexity = 2
+ number_of_inputs = 0
+ number_of_outputs = 0
+
+/obj/item/integrated_circuit/time/delay
+ name = "two-sec delay circuit"
+ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
+ This circuit is set to send a pulse after a delay of two seconds."
+ number_of_activators = 2
+ var/delay = 20
+ activator_names = list(
+ "incoming pulse",
+ "outgoing pulse"
+ )
+
+/obj/item/integrated_circuit/time/delay/work()
+ if(..())
+ var/datum/integrated_io/out_pulse = activators[2]
+ sleep(delay)
+ out_pulse.push_data()
+
+/obj/item/integrated_circuit/time/delay/five_sec
+ name = "five-sec delay circuit"
+ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
+ This circuit is set to send a pulse after a delay of five seconds."
+ delay = 10
+
+/obj/item/integrated_circuit/time/delay/one_sec
+ name = "one-sec delay circuit"
+ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
+ This circuit is set to send a pulse after a delay of one second."
+ delay = 10
+
+/obj/item/integrated_circuit/time/delay/half_sec
+ name = "half-sec delay circuit"
+ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
+ This circuit is set to send a pulse after a delay of half a second."
+ delay = 5
+
+/obj/item/integrated_circuit/time/delay/tenth_sec
+ name = "tenth-sec delay circuit"
+ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
+ This circuit is set to send a pulse after a delay of 1/10th of a second."
+ delay = 1
+
+/obj/item/integrated_circuit/time/delay/custom
+ name = "custom delay circuit"
+ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
+ This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse."
+ number_of_inputs = 1
+ input_names = list(
+ "delay time",
+ )
+
+/obj/item/integrated_circuit/time/delay/custom/work()
+ var/datum/integrated_io/delay_input = inputs[1]
+ if(delay_input.data && isnum(delay_input.data) )
+ var/new_delay = min(delay_input.data, 1)
+ new_delay = max(new_delay, 36000) //An hour.
+ delay = new_delay
+
+ ..()
+
+/obj/item/integrated_circuit/time/ticker
+ name = "ticker circuit"
+ desc = "This circuit sends an automatic pulse every four seconds."
+ complexity = 8
+ number_of_inputs = 1
+ number_of_activators = 1
+ var/ticks_to_pulse = 2
+ var/ticks_completed = 0
+ input_names = list(
+ "toggle ticking"
+ )
+ activator_names = list(
+ "outgoing pulse"
+ )
+
+/obj/item/integrated_circuit/time/ticker/New()
+ ..()
+ processing_objects |= src
+
+/obj/item/integrated_circuit/time/ticker/Destroy()
+ processing_objects -= src
+
+/obj/item/integrated_circuit/time/ticker/process()
+ ticks_completed++
+ if( (ticks_completed % ticks_to_pulse) == 0)
+ var/datum/integrated_io/pulser = activators[1]
+ pulser.push_data()
+
+/obj/item/integrated_circuit/time/ticker/fast
+ name = "fast ticker"
+ desc = "This advanced circuit sends an automatic pulse every two seconds."
+ complexity = 12
+ ticks_to_pulse = 1
+
+/obj/item/integrated_circuit/time/ticker/slow
+ name = "slow ticker"
+ desc = "This simple circuit sends an automatic pulse every six seconds."
+ complexity = 4
+ ticks_to_pulse = 3
+
+
+/obj/item/integrated_circuit/time/clock
+ name = "integrated clock"
+ desc = "Tells you what the local time is, specific to your station or planet."
+ number_of_inputs = 0
+ number_of_outputs = 6
+ number_of_activators = 1
+ output_names = list(
+ "time (string)",
+ "minute (string)",
+ "hour (string)",
+ "minute (number)",
+ "hour (number)",
+ )
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/tools.dm b/code/modules/integrated_electronics/tools.dm
new file mode 100644
index 00000000000..3835c8d5ed5
--- /dev/null
+++ b/code/modules/integrated_electronics/tools.dm
@@ -0,0 +1,199 @@
+#define WIRE "wire"
+#define WIRING "wiring"
+#define UNWIRE "unwire"
+#define UNWIRING "unwiring"
+
+
+/obj/item/device/integrated_electronics/wirer
+ name = "circuit wirer"
+ desc = "It's a small wiring tool, with a wire roll, electric soldering iron, wire cutter, and more in one package. \
+ The wires used are generally useful for small electronics, such as circuitboards and breadboards, as opposed to larger wires \
+ used for power or data transmission."
+ icon = 'icons/obj/hacktool.dmi'
+ icon_state = "hacktool-g"
+ flags = CONDUCT
+ w_class = 2
+ var/datum/integrated_io/selected_io = null
+ var/mode = WIRE
+
+/obj/item/device/integrated_electronics/wirer/New()
+ ..()
+
+/obj/item/device/integrated_electronics/wirer/proc/wire(var/datum/integrated_io/io, mob/user)
+ if(mode == WIRE)
+ selected_io = io
+ user << "You attach a data wire to \the [selected_io.holder]'s [selected_io.name] data channel."
+ mode = WIRING
+ else if(mode == WIRING)
+ if(io == selected_io)
+ user << "Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless."
+ return
+ if(io.io_type != selected_io.io_type)
+ user << "Those two types of channels are incompatable. The first is a [selected_io.io_type], \
+ while the second is a [io.io_type]."
+ return
+ selected_io.linked |= io
+ io.linked |= selected_io
+
+ user << "You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name]."
+ mode = WIRE
+ //io.updateDialog()
+ //selected_io.updateDialog()
+ selected_io.holder.interact(user) // This is to update the UI.
+ selected_io = null
+
+ else if(mode == UNWIRE)
+ selected_io = io
+ if(!io.linked.len)
+ user << "There is nothing connected to \the [selected_io] data channel."
+ selected_io = null
+ return
+ user << "You prepare to detach a data wire from \the [selected_io.holder]'s [selected_io.name] data channel."
+ mode = UNWIRING
+ return
+
+ else if(mode == UNWIRING)
+ if(io == selected_io)
+ user << "You can't wire a pin into each other, so unwiring \the [selected_io.holder] from \
+ the same pin is rather moot."
+ return
+ if(selected_io in io.linked)
+ io.linked.Remove(selected_io)
+ selected_io.linked.Remove(io)
+ user << "You disconnect \the [selected_io.holder]'s [selected_io.name] from \
+ \the [io.holder]'s [io.name]."
+ //io.updateDialog()
+ //selected_io.updateDialog()
+ selected_io.holder.interact(user) // This is to update the UI.
+ selected_io = null
+ mode = UNWIRE
+ else
+ user << "\The [selected_io.holder]'s [selected_io.name] and \the [io.holder]'s \
+ [io.name] are not connected."
+ return
+ return
+
+/obj/item/device/integrated_electronics/wirer/attack_self(mob/user)
+ switch(mode)
+ if(WIRE)
+ mode = UNWIRE
+ if(WIRING)
+ if(selected_io)
+ user << "You decide not to wire the data channel."
+ selected_io = null
+ mode = UNWIRE
+ if(UNWIRE)
+ mode = WIRE
+ if(UNWIRING)
+ if(selected_io)
+ user << "You decide not to disconnect the data channel."
+ selected_io = null
+ mode = UNWIRE
+ user << "You set \the [src] to [mode]."
+
+#undef WIRE
+#undef WIRING
+#undef UNWIRE
+#undef UNWIRING
+
+/obj/item/weapon/storage/bag/circuits
+ name = "circuit satchel"
+ desc = "This bag's essential for any circuitry projects."
+ icon = 'icons/obj/mining.dmi'
+ icon_state = "satchel"
+ slot_flags = SLOT_BELT | SLOT_POCKET
+ w_class = 2
+ storage_slots = 200
+ max_storage_space = 400
+ max_w_class = 3
+ display_contents_with_number = 1
+ can_hold = list(/obj/item/integrated_circuit)
+
+/obj/item/weapon/storage/bag/circuits/pre_filled/New()
+ ..()
+ var/i = 10
+ while(i)
+ new /obj/item/integrated_circuit/arithmetic/addition(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/arithmetic/subtraction(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/arithmetic/multiplication(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/arithmetic/division(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/arithmetic/absolute(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/arithmetic/average(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/logic/equals(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/logic/less_than(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/logic/less_than_or_equal(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/logic/greater_than(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/logic/greater_than_or_equal(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/logic/not(src)
+ i--
+ i = 10
+ while(i)
+ new /obj/item/integrated_circuit/memory(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/memory/medium(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/memory/large(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/memory/huge(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/input/numberpad(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/input/button(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/output/screen(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/transfer/splitter(src)
+ i--
+ i = 5
+ while(i)
+ new /obj/item/integrated_circuit/transfer/activator_splitter(src)
+ i--
+ new /obj/item/device/electronic_assembly(src)
+ new /obj/item/device/integrated_electronics/wirer(src)
\ No newline at end of file
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 9271e505032..01dfce8e8ce 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -290,6 +290,76 @@
if(muzzle_flash)
set_light(0)
+// Similar to the above proc, but does not require a user, which is ideal for things like turrets.
+/obj/item/weapon/gun/proc/Fire_userless(atom/target)
+ if(!target)
+ return
+
+ if(world.time < next_fire_time)
+ return
+
+ var/shoot_time = (burst - 1)* burst_delay
+ next_fire_time = world.time + shoot_time
+
+ var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed.
+ for(var/i in 1 to burst)
+ var/obj/projectile = consume_next_projectile()
+ if(!projectile)
+ handle_click_empty()
+ break
+
+ if(istype(projectile, /obj/item/projectile))
+ var/obj/item/projectile/P = projectile
+
+ var/acc = burst_accuracy[min(i, burst_accuracy.len)]
+ var/disp = dispersion[min(i, dispersion.len)]
+
+ P.accuracy = accuracy + acc
+ P.dispersion = disp
+
+ P.shot_from = src.name
+ P.silenced = silenced
+
+ P.launch(target)
+
+ if(silenced)
+ playsound(src, fire_sound, 10, 1)
+ else
+ playsound(src, fire_sound, 50, 1)
+
+ if(muzzle_flash)
+ set_light(muzzle_flash)
+ update_icon()
+
+ //process_accuracy(projectile, user, target, acc, disp)
+
+ // if(pointblank)
+ // process_point_blank(projectile, user, target)
+
+ // if(process_projectile(projectile, null, target, user.zone_sel.selecting, clickparams))
+ // handle_post_fire(null, target, pointblank, reflex)
+
+ // update_icon()
+
+ if(i < burst)
+ sleep(burst_delay)
+
+ if(!(target && target.loc))
+ target = targloc
+ //pointblank = 0
+
+ log_and_message_admins("Fired [src].")
+
+ //admin_attack_log(usr, attacker_message="Fired [src]", admin_message="fired a gun ([src]) (MODE: [src.mode_name]) [reflex ? "by reflex" : "manually"].")
+
+ //update timing
+ next_fire_time = world.time + fire_delay
+
+ if(muzzle_flash)
+ set_light(0)
+
+
+
//obtains the next projectile to fire
/obj/item/weapon/gun/proc/consume_next_projectile()
return null
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index c0ecdbfc3d5..943dd7a903b 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -1486,6 +1486,352 @@ CIRCUITS BELOW
build_path = /obj/item/weapon/cartridge/captain
sort_string = "VBAAO"
+
+
+/datum/design/item/wirer
+ name = "Custom wirer tool"
+ id = "wirer"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500)
+ build_path = /obj/item/device/integrated_electronics/wirer
+ sort_string = "VBVAA"
+
+
+
+/datum/design/item/custom_circuit_assembly
+ name = "Small custom assembly"
+ desc = "An customizable assembly for simple, small devices."
+ id = "assembly-small"
+ req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000)
+ build_path = /obj/item/device/electronic_assembly
+ sort_string = "VCAAA"
+
+/datum/design/item/custom_circuit_assembly/medium
+ name = "Medium custom assembly"
+ desc = "An customizable assembly suited for more ambitious mechanisms."
+ id = "assembly-medium"
+ req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 20000)
+ build_path = /obj/item/device/electronic_assembly/medium
+
+/datum/design/item/custom_circuit_assembly/large
+ name = "Large custom assembly"
+ desc = "An customizable assembly for large machines."
+ id = "assembly-large"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 40000)
+ build_path = /obj/item/device/electronic_assembly/large
+
+/datum/design/circuit/integrated_circuit
+ req_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2)
+
+/datum/design/circuit/integrated_circuit/AssembleDesignName()
+ ..()
+ name = "Custom circuitry ([item_name])"
+
+/datum/design/circuit/integrated_circuit/AssembleDesignDesc()
+ if(!desc)
+ desc = "Allows for the construction of \a [name] custom circuit."
+
+/datum/design/circuit/integrated_circuit/arithmetic/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Arithmetic\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/arithmetic/addition
+ id = "cc-addition"
+ build_path = /obj/item/integrated_circuit/arithmetic/addition
+ sort_string = "WAAAA"
+
+/datum/design/circuit/integrated_circuit/arithmetic/subtraction
+ id = "cc-subtraction"
+ build_path = /obj/item/integrated_circuit/arithmetic/subtraction
+ sort_string = "WAAAB"
+
+/datum/design/circuit/integrated_circuit/arithmetic/multiplication
+ id = "cc-multiplication"
+ build_path = /obj/item/integrated_circuit/arithmetic/multiplication
+ sort_string = "WAAAC"
+
+/datum/design/circuit/integrated_circuit/arithmetic/division
+ id = "cc-division"
+ build_path = /obj/item/integrated_circuit/arithmetic/division
+ sort_string = "WAAAD"
+
+/datum/design/circuit/integrated_circuit/arithmetic/absolute
+ id = "cc-absolute"
+ build_path = /obj/item/integrated_circuit/arithmetic/absolute
+ sort_string = "WAAAE"
+
+/datum/design/circuit/integrated_circuit/arithmetic/average
+ id = "cc-average"
+ build_path = /obj/item/integrated_circuit/arithmetic/average
+ sort_string = "WAAAF"
+
+/datum/design/circuit/integrated_circuit/arithmetic/pi
+ id = "cc-pi"
+ build_path = /obj/item/integrated_circuit/arithmetic/pi
+ sort_string = "WAAAG"
+
+
+
+/datum/design/circuit/integrated_circuit/converter/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Conversion\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/converter/num2text
+ id = "cc-num2text"
+ build_path = /obj/item/integrated_circuit/converter/num2text
+ sort_string = "WAABA"
+
+/datum/design/circuit/integrated_circuit/converter/text2num
+ id = "cc-text2num"
+ build_path = /obj/item/integrated_circuit/converter/text2num
+ sort_string = "WAABB"
+
+/datum/design/circuit/integrated_circuit/converter/ref2text
+ id = "cc-ref2text"
+ build_path = /obj/item/integrated_circuit/converter/ref2text
+ sort_string = "WAABC"
+
+/datum/design/circuit/integrated_circuit/converter/lowercase
+ id = "cc-lowercase"
+ build_path = /obj/item/integrated_circuit/converter/lowercase
+ sort_string = "WAABD"
+
+/datum/design/circuit/integrated_circuit/converter/uppercase
+ id = "cc-uppercase"
+ build_path = /obj/item/integrated_circuit/converter/uppercase
+ sort_string = "WAABD"
+
+
+
+/datum/design/circuit/integrated_circuit/coordinate/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Coordinate\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/coordinate/gps
+ id = "cc-gps"
+ build_path = /obj/item/integrated_circuit/gps
+ sort_string = "WAACA"
+
+/datum/design/circuit/integrated_circuit/coordinate/abs_to_rel_coords
+ id = "cc-abs_to_rel_coords"
+ build_path = /obj/item/integrated_circuit/abs_to_rel_coords
+ sort_string = "WAACB"
+
+
+
+/datum/design/circuit/integrated_circuit/transfer/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Transfer\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/transfer/splitter
+ id = "cc-splitter"
+ build_path = /obj/item/integrated_circuit/transfer/splitter
+ sort_string = "WAADA"
+
+/datum/design/circuit/integrated_circuit/transfer/splitter4
+ id = "cc-splitter4"
+ build_path = /obj/item/integrated_circuit/transfer/splitter/medium
+ sort_string = "WAADB"
+
+/datum/design/circuit/integrated_circuit/transfer/splitter8
+ id = "cc-splitter8"
+ build_path = /obj/item/integrated_circuit/transfer/splitter/large
+ sort_string = "WAADC"
+
+/datum/design/circuit/integrated_circuit/transfer/activator_splitter
+ id = "cc-activator_splitter"
+ build_path = /obj/item/integrated_circuit/transfer/activator_splitter
+ sort_string = "WAADD"
+
+/datum/design/circuit/integrated_circuit/transfer/activator_splitter4
+ id = "cc-activator_splitter4"
+ build_path = /obj/item/integrated_circuit/transfer/activator_splitter/medium
+ sort_string = "WAADE"
+
+/datum/design/circuit/integrated_circuit/transfer/activator_splitter8
+ id = "cc-activator_splitter8"
+ build_path = /obj/item/integrated_circuit/transfer/activator_splitter/large
+ sort_string = "WAADF"
+
+
+
+/datum/design/circuit/integrated_circuit/input_output/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Input/Output\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/input_output/button
+ id = "cc-button"
+ build_path = /obj/item/integrated_circuit/input/button
+ sort_string = "WAAEA"
+
+/datum/design/circuit/integrated_circuit/input_output/numberpad
+ id = "cc-numberpad"
+ build_path = /obj/item/integrated_circuit/input/numberpad
+ sort_string = "WAAEB"
+
+/datum/design/circuit/integrated_circuit/input_output/textpad
+ id = "cc-textpad"
+ build_path = /obj/item/integrated_circuit/input/textpad
+ sort_string = "WAAEC"
+
+/datum/design/circuit/integrated_circuit/input_output/screen
+ id = "cc-screen"
+ build_path = /obj/item/integrated_circuit/output/screen
+ sort_string = "WAAED"
+
+
+
+/datum/design/circuit/integrated_circuit/logic/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Logic\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/logic/equals
+ id = "cc-equals"
+ build_path = /obj/item/integrated_circuit/logic/equals
+ sort_string = "WAAFA"
+
+/datum/design/circuit/integrated_circuit/logic/not
+ id = "cc-not"
+ build_path = /obj/item/integrated_circuit/logic/not
+ sort_string = "WAAFB"
+
+/datum/design/circuit/integrated_circuit/logic/and
+ id = "cc-and"
+ build_path = /obj/item/integrated_circuit/logic/and
+ sort_string = "WAAFC"
+
+/datum/design/circuit/integrated_circuit/logic/or
+ id = "cc-or"
+ build_path = /obj/item/integrated_circuit/logic/or
+ sort_string = "WAAFD"
+
+/datum/design/circuit/integrated_circuit/logic/less_than
+ id = "cc-less_than"
+ build_path = /obj/item/integrated_circuit/logic/less_than
+ sort_string = "WAAFE"
+
+/datum/design/circuit/integrated_circuit/logic/less_than_or_equal
+ id = "cc-less_than_or_equal"
+ build_path = /obj/item/integrated_circuit/logic/less_than_or_equal
+ sort_string = "WAAFF"
+
+/datum/design/circuit/integrated_circuit/logic/greater_than
+ id = "cc-greater_than"
+ build_path = /obj/item/integrated_circuit/logic/greater_than
+ sort_string = "WAAFG"
+
+/datum/design/circuit/integrated_circuit/logic/greater_than_or_equal
+ id = "cc-greater_than_or_equal"
+ build_path = /obj/item/integrated_circuit/logic/greater_than_or_equal
+ sort_string = "WAAFH"
+
+
+
+/datum/design/circuit/integrated_circuit/manipulation/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Manipulation\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/manipulation/weapon_firing
+ id = "cc-weapon_firing"
+ build_path = /obj/item/integrated_circuit/manipulation/weapon_firing
+ sort_string = "WAAGA"
+ req_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_COMBAT = 5)
+
+/datum/design/circuit/integrated_circuit/manipulation/weapon_firing
+ id = "cc-smoke"
+ build_path = /obj/item/integrated_circuit/manipulation/smoke
+ sort_string = "WAAGB"
+ req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4, TECH_BIOMED = 5)
+
+
+
+/datum/design/circuit/integrated_circuit/memory/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Memory\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/memory
+ id = "cc-memory"
+ build_path = /obj/item/integrated_circuit/memory
+ sort_string = "WAAHA"
+
+/datum/design/circuit/integrated_circuit/memory/medium
+ id = "cc-memory4"
+ build_path = /obj/item/integrated_circuit/memory/medium
+ sort_string = "WAAHB"
+
+/datum/design/circuit/integrated_circuit/memory/large
+ id = "cc-memory8"
+ build_path = /obj/item/integrated_circuit/memory/large
+ sort_string = "WAAHC"
+
+/datum/design/circuit/integrated_circuit/memory/huge
+ id = "cc-memory16"
+ build_path = /obj/item/integrated_circuit/memory/huge
+ sort_string = "WAAHD"
+
+/datum/design/circuit/integrated_circuit/memory/constant
+ id = "cc-constant"
+ build_path = /obj/item/integrated_circuit/memory/constant
+ sort_string = "WAAHH"
+
+/datum/design/circuit/integrated_circuit/time/AssembleDesignName()
+ ..()
+ name = "Custom circuitry \[Time\] ([item_name])"
+
+/datum/design/circuit/integrated_circuit/time/delay
+ id = "cc-delay"
+ build_path = /obj/item/integrated_circuit/time/delay
+ sort_string = "WAAIA"
+
+/datum/design/circuit/integrated_circuit/time/delay/five_sec
+ id = "cc-five_sec_delay"
+ build_path = /obj/item/integrated_circuit/time/delay/five_sec
+ sort_string = "WAAIB"
+
+/datum/design/circuit/integrated_circuit/time/delay/one_sec
+ id = "cc-one_sec_delay"
+ build_path = /obj/item/integrated_circuit/time/delay/one_sec
+ sort_string = "WAAIC"
+
+/datum/design/circuit/integrated_circuit/time/delay/half_sec
+ id = "cc-half_sec_delay"
+ build_path = /obj/item/integrated_circuit/time/delay/half_sec
+ sort_string = "WAAID"
+
+/datum/design/circuit/integrated_circuit/time/delay/tenth_sec
+ id = "cc-tenth_sec_delay"
+ build_path = /obj/item/integrated_circuit/time/delay/tenth_sec
+ sort_string = "WAAIF"
+
+/datum/design/circuit/integrated_circuit/time/delay/custom
+ id = "cc-custom_delay"
+ build_path = /obj/item/integrated_circuit/time/delay/custom
+ sort_string = "WAAIG"
+
+/datum/design/circuit/integrated_circuit/time/ticker
+ id = "cc-ticker"
+ build_path = /obj/item/integrated_circuit/time/ticker
+ sort_string = "WAAIH"
+
+/datum/design/circuit/integrated_circuit/time/ticker/slow
+ id = "cc-ticker_slow"
+ build_path = /obj/item/integrated_circuit/time/ticker/slow
+ sort_string = "WAAII"
+
+/datum/design/circuit/integrated_circuit/time/ticker/fast
+ id = "cc-ticker_fast"
+ build_path = /obj/item/integrated_circuit/time/ticker/fast
+ sort_string = "WAAIJ"
+ req_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4)
+
+/datum/design/circuit/integrated_circuit/time/clock
+ id = "cc-clock"
+ build_path = /obj/item/integrated_circuit/time/clock
+ sort_string = "WAAIK"
+
/* Uncomment if someone makes these buildable
/datum/design/circuit/general_alert
name = "general alert console"
diff --git a/code/modules/shuttles/shuttle_ferry.dm b/code/modules/shuttles/shuttle_ferry.dm
index 5d6663f3b57..0a288a1ba9a 100644
--- a/code/modules/shuttles/shuttle_ferry.dm
+++ b/code/modules/shuttles/shuttle_ferry.dm
@@ -16,7 +16,7 @@
//TODO: change location to a string and use a mapping for area and dock targets.
var/dock_target_station
var/dock_target_offsite
-
+
var/last_dock_attempt_time = 0
/datum/shuttle/ferry/short_jump(var/area/origin,var/area/destination)
@@ -85,15 +85,15 @@
long_jump(interim=area_transition, travel_time=move_time, direction=transit_direction)
else
short_jump()
-
+
process_state = WAIT_ARRIVE
-
+
if (WAIT_ARRIVE)
if (moving_status == SHUTTLE_IDLE)
dock()
in_use = null //release lock
process_state = WAIT_FINISH
-
+
if (WAIT_FINISH)
if (skip_docking_checks() || docking_controller.docked() || world.time > last_dock_attempt_time + DOCK_ATTEMPT_TIMEOUT)
process_state = IDLE_STATE
diff --git a/icons/obj/electronic_assemblies.dmi b/icons/obj/electronic_assemblies.dmi
new file mode 100644
index 00000000000..e4fd3c230bb
Binary files /dev/null and b/icons/obj/electronic_assemblies.dmi differ
diff --git a/polaris.dme b/polaris.dme
index efddd1da88d..184986a81ca 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -1365,6 +1365,18 @@
#include "code\modules\hydroponics\trays\tray_soil.dm"
#include "code\modules\hydroponics\trays\tray_tools.dm"
#include "code\modules\hydroponics\trays\tray_update_icons.dm"
+#include "code\modules\integrated_electronics\_defines.dm"
+#include "code\modules\integrated_electronics\arithmetic.dm"
+#include "code\modules\integrated_electronics\assemblies.dm"
+#include "code\modules\integrated_electronics\converters.dm"
+#include "code\modules\integrated_electronics\coordinate.dm"
+#include "code\modules\integrated_electronics\data_transfer.dm"
+#include "code\modules\integrated_electronics\input_output.dm"
+#include "code\modules\integrated_electronics\logic.dm"
+#include "code\modules\integrated_electronics\manipulation.dm"
+#include "code\modules\integrated_electronics\memory.dm"
+#include "code\modules\integrated_electronics\time.dm"
+#include "code\modules\integrated_electronics\tools.dm"
#include "code\modules\library\lib_items.dm"
#include "code\modules\library\lib_machines.dm"
#include "code\modules\library\lib_readme.dm"