diff --git a/code/__defines/unit_tests.dm b/code/__defines/unit_tests.dm
index 478c75fdb2..840673221c 100644
--- a/code/__defines/unit_tests.dm
+++ b/code/__defines/unit_tests.dm
@@ -1,4 +1,5 @@
#define ASCII_ESC ascii2text(27)
#define ASCII_RED "[ASCII_ESC]\[31m"
#define ASCII_GREEN "[ASCII_ESC]\[32m"
+#define ASCII_YELLOW "[ASCII_ESC]\[33m"
#define ASCII_RESET "[ASCII_ESC]\[0m"
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 17d3e32f92..eec5638523 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -54,6 +54,18 @@
part.implants.Remove(src)
..()
+/obj/item/weapon/implant/attackby(obj/item/I, mob/user)
+ if(istype(I, /obj/item/weapon/implanter))
+ var/obj/item/weapon/implanter/implanter = I
+ if(implanter.imp)
+ return // It's full.
+ user.drop_from_inventory(src)
+ forceMove(implanter)
+ implanter.imp = src
+ implanter.update()
+ else
+ ..()
+
/obj/item/weapon/implant/tracking
name = "tracking implant"
desc = "Track with this."
diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm
new file mode 100644
index 0000000000..cf55cbd706
--- /dev/null
+++ b/code/game/objects/items/weapons/implants/implantcircuits.dm
@@ -0,0 +1,44 @@
+/obj/item/weapon/implant/integrated_circuit
+ name = "electronic implant"
+ icon = 'icons/obj/electronic_assemblies.dmi'
+ icon_state = "setup_implant"
+ var/obj/item/device/electronic_assembly/implant/IC = null
+
+/obj/item/weapon/implant/integrated_circuit/islegal()
+ return TRUE
+
+/obj/item/weapon/implant/integrated_circuit/New()
+ ..()
+ IC = new(src)
+ IC.implant = src
+
+/obj/item/weapon/implant/integrated_circuit/Destroy()
+ IC.implant = null
+ qdel(IC)
+ ..()
+
+/obj/item/weapon/implant/integrated_circuit/get_data()
+ var/dat = {"
+ Implant Specifications:
+ Name: Modular Implant
+ Life: 3 years.
+ Important Notes: EMP can cause malfunctions in the internal electronics of this implant.
+
+ Implant Details:
+ Function: Contains no innate functions until other components are added.
+ Special Features:
+ Modular Circuitry- Can be loaded with specific modular circuitry in order to fulfill a wide possibility of functions.
+ Integrity: Implant is not shielded from electromagnetic interferance, otherwise it is independant of subject's status."}
+ return dat
+
+/obj/item/weapon/implant/integrated_circuit/emp_act(severity)
+ IC.emp_act(severity)
+
+/obj/item/weapon/implant/integrated_circuit/examine(mob/user)
+ IC.examine(user)
+
+/obj/item/weapon/implant/integrated_circuit/attackby(var/obj/item/O, var/mob/user)
+ if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) )
+ IC.attackby(O, user)
+ else
+ ..()
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm
index de8f00dddb..d9daa035d5 100644
--- a/code/modules/integrated_electronics/_defines.dm
+++ b/code/modules/integrated_electronics/_defines.dm
@@ -29,6 +29,7 @@ var/list/all_integrated_circuits = list()
var/cooldown_per_use = 1 SECOND
var/spawn_flags = null // Used for world initializing, see the #defines above.
var/category_text = "NO CATEGORY" // To show up on circuit printer, and perhaps other places.
+ var/autopulse = -1 // When input is received, the circuit will pulse itself if set to 1. 0 means it won't. -1 means it is permanently off.
/obj/item/integrated_circuit/examine(mob/user)
..()
@@ -71,7 +72,8 @@ var/list/all_integrated_circuits = list()
/obj/item/integrated_circuit/nano_host()
if(istype(src.loc, /obj/item/device/electronic_assembly))
- return loc
+ var/obj/item/device/electronic_assembly/assembly = loc
+ return assembly.resolve_nano_host()
return ..()
/obj/item/integrated_circuit/emp_act(severity)
@@ -112,6 +114,14 @@ var/list/all_integrated_circuits = list()
if(!CanInteract(user, physical_state))
return
+ var/window_height = 350
+ var/window_width = 600
+
+ //var/table_edge_width = "[(window_width - window_width * 0.1) / 4]px"
+ //var/table_middle_width = "[(window_width - window_width * 0.1) - (table_edge_width * 2)]px"
+ var/table_edge_width = "30%"
+ var/table_middle_width = "40%"
+
var/HTML = list()
HTML += "[src.name]"
HTML += ""
@@ -122,9 +132,12 @@ var/list/all_integrated_circuits = list()
HTML += "
\[Remove\]"
HTML += "
"
- HTML += ""
- HTML += ""
- HTML += ""
+ //HTML += ""
+ //HTML += ""
+ //HTML += ""
+ HTML += ""
+ HTML += ""
+ HTML += ""
HTML += ""
var/column_width = 3
@@ -196,11 +209,16 @@ var/list/all_integrated_circuits = list()
HTML += ""
HTML += "
"
- HTML += "
Complexity: [complexity]"
- HTML += "
[extended_desc]"
+ if(autopulse != -1)
+ HTML += "
Meta Variables;"
+ HTML += "
\[Autopulse\] = [autopulse ? "ON" : "OFF"]"
+ HTML += "
"
+
+ HTML += "
Complexity: [complexity]"
+ HTML += "
[extended_desc]"
HTML += ""
- user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1")
+ user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
onclose(user, "circuit-\ref[src]")
@@ -229,6 +247,10 @@ var/list/all_integrated_circuits = list()
if(href_list["rename"])
rename_component(usr)
+ if(href_list["autopulse"])
+ if(autopulse != -1)
+ autopulse = !autopulse
+
if(href_list["remove"])
if(istype(held_item, /obj/item/weapon/screwdriver))
disconnect_all()
@@ -267,7 +289,7 @@ var/list/all_integrated_circuits = list()
. = ..()
/datum/integrated_io/nano_host()
- return holder
+ return holder.nano_host()
/datum/integrated_io/proc/data_as_type(var/as_type)
@@ -285,7 +307,8 @@ var/list/all_integrated_circuits = list()
if(isweakref(data))
var/weakref/w = data
var/atom/A = w.resolve()
- return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed.
+ //return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed.
+ return A ? "(\ref[A] \[Ref\])" : "(null)"
return "([data])" // Nothing special needed for numbers or other stuff.
/datum/integrated_io/activate/display_data()
diff --git a/code/modules/integrated_electronics/arithmetic.dm b/code/modules/integrated_electronics/arithmetic.dm
index 00676e778a..37eabf2027 100644
--- a/code/modules/integrated_electronics/arithmetic.dm
+++ b/code/modules/integrated_electronics/arithmetic.dm
@@ -5,6 +5,11 @@
outputs = list("result")
activators = list("compute")
category_text = "Arithmetic"
+ autopulse = 1
+
+/obj/item/integrated_circuit/arithmetic/on_data_written()
+ if(autopulse == 1)
+ check_then_do_work()
// +Adding+ //
@@ -195,8 +200,8 @@
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)
+ if(isnum(I.data))
+ result = abs(I.data)
for(var/datum/integrated_io/output/O in outputs)
O.data = result
@@ -260,4 +265,45 @@
for(var/datum/integrated_io/output/O in outputs)
O.data = result
- O.push_data()
\ No newline at end of file
+ O.push_data()
+
+// Square Root //
+
+/obj/item/integrated_circuit/arithmetic/square_root
+ name = "square root circuit"
+ desc = "This outputs the square root of a number you put in."
+ icon_state = "square_root"
+ inputs = list("A")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/arithmetic/square_root/do_work()
+ var/result = 0
+ for(var/datum/integrated_io/input/I in inputs)
+ I.pull_data()
+ if(isnum(I.data))
+ result = sqrt(I.data)
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = result
+ O.push_data()
+
+// % Modulo % //
+
+/obj/item/integrated_circuit/arithmetic/modulo
+ name = "modulo circuit"
+ desc = "Gets the remainder of A / B."
+ icon_state = "modulo"
+ inputs = list("A", "B")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/arithmetic/modulo/do_work()
+ var/result = 0
+ var/datum/integrated_io/input/A = inputs[1]
+ var/datum/integrated_io/input/B = inputs[2]
+ if(isnum(A.data) && isnum(B.data) && B.data != 0)
+ result = A.data % B.data
+
+ for(var/datum/integrated_io/output/O in outputs)
+ O.data = result
+ O.push_data()
+
diff --git a/code/modules/integrated_electronics/assemblies.dm b/code/modules/integrated_electronics/assemblies.dm
index 3b9e7aab06..ff994aa43c 100644
--- a/code/modules/integrated_electronics/assemblies.dm
+++ b/code/modules/integrated_electronics/assemblies.dm
@@ -1,33 +1,59 @@
+#define IC_COMPONENTS_BASE 20
+#define IC_COMPLEXITY_BASE 80
+
/obj/item/device/electronic_assembly
name = "electronic assembly"
desc = "It's a case, for building electronics with."
- w_class = 2
+ w_class = ITEMSIZE_SMALL
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "setup_small"
- var/max_components = 10
- var/max_complexity = 40
+ show_messages = TRUE
+ var/max_components = IC_COMPONENTS_BASE
+ var/max_complexity = IC_COMPLEXITY_BASE
var/opened = 0
/obj/item/device/electronic_assembly/medium
name = "electronic mechanism"
icon_state = "setup_medium"
- w_class = 3
- max_components = 20
- max_complexity = 80
+ w_class = ITEMSIZE_NORMAL
+ max_components = IC_COMPONENTS_BASE * 2
+ max_complexity = IC_COMPLEXITY_BASE * 2
/obj/item/device/electronic_assembly/large
name = "electronic machine"
icon_state = "setup_large"
- w_class = 4
- max_components = 30
- max_complexity = 120
+ w_class = ITEMSIZE_LARGE
+ max_components = IC_COMPONENTS_BASE * 3
+ max_complexity = IC_COMPLEXITY_BASE * 3
/obj/item/device/electronic_assembly/drone
name = "electronic drone"
icon_state = "setup_drone"
- w_class = 3
- max_components = 25
- max_complexity = 100
+ w_class = ITEMSIZE_NORMAL
+ max_components = IC_COMPONENTS_BASE * 1.5
+ max_complexity = IC_COMPLEXITY_BASE * 1.5
+
+/obj/item/device/electronic_assembly/implant
+ name = "electronic implant"
+ icon_state = "setup_implant"
+ w_class = ITEMSIZE_TINY
+ max_components = IC_COMPONENTS_BASE / 2
+ max_complexity = IC_COMPLEXITY_BASE / 2
+ var/obj/item/weapon/implant/integrated_circuit/implant = null
+
+/obj/item/device/electronic_assembly/implant/update_icon()
+ ..()
+ implant.icon_state = icon_state
+
+
+/obj/item/device/electronic_assembly/implant/nano_host()
+ return implant
+
+/obj/item/device/electronic_assembly/proc/resolve_nano_host()
+ return src
+
+/obj/item/device/electronic_assembly/implant/resolve_nano_host()
+ return implant
/obj/item/device/electronic_assembly/interact(mob/user)
if(!CanInteract(user, physical_state))
@@ -79,6 +105,12 @@
to_chat(M, "The machine now has a label reading '[input]'.")
name = input
+/obj/item/device/electronic_assembly/proc/can_move()
+ return FALSE
+
+/obj/item/device/electronic_assembly/drone/can_move()
+ return TRUE
+
/obj/item/device/electronic_assembly/update_icon()
if(opened)
icon_state = initial(icon_state) + "-open"
diff --git a/code/modules/integrated_electronics/converters.dm b/code/modules/integrated_electronics/converters.dm
index b039299a55..96494ba469 100644
--- a/code/modules/integrated_electronics/converters.dm
+++ b/code/modules/integrated_electronics/converters.dm
@@ -5,6 +5,11 @@
outputs = list("output")
activators = list("convert")
category_text = "Converter"
+ autopulse = 1
+
+/obj/item/integrated_circuit/converter/on_data_written()
+ if(autopulse == 1)
+ check_then_do_work()
/obj/item/integrated_circuit/converter/num2text
name = "number to string"
@@ -104,4 +109,67 @@
var/datum/integrated_io/outgoing = outputs[1]
outgoing.data = result
- outgoing.push_data()
\ No newline at end of file
+ outgoing.push_data()
+
+/obj/item/integrated_circuit/converter/radians2degrees
+ name = "radians to degrees converter"
+ desc = "Converts radians to degrees."
+ inputs = list("radian")
+ outputs = list("degrees")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/converter/radians2degrees/do_work()
+ var/result = null
+ var/datum/integrated_io/incoming = inputs[1]
+ var/datum/integrated_io/outgoing = outputs[1]
+ incoming.pull_data()
+ if(incoming.data && isnum(incoming.data))
+ result = ToDegrees(incoming.data)
+
+ outgoing.data = result
+ outgoing.push_data()
+
+/obj/item/integrated_circuit/converter/degrees2radians
+ name = "degrees to radians converter"
+ desc = "Converts degrees to radians."
+ inputs = list("degrees")
+ outputs = list("radians")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/converter/degrees2radians/do_work()
+ var/result = null
+ var/datum/integrated_io/incoming = inputs[1]
+ var/datum/integrated_io/outgoing = outputs[1]
+ incoming.pull_data()
+ if(incoming.data && isnum(incoming.data))
+ result = ToRadians(incoming.data)
+
+ outgoing.data = result
+ outgoing.push_data()
+
+
+/obj/item/integrated_circuit/converter/abs_to_rel_coords
+ name = "abs to rel coordinate converter"
+ desc = "Easily convert absolute coordinates to relative coordinates with this."
+ complexity = 4
+ inputs = list("X1 (abs)", "Y1 (abs)", "X2 (abs)", "Y2 (abs)")
+ outputs = list("X (rel)", "Y (rel)")
+ activators = list("compute rel coordinates")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_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()
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/coordinate.dm b/code/modules/integrated_electronics/coordinate.dm
deleted file mode 100644
index 0941c290f4..0000000000
--- a/code/modules/integrated_electronics/coordinate.dm
+++ /dev/null
@@ -1,54 +0,0 @@
-//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."
- icon_state = "gps"
- complexity = 4
- inputs = list()
- outputs = list("X (abs)", "Y (abs)")
- activators = list("get coordinates")
- spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
- category_text = "Coords"
-
-/obj/item/integrated_circuit/gps/do_work()
- 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
- inputs = list("X1 (abs)", "Y1 (abs)", "X2 (abs)", "Y2 (abs)")
- outputs = list("X (rel)", "Y (rel)")
- activators = list("compute rel coordinates")
- spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
- category_text = "Coords"
-
-/obj/item/integrated_circuit/abs_to_rel_coords/do_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()
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/data_transfer.dm b/code/modules/integrated_electronics/data_transfer.dm
index bf4ddf4b6f..7e37995df5 100644
--- a/code/modules/integrated_electronics/data_transfer.dm
+++ b/code/modules/integrated_electronics/data_transfer.dm
@@ -1,5 +1,10 @@
/obj/item/integrated_circuit/transfer
category_text = "Data Transfer"
+ autopulse = 1
+
+/obj/item/integrated_circuit/transfer/on_data_written()
+ if(autopulse == 1)
+ check_then_do_work()
/obj/item/integrated_circuit/transfer/splitter
name = "splitter"
diff --git a/code/modules/integrated_electronics/input_output.dm b/code/modules/integrated_electronics/input_output.dm
index 5bb3ea6aec..296104d938 100644
--- a/code/modules/integrated_electronics/input_output.dm
+++ b/code/modules/integrated_electronics/input_output.dm
@@ -321,11 +321,74 @@
data_received.write_data_to_pin(message)
text_received.write_data_to_pin(text)
+//This circuit gives information on where the machine is.
+/obj/item/integrated_circuit/input/gps
+ name = "global positioning system"
+ desc = "This allows you to easily know the position of a machine containing this device."
+ icon_state = "gps"
+ complexity = 4
+ inputs = list()
+ outputs = list("X (abs)", "Y (abs)")
+ activators = list("get coordinates")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/input/gps/do_work()
+ 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/input/microphone
+ name = "microphone"
+ desc = "Useful for spying on people or for voice activated machines."
+ icon_state = "recorder"
+ complexity = 8
+ inputs = list()
+ outputs = list("speaker \", "message \")
+ activators = list("on message received")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/input/microphone/New()
+ ..()
+ listening_objects |= src
+
+/obj/item/integrated_circuit/input/microphone/Destroy()
+ listening_objects -= src
+ ..()
+
+/obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
+ var/datum/integrated_io/V = outputs[1]
+ var/datum/integrated_io/O = outputs[2]
+ var/datum/integrated_io/A = activators[1]
+ if(M && msg)
+ if(speaking)
+ if(!speaking.machine_understands)
+ msg = speaking.scramble(msg)
+ V.data = M.GetVoice()
+ O.data = msg
+ A.push_data()
+
+
+
+
+
+
/obj/item/integrated_circuit/output
category_text = "Output"
/obj/item/integrated_circuit/output/screen
- name = "screen"
+ name = "small screen"
desc = "This small screen can display a single piece of data, when the machine is examined closely."
icon_state = "screen"
inputs = list("displayed data")
@@ -343,6 +406,28 @@
else
stuff_to_display = I.data
+/obj/item/integrated_circuit/output/screen/medium
+ name = "screen"
+ desc = "This screen allows for people holding the device to see a piece of data."
+ icon_state = "screen_medium"
+
+/obj/item/integrated_circuit/output/screen/medium/do_work()
+ ..()
+ var/list/nearby_things = range(0, get_turf(src))
+ for(var/mob/M in nearby_things)
+ var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src
+ visible_message("\icon[O] [stuff_to_display]")
+
+/obj/item/integrated_circuit/output/screen/large
+ name = "large screen"
+ desc = "This screen allows for people able to see the device to see a piece of data."
+ icon_state = "screen_large"
+
+/obj/item/integrated_circuit/output/screen/large/do_work()
+ ..()
+ var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src
+ O.visible_message("\icon[O] [stuff_to_display]")
+
/obj/item/integrated_circuit/output/light
name = "light"
desc = "This light can turn on and off on command."
@@ -415,6 +500,24 @@
activators = list("play sound")
var/list/sounds = list()
+/obj/item/integrated_circuit/output/text_to_speech
+ name = "text-to-speech circuit"
+ desc = "A miniature speaker is attached to this component."
+ extended_desc = "This unit is more advanced than the plain speaker circuit, able to transpose any valid text to speech."
+ icon_state = "speaker"
+ complexity = 12
+ cooldown_per_use = 4 SECONDS
+ inputs = list("text")
+ outputs = list()
+ activators = list("to speech")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/output/text_to_speech/do_work()
+ var/datum/integrated_io/text = inputs[1]
+ if(istext(text.data))
+ var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src
+ audible_message("\icon[O] \The [O.name] states, \"[text.data]\"")
+
/obj/item/integrated_circuit/output/sound/New()
..()
extended_desc = list()
diff --git a/code/modules/integrated_electronics/logic.dm b/code/modules/integrated_electronics/logic.dm
index 6d53f6aae7..d477be3cbe 100644
--- a/code/modules/integrated_electronics/logic.dm
+++ b/code/modules/integrated_electronics/logic.dm
@@ -6,6 +6,11 @@
outputs = list("result")
activators = list("compare", "on true result")
category_text = "Logic"
+ autopulse = 1
+
+/obj/item/integrated_circuit/logic/on_data_written()
+ if(autopulse == 1)
+ check_then_do_work()
/obj/item/integrated_circuit/logic/do_work()
var/datum/integrated_io/O = outputs[1]
diff --git a/code/modules/integrated_electronics/manipulation.dm b/code/modules/integrated_electronics/manipulation.dm
index 524c060d2d..f49b96d16c 100644
--- a/code/modules/integrated_electronics/manipulation.dm
+++ b/code/modules/integrated_electronics/manipulation.dm
@@ -105,7 +105,7 @@
Southwest = 10
\
\
Pulsing the 'step towards dir' activator pin will cause the machine to move a meter in that direction, assuming it is not \
- being held, or anchored in some way. It should be noted that heavy machines will be unable to move."
+ being held, or anchored in some way. It should be noted that the ability to move is dependant on the type of assembly that this circuit inhabits."
complexity = 20
inputs = list("dir num")
outputs = list()
@@ -117,7 +117,7 @@
var/turf/T = get_turf(src)
if(T && istype(loc, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/machine = loc
- if(machine.anchored || machine.w_class >= ITEMSIZE_LARGE)
+ if(machine.anchored || !machine.can_move())
return
if(machine.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held.
var/datum/integrated_io/wanted_dir = inputs[1]
diff --git a/code/modules/integrated_electronics/memory.dm b/code/modules/integrated_electronics/memory.dm
index edf263dd96..f9cd109dce 100644
--- a/code/modules/integrated_electronics/memory.dm
+++ b/code/modules/integrated_electronics/memory.dm
@@ -61,7 +61,7 @@
"output pin 6",
"output pin 7",
"output pin 8")
- spawn_flags = IC_SPAWN_RESEARCH
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
/obj/item/integrated_circuit/memory/huge
diff --git a/code/modules/integrated_electronics/time.dm b/code/modules/integrated_electronics/time.dm
index 8a6a0c9c04..50bcc5e386 100644
--- a/code/modules/integrated_electronics/time.dm
+++ b/code/modules/integrated_electronics/time.dm
@@ -44,7 +44,7 @@
This circuit is set to send a pulse after a delay of half a second."
icon_state = "delay-5"
delay = 5
- spawn_flags = IC_SPAWN_RESEARCH
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/tenth_sec
name = "tenth-sec delay circuit"
@@ -52,7 +52,7 @@
This circuit is set to send a pulse after a delay of 1/10th of a second."
icon_state = "delay-1"
delay = 1
- spawn_flags = IC_SPAWN_RESEARCH
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/custom
name = "custom delay circuit"
diff --git a/code/modules/integrated_electronics/tools.dm b/code/modules/integrated_electronics/tools.dm
index 1d3b2cf4a9..6c76b9b4ff 100644
--- a/code/modules/integrated_electronics/tools.dm
+++ b/code/modules/integrated_electronics/tools.dm
@@ -164,15 +164,33 @@
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "circuit_kit"
w_class = 3
- display_contents_with_number = 1
+ display_contents_with_number = 0
+ can_hold = list(
+ /obj/item/integrated_circuit,
+ /obj/item/weapon/storage/bag/circuits/mini,
+ /obj/item/device/electronic_assembly,
+ /obj/item/device/integrated_electronics,
+ /obj/item/weapon/crowbar,
+ /obj/item/weapon/screwdriver
+ )
/obj/item/weapon/storage/bag/circuits/basic/New()
..()
spawn(2 SECONDS) // So the list has time to initialize.
- for(var/obj/item/integrated_circuit/IC in all_integrated_circuits)
- if(IC.spawn_flags & IC_SPAWN_DEFAULT)
- for(var/i = 1 to 3)
- new IC.type(src)
+// for(var/obj/item/integrated_circuit/IC in all_integrated_circuits)
+// if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+// for(var/i = 1 to 3)
+// new IC.type(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/arithmetic(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/trig(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/input(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/output(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/memory(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/logic(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/time(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/reagents(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/transfer(src)
+ new /obj/item/weapon/storage/bag/circuits/mini/converter(src)
new /obj/item/device/electronic_assembly(src)
new /obj/item/device/integrated_electronics/wirer(src)
@@ -193,4 +211,151 @@
new /obj/item/device/integrated_electronics/debugger(src)
new /obj/item/weapon/crowbar(src)
new /obj/item/weapon/screwdriver(src)
- make_exact_fit()
\ No newline at end of file
+ make_exact_fit()
+
+/obj/item/weapon/storage/bag/circuits/mini/
+ name = "circuit box"
+ desc = "Used to partition categories of circuits, for a neater workspace."
+ w_class = 2
+ display_contents_with_number = 1
+ can_hold = list(/obj/item/integrated_circuit)
+
+/obj/item/weapon/storage/bag/circuits/mini/arithmetic
+ name = "arithmetic circuit box"
+ desc = "Warning: Contains math."
+ icon_state = "box_arithmetic"
+
+/obj/item/weapon/storage/bag/circuits/mini/arithmetic/New()
+ ..()
+ for(var/obj/item/integrated_circuit/arithmetic/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+/obj/item/weapon/storage/bag/circuits/mini/trig
+ name = "trig circuit box"
+ desc = "Danger: Contains more math."
+ icon_state = "box_trig"
+
+/obj/item/weapon/storage/bag/circuits/mini/trig/New()
+ ..()
+ for(var/obj/item/integrated_circuit/trig/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+/obj/item/weapon/storage/bag/circuits/mini/input
+ name = "input circuit box"
+ desc = "Tell these circuits everything you know."
+ icon_state = "box_input"
+
+/obj/item/weapon/storage/bag/circuits/mini/input/New()
+ ..()
+ for(var/obj/item/integrated_circuit/input/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+/obj/item/weapon/storage/bag/circuits/mini/output
+ name = "output circuit box"
+ desc = "Circuits to interface with the world beyond itself."
+ icon_state = "box_output"
+
+/obj/item/weapon/storage/bag/circuits/mini/output/New()
+ ..()
+ for(var/obj/item/integrated_circuit/output/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+/obj/item/weapon/storage/bag/circuits/mini/memory
+ name = "memory circuit box"
+ desc = "Machines can be quite forgetful without these."
+ icon_state = "box_memory"
+
+/obj/item/weapon/storage/bag/circuits/mini/memory/New()
+ ..()
+ for(var/obj/item/integrated_circuit/memory/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+
+/obj/item/weapon/storage/bag/circuits/mini/logic
+ name = "logic circuit box"
+ desc = "May or may not be Turing complete."
+ icon_state = "box_logic"
+
+/obj/item/weapon/storage/bag/circuits/mini/logic/New()
+ ..()
+ for(var/obj/item/integrated_circuit/logic/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+/obj/item/weapon/storage/bag/circuits/mini/time
+ name = "time circuit box"
+ desc = "No time machine parts, sadly."
+ icon_state = "box_time"
+
+/obj/item/weapon/storage/bag/circuits/mini/time/New()
+ ..()
+ for(var/obj/item/integrated_circuit/time/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+/obj/item/weapon/storage/bag/circuits/mini/reagents
+ name = "reagent circuit box"
+ desc = "Unlike most electronics, these circuits are supposed to come in contact with liquids."
+ icon_state = "box_reagents"
+
+/obj/item/weapon/storage/bag/circuits/mini/reagents/New()
+ ..()
+ for(var/obj/item/integrated_circuit/reagent/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+/obj/item/weapon/storage/bag/circuits/mini/transfer
+ name = "transfer circuit box"
+ desc = "Useful for moving data representing something arbitrary to another arbitrary virtual place."
+ icon_state = "box_transfer"
+
+/obj/item/weapon/storage/bag/circuits/mini/transfer/New()
+ ..()
+ for(var/obj/item/integrated_circuit/transfer/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
+
+
+/obj/item/weapon/storage/bag/circuits/mini/converter
+ name = "converter circuit box"
+ desc = "Transform one piece of data to another type of data with these."
+ icon_state = "box_converter"
+
+/obj/item/weapon/storage/bag/circuits/mini/converter/New()
+ ..()
+ for(var/obj/item/integrated_circuit/converter/IC in all_integrated_circuits)
+ if(IC.spawn_flags & IC_SPAWN_DEFAULT)
+ for(var/i = 1 to 3)
+ new IC.type(src)
+ make_exact_fit()
\ No newline at end of file
diff --git a/code/modules/integrated_electronics/trig.dm b/code/modules/integrated_electronics/trig.dm
new file mode 100644
index 0000000000..e8e2e09ca9
--- /dev/null
+++ b/code/modules/integrated_electronics/trig.dm
@@ -0,0 +1,135 @@
+//These circuits do not-so-simple math.
+/obj/item/integrated_circuit/trig
+ complexity = 1
+ inputs = list("A","B","C","D","E","F","G","H")
+ outputs = list("result")
+ activators = list("compute")
+ category_text = "Trig"
+ extended_desc = "Input and output are in degrees."
+ autopulse = 1
+
+/obj/item/integrated_circuit/trig/on_data_written()
+ if(autopulse == 1)
+ check_then_do_work()
+
+// Sine //
+
+/obj/item/integrated_circuit/trig/sine
+ name = "sin circuit"
+ desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A."
+ icon_state = "sine"
+ inputs = list("A")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/trig/sine/do_work()
+ var/result = null
+ var/datum/integrated_io/input/A = inputs[1]
+ A.pull_data()
+ if(isnum(A.data))
+ result = sin(A.data)
+
+ var/datum/integrated_io/output/O = outputs[1]
+ O.data = result
+ O.push_data()
+
+// Cosine //
+
+/obj/item/integrated_circuit/trig/cosine
+ name = "cos circuit"
+ desc = "Outputs the cosine of A."
+ icon_state = "cosine"
+ inputs = list("A")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/trig/cosine/do_work()
+ var/result = null
+ var/datum/integrated_io/input/A = inputs[1]
+ A.pull_data()
+ if(isnum(A.data))
+ result = cos(A.data)
+
+ var/datum/integrated_io/output/O = outputs[1]
+ O.data = result
+ O.push_data()
+
+// Tangent //
+
+/obj/item/integrated_circuit/trig/tangent
+ name = "tan circuit"
+ desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance."
+ icon_state = "tangent"
+ inputs = list("A")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/trig/tangent/do_work()
+ var/result = null
+ var/datum/integrated_io/input/A = inputs[1]
+ A.pull_data()
+ if(isnum(A.data))
+ result = Tan(A.data)
+
+ var/datum/integrated_io/output/O = outputs[1]
+ O.data = result
+ O.push_data()
+
+// Cosecant //
+
+/obj/item/integrated_circuit/trig/cosecant
+ name = "csc circuit"
+ desc = "Outputs the cosecant of A."
+ icon_state = "cosecant"
+ inputs = list("A")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/trig/cosecant/do_work()
+ var/result = null
+ var/datum/integrated_io/input/A = inputs[1]
+ A.pull_data()
+ if(isnum(A.data))
+ result = Csc(A.data)
+
+ var/datum/integrated_io/output/O = outputs[1]
+ O.data = result
+ O.push_data()
+
+
+// Secant //
+
+/obj/item/integrated_circuit/trig/secant
+ name = "sec circuit"
+ desc = "Outputs the secant of A. Has nothing to do with the security department."
+ icon_state = "secant"
+ inputs = list("A")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/trig/secant/do_work()
+ var/result = null
+ var/datum/integrated_io/input/A = inputs[1]
+ A.pull_data()
+ if(isnum(A.data))
+ result = Sec(A.data)
+
+ var/datum/integrated_io/output/O = outputs[1]
+ O.data = result
+ O.push_data()
+
+
+// Cotangent //
+
+/obj/item/integrated_circuit/trig/cotangent
+ name = "cot circuit"
+ desc = "Outputs the cotangent of A. Has nothing to do with the security department."
+ icon_state = "cotangent"
+ inputs = list("A")
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
+/obj/item/integrated_circuit/trig/cotangent/do_work()
+ var/result = null
+ var/datum/integrated_io/input/A = inputs[1]
+ A.pull_data()
+ if(isnum(A.data))
+ result = Cot(A.data)
+
+ var/datum/integrated_io/output/O = outputs[1]
+ O.data = result
+ O.push_data()
\ No newline at end of file
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index b2f6a9c447..8e91f3f06a 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -1557,6 +1557,7 @@ CIRCUITS BELOW
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
+ sort_string = "VCAAB"
/datum/design/item/custom_circuit_assembly/drone
name = "Drone custom assembly"
@@ -1565,6 +1566,7 @@ CIRCUITS BELOW
req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4)
materials = list(DEFAULT_WALL_MATERIAL = 30000)
build_path = /obj/item/device/electronic_assembly/drone
+ sort_string = "VCAAC"
/datum/design/item/custom_circuit_assembly/large
name = "Large custom assembly"
@@ -1573,6 +1575,16 @@ CIRCUITS BELOW
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
+ sort_string = "VCAAD"
+
+/datum/design/item/custom_circuit_assembly/implant
+ name = "Implant custom assembly"
+ desc = "An customizable assembly for very small devices, implanted into living entities."
+ id = "assembly-implant"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5)
+ materials = list(DEFAULT_WALL_MATERIAL = 2000)
+ build_path = /obj/item/weapon/implant/integrated_circuit
+ sort_string = "VCAAE"
/* Uncomment if someone makes these buildable
/datum/design/circuit/general_alert
diff --git a/code/unit_tests/integrated_circuits/arithmetic.dm b/code/unit_tests/integrated_circuits/arithmetic.dm
new file mode 100644
index 0000000000..1e62f6e7b7
--- /dev/null
+++ b/code/unit_tests/integrated_circuits/arithmetic.dm
@@ -0,0 +1,174 @@
+/datum/unit_test/integrated_circuits/additon_1
+ name = "Arithmetic Circuits: Addition - Basic"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/addition
+ inputs_to_give = list(25, 75)
+ expected_outputs = list(100)
+
+/datum/unit_test/integrated_circuits/additon_2
+ name = "Arithmetic Circuits: Addition - Multiple"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/addition
+ inputs_to_give = list(7, 5, 3, 26, 974, -51, 77, 0)
+ expected_outputs = list(1041)
+
+
+
+/datum/unit_test/integrated_circuits/subtraction_1
+ name = "Arithmetic Circuits: Subtraction - Basic"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/subtraction
+ inputs_to_give = list(20, 15)
+ expected_outputs = list(5)
+
+/datum/unit_test/integrated_circuits/subtraction_2
+ name = "Arithmetic Circuits: Subtraction - Multiple"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/subtraction
+ inputs_to_give = list(5, 50, 30)
+ expected_outputs = list(-75)
+
+
+
+/datum/unit_test/integrated_circuits/multiplication_1
+ name = "Arithmetic Circuits: Multiplication - Basic"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/multiplication
+ inputs_to_give = list(5, 20)
+ expected_outputs = list(100)
+
+/datum/unit_test/integrated_circuits/multiplication_2
+ name = "Arithmetic Circuits: Multiplication - Multiple"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/multiplication
+ inputs_to_give = list(2, 10, 20)
+ expected_outputs = list(400)
+
+/datum/unit_test/integrated_circuits/multiplication_3
+ name = "Arithmetic Circuits: Multiplication - Decimal"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/multiplication
+ inputs_to_give = list(100, 0.5)
+ expected_outputs = list(50)
+
+
+/datum/unit_test/integrated_circuits/division_1
+ name = "Arithmetic Circuits: Division - Basic"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/division
+ inputs_to_give = list(100, 5)
+ expected_outputs = list(20)
+
+/datum/unit_test/integrated_circuits/division_2
+ name = "Arithmetic Circuits: Division - Multiple"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/division
+ inputs_to_give = list(500, 100, 10)
+ expected_outputs = list(0.5)
+
+/datum/unit_test/integrated_circuits/division_3
+ name = "Arithmetic Circuits: Division - Decimal"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/division
+ inputs_to_give = list(100, 0.5)
+ expected_outputs = list(200)
+
+
+
+/datum/unit_test/integrated_circuits/exponent_1
+ name = "Arithmetic Circuits: Exponent - Basic"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/exponent
+ inputs_to_give = list(20, 2)
+ expected_outputs = list(400)
+
+/datum/unit_test/integrated_circuits/exponent_2
+ name = "Arithmetic Circuits: Exponent - Powers"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/exponent
+ inputs_to_give = list(5, 4)
+ expected_outputs = list(625)
+
+
+
+/datum/unit_test/integrated_circuits/sign_1
+ name = "Arithmetic Circuits: Sign - Positive"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/sign
+ inputs_to_give = list(5)
+ expected_outputs = list(1)
+
+/datum/unit_test/integrated_circuits/sign_2
+ name = "Arithmetic Circuits: Sign - Negative"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/sign
+ inputs_to_give = list(-500)
+ expected_outputs = list(-1)
+
+/datum/unit_test/integrated_circuits/sign_3
+ name = "Arithmetic Circuits: Sign - Zero"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/sign
+ inputs_to_give = list(0)
+ expected_outputs = list(0)
+
+
+
+/datum/unit_test/integrated_circuits/round_1
+ name = "Arithmetic Circuits: Round - Basic"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/round
+ inputs_to_give = list(4.25)
+ expected_outputs = list(4)
+
+/datum/unit_test/integrated_circuits/round_2
+ name = "Arithmetic Circuits: Round - Floor"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/round
+ inputs_to_give = list(8.95)
+ expected_outputs = list(8)
+
+/datum/unit_test/integrated_circuits/round_3
+ name = "Arithmetic Circuits: Round - Round to X"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/round
+ inputs_to_give = list(45.68, 0.1)
+ expected_outputs = list(45.7)
+
+
+
+/datum/unit_test/integrated_circuits/absolute_1
+ name = "Arithmetic Circuits: Absolute - Positive"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/absolute
+ inputs_to_give = list(50)
+ expected_outputs = list(50)
+
+/datum/unit_test/integrated_circuits/absolute_2
+ name = "Arithmetic Circuits: Absolute - Negative"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/absolute
+ inputs_to_give = list(-20)
+ expected_outputs = list(20)
+
+/datum/unit_test/integrated_circuits/absolute_3
+ name = "Arithmetic Circuits: Absolute - Zero"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/absolute
+ inputs_to_give = list(0)
+ expected_outputs = list(0)
+
+
+
+/datum/unit_test/integrated_circuits/average_1
+ name = "Arithmetic Circuits: Average - Basic"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/average
+ inputs_to_give = list(8, 20, 14, 6)
+ expected_outputs = list(12)
+
+/datum/unit_test/integrated_circuits/average_2
+ name = "Arithmetic Circuits: Average - Negatives"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/average
+ inputs_to_give = list(30, -5, 8, -50, 4)
+ expected_outputs = list(-2.6)
+
+
+
+/datum/unit_test/integrated_circuits/square_root_1
+ name = "Arithmetic Circuits: Square Root"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/square_root
+ inputs_to_give = list(64)
+ expected_outputs = list(8)
+
+
+
+/datum/unit_test/integrated_circuits/modulo_1
+ name = "Arithmetic Circuits: Modulo - 1"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/modulo
+ inputs_to_give = list(8, 5)
+ expected_outputs = list(3)
+
+/datum/unit_test/integrated_circuits/modulo_2
+ name = "Arithmetic Circuits: Modulo - 2"
+ circuit_type = /obj/item/integrated_circuit/arithmetic/modulo
+ inputs_to_give = list(20, 5)
+ expected_outputs = list(0)
\ No newline at end of file
diff --git a/code/unit_tests/integrated_circuits/circuits.dm b/code/unit_tests/integrated_circuits/circuits.dm
new file mode 100644
index 0000000000..16fb2728de
--- /dev/null
+++ b/code/unit_tests/integrated_circuits/circuits.dm
@@ -0,0 +1,73 @@
+
+/datum/unit_test/integrated_circuits
+ name = "circuit template"
+ var/circuit_type = null
+ var/obj/item/integrated_circuit/IC = null
+ var/list/inputs_to_give = list()
+ var/list/expected_outputs = list()
+
+// Use this to set up.
+/datum/unit_test/integrated_circuits/proc/arrange()
+ IC = new circuit_type(get_standard_turf()) // Make the circuit
+ IC.cooldown_per_use = 0
+
+// Use this when finished to remove clutter for the next test.
+/datum/unit_test/integrated_circuits/proc/clean_up()
+ qdel(IC)
+
+// Override this if needing special output (e.g. rounding to avoid floating point fun).
+/datum/unit_test/integrated_circuits/proc/assess()
+ var/output_wrong = FALSE
+ var/i = 1
+ for(var/datum/integrated_io/io in IC.outputs)
+ if(io.data != expected_outputs[i])
+ log_bad("[io.name] did not match expected output of [expected_outputs[i]]. Output was [isnull(io.data) ? "NULL" : io.data].")
+ output_wrong = TRUE
+ i++
+ return output_wrong
+
+// Useful when doing floating point fun.
+/datum/unit_test/integrated_circuits/floor/assess()
+ var/output_wrong = FALSE
+ var/i = 1
+ for(var/datum/integrated_io/io in IC.outputs)
+ if(round(io.data) != expected_outputs[i])
+ log_bad("[io.name] did not match expected output of [expected_outputs[i]]. Output was [isnull(io.data) ? "NULL" : round(io.data)].")
+ output_wrong = TRUE
+ i++
+ return output_wrong
+
+/datum/unit_test/integrated_circuits/start_test()
+ var/output_wrong = FALSE
+ if(!circuit_type)
+ fail("[name] did not supply a circuit_type path.")
+ return TRUE
+ try
+ // Arrange
+ arrange()
+
+ var/i = 1
+ for(var/input in inputs_to_give)
+ var/datum/integrated_io/io = IC.inputs[i]
+ io.write_data_to_pin(input)
+ i++
+
+ // Act
+ IC.do_work()
+
+ output_wrong = assess()
+
+ clean_up()
+
+ catch(var/exception/e)
+ log_bad("[name] caught an exception: [e] on [e.file]:[e.line]")
+ output_wrong = TRUE
+
+ // Assert
+ if(output_wrong)
+ fail("[name] failed.")
+ return TRUE
+ else
+ pass("[name] matched all expected outputs.")
+ return TRUE
+
diff --git a/code/unit_tests/integrated_circuits/converter.dm b/code/unit_tests/integrated_circuits/converter.dm
new file mode 100644
index 0000000000..b2a414f4d8
--- /dev/null
+++ b/code/unit_tests/integrated_circuits/converter.dm
@@ -0,0 +1,52 @@
+/datum/unit_test/integrated_circuits/num2text
+ name = "Converter Circuits: Num2Text"
+ circuit_type = /obj/item/integrated_circuit/converter/num2text
+ inputs_to_give = list(10250)
+ expected_outputs = list("10250")
+
+
+
+/datum/unit_test/integrated_circuits/text2num
+ name = "Converter Circuits: Text2Num"
+ circuit_type = /obj/item/integrated_circuit/converter/text2num
+ inputs_to_give = list("2005")
+ expected_outputs = list(2005)
+
+
+
+/datum/unit_test/integrated_circuits/lowercase
+ name = "Converter Circuits: Lowercase"
+ circuit_type = /obj/item/integrated_circuit/converter/lowercase
+ inputs_to_give = list("Lorem ipsum...")
+ expected_outputs = list("lorem ipsum...")
+
+
+
+/datum/unit_test/integrated_circuits/uppercase
+ name = "Converter Circuits: Uppercase"
+ circuit_type = /obj/item/integrated_circuit/converter/uppercase
+ inputs_to_give = list("Lorem ipsum...")
+ expected_outputs = list("LOREM IPSUM...")
+
+
+
+/datum/unit_test/integrated_circuits/concatenatior
+ name = "Converter Circuits: Concatenatior"
+ circuit_type = /obj/item/integrated_circuit/converter/concatenatior
+ inputs_to_give = list("Lorem", " ", "ipsum", "...")
+ expected_outputs = list("Lorem ipsum...")
+
+
+
+/datum/unit_test/integrated_circuits/floor/radians2degrees
+ name = "Converter Circuits: Radians2Degrees"
+ circuit_type = /obj/item/integrated_circuit/converter/radians2degrees
+ inputs_to_give = list(1.57)
+ expected_outputs = list(89) // 89.95437
+
+
+/datum/unit_test/integrated_circuits/floor/degrees2radians
+ name = "Converter Circuits: Degrees2Radians"
+ circuit_type = /obj/item/integrated_circuit/converter/degrees2radians
+ inputs_to_give = list(90)
+ expected_outputs = list(1) // 1.570796
\ No newline at end of file
diff --git a/code/unit_tests/integrated_circuits/data_transfer.dm b/code/unit_tests/integrated_circuits/data_transfer.dm
new file mode 100644
index 0000000000..1d02e8f837
--- /dev/null
+++ b/code/unit_tests/integrated_circuits/data_transfer.dm
@@ -0,0 +1,17 @@
+/datum/unit_test/integrated_circuits/splitter
+ name = "Data Transfer Circuits: Splitter"
+ circuit_type = /obj/item/integrated_circuit/transfer/splitter
+ inputs_to_give = list("Test")
+ expected_outputs = list("Test", "Test")
+
+/datum/unit_test/integrated_circuits/splitter4
+ name = "Data Transfer Circuits: Splitter 4"
+ circuit_type = /obj/item/integrated_circuit/transfer/splitter/medium
+ inputs_to_give = list("Test")
+ expected_outputs = list("Test", "Test", "Test", "Test")
+
+/datum/unit_test/integrated_circuits/splitter8
+ name = "Data Transfer Circuits: Splitter 8"
+ circuit_type = /obj/item/integrated_circuit/transfer/splitter/large
+ inputs_to_give = list("Test")
+ expected_outputs = list("Test", "Test", "Test", "Test", "Test", "Test", "Test", "Test")
\ No newline at end of file
diff --git a/code/unit_tests/integrated_circuits/logic.dm b/code/unit_tests/integrated_circuits/logic.dm
new file mode 100644
index 0000000000..314150f3b4
--- /dev/null
+++ b/code/unit_tests/integrated_circuits/logic.dm
@@ -0,0 +1,186 @@
+/datum/unit_test/integrated_circuits/equals_1
+ name = "Logic Circuits: Equals - String True"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/equals
+ inputs_to_give = list("Test", "Test")
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/equals_2
+ name = "Logic Circuits: Equals - String False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/equals
+ inputs_to_give = list("Test", "Nope")
+ expected_outputs = list(FALSE)
+
+/datum/unit_test/integrated_circuits/equals_3
+ name = "Logic Circuits: Equals - Number True"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/equals
+ inputs_to_give = list(525, 525)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/equals_4
+ name = "Logic Circuits: Equals - Number False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/equals
+ inputs_to_give = list(1020, -580)
+ expected_outputs = list(FALSE)
+
+/datum/unit_test/integrated_circuits/equals_5
+ name = "Logic Circuits: Equals - Null True"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/equals
+ inputs_to_give = list(null, null)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/equals_6
+ name = "Logic Circuits: Equals - Ref True"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/equals
+ inputs_to_give = list()
+ expected_outputs = list(TRUE)
+ var/obj/A = null
+
+/datum/unit_test/integrated_circuits/equals_6/arrange()
+ A = new(get_standard_turf())
+ inputs_to_give = list(weakref(A), weakref(A))
+ ..()
+
+/datum/unit_test/integrated_circuits/equals_6/clean_up()
+ qdel(A)
+ ..()
+
+/datum/unit_test/integrated_circuits/equals_7
+ name = "Logic Circuits: Equals - Ref False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/equals
+ inputs_to_give = list()
+ expected_outputs = list(FALSE)
+ var/obj/A = null
+ var/obj/B = null
+
+/datum/unit_test/integrated_circuits/equals_7/arrange()
+ A = new(get_standard_turf())
+ B = new(get_standard_turf())
+ inputs_to_give = list(weakref(A), weakref(B))
+ ..()
+
+/datum/unit_test/integrated_circuits/equals_7/clean_up()
+ qdel(A)
+ qdel(B)
+ ..()
+
+
+
+/datum/unit_test/integrated_circuits/and_1
+ name = "Logic Circuits: And - True"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/and
+ inputs_to_give = list("One", "Two")
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/and_2
+ name = "Logic Circuits: And - False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/and
+ inputs_to_give = list("One", null)
+ expected_outputs = list(FALSE)
+
+
+
+/datum/unit_test/integrated_circuits/or_1
+ name = "Logic Circuits: Or - True First"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/or
+ inputs_to_give = list("One", null)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/or_2
+ name = "Logic Circuits: Or - True Second"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/or
+ inputs_to_give = list(null, "Two")
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/or_3
+ name = "Logic Circuits: Or - True Both"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/or
+ inputs_to_give = list("One", "Two")
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/or_4
+ name = "Logic Circuits: Or - False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/or
+ inputs_to_give = list(null, null)
+ expected_outputs = list(FALSE)
+
+
+
+/datum/unit_test/integrated_circuits/less_than_1
+ name = "Logic Circuits: Less Than - True"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/less_than
+ inputs_to_give = list(50, 100)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/less_than_2
+ name = "Logic Circuits: Less Than - False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/less_than
+ inputs_to_give = list(500, 50)
+ expected_outputs = list(FALSE)
+
+
+
+/datum/unit_test/integrated_circuits/less_than_or_equal_1
+ name = "Logic Circuits: Less Than Or Equal - True 1"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/less_than_or_equal
+ inputs_to_give = list(40, 50)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/less_than_or_equal_2
+ name = "Logic Circuits: Less Than Or Equal - True 2"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/less_than_or_equal
+ inputs_to_give = list(40, 40)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/less_than_or_equal_3
+ name = "Logic Circuits: Less Than Or Equal - False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/less_than_or_equal
+ inputs_to_give = list(40, 30)
+ expected_outputs = list(FALSE)
+
+
+
+/datum/unit_test/integrated_circuits/greater_than_1
+ name = "Logic Circuits: Greater Than - True"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than
+ inputs_to_give = list(100, 50)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/greater_than_2
+ name = "Logic Circuits: Greater Than - False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than
+ inputs_to_give = list(25, 800)
+ expected_outputs = list(FALSE)
+
+
+
+/datum/unit_test/integrated_circuits/greater_than_or_equal_1
+ name = "Logic Circuits: Greater Than Or Equal - True 1"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than_or_equal
+ inputs_to_give = list(250, 30)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/greater_than_or_equal_2
+ name = "Logic Circuits: Greater Than Or Equal - True 2"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than_or_equal
+ inputs_to_give = list(30, 30)
+ expected_outputs = list(TRUE)
+
+/datum/unit_test/integrated_circuits/greater_than_or_equal_3
+ name = "Logic Circuits: Greater Than Or Equal - False"
+ circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than_or_equal
+ inputs_to_give = list(-40, 100)
+ expected_outputs = list(FALSE)
+
+
+
+/datum/unit_test/integrated_circuits/not_1
+ name = "Logic Circuits: Not - Invert to False"
+ circuit_type = /obj/item/integrated_circuit/logic/unary/not
+ inputs_to_give = list(1)
+ expected_outputs = list(0)
+
+/datum/unit_test/integrated_circuits/not_2
+ name = "Logic Circuits: Not - Invert to True"
+ circuit_type = /obj/item/integrated_circuit/logic/unary/not
+ inputs_to_give = list(0)
+ expected_outputs = list(1)
\ No newline at end of file
diff --git a/code/unit_tests/integrated_circuits/prefabs.dm b/code/unit_tests/integrated_circuits/prefabs.dm
new file mode 100644
index 0000000000..056c0d1568
--- /dev/null
+++ b/code/unit_tests/integrated_circuits/prefabs.dm
@@ -0,0 +1,55 @@
+/datum/unit_test/integrated_circuit_prefabs_shall_respect_complexity_and_size_contraints
+ name = "Integrated Circuit Prefabs Shall Respect Complexity and Size Constraints"
+
+/datum/unit_test/integrated_circuit_prefabs_shall_respect_complexity_and_size_contraints/start_test()
+ var/list/failed_prefabs = list()
+ for(var/prefab_type in subtypesof(/decl/prefab/ic_assembly))
+ var/decl/prefab/ic_assembly/prefab = decls_repository.get_decl(prefab_type)
+ var/obj/item/device/electronic_assembly/assembly = prefab.assembly_type
+
+ var/available_size = initial(assembly.max_components)
+ var/available_complexity = initial(assembly.max_complexity)
+ for(var/ic in prefab.integrated_circuits)
+ var/datum/ic_assembly_integrated_circuits/iaic = ic
+ var/obj/item/integrated_circuit/circuit = iaic.circuit_type
+ available_size -= initial(circuit.size)
+ available_complexity -= initial(circuit.complexity)
+ if(available_size < 0)
+ log_bad("[prefab_type] has an excess component size of [abs(available_size)]")
+ failed_prefabs |= prefab_type
+ if(available_complexity < 0)
+ log_bad("[prefab_type] has an excess component complexity of [abs(available_complexity)]")
+ failed_prefabs |= prefab_type
+
+ if(failed_prefabs.len)
+ fail("The following integrated prefab types are out of bounds: [english_list(failed_prefabs)]")
+ else
+ pass("All integrated circuit prefabs are within complexity and size limits.")
+
+ return 1
+
+/datum/unit_test/integrated_circuit_prefabs_shall_not_fail_to_create
+ name = "Integrated Circuit Prefabs Shall Not Fail To Create"
+
+/datum/unit_test/integrated_circuit_prefabs_shall_not_fail_to_create/start_test()
+ var/list/failed_prefabs = list()
+ for(var/prefab_type in subtypesof(/decl/prefab/ic_assembly))
+ var/decl/prefab/ic_assembly/prefab = decls_repository.get_decl(prefab_type)
+
+ try
+ var/built_item = prefab.create(get_standard_turf())
+ if(built_item)
+ qdel(built_item)
+ else
+ log_bad("[prefab_type] failed to create or return its item.")
+ failed_prefabs |= prefab_type
+ catch(var/exception/e)
+ log_bad("[prefab_type] caused an exception: [e] on [e.file]:[e.line]")
+ failed_prefabs |= prefab_type
+
+ if(failed_prefabs.len)
+ fail("The following integrated prefab types failed to create their assemblies: [english_list(failed_prefabs)]")
+ else
+ pass("All integrated circuit prefabs are within complexity and size limits.")
+
+ return 1
\ No newline at end of file
diff --git a/code/unit_tests/integrated_circuits/trig.dm b/code/unit_tests/integrated_circuits/trig.dm
new file mode 100644
index 0000000000..5ba351e2df
--- /dev/null
+++ b/code/unit_tests/integrated_circuits/trig.dm
@@ -0,0 +1,33 @@
+/datum/unit_test/integrated_circuits/floor/sine_1
+ name = "Trig Circuits: Sine - 1"
+ circuit_type = /obj/item/integrated_circuit/trig/sine
+ inputs_to_give = list(90)
+ expected_outputs = list(1)
+
+/datum/unit_test/integrated_circuits/floor/sine_2
+ name = "Trig Circuits: Sine - 2"
+ circuit_type = /obj/item/integrated_circuit/trig/sine
+ inputs_to_give = list(0)
+ expected_outputs = list(0)
+
+
+
+/datum/unit_test/integrated_circuits/floor/cosine_1
+ name = "Trig Circuits: Cosine - 1"
+ circuit_type = /obj/item/integrated_circuit/trig/cosine
+ inputs_to_give = list(90)
+ expected_outputs = list(0)
+
+/datum/unit_test/integrated_circuits/floor/cosine_2
+ name = "Trig Circuits: Cosine - 2"
+ circuit_type = /obj/item/integrated_circuit/trig/cosine
+ inputs_to_give = list(0)
+ expected_outputs = list(1)
+
+
+
+/datum/unit_test/integrated_circuits/floor/tangent_1
+ name = "Trig Circuits: Tangent - 1"
+ circuit_type = /obj/item/integrated_circuit/trig/tangent
+ inputs_to_give = list(45)
+ expected_outputs = list(1)
\ No newline at end of file
diff --git a/code/unit_tests/unit_test.dm b/code/unit_tests/unit_test.dm
index a090548623..f05514ce74 100644
--- a/code/unit_tests/unit_test.dm
+++ b/code/unit_tests/unit_test.dm
@@ -96,4 +96,13 @@ var/total_unit_tests = 0
world.Del()
else
log_unit_test("[ASCII_RED]!!! \[[failed_unit_tests]\\[total_unit_tests]\] Unit Tests Failed !!![ASCII_RESET]")
- world.Del()
\ No newline at end of file
+ world.Del()
+
+/datum/unit_test/proc/get_standard_turf()
+ return locate(20,20,1)
+
+/datum/unit_test/proc/log_bad(var/message)
+ log_unit_test("[ASCII_RED]\[[name]\]: [message][ASCII_RESET]")
+
+/datum/unit_test/proc/log_debug(var/message)
+ log_unit_test("[ASCII_YELLOW]--- DEBUG --- \[[name]\]: [message][ASCII_RESET]")
\ No newline at end of file
diff --git a/icons/obj/electronic_assemblies.dmi b/icons/obj/electronic_assemblies.dmi
index bd5263b7f3..8fd1c4f5e1 100644
Binary files a/icons/obj/electronic_assemblies.dmi and b/icons/obj/electronic_assemblies.dmi differ
diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi
index 9a32f79a4c..a725b4cc86 100644
Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ
diff --git a/polaris.dme b/polaris.dme
index db14ac1bd1..413a2fd1ca 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -879,6 +879,7 @@
#include "code\game\objects\items\weapons\implants\implant.dm"
#include "code\game\objects\items\weapons\implants\implantcase.dm"
#include "code\game\objects\items\weapons\implants\implantchair.dm"
+#include "code\game\objects\items\weapons\implants\implantcircuits.dm"
#include "code\game\objects\items\weapons\implants\implanter.dm"
#include "code\game\objects\items\weapons\implants\implantfreedom.dm"
#include "code\game\objects\items\weapons\implants\implantlanguage.dm"
@@ -1391,7 +1392,6 @@
#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"
@@ -1400,6 +1400,7 @@
#include "code\modules\integrated_electronics\reagents.dm"
#include "code\modules\integrated_electronics\time.dm"
#include "code\modules\integrated_electronics\tools.dm"
+#include "code\modules\integrated_electronics\trig.dm"
#include "code\modules\integrated_electronics\~defines.dm"
#include "code\modules\library\lib_items.dm"
#include "code\modules\library\lib_machines.dm"
@@ -2117,6 +2118,12 @@
#include "code\unit_tests\research_tests.dm"
#include "code\unit_tests\unit_test.dm"
#include "code\unit_tests\zas_tests.dm"
+#include "code\unit_tests\integrated_circuits\arithmetic.dm"
+#include "code\unit_tests\integrated_circuits\circuits.dm"
+#include "code\unit_tests\integrated_circuits\converter.dm"
+#include "code\unit_tests\integrated_circuits\data_transfer.dm"
+#include "code\unit_tests\integrated_circuits\logic.dm"
+#include "code\unit_tests\integrated_circuits\trig.dm"
#include "code\ZAS\_docs.dm"
#include "code\ZAS\Airflow.dm"
#include "code\ZAS\Atom.dm"