#define IC_INPUT "input"
#define IC_OUTPUT "output"
#define IC_ACTIVATOR "activator"
#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 = ITEMSIZE_TINY
var/extended_desc = null
var/list/inputs = list()
var/list/outputs = list()
var/list/activators = list()
var/next_use = 0 //Uses world.time
var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
var/cooldown_per_use = 1 SECOND
var/category = /obj/item/integrated_circuit // Used by the toolsets to filter out category types
/obj/item/integrated_circuit/examine(mob/user)
..()
to_chat(user, "This board has [inputs.len] input pin\s and [outputs.len] output pin\s.")
for(var/datum/integrated_io/input/I in inputs)
if(I.linked.len)
to_chat(user, "The [I] is connected to [I.get_linked_to_desc()].")
for(var/datum/integrated_io/output/O in outputs)
if(O.linked.len)
to_chat(user, "The [O] is connected to [O.get_linked_to_desc()].")
for(var/datum/integrated_io/activate/A in activators)
if(A.linked.len)
to_chat(user, "The [A] is connected to [A.get_linked_to_desc()].")
interact(user)
/obj/item/integrated_circuit/New()
setup_io(inputs, /datum/integrated_io/input)
setup_io(outputs, /datum/integrated_io/output)
setup_io(activators, /datum/integrated_io/activate)
..()
/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type)
var/list/io_list_copy = io_list.Copy()
io_list.Cut()
for(var/io_entry in io_list_copy)
io_list.Add(new io_type(src, io_entry, io_list_copy[io_entry]))
/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit.
return
/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/nano_host()
if(istype(src.loc, /obj/item/device/electronic_assembly))
return loc
return ..()
/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
if(!CanInteract(M, physical_state))
return
var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name) as null|text, MAX_NAME_LEN)
if(src && input && CanInteract(M, physical_state))
to_chat(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(IC_INPUT)
if(pin_number > inputs.len)
return null
return inputs[pin_number]
if(IC_OUTPUT)
if(pin_number > outputs.len)
return null
return outputs[pin_number]
if(IC_ACTIVATOR)
if(pin_number > activators.len)
return null
return activators[pin_number]
return null
/obj/item/integrated_circuit/interact(mob/user)
if(!CanInteract(user, physical_state))
return
var/HTML = list()
HTML += "
[src.name]"
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")
onclose(user, "circuit-\ref[src]")
/obj/item/integrated_circuit/Topic(href, href_list, state = physical_state)
if(..())
return 1
var/pin = locate(href_list["pin"]) in inputs + outputs + activators
var/obj/held_item = usr.get_active_hand()
if(href_list["wire"])
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(pin)
wirer.wire(pin, usr)
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, usr)
else
to_chat(usr, "You can't do a whole lot without the proper tools.")
if(href_list["examine"])
examine(usr)
if(href_list["rename"])
rename_component(usr)
if(href_list["remove"])
if(istype(held_item, /obj/item/weapon/screwdriver))
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "You pop \the [src] out of the case, and slide it out.")
else
to_chat(usr, "You need a screwdriver to remove components.")
var/obj/item/device/electronic_assembly/ea = loc
if(istype(ea))
ea.interact(usr)
return
interact(usr) // To refresh the UI.
/datum/integrated_io
var/name = "input/output"
var/obj/item/integrated_circuit/holder = null
var/weakref/data = null // This is a weakref, to reduce typecasts. Note that oftentimes numbers and text may also occupy this.
var/list/linked = list()
var/io_type = DATA_CHANNEL
/datum/integrated_io/New(var/newloc, var/name, var/data)
..()
src.name = name
src.data = data
holder = newloc
if(!istype(holder))
message_admins("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.")
/datum/integrated_io/Destroy()
disconnect()
data = null
holder = null
. = ..()
/datum/integrated_io/nano_host()
return holder
/datum/integrated_io/proc/data_as_type(var/as_type)
if(!isweakref(data))
return
var/weakref/w = data
var/output = w.resolve()
return istype(output, as_type) ? output : null
/datum/integrated_io/proc/display_data()
if(isnull(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(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 "([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))
write_data_to_pin(rand(-10000, 10000))
if(istext(data))
write_data_to_pin("ERROR")
push_data()
/datum/integrated_io/activate/scramble()
push_data()
/datum/integrated_io/proc/write_data_to_pin(var/new_data)
if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data)) // Anything else is a type we don't want.
data = new_data
holder.on_data_written()
/datum/integrated_io/proc/push_data()
for(var/datum/integrated_io/io in linked)
io.write_data_to_pin(data)
/datum/integrated_io/activate/push_data()
for(var/datum/integrated_io/io in linked)
io.holder.check_then_do_work()
/datum/integrated_io/proc/pull_data()
for(var/datum/integrated_io/io in linked)
write_data_to_pin(io.data)
/datum/integrated_io/proc/get_linked_to_desc()
if(linked.len)
return "the [english_list(linked)]"
return "nothing"
/datum/integrated_io/proc/disconnect()
//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/check_then_do_work()
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
next_use = world.time + cooldown_per_use
do_work()
/obj/item/integrated_circuit/proc/do_work()
return
/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()