Port Integrated Electronics from Polaris (#3371)

Ports Polaris' integrated electronics system, whichallows for Roboticists & Electricians/Engineers to build custom devices and machines for a variety of purposes.
This commit is contained in:
Lohikar
2017-09-12 21:41:39 -05:00
committed by GitHub
parent ee2c01c1ec
commit e28c29a551
77 changed files with 5240 additions and 43 deletions

View File

@@ -0,0 +1,67 @@
#define IC_INPUT "input"
#define IC_OUTPUT "output"
#define IC_ACTIVATOR "activator"
// Pin functionality.
#define DATA_CHANNEL "data channel"
#define PULSE_CHANNEL "pulse channel"
// Methods of obtaining a circuit. These are also defined in SSelectronics.
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
// Displayed along with the pin name to show what type of pin it is.
#define IC_FORMAT_ANY "\<ANY\>"
#define IC_FORMAT_STRING "\<TEXT\>"
#define IC_FORMAT_CHAR "\<CHAR\>"
#define IC_FORMAT_COLOR "\<COLOR\>"
#define IC_FORMAT_NUMBER "\<NUM\>"
#define IC_FORMAT_DIR "\<DIR\>"
#define IC_FORMAT_BOOLEAN "\<BOOL\>"
#define IC_FORMAT_REF "\<REF\>"
#define IC_FORMAT_LIST "\<LIST\>"
#define IC_FORMAT_PULSE "\<PULSE\>"
// Used inside input/output list to tell the constructor what pin to make.
#define IC_PINTYPE_ANY /datum/integrated_io
#define IC_PINTYPE_STRING /datum/integrated_io/string
#define IC_PINTYPE_CHAR /datum/integrated_io/char
#define IC_PINTYPE_COLOR /datum/integrated_io/color
#define IC_PINTYPE_NUMBER /datum/integrated_io/number
#define IC_PINTYPE_DIR /datum/integrated_io/dir
#define IC_PINTYPE_BOOLEAN /datum/integrated_io/boolean
#define IC_PINTYPE_REF /datum/integrated_io/ref
#define IC_PINTYPE_LIST /datum/integrated_io/list
#define IC_PINTYPE_PULSE_IN /datum/integrated_io/activate
#define IC_PINTYPE_PULSE_OUT /datum/integrated_io/activate/out
// Data limits.
#define IC_MAX_LIST_LENGTH 200
/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/obj/item/device/electronic_assembly/assembly // Reference to the assembly holding this circuit, if any.
var/extended_desc
var/list/inputs = list()
var/list/inputs_default = list() // Assoc list which will fill a pin with data upon creation. e.g. "2" = 0 will set input pin 2 to equal 0 instead of null.
var/list/outputs = list()
var/list/outputs_default = list() // Ditto, for output.
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/size //This acts as a limitation on building machines, bigger components cost more 'space'. -1 for size 0
var/cooldown_per_use = 1 SECOND // Circuits are limited in how many times they can be work()'d by this variable.
var/power_draw_per_use = 0 // How much power is drawn when work()'d.
var/power_draw_idle = 0 // How much power is drawn when doing nothing.
var/spawn_flags // Used for world initializing, see the #defines above.
var/category_text = "NO CATEGORY THIS IS A BUG" // To show up on circuit printer, and perhaps other places.
var/removable = TRUE // Determines if a circuit is removable from the assembly.
var/displayed_name = ""
var/allow_multitool = TRUE // Allows additional multitool functionality
// Used as a global var, (Do not set manually in children).

View File

@@ -0,0 +1,336 @@
#define IC_COMPONENTS_BASE 20
#define IC_COMPLEXITY_BASE 60
/obj/item/device/electronic_assembly
name = "electronic assembly"
desc = "It's a case, for building small electronics with."
w_class = ITEMSIZE_SMALL
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "setup_small"
var/max_components = IC_COMPONENTS_BASE
var/max_complexity = IC_COMPLEXITY_BASE
var/opened = 0
var/obj/item/weapon/cell/device/battery // Internal cell which most circuits need to work.
/obj/item/device/electronic_assembly/medium
name = "electronic mechanism"
icon_state = "setup_medium"
desc = "It's a case, for building medium-sized electronics with."
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"
desc = "It's a case, for building large electronics with."
w_class = ITEMSIZE_LARGE
max_components = IC_COMPONENTS_BASE * 4
max_complexity = IC_COMPLEXITY_BASE * 4
/obj/item/device/electronic_assembly/drone
name = "electronic drone"
icon_state = "setup_drone"
desc = "It's a case, for building mobile electronics with."
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"
desc = "It's a case, for building very tiny electronics with."
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/Initialize(mapload, printed = FALSE)
..()
if (!printed)
battery = new(src)
START_PROCESSING(SSelectronics, src)
/obj/item/device/electronic_assembly/Destroy()
QDEL_NULL(battery)
STOP_PROCESSING(SSelectronics, src)
return ..()
/obj/item/device/electronic_assembly/process()
handle_idle_power()
/obj/item/device/electronic_assembly/proc/handle_idle_power()
// First we generate power.
for(var/obj/item/integrated_circuit/passive/power/P in contents)
P.make_energy()
// Now spend it.
for(var/obj/item/integrated_circuit/IC in contents)
if(IC.power_draw_idle && !draw_power(IC.power_draw_idle))
IC.power_fail()
/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/proc/check_interactivity(mob/user)
if(!CanInteract(user, physical_state))
return 0
return 1
/obj/item/device/electronic_assembly/interact(mob/user)
if(!check_interactivity(user))
return
var/total_parts = 0
var/total_complexity = 0
for(var/obj/item/integrated_circuit/part in contents)
total_parts += part.size
total_complexity = total_complexity + part.complexity
var/list/HTML = list()
HTML += "<br><a href='?src=\ref[src]'>Refresh</a> | "
HTML += "<a href='?src=\ref[src];rename=1'>Rename</a><br>"
HTML += "[total_parts]/[max_components] ([round((total_parts / max_components) * 100, 0.1)]%) space taken up in the assembly.<br>"
HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.<br>"
if(battery)
HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. <a href='?src=\ref[src];remove_cell=1'>Remove</a>"
else
HTML += "<span class='danger'>No powercell detected!</span>"
HTML += "<br><br>"
HTML += "Components:<hr>"
HTML += "Built in:<br>"
//Put removable circuits in separate categories from non-removable
for(var/obj/item/integrated_circuit/circuit in contents)
if(!circuit.removable)
HTML += "<a href=?src=\ref[circuit];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
HTML += "<a href=?src=\ref[circuit];rename=1;from_assembly=1>Rename</a> | "
HTML += "<a href=?src=\ref[circuit];scan=1;from_assembly=1>Scan with Debugger</a> | "
HTML += "<a href=?src=\ref[circuit];bottom=\ref[circuit];from_assembly=1>Move to Bottom</a>"
HTML += "<br>"
HTML += "<hr>"
HTML += "Removable:<br>"
for(var/obj/item/integrated_circuit/circuit in contents)
if(circuit.removable)
HTML += "<a href=?src=\ref[circuit];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
HTML += "<a href=?src=\ref[circuit];rename=1;from_assembly=1>Rename</a> | "
HTML += "<a href=?src=\ref[circuit];scan=1;from_assembly=1>Scan with Debugger</a> | "
HTML += "<a href=?src=\ref[circuit];remove=1;from_assembly=1>Remove</a> | "
HTML += "<a href=?src=\ref[circuit];bottom=\ref[circuit];from_assembly=1>Move to Bottom</a>"
HTML += "<br>"
var/datum/browser/B = new(user, "assembly-\ref[src]", name, 600, 400)
B.set_content(HTML.Join())
B.open(FALSE)
/obj/item/device/electronic_assembly/Topic(href, href_list[])
if(..())
return 1
if(!opened)
to_chat(usr, "<span class='warning'>\The [src] is not open!</span>")
return
if(href_list["rename"])
rename(usr)
if(href_list["remove_cell"])
if(!battery)
to_chat(usr, "<span class='warning'>There's no power cell to remove from \the [src].</span>")
else
var/turf/T = get_turf(src)
battery.forceMove(T)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pull \the [battery] out of \the [src]'s power supply.</span>")
battery = null
interact(usr) // To refresh the UI.
/obj/item/device/electronic_assembly/verb/rename()
set name = "Rename Circuit"
set category = "Object"
set desc = "Rename your circuit, useful to stay organized."
var/mob/M = usr
if(!check_interactivity(M))
return
var/input = sanitizeSafe(input("What do you want to name this?", "Rename", src.name) as null|text, MAX_NAME_LEN)
if(src && input)
to_chat(M, "<span class='notice'>The machine now has a label reading '[input]'.</span>")
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"
else
icon_state = initial(icon_state)
/obj/item/device/electronic_assembly/GetAccess()
. = list()
for(var/obj/item/integrated_circuit/part in contents)
. |= part.GetAccess()
/obj/item/device/electronic_assembly/examine(mob/user)
. = ..(user, 1)
if(.)
for(var/obj/item/integrated_circuit/IC in contents)
IC.external_examine(user)
if(opened)
interact(user)
/obj/item/device/electronic_assembly/proc/get_part_complexity()
. = 0
for(var/obj/item/integrated_circuit/part in contents)
. += part.complexity
/obj/item/device/electronic_assembly/proc/get_part_size()
. = 0
for(var/obj/item/integrated_circuit/part in contents)
. += part.size
// Returns true if the circuit made it inside.
/obj/item/device/electronic_assembly/proc/add_circuit(obj/item/integrated_circuit/IC, mob/user)
if(!opened)
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
return FALSE
if(IC.w_class > w_class)
to_chat(user, "<span class='warning'>\The [IC] is way too big to fit into \the [src].</span>")
return FALSE
var/total_part_size = get_part_size()
var/total_complexity = get_part_complexity()
if((total_part_size + IC.size) > max_components)
to_chat(user, "<span class='warning'>You can't seem to add the '[IC.name]', as there's insufficient space.</span>")
return FALSE
if((total_complexity + IC.complexity) > max_complexity)
to_chat(user, "<span class='warning'>You can't seem to add the '[IC.name]', since this setup's too complicated for the case.</span>")
return FALSE
if(!IC.forceMove(src))
return FALSE
IC.assembly = src
return TRUE
/obj/item/device/electronic_assembly/afterattack(atom/target, mob/user, proximity)
if(proximity)
var/scanned = FALSE
for(var/obj/item/integrated_circuit/input/sensor/S in contents)
if(S.scan(target))
scanned = TRUE
if(scanned)
visible_message("<span class='notice'>\The [user] waves \the [src] around [target].</span>")
/obj/item/device/electronic_assembly/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/integrated_circuit))
if(!user.unEquip(I))
return FALSE
if(add_circuit(I, user))
to_chat(user, "<span class='notice'>You slide \the [I] inside \the [src].</span>")
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
interact(user)
return TRUE
else if(istype(I, /obj/item/weapon/crowbar))
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
opened = !opened
to_chat(user, "<span class='notice'>You [opened ? "open" : "close"] \the [src].</span>")
update_icon()
return TRUE
else if(istype(I, /obj/item/device/integrated_electronics/wirer) || istype(I, /obj/item/device/integrated_electronics/debugger) || istype(I, /obj/item/weapon/screwdriver))
if(opened)
interact(user)
else
to_chat(user, "<span class='warning'>\The [src] isn't open, so you can't fiddle with the internal components. \
Try using a crowbar.</span>")
else if(istype(I, /obj/item/weapon/cell/device))
if(!opened)
to_chat(user, "<span class='warning'>\The [src] isn't open, so you can't put anything inside. Try using a crowbar.</span>")
return FALSE
if(battery)
to_chat(user, "<span class='warning'>\The [src] already has \a [battery] inside. Remove it first if you want to replace it.</span>")
return FALSE
var/obj/item/weapon/cell/device/cell = I
user.drop_item(cell)
cell.forceMove(src)
battery = cell
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "<span class='notice'>You slot \the [cell] inside \the [src]'s power supply.</span>")
interact(user)
return TRUE
else
return ..()
/obj/item/device/electronic_assembly/attack_self(mob/user)
if(!check_interactivity(user))
return
if(opened)
interact(user)
var/list/input_selection = list()
var/list/available_inputs = list()
for(var/obj/item/integrated_circuit/input/input in contents)
if(input.can_be_asked_input)
available_inputs.Add(input)
var/i = 0
for(var/obj/item/integrated_circuit/s in available_inputs)
if(s.name == input.name && s.displayed_name == input.displayed_name && s != input)
i++
var/disp_name= "[input.displayed_name] \[[input.name]\]"
if(i)
disp_name += " ([i+1])"
input_selection.Add(disp_name)
var/obj/item/integrated_circuit/input/choice
if(available_inputs)
var/selection = input(user, "What do you want to interact with?", "Interaction") as null|anything in input_selection
if(selection)
var/index = input_selection.Find(selection)
choice = available_inputs[index]
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)
// Returns true if power was successfully drawn.
/obj/item/device/electronic_assembly/proc/draw_power(amount)
if(battery && battery.checked_use(amount * CELLRATE))
return TRUE
return FALSE
// Ditto for giving.
/obj/item/device/electronic_assembly/proc/give_power(amount)
if(battery && battery.give(amount * CELLRATE))
return TRUE
return FALSE

View File

@@ -0,0 +1,81 @@
/obj/item/device/assembly/electronic_assembly
name = "electronic device"
desc = "It's a case for building electronics with. It can be attached to other small devices."
icon_state = "setup_device"
var/opened = 0
var/obj/item/device/electronic_assembly/device/EA
/obj/item/device/assembly/electronic_assembly/Initialize()
EA = new(src)
EA.holder = src
. = ..()
/obj/item/device/assembly/electronic_assembly/attackby(obj/item/I, mob/user)
if (iscrowbar(I))
toggle_open(user)
else if (opened)
EA.attackby(I, user)
else
..()
/obj/item/device/assembly/electronic_assembly/proc/toggle_open(mob/user)
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
opened = !opened
EA.opened = opened
to_chat(user, "<span class='notice'>You [opened ? "open" : "close"] \the [src].</span>")
secured = 1
update_icon()
/obj/item/device/assembly/electronic_assembly/update_icon()
if(EA)
icon_state = initial(icon_state)
else
icon_state = "[initial(icon_state)]0"
if(opened)
icon_state = "[icon_state]-open"
/obj/item/device/assembly/electronic_assembly/attack_self(mob/user as mob)
if(EA)
EA.attack_self(user)
//Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
/obj/item/device/assembly/electronic_assembly/pulsed(radio = 0)
if(EA)
for(var/obj/item/integrated_circuit/built_in/device_input/I in EA.contents)
I.do_work()
/obj/item/device/assembly/electronic_assembly/examine(mob/user)
. = ..(user, 1)
if(EA)
for(var/obj/item/integrated_circuit/IC in EA.contents)
IC.external_examine(user)
/obj/item/device/assembly/electronic_assembly/verb/toggle()
set src in usr
set category = "Object"
set name = "Open/Close Device Assembly"
set desc = "Open or close device assembly!"
toggle_open(usr)
/obj/item/device/electronic_assembly/device
name = "electronic device"
icon_state = "setup_device"
desc = "It's a tiny electronic device with specific use for attaching to other devices."
var/obj/item/device/assembly/electronic_assembly/holder
w_class = ITEMSIZE_TINY
max_components = IC_COMPONENTS_BASE * 3/4
max_complexity = IC_COMPLEXITY_BASE * 3/4
/obj/item/device/electronic_assembly/device/Initialize()
. = ..()
var/obj/item/integrated_circuit/built_in/device_input/input = new(src)
var/obj/item/integrated_circuit/built_in/device_output/output = new(src)
input.assembly = src
output.assembly = src
/obj/item/device/electronic_assembly/device/check_interactivity(mob/user)
if(!CanInteract(user, state = deep_inventory_state))
return 0
return 1

View File

@@ -0,0 +1,78 @@
/obj/item/integrated_circuit/proc/setup_io(list/io_list, io_type, list/io_default_list)
var/list/io_list_copy = io_list.Copy()
io_list.Cut()
var/i = 0
for(var/io_entry in io_list_copy)
var/default_data = null
var/io_type_override = null
// Override the default data.
if(LAZYLEN(io_default_list)) // List containing special pin types that need to be added.
default_data = io_default_list["[i]"] // This is deliberately text because the index is a number in text form.
// Override the pin type.
if(io_list_copy[io_entry])
io_type_override = io_list_copy[io_entry]
if(io_type_override)
io_list += new io_type_override(src, io_entry, default_data)
else
io_list += new io_type(src, io_entry, default_data)
/obj/item/integrated_circuit/proc/set_pin_data(pin_type, pin_number, datum/new_data)
if (istype(new_data) && !isweakref(new_data))
PROCLOG_WEIRD("converting hardref to [DEBUG_REF(new_data)] into weakref.")
new_data = WEAKREF(new_data)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
if (!pin)
CRASH("Invalid pin ref.")
return pin.write_data_to_pin(new_data)
/obj/item/integrated_circuit/proc/get_pin_data(pin_type, pin_number)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
return pin.get_data()
/obj/item/integrated_circuit/proc/get_pin_data_as_type(pin_type, pin_number, as_type)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
return pin.data_as_type(as_type)
/obj/item/integrated_circuit/proc/activate_pin(pin_number)
var/datum/integrated_io/activate/A = activators[pin_number]
A.push_data()
/datum/integrated_io/proc/get_data()
if(isnull(data))
return
if(isweakref(data))
return data.resolve()
return data
/obj/item/integrated_circuit/proc/get_pin_ref(pin_type, 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/proc/handle_wire(datum/integrated_io/pin, obj/item/device/integrated_electronics/tool)
if(istype(tool, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = tool
if(pin)
wirer.wire(pin, usr)
return 1
else if(istype(tool, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = tool
if(pin)
debugger.write_data(pin, usr)
return 1
return 0

View File

@@ -0,0 +1,355 @@
/*
Integrated circuits are essentially modular machines. Each circuit has a specific function, and combining them inside Electronic Assemblies allows
a creative player the means to solve many problems. Circuits are held inside an electronic assembly, and are wired using special tools.
*/
/obj/item/integrated_circuit/examine(mob/user)
interact(user)
external_examine(user)
. = ..()
// This should be used when someone is examining while the case is opened.
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
to_chat(user, "This board has [inputs.len] input pin\s, [outputs.len] output pin\s and [activators.len] activation pin\s.")
for(var/datum/integrated_io/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/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()].")
any_examine(user)
interact(user)
// This should be used when someone is examining from an 'outside' perspective, e.g. reading a screen or LED.
/obj/item/integrated_circuit/proc/external_examine(mob/user)
any_examine(user)
/obj/item/integrated_circuit/proc/any_examine(mob/user)
return
/obj/item/integrated_circuit/Initialize()
displayed_name = name
if(!size)
size = w_class
if(size == -1)
size = 0
setup_io(inputs, /datum/integrated_io, inputs_default)
setup_io(outputs, /datum/integrated_io, outputs_default)
setup_io(activators, /datum/integrated_io/activate)
. = ..()
/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))
var/obj/item/device/electronic_assembly/assembly = loc
return assembly.resolve_nano_host()
return ..()
/obj/item/integrated_circuit/emp_act(severity)
for(var/datum/integrated_io/io in inputs + outputs + activators)
io.scramble()
/obj/item/integrated_circuit/proc/check_interactivity(mob/user)
if(assembly)
return assembly.check_interactivity(user)
else if(!CanInteract(user, physical_state))
return 0
return 1
/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(!check_interactivity(M))
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 && assembly.check_interactivity(M))
to_chat(M, "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>")
displayed_name = input
/obj/item/integrated_circuit/interact(mob/user)
if(!check_interactivity(user))
return
var/window_height = 350
var/window_width = 600
var/table_edge_width = "30%"
var/table_middle_width = "40%"
var/list/HTML = list(
"<div align='center'>",
"<table border='1' style='undefined;table-layout: fixed; width: 80%'>",
"<br><a href='?src=\ref[src];return=1'>Return to Assembly</a>",
"<br><a href='?src=\ref[src];'>Refresh</a> | ",
"<a href='?src=\ref[src];rename=1'>Rename</a> | ",
"<a href='?src=\ref[src];scan=1'>Scan with Device</a> | "
)
if(src.removable)
HTML += "<a href='?src=\ref[src];remove=1'>Remove</a><br>"
HTML += "<colgroup>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "<col style='width: [table_middle_width]'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "</colgroup>"
var/column_width = 3
var/row_height = max(inputs.len, outputs.len, 1)
for(var/i = 1 to row_height)
HTML += "<tr>"
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = list()
var/height = 1
switch(j)
if(1)
io = get_pin_ref(IC_INPUT, i)
if(io)
words += "<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]>[io.display_pin_type()] [io.name]</a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]>[linked.name]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder.displayed_name]</a><br>"
if(outputs.len > inputs.len)
height = 1
if(2)
if(i == 1)
words += "[src.displayed_name]<br>[src.name != src.displayed_name ? "([src.name])":""]<hr>[src.desc]"
height = row_height
else
continue
if(3)
io = get_pin_ref(IC_OUTPUT, i)
if(io)
words += "<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]>[io.display_pin_type()] [io.name]</a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]>[linked.name]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder.displayed_name]</a><br>"
if(inputs.len > outputs.len)
height = 1
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
HTML += "</tr>"
for(var/activator in activators)
var/datum/integrated_io/io = activator
var/words = list(
"<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]><span class='bad'>[io.name]</span></a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]><span class='bad'>[io.data?"\<PULSE OUT\>":"\<PULSE IN\>"]</span></a></b><br>"
)
if(io.linked.len)
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]><span class='bad'>[linked.name]</span></a> \
@ <a href=?src=\ref[linked.holder];examine=1;><span class='bad'>[linked.holder.displayed_name]</span></a><br>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
HTML += "</tr>"
HTML += "</table>"
HTML += "</div>"
// HTML += "<br><font color='33CC33'>Meta Variables;</font>" // If more meta vars get introduced, uncomment this.
// HTML += "<br>"
HTML += "<br><span class='highlight'>Complexity: [complexity]</span>"
if(power_draw_idle)
HTML += "<br><span class='highlight'>Power Draw: [power_draw_idle] W (Idle)</span>"
if(power_draw_per_use)
HTML += "<br><span class='highlight'>Power Draw: [power_draw_per_use] W (Active)</span>" // Borgcode says that powercells' checked_use() takes joules as input.
HTML += "<br><span class='highlight'>[extended_desc]</span>"
var/datum/browser/B = new(user, assembly ? "assembly-\ref[assembly]" : "circuit-\ref[src]", (displayed_name && displayed_name != name) ? "[displayed_name] ([name])" : name, window_width, window_height)
B.set_content(HTML.Join())
B.open()
/obj/item/integrated_circuit/Topic(href, href_list, state = interactive_state)
if(!check_interactivity(usr))
return
if (assembly && !assembly.opened)
to_chat(usr, "<span class='warning'>\The [assembly] is not open!</span>")
return
if(..())
return 1
var/update = 1
var/obj/item/device/electronic_assembly/A = src.assembly
var/update_to_assembly = 0
var/datum/integrated_io/pin = locate(href_list["pin"]) in inputs + outputs + activators
var/datum/integrated_io/linked = null
if(href_list["link"])
linked = locate(href_list["link"]) in pin.linked
var/obj/held_item = usr.get_active_hand()
if(href_list["rename"])
rename_component(usr)
if(href_list["from_assembly"])
update = 0
var/obj/item/device/electronic_assembly/ea = loc
if(istype(ea))
ea.interact(usr)
if(href_list["pin_name"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = 1
else
var/obj/item/device/multitool/M = held_item
M.wire(pin,usr)
if(href_list["pin_data"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = 1
else
var/datum/integrated_io/io = pin
io.ask_for_pin_data(usr) // The pins themselves will determine how to ask for data, and will validate the data.
if(href_list["pin_unwire"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = 1
else
var/obj/item/device/multitool/M = held_item
M.unwire(pin, linked, usr)
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(linked)
wirer.wire(linked, usr)
else 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, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
if(href_list["examine"])
var/obj/item/integrated_circuit/examined
if(href_list["examined"])
examined = href_list["examined"]
else
examined = src
examined.interact(usr)
update = 0
if(href_list["bottom"])
var/obj/item/integrated_circuit/circuit = locate(href_list["bottom"]) in src.assembly.contents
var/assy = circuit.assembly
if(!circuit)
return
circuit.loc = null
circuit.loc = assy
. = 1
update_to_assembly = 1
if(href_list["scan"])
if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/D = held_item
if(D.accepting_refs)
D.afterattack(src, usr, TRUE)
else
to_chat(usr, "<span class='warning'>The Debugger's 'ref scanner' needs to be on.</span>")
else
to_chat(usr, "<span class='warning'>You need a multitool/debugger set to 'ref' mode to do that.</span>")
if(href_list["return"])
if(A)
update_to_assembly = 1
usr << browse(null, "window=circuit-\ref[src]")
else
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
if(href_list["remove"])
if(!A)
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
return
if(!removable)
to_chat(usr, "<span class='warning'>\The [src] seems to be permanently attached to the case.</span>")
return
var/obj/item/device/electronic_assembly/ea = loc
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
assembly = null
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
if(istype(ea))
ea.interact(usr)
update = 0
return
if(update)
if(istype(A) && update_to_assembly)
A.interact(usr)
else
interact(usr) // To refresh the UI.
/obj/item/integrated_circuit/proc/push_data()
for(var/datum/integrated_io/O in outputs)
O.push_data()
/obj/item/integrated_circuit/proc/pull_data()
for(var/datum/integrated_io/I in inputs)
I.push_data()
/obj/item/integrated_circuit/proc/draw_idle_power()
if(assembly)
return assembly.draw_power(power_draw_idle)
// Override this for special behaviour when there's no power left.
/obj/item/integrated_circuit/proc/power_fail()
return
// Returns true if there's enough power to work().
/obj/item/integrated_circuit/proc/check_power()
if(!assembly)
return FALSE // Not in an assembly, therefore no power.
if(assembly.draw_power(power_draw_per_use))
return TRUE // Battery has enough.
return FALSE // Not enough power.
/obj/item/integrated_circuit/proc/check_then_do_work(ignore_power = FALSE)
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
if(power_draw_per_use && !ignore_power)
if(!check_power())
power_fail()
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/I in inputs)
I.disconnect()
for(var/datum/integrated_io/O in outputs)
O.disconnect()
for(var/datum/integrated_io/activate/A in activators)
A.disconnect()

View File

@@ -0,0 +1,188 @@
/*
Pins both hold data for circuits, as well move data between them. Some also cause circuits to do their function. DATA_CHANNEL pins are the data holding/moving kind,
where as PULSE_CHANNEL causes circuits to work() when their pulse hits them.
A visualization of how pins work is below. Imagine the below image involves an addition circuit.
When the bottom pin, the activator, receives a pulse, all the numbers on the left (input) get added, and the answer goes on the right side (output).
Inputs Outputs
A [2]\ /[8] result
B [1]-\|++|/
C [4]-/|++|
D [1]/ ||
||
Activator
*/
/datum/integrated_io
var/name = "input/output"
var/obj/item/integrated_circuit/holder = null
var/datum/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/new_data)
..()
src.name = name
if(new_data)
src.data = new_data
holder = newloc
if(!istype(holder))
message_admins("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.")
log_debug("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.nano_host()
/datum/integrated_io/proc/data_as_type(var/as_type)
if(!isweakref(data))
return
var/datum/weakref/w = data
var/output = w.resolve()
return istype(output, as_type) ? output : null
/datum/integrated_io/proc/display_data(var/input)
if(isnull(input))
return "(null)" // Empty data means nothing to show.
if(istext(input))
return "(\"[input]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'.
/*
list[](
"A",
"B",
"C"
)
*/
if(islist(input))
var/list/my_list = input
var/result = "list\[[my_list.len]\]("
if(my_list.len)
result += "<br>"
var/pos = 0
for(var/line in my_list)
result += "[display_data(line)]"
pos++
if(pos != my_list.len)
result += ",<br>"
result += "<br>"
result += ")"
return result
if(isweakref(input))
var/datum/weakref/w = input
var/atom/A = w.resolve()
//return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed.
return A ? "(\ref[A] \[Ref\])" : "(null)"
return "([input])" // Nothing special needed for numbers or other stuff.
/datum/integrated_io/activate/display_data()
return "(\[pulse\])"
/datum/integrated_io/proc/display_pin_type()
return IC_FORMAT_ANY
/datum/integrated_io/activate/display_pin_type()
return IC_FORMAT_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 -= src
//Now that we're removed from them, we gotta remove them from us.
linked -= their_io
/datum/integrated_io/proc/ask_for_data_type(mob/user, var/default, var/list/allowed_data_types = list("string","number","null"))
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in allowed_data_types
if(!holder.check_interactivity(user))
return
var/new_data = null
switch(type_to_use)
if("string")
new_data = sanitize(input("Now type in a string.","[src] string writing", istext(default) ? default : null) as null|text)
if(istext(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
return new_data
if("number")
new_data = input("Now type in a number.","[src] number writing", isnum(default) ? default : null) as null|num
if(isnum(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
return new_data
if("null")
if(holder.check_interactivity(user))
to_chat(user, "<span class='notice'>You clear the pin's memory.</span>")
return new_data
// Basically a null check
/datum/integrated_io/proc/is_valid()
return !isnull(data)
// This proc asks for the data to write, then writes it.
/datum/integrated_io/proc/ask_for_pin_data(mob/user)
var/new_data = ask_for_data_type(user)
write_data_to_pin(new_data)
/datum/integrated_io/activate/ask_for_pin_data(mob/user) // This just pulses the pin.
holder.check_then_do_work(ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [holder]'s [src] pin.</span>")
/datum/integrated_io/activate
name = "activation pin"
io_type = PULSE_CHANNEL
/datum/integrated_io/activate/out // All this does is just make the UI say 'out' instead of 'in'
data = 1

View File

@@ -0,0 +1,159 @@
/obj/item/device/integrated_circuit_printer
name = "integrated circuit printer"
desc = "A portable(ish) machine made to print tiny modular circuitry out of metal."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "circuit_printer"
w_class = ITEMSIZE_LARGE
var/metal = 0
var/max_metal = 100
var/metal_per_sheet = 10 // One sheet equals this much metal.
var/upgraded = FALSE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits.
var/can_clone = FALSE // Same for above, but will allow the printer to duplicate a specific assembly.
var/current_category
var/obj/item/device/electronic_assembly/assembly_to_clone
/obj/item/device/integrated_circuit_printer/upgraded
upgraded = TRUE
can_clone = TRUE
/obj/item/device/integrated_circuit_printer/attackby(var/obj/item/O, var/mob/user)
if(istype(O,/obj/item/stack/material))
var/obj/item/stack/material/stack = O
if(stack.material.name == DEFAULT_WALL_MATERIAL)
var/num = min((max_metal - metal) / metal_per_sheet, stack.amount)
if(num < 1)
to_chat(user, "<span class='warning'>\The [src] is too full to add more metal.</span>")
return
if(stack.use(num))
to_chat(user, "<span class='notice'>You add [num] sheet\s to \the [src].</span>")
metal += num * metal_per_sheet
interact(user)
return TRUE
if(istype(O,/obj/item/integrated_circuit))
to_chat(user, "<span class='notice'>You insert the circuit into \the [src]. </span>")
user.unEquip(O)
metal = min(metal + O.w_class, max_metal)
qdel(O)
interact(user)
return TRUE
if(istype(O,/obj/item/weapon/disk/integrated_circuit/upgrade/advanced))
if(upgraded)
to_chat(user, "<span class='warning'>\The [src] already has this upgrade. </span>")
return TRUE
to_chat(user, "<span class='notice'>You install \the [O] into \the [src]. </span>")
upgraded = TRUE
interact(user)
return TRUE
if(istype(O,/obj/item/weapon/disk/integrated_circuit/upgrade/clone))
if(can_clone)
to_chat(user, "<span class='warning'>\The [src] already has this upgrade. </span>")
return TRUE
to_chat(user, "<span class='notice'>You install \the [O] into \the [src]. </span>")
can_clone = TRUE
interact(user)
return TRUE
return ..()
/obj/item/device/integrated_circuit_printer/attack_self(var/mob/user)
interact(user)
/obj/item/device/integrated_circuit_printer/interact(mob/user)
var/window_height = 600
var/window_width = 500
if(isnull(current_category))
current_category = SSelectronics.printer_recipe_list[1]
var/HTML = "<center><h2>Integrated Circuit Printer</h2></center><br>"
HTML += "Metal: [metal/metal_per_sheet]/[max_metal/metal_per_sheet] sheets.<br>"
HTML += "Circuits available: [upgraded ? "Regular":"Advanced"]."
HTML += "Assembly Cloning: [can_clone ? "Available": "Unavailable"]."
if(assembly_to_clone)
HTML += "Assembly '[assembly_to_clone.name]' loaded."
HTML += "Crossed out circuits mean that the printer is not sufficentally upgraded to create that circuit.<br>"
HTML += "<hr>"
HTML += "Categories:"
for(var/category in SSelectronics.printer_recipe_list)
if(category != current_category)
HTML += " <a href='?src=\ref[src];category=[category]'>[category]</a> "
else // Bold the button if it's already selected.
HTML += " <b>[category]</b> "
HTML += "<hr>"
HTML += "<center><h4>[current_category]</h4></center>"
var/list/current_list = SSelectronics.printer_recipe_list[current_category]
for(var/obj/O in current_list)
var/can_build = TRUE
if(istype(O, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = O
if((IC.spawn_flags & IC_SPAWN_RESEARCH) && (!(IC.spawn_flags & IC_SPAWN_DEFAULT)) && !upgraded)
can_build = FALSE
if(can_build)
HTML += "<A href='?src=\ref[src];build=[O.type]'>[O.name]</A>: [O.desc]<br>"
else
HTML += "<s>[O.name]: [O.desc]</s><br>"
var/datum/browser/B = new(user, "integrated_printer", null, window_width, window_height)
B.set_content(HTML)
B.open(FALSE)
/obj/item/device/integrated_circuit_printer/Topic(href, href_list)
if(..())
return 1
add_fingerprint(usr)
if(href_list["category"])
current_category = href_list["category"]
if(href_list["build"])
var/build_type = text2path(href_list["build"])
if(!build_type || !ispath(build_type))
return 1
var/cost = 1
var/is_asm = FALSE
if(ispath(build_type, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/E = build_type
cost = round( (initial(E.max_complexity) + initial(E.max_components) ) / 4)
is_asm = TRUE
else if(ispath(build_type, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = build_type
cost = initial(IC.w_class)
if(metal - cost < 0)
to_chat(usr, "<span class='warning'>You need [cost] metal to build that!.</span>")
return 1
metal -= cost
if (is_asm)
new build_type(get_turf(loc), TRUE)
else
new build_type(get_turf(loc))
interact(usr)
// FUKKEN UPGRADE DISKS
/obj/item/weapon/disk/integrated_circuit/upgrade
name = "integrated circuit printer upgrade disk"
desc = "Install this into your integrated circuit printer to enhance it."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "upgrade_disk"
item_state = "card-id"
w_class = ITEMSIZE_SMALL
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4)
/obj/item/weapon/disk/integrated_circuit/upgrade/advanced
name = "integrated circuit printer upgrade disk - advanced designs"
desc = "Install this into your integrated circuit printer to enhance it. This one adds new, advanced designs to the printer."
// To be implemented later.
/obj/item/weapon/disk/integrated_circuit/upgrade/clone
name = "integrated circuit printer upgrade disk - circuit cloner"
desc = "Install this into your integrated circuit printer to enhance it. This one allows the printer to duplicate assemblies."
icon_state = "upgrade_disk_clone"
origin_tech = list(TECH_ENGINEERING = 5, TECH_DATA = 6)

View File

@@ -0,0 +1,25 @@
// These pins only contain 0 or 1. Null is not allowed.
/datum/integrated_io/boolean
name = "boolean pin"
data = FALSE
/datum/integrated_io/boolean/ask_for_pin_data(mob/user) // 'Ask' is a bit misleading, acts more like a toggle.
var/new_data = !data
write_data_to_pin(new_data)
/datum/integrated_io/boolean/write_data_to_pin(var/new_data)
if(new_data == FALSE || new_data == TRUE)
data = new_data
holder.on_data_written()
/datum/integrated_io/boolean/scramble()
write_data_to_pin(rand(FALSE,TRUE))
push_data()
/datum/integrated_io/boolean/display_pin_type()
return IC_FORMAT_BOOLEAN
/datum/integrated_io/boolean/display_data(var/input)
if(data == TRUE)
return "(True)"
return "(False)"

View File

@@ -0,0 +1,27 @@
// These pins can only contain a 1 character string or null.
/datum/integrated_io/char
name = "char pin"
/datum/integrated_io/char/ask_for_pin_data(mob/user)
var/new_data = sanitize(input("Please type in one character.","[src] char writing") as null|text)
if(holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data ? "'[new_data]'" : "NULL"] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/char/write_data_to_pin(var/new_data)
if(isnull(new_data) || istext(new_data))
if(length(new_data) > 1)
return
data = new_data
holder.on_data_written()
// This makes the text go from "A" to "%".
/datum/integrated_io/char/scramble()
if(!is_valid())
return
var/list/options = list("!","@","#","$","%","^","&","*") + alphabet_uppercase
data = pick(options)
push_data()
/datum/integrated_io/char/display_pin_type()
return IC_FORMAT_CHAR

View File

@@ -0,0 +1,44 @@
// These pins can only contain a color (in the form of #FFFFFF) or null.
/datum/integrated_io/color
name = "color pin"
/datum/integrated_io/color/ask_for_pin_data(mob/user)
var/new_data = input("Please select a color.","[src] color writing") as null|color
if(holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input a <font color='[new_data]'>new color</font> into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/color/write_data_to_pin(new_data)
// Since this is storing the color as a string hex color code, we need to make sure it's actually one.
if(isnull(new_data) || istext(new_data))
if(istext(new_data))
new_data = uppertext(new_data)
if(length(new_data) != 7) // We can hex if we want to, we can leave your strings behind
return // Cause your strings don't hex and if they don't hex
var/friends = copytext(new_data, 2, 8) // Well they're are no strings of mine
// I say, we can go where we want to, a place where they will never find
var/safety_dance = 1
while(safety_dance >= 7) // And we can act like we come from out of this world.log
var/hex = copytext(friends, safety_dance, safety_dance+1)
if(!(hex in list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")))
return // Leave the fake one far behind,
safety_dance++
data = new_data // And we can hex
holder.on_data_written()
// This randomizes the color.
/datum/integrated_io/color/scramble()
if(!is_valid())
return
var/new_data = get_random_colour(simple = FALSE, lower = 0, upper = 255)
data = new_data
push_data()
/datum/integrated_io/color/display_pin_type()
return IC_FORMAT_COLOR
/datum/integrated_io/color/display_data(input)
if(!isnull(data))
return "(<font color='[data]'>[data]</font>)"
return ..()

View File

@@ -0,0 +1,33 @@
// These pins can only contain directions (1,2,4,8...) or null.
/datum/integrated_io/dir
name = "dir pin"
/datum/integrated_io/dir/ask_for_pin_data(mob/user)
var/new_data = input("Please type in a valid dir number. \
Valid dirs are;\n\
North/Fore = [NORTH],\n\
South/Aft = [SOUTH],\n\
East/Starboard = [EAST],\n\
West/Port = [WEST],\n\
Northeast = [NORTHEAST],\n\
Northwest = [NORTHWEST],\n\
Southeast = [SOUTHEAST],\n\
Southwest = [SOUTHWEST],\n\
Up = [UP],\n\
Down = [DOWN]","[src] dir writing") as null|num
if(isnum(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/dir/write_data_to_pin(var/new_data)
if(isnull(new_data) || new_data in alldirs + list(UP, DOWN))
data = new_data
holder.on_data_written()
/datum/integrated_io/dir/display_pin_type()
return IC_FORMAT_DIR
/datum/integrated_io/dir/display_data(var/input)
if(!isnull(data))
return "([dir2text(data)])"
return ..()

View File

@@ -0,0 +1,149 @@
// These pins contain a list. Null is not allowed.
/datum/integrated_io/list
name = "list pin"
data = list()
/datum/integrated_io/list/ask_for_pin_data(mob/user)
interact(user)
/datum/integrated_io/list/proc/interact(mob/user)
var/list/my_list = data
var/t = "<h2>[src]</h2><br>"
t += "List length: [my_list.len]<br>"
t += "<a href='?src=\ref[src]'>Refresh</a> | "
t += "<a href='?src=\ref[src];add=1'>Add</a> | "
t += "<a href='?src=\ref[src];swap=1'>Swap</a> | "
t += "<a href='?src=\ref[src];clear=1'>Clear</a><br>"
t += "<hr>"
var/i = 0
for(var/line in my_list)
i++
t += "#[i] | [display_data(line)] | "
t += "<a href='?src=\ref[src];edit=1;pos=[i]'>Edit</a> | "
t += "<a href='?src=\ref[src];remove=1;pos=[i]'>Remove</a><br>"
var/datum/browser/B = new(user, "list_pin_\ref[src]", null, 500, 400)
B.set_content(t)
B.open(FALSE)
/datum/integrated_io/list/proc/add_to_list(mob/user, new_entry)
if(!new_entry && user)
new_entry = ask_for_data_type(user)
if(is_valid(new_entry))
Add(new_entry)
/datum/integrated_io/list/proc/Add(new_entry)
var/list/my_list = data
if(my_list.len > IC_MAX_LIST_LENGTH)
my_list.Cut(1, 2)
my_list.Add(new_entry)
/datum/integrated_io/list/proc/remove_from_list_by_position(mob/user, position)
var/list/my_list = data
if(!my_list.len)
to_chat(user, "<span class='warning'>The list is empty, there's nothing to remove.</span>")
return
if(!position)
return
var/target_entry = my_list.Find(position)
if(target_entry)
my_list -= target_entry
/datum/integrated_io/list/proc/remove_from_list(mob/user, target_entry)
var/list/my_list = data
if(!my_list.len)
to_chat(user, "<span class='warning'>The list is empty, there's nothing to remove.</span>")
return
if(!target_entry)
target_entry = input("Which piece of data do you want to remove?", "Remove") as null|anything in my_list
if(target_entry)
my_list -= target_entry
/datum/integrated_io/list/proc/edit_in_list(mob/user, target_entry)
var/list/my_list = data
if(!my_list.len)
to_chat(user, "<span class='warning'>The list is empty, there's nothing to modify.</span>")
return
if(!target_entry)
target_entry = input("Which piece of data do you want to edit?", "Edit") as null|anything in my_list
if(target_entry)
var/edited_entry = ask_for_data_type(user, target_entry)
if(edited_entry)
target_entry = edited_entry
/datum/integrated_io/list/proc/edit_in_list_by_position(mob/user, var/position)
var/list/my_list = data
if(!my_list.len)
to_chat(user, "<span class='warning'>The list is empty, there's nothing to modify.</span>")
return
if(!position)
return
var/target_entry = my_list.Find(position)
if(target_entry)
var/edited_entry = ask_for_data_type(user, target_entry)
if(edited_entry)
target_entry = edited_entry
/datum/integrated_io/list/proc/swap_inside_list(mob/user, var/first_target, var/second_target)
var/list/my_list = data
if(my_list.len <= 1)
to_chat(user, "<span class='warning'>The list is empty, or too small to do any meaningful swapping.</span>")
return
if(!first_target)
first_target = input("Which piece of data do you want to swap? (1)", "Swap") as null|anything in my_list
if(first_target)
if(!second_target)
second_target = input("Which piece of data do you want to swap? (2)", "Swap") as null|anything in my_list - first_target
if(second_target)
var/first_pos = my_list.Find(first_target)
var/second_pos = my_list.Find(second_target)
my_list.Swap(first_pos, second_pos)
/datum/integrated_io/list/proc/clear_list(mob/user)
var/list/my_list = data
my_list.Cut()
/datum/integrated_io/list/scramble()
var/list/my_list = data
my_list = shuffle(my_list)
push_data()
/datum/integrated_io/list/write_data_to_pin(var/new_data)
if(islist(new_data))
var/list/new_list = new_data
data = new_list.Copy()
holder.on_data_written()
/datum/integrated_io/list/display_pin_type()
return IC_FORMAT_LIST
/datum/integrated_io/list/Topic(href, href_list, state = interactive_state)
if(!holder.check_interactivity(usr))
return
if(..())
return 1
if(href_list["add"])
add_to_list(usr)
if(href_list["swap"])
swap_inside_list(usr)
if(href_list["clear"])
clear_list(usr)
if(href_list["remove"])
if(href_list["pos"])
remove_from_list_by_position(usr, text2num(href_list["pos"]))
else
remove_from_list(usr)
if(href_list["edit"])
if(href_list["pos"])
edit_in_list_by_position(usr, text2num(href_list["pos"]))
else
edit_in_list(usr)
holder.interact(usr) // Refresh the main UI,
interact(usr) // and the list UI.

View File

@@ -0,0 +1,17 @@
// These pins can only contain numbers (int and floating point) or null.
/datum/integrated_io/number
name = "number pin"
/datum/integrated_io/number/ask_for_pin_data(mob/user)
var/new_data = input("Please type in a number.","[src] number writing") as null|num
if(isnum(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/number/write_data_to_pin(var/new_data)
if(isnull(new_data) || isnum(new_data))
data = new_data
holder.on_data_written()
/datum/integrated_io/number/display_pin_type()
return IC_FORMAT_NUMBER

View File

@@ -0,0 +1,14 @@
// These pins only contain weakrefs or null.
/datum/integrated_io/ref
name = "ref pin"
/datum/integrated_io/ref/ask_for_pin_data(mob/user) // This clears the pin.
write_data_to_pin(null)
/datum/integrated_io/ref/write_data_to_pin(var/new_data)
if(isnull(new_data) || isweakref(new_data))
data = new_data
holder.on_data_written()
/datum/integrated_io/ref/display_pin_type()
return IC_FORMAT_REF

View File

@@ -0,0 +1,29 @@
// These pins can only contain text and null.
/datum/integrated_io/string
name = "string pin"
/datum/integrated_io/string/ask_for_pin_data(mob/user)
var/new_data = sanitize(input("Please type in a string.","[src] string writing") as null|text)
if(holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data ? "new_data" : "NULL"] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/string/write_data_to_pin(var/new_data)
if(isnull(new_data) || istext(new_data))
data = new_data
holder.on_data_written()
// This makes the text go "from this" to "#G&*!HD$%L"
/datum/integrated_io/string/scramble()
if(!is_valid())
return
var/string_length = length(data)
var/list/options = list("!","@","#","$","%","^","&","*") + alphabet_uppercase
var/new_data = ""
while(string_length)
new_data += pick(options)
string_length--
push_data()
/datum/integrated_io/string/display_pin_type()
return IC_FORMAT_STRING

View File

@@ -0,0 +1,461 @@
#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/electronic_assemblies.dmi'
icon_state = "wirer-wire"
item_state = "wirer"
flags = CONDUCT
w_class = 2
var/datum/integrated_io/selected_io
var/mode = WIRE
/obj/item/device/integrated_electronics/wirer/update_icon()
icon_state = "wirer-[mode]"
/obj/item/device/integrated_electronics/wirer/proc/wire(var/datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
return
switch (mode)
if (WIRE)
selected_io = io
to_chat(user, "<span class='notice'>You attach a data wire to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
mode = WIRING
update_icon()
if (WIRING)
if(io == selected_io)
to_chat(user, "<span class='warning'>Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless.</span>")
return
if(io.io_type != selected_io.io_type)
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
while the second is a [io.io_type].</span>")
return
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
return
selected_io.linked |= io
io.linked |= selected_io
to_chat(user, "<span class='notice'>You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name].</span>")
mode = WIRE
update_icon()
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
if (UNWIRE)
selected_io = io
if(!io.linked.len)
to_chat(user, "<span class='warning'>There is nothing connected to \the [selected_io] data channel.</span>")
selected_io = null
return
to_chat(user, "<span class='notice'>You prepare to detach a data wire from \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
mode = UNWIRING
update_icon()
if (UNWIRING)
if(io == selected_io)
to_chat(user, "<span class='warning'>You can't wire a pin into each other, so unwiring \the [selected_io.holder] from \
the same pin is rather moot.</span>")
return
if(selected_io in io.linked)
io.linked.Remove(selected_io)
selected_io.linked.Remove(io)
to_chat(user, "<span class='notice'>You disconnect \the [selected_io.holder]'s [selected_io.name] from \
\the [io.holder]'s [io.name].</span>")
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
mode = UNWIRE
update_icon()
else
to_chat(user, "<span class='warning'>\The [selected_io.holder]'s [selected_io.name] and \the [io.holder]'s \
[io.name] are not connected.</span>")
/obj/item/device/integrated_electronics/wirer/attack_self(mob/user)
switch(mode)
if(WIRE)
mode = UNWIRE
if(WIRING)
if(selected_io)
to_chat(user, "<span class='notice'>You decide not to wire the data channel.</span>")
selected_io = null
mode = WIRE
if(UNWIRE)
mode = WIRE
if(UNWIRING)
if(selected_io)
to_chat(user, "<span class='notice'>You decide not to disconnect the data channel.</span>")
selected_io = null
mode = UNWIRE
update_icon()
to_chat(user, "<span class='notice'>You set \the [src] to [mode].</span>")
#undef WIRE
#undef WIRING
#undef UNWIRE
#undef UNWIRING
/obj/item/device/integrated_electronics/debugger
name = "circuit debugger"
desc = "This small tool allows one working with custom machinery to directly set data to a specific pin, useful for writing \
settings to specific circuits, or for debugging purposes. It can also pulse activation pins."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "debugger"
flags = CONDUCT
w_class = 2
var/data_to_write = null
var/accepting_refs = 0
/obj/item/device/integrated_electronics/debugger/attack_self(mob/user)
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null")
if(!CanInteract(user, physical_state))
return
var/new_data = null
switch(type_to_use)
if("string")
accepting_refs = 0
new_data = sanitize(input("Now type in a string.","[src] string writing") as null|text)
if(istext(new_data) && CanInteract(user, physical_state))
data_to_write = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to \"[new_data]\".</span>")
if("number")
accepting_refs = 0
new_data = input("Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && CanInteract(user, physical_state))
data_to_write = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [new_data].</span>")
if("ref")
accepting_refs = 1
to_chat(user, "<span class='notice'>You turn \the [src]'s ref scanner on. Slide it across \
an object for a ref of that object to save it in memory.</span>")
if("null")
data_to_write = null
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
/obj/item/device/integrated_electronics/debugger/afterattack(atom/target, mob/living/user, proximity)
if(accepting_refs && proximity)
data_to_write = WEAKREF(target)
visible_message("<span class='notice'>[user] slides [src]'s ref scanner over \the [target].</span>")
to_chat(user, "<span class='notice'>You set \the [src]'s memory to a reference to [target.name] \[Ref\]. The ref scanner is \
now off.</span>")
accepting_refs = 0
/obj/item/device/integrated_electronics/debugger/proc/write_data(var/datum/integrated_io/io, mob/user)
switch (io.io_type)
if (DATA_CHANNEL)
io.write_data_to_pin(data_to_write)
var/data_to_show = data_to_write
if(isweakref(data_to_write))
var/datum/weakref/w = data_to_write
var/atom/A = w.resolve()
data_to_show = A.name
to_chat(user, "<span class='notice'>You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].</span>")
if (PULSE_CHANNEL)
io.holder.check_then_do_work(ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [io.holder]'s '[io]' pin.</span>")
io.holder.interact(user) // This is to update the UI.
/obj/item/device/multitool
var/datum/integrated_io/selected_io = null
var/mode = 0
/obj/item/device/multitool/attack_self(mob/user)
if(selected_io)
selected_io = null
to_chat(user, "<span class='notice'>You clear the wired connection from the multitool.</span>")
else
..()
update_icon()
/obj/item/device/multitool/update_icon()
if(selected_io)
if(buffer || connecting || buffer_object)
icon_state = "multitool_tracking"
else
icon_state = "multitool_red"
else
if(buffer || connecting || buffer_object)
icon_state = "multitool_tracking_fail"
else
icon_state = "multitool"
/obj/item/device/multitool/proc/wire(datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
return
if(selected_io)
if(io == selected_io)
to_chat(user, "<span class='warning'>Wiring \the [selected_io.holder]'s '[selected_io.name]' pin into itself is rather pointless.</span>")
return
if(io.io_type != selected_io.io_type)
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
while the second is a [io.io_type].</span>")
return
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
return
selected_io.linked |= io
io.linked |= selected_io
to_chat(user, "<span class='notice'>You connect \the [selected_io.holder]'s '[selected_io.name]' pin to \the [io.holder]'s '[io.name]' pin.</span>")
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
else
selected_io = io
to_chat(user, "<span class='notice'>You link \the multitool to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
update_icon()
/obj/item/device/multitool/proc/unwire(datum/integrated_io/io1, datum/integrated_io/io2, mob/user)
if(!io1.linked.len || !io2.linked.len)
to_chat(user, "<span class='warning'>There is nothing connected to the data channel.</span>")
return
if(!(io1 in io2.linked) || !(io2 in io1.linked) )
to_chat(user, "<span class='warning'>These data pins aren't connected!</span>")
return
else
io1.linked.Remove(io2)
io2.linked.Remove(io1)
to_chat(user, "<span class='notice'>You clip the data connection between the [io1.holder.displayed_name]'s \
'[io1.name]' pin and the [io2.holder.displayed_name]'s '[io2.name]' pin.</span>")
io1.holder.interact(user) // This is to update the UI.
update_icon()
/obj/item/weapon/storage/bag/circuits
name = "circuit kit"
desc = "This kit's essential for any circuitry projects."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "circuit_kit"
w_class = 3
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/device/multitool
)
/obj/item/weapon/storage/bag/circuits/basic/fill()
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/weapon/storage/bag/circuits/mini/power(src)
new /obj/item/device/electronic_assembly(src)
new /obj/item/device/assembly/electronic_assembly(src)
new /obj/item/device/assembly/electronic_assembly(src)
new /obj/item/device/multitool(src)
new /obj/item/weapon/screwdriver(src)
new /obj/item/weapon/crowbar(src)
make_exact_fit()
/obj/item/weapon/storage/bag/circuits/all/fill()
..()
new /obj/item/weapon/storage/bag/circuits/mini/arithmetic/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/trig/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/input/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/output/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/memory/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/logic/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/smart/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/manipulation/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/time/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/reagents/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/transfer/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/converter/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/power/all(src)
new /obj/item/device/electronic_assembly(src)
new /obj/item/device/electronic_assembly/medium(src)
new /obj/item/device/electronic_assembly/large(src)
new /obj/item/device/electronic_assembly/drone(src)
new /obj/item/device/integrated_electronics/wirer(src)
new /obj/item/device/integrated_electronics/debugger(src)
new /obj/item/weapon/crowbar(src)
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)
var/spawn_flags_to_use = IC_SPAWN_DEFAULT
var/list/spawn_types = list()
/obj/item/weapon/storage/bag/circuits/mini/fill()
spawn_types = typecacheof(spawn_types)
for (var/thing in typecache_filter_list(SSelectronics.all_integrated_circuits, spawn_types))
var/obj/item/integrated_circuit/IC = thing
if (IC.spawn_flags & spawn_flags_to_use)
for (var/i in 1 to 4)
new IC.type(src)
make_exact_fit()
/obj/item/weapon/storage/bag/circuits/mini/arithmetic
name = "arithmetic circuit box"
desc = "Warning: Contains math."
icon_state = "box_arithmetic"
spawn_types = list(
/obj/item/integrated_circuit/arithmetic
)
/obj/item/weapon/storage/bag/circuits/mini/arithmetic/all // Don't believe this will ever be needed.
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/trig
name = "trig circuit box"
desc = "Danger: Contains more math."
icon_state = "box_trig"
spawn_types = list(
/obj/item/integrated_circuit/trig
)
/obj/item/weapon/storage/bag/circuits/mini/trig/all // Ditto
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/input
name = "input circuit box"
desc = "Tell these circuits everything you know."
icon_state = "box_input"
spawn_types = list(
/obj/item/integrated_circuit/input
)
/obj/item/weapon/storage/bag/circuits/mini/input/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/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"
spawn_types = list(
/obj/item/integrated_circuit/output
)
/obj/item/weapon/storage/bag/circuits/mini/output/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/memory
name = "memory circuit box"
desc = "Machines can be quite forgetful without these."
icon_state = "box_memory"
spawn_types = list(
/obj/item/integrated_circuit/memory
)
/obj/item/weapon/storage/bag/circuits/mini/memory/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/logic
name = "logic circuit box"
desc = "May or may not be Turing complete."
icon_state = "box_logic"
spawn_types = list(
/obj/item/integrated_circuit/logic
)
/obj/item/weapon/storage/bag/circuits/mini/logic/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/time
name = "time circuit box"
desc = "No time machine parts, sadly."
icon_state = "box_time"
spawn_types = list(
/obj/item/integrated_circuit/time
)
/obj/item/weapon/storage/bag/circuits/mini/time/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/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"
spawn_types = list(
/obj/item/integrated_circuit/reagent
)
/obj/item/weapon/storage/bag/circuits/mini/reagents/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/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"
spawn_types = list(
/obj/item/integrated_circuit/transfer
)
/obj/item/weapon/storage/bag/circuits/mini/transfer/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/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"
spawn_types = list(
/obj/item/integrated_circuit/converter
)
/obj/item/weapon/storage/bag/circuits/mini/converter/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/smart
name = "smart box"
desc = "Sentience not included."
icon_state = "box_ai"
spawn_types = list(
/obj/item/integrated_circuit/smart
)
/obj/item/weapon/storage/bag/circuits/mini/smart/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/manipulation
name = "manipulation box"
desc = "Make your machines actually useful with these."
icon_state = "box_manipulation"
spawn_types = list(
/obj/item/integrated_circuit/manipulation
)
/obj/item/weapon/storage/bag/circuits/mini/manipulation/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/power
name = "power circuit box"
desc = "Electronics generally require electricity."
icon_state = "box_power"
spawn_types = list(
/obj/item/integrated_circuit/passive/power,
/obj/item/integrated_circuit/power
)
/obj/item/weapon/storage/bag/circuits/mini/power/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH

View File

@@ -0,0 +1,7 @@
// 'Passive' components do not have any pins, and instead contribute in some form to the assembly holding them.
/obj/item/integrated_circuit/passive
inputs = list()
outputs = list()
activators = list()
power_draw_idle = 0
power_draw_per_use = 0

View File

@@ -0,0 +1,106 @@
/obj/item/integrated_circuit/passive/power
name = "power thingy"
desc = "Does power stuff."
complexity = 5
origin_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 2, TECH_DATA = 2)
category_text = "Power - Passive"
/obj/item/integrated_circuit/passive/power/proc/make_energy()
return
// For calculators.
/obj/item/integrated_circuit/passive/power/solar_cell
name = "tiny photovoltaic cell"
desc = "It's a very tiny solar cell, generally used in calculators."
extended_desc = "The cell generates 1W of energy per second in optimal lighting conditions. Less light will result in less power being generated."
icon_state = "solar_cell"
complexity = 8
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/max_power = 1
/obj/item/integrated_circuit/passive/power/solar_cell/make_energy()
var/turf/T = get_turf(src)
var/light_amount = T ? T.get_lumcount() : 0
var/adjusted_power = max(max_power * light_amount, 0)
adjusted_power = round(adjusted_power, 0.1)
if(adjusted_power && assembly)
assembly.give_power(adjusted_power)
// For fat machines that need fat power, like drones.
/obj/item/integrated_circuit/passive/power/relay
name = "tesla power relay"
desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them."
w_class = ITEMSIZE_NORMAL
extended_desc = "The siphon generates 250W of energy, so long as an APC is in the same room, with a cell that has energy. It will always drain \
from the 'equipment' power channel."
icon_state = "power_relay"
complexity = 7
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2)
spawn_flags = IC_SPAWN_RESEARCH
var/power_amount = 250
// For really fat machines.
/obj/item/integrated_circuit/passive/power/relay/large
name = "large tesla power relay"
desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them, now in industiral size!"
w_class = ITEMSIZE_LARGE
extended_desc = "The siphon generates 2 kW of energy, so long as an APC is in the same room, with a cell that has energy. It will always drain \
from the 'equipment' power channel."
icon_state = "power_relay"
complexity = 15
origin_tech = list(TECH_POWER = 6, TECH_ENGINEERING = 5, TECH_DATA = 4)
spawn_flags = IC_SPAWN_RESEARCH
power_amount = 2000
/obj/item/integrated_circuit/passive/power/relay/make_energy()
if(!assembly)
return
var/area/A = get_area(src)
if(A)
if(A.powered(EQUIP) && assembly.give_power(power_amount))
A.use_power(power_amount, EQUIP)
// give_power() handles CELLRATE on its own.
// For implants.
/obj/item/integrated_circuit/passive/power/metabolic_siphon
name = "metabolic siphon"
desc = "A complicated piece of technology which converts bodily nutriments of a host into electricity."
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a biological entity. The entity will feel an increased \
appetite and will need to eat more often due to this. This device will fail if used inside synthetic entities."
icon_state = "setup_implant"
complexity = 10
origin_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_BIO = 5)
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/passive/power/metabolic_siphon/proc/test_validity(var/mob/living/carbon/human/host)
if(!host || host.isSynthetic() || host.stat == DEAD || host.nutrition <= 10)
return FALSE // Robots and dead people don't have a metabolism.
return TRUE
/obj/item/integrated_circuit/passive/power/metabolic_siphon/make_energy()
var/mob/living/carbon/human/host
if(assembly && istype(assembly, /obj/item/device/electronic_assembly/implant))
var/obj/item/device/electronic_assembly/implant/implant_assembly = assembly
if(implant_assembly.implant.imp_in)
host = implant_assembly.implant.imp_in
if(test_validity(host))
assembly.give_power(10)
host.nutrition = max(host.nutrition - HUNGER_FACTOR, 0)
/obj/item/integrated_circuit/passive/power/metabolic_siphon/synthetic
name = "internal energy siphon"
desc = "A small circuit designed to be connected to an internal power wire inside a synthetic entity."
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a synthetic entity. The entity need to recharge \
more often due to this. This device will fail if used inside organic entities."
icon_state = "setup_implant"
complexity = 10
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 4, TECH_DATA = 3)
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/passive/power/metabolic_siphon/synthetic/test_validity(var/mob/living/carbon/human/host)
if(!host || !host.isSynthetic() || host.stat == DEAD || host.nutrition <= 10)
return FALSE // This time we don't want a metabolism.
return TRUE

View File

@@ -0,0 +1,314 @@
//These circuits do simple math.
/obj/item/integrated_circuit/arithmetic
complexity = 1
inputs = list(
"A" = IC_PINTYPE_NUMBER,
"B" = IC_PINTYPE_NUMBER,
"C" = IC_PINTYPE_NUMBER,
"D" = IC_PINTYPE_NUMBER,
"E" = IC_PINTYPE_NUMBER,
"F" = IC_PINTYPE_NUMBER,
"G" = IC_PINTYPE_NUMBER,
"H" = IC_PINTYPE_NUMBER
)
outputs = list("result" = IC_PINTYPE_NUMBER)
activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT)
category_text = "Arithmetic"
power_draw_per_use = 5 // Math is pretty cheap.
// +Adding+ //
/obj/item/integrated_circuit/arithmetic/addition
name = "addition circuit"
desc = "This circuit can add numbers together."
extended_desc = "The order that the calculation goes is;<br>\
result = ((((A + B) + C) + D) ... ) and so on, until all pins have been added. \
Null pins are ignored."
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/addition/do_work()
var/result = 0
for(var/datum/integrated_io/I in inputs)
I.pull_data()
if(isnum(I.data))
result = result + I.data
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// -Subtracting- //
/obj/item/integrated_circuit/arithmetic/subtraction
name = "subtraction circuit"
desc = "This circuit can subtract numbers."
extended_desc = "The order that the calculation goes is;<br>\
result = ((((A - B) - C) - D) ... ) and so on, until all pins have been subtracted. \
Null pins are ignored. Pin A <b>must</b> be a number or the circuit will not function."
icon_state = "subtraction"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/subtraction/do_work()
var/datum/integrated_io/A = inputs[1]
if(!isnum(A.data))
return
var/result = A.data
for(var/datum/integrated_io/I in inputs)
if(I == A)
continue
I.pull_data()
if(isnum(I.data))
result = result - I.data
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// *Multiply* //
/obj/item/integrated_circuit/arithmetic/multiplication
name = "multiplication circuit"
desc = "This circuit can multiply numbers."
extended_desc = "The order that the calculation goes is;<br>\
result = ((((A * B) * C) * D) ... ) and so on, until all pins have been multiplied. \
Null pins are ignored. Pin A <b>must</b> be a number or the circuit will not function."
icon_state = "multiplication"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/multiplication/do_work()
var/datum/integrated_io/A = inputs[1]
if(!isnum(A.data))
return
var/result = A.data
for(var/datum/integrated_io/I in inputs)
if(I == A)
continue
I.pull_data()
if(isnum(I.data))
result = result * I.data
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// /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!"
extended_desc = "The order that the calculation goes is;<br>\
result = ((((A / B) / C) / D) ... ) and so on, until all pins have been divided. \
Null pins, and pins containing 0, are ignored. Pin A <b>must</b> be a number or the circuit will not function."
icon_state = "division"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/division/do_work()
var/datum/integrated_io/A = inputs[1]
if(!isnum(A.data))
return
var/result = A.data
for(var/datum/integrated_io/I in inputs)
if(I == A)
continue
I.pull_data()
if(isnum(I.data) && I.data != 0) //No runtimes here.
result = result / I.data
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
//^ Exponent ^//
/obj/item/integrated_circuit/arithmetic/exponent
name = "exponent circuit"
desc = "Outputs A to the power of B."
icon_state = "exponent"
inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/exponent/do_work()
var/result = 0
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
if(isnum(A.data) && isnum(B.data))
result = A.data ** B.data
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// +-Sign-+ //
/obj/item/integrated_circuit/arithmetic/sign
name = "sign circuit"
desc = "This will say if a number is positive, negative, or zero."
extended_desc = "Will output 1, -1, or 0, depending on if A is a postive number, a negative number, or zero, respectively."
icon_state = "sign"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/sign/do_work()
var/result = 0
var/datum/integrated_io/A = inputs[1]
if(isnum(A.data))
if(A.data > 0)
result = 1
else if (A.data < 0)
result = -1
else
result = 0
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Round //
/obj/item/integrated_circuit/arithmetic/round
name = "round circuit"
desc = "Rounds A to the nearest B multiple of A."
extended_desc = "If B is not given a number, it will output the floor of A instead."
icon_state = "round"
inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/round/do_work()
var/result = 0
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
if(isnum(A.data))
if(isnum(B.data) && B.data != 0)
result = round(A.data, B.data)
else
result = round(A.data)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// 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"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/absolute/do_work()
var/result = 0
for(var/datum/integrated_io/I in inputs)
I.pull_data()
if(isnum(I.data))
result = abs(I.data)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// 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."
extended_desc = "Note that null pins are ignored, where as a pin containing 0 is included in the averaging calculation."
icon_state = "average"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/average/do_work()
var/result = 0
var/inputs_used = 0
for(var/datum/integrated_io/I in inputs)
I.pull_data()
if(isnum(I.data))
inputs_used++
result = result + I.data
if(inputs_used)
result = result / inputs_used
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// 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"
inputs = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/pi/do_work()
set_pin_data(IC_OUTPUT, 1, M_PI)
push_data()
activate_pin(2)
// Random //
/obj/item/integrated_circuit/arithmetic/random
name = "random number generator circuit"
desc = "This gives a random (integer) number between values A and B inclusive."
extended_desc = "'Inclusive' means that the upper bound is included in the range of numbers, e.g. L = 1 and H = 3 will allow \
for outputs of 1, 2, or 3. H being the higher number is not <i>strictly</i> required."
icon_state = "random"
inputs = list("L" = IC_PINTYPE_NUMBER,"H" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/random/do_work()
var/result = 0
var/L = get_pin_data(IC_INPUT, 1)
var/H = get_pin_data(IC_INPUT, 2)
if(isnum(L) && isnum(H))
result = rand(L, H)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// 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" = IC_PINTYPE_NUMBER)
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/I in inputs)
I.pull_data()
if(isnum(I.data))
result = sqrt(I.data)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// % Modulo % //
/obj/item/integrated_circuit/arithmetic/modulo
name = "modulo circuit"
desc = "Gets the remainder of A / B."
icon_state = "modulo"
inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/modulo/do_work()
var/result = 0
var/A = get_pin_data(IC_INPUT, 1)
var/B = get_pin_data(IC_INPUT, 2)
if(isnum(A) && isnum(B) && B != 0)
result = A % B
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)

View File

@@ -0,0 +1,28 @@
/obj/item/integrated_circuit/built_in
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"
size = -1
w_class = ITEMSIZE_TINY
removable = FALSE // Determines if a circuit is removable from the assembly.
/obj/item/integrated_circuit/built_in/device_input
name = "assembly input"
desc = "A built in chip for handling pulses from attached assembly items."
complexity = 0 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
activators = list("on pulsed" = IC_PINTYPE_PULSE_OUT)
/obj/item/integrated_circuit/built_in/device_input/do_work()
activate_pin(1)
/obj/item/integrated_circuit/built_in/device_output
name = "assembly out"
desc = "A built in chip for pulsing attached assembly items."
complexity = 0 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
activators = list("pulse attached" = IC_PINTYPE_PULSE_IN)
/obj/item/integrated_circuit/built_in/device_output/do_work()
if(istype(assembly, /obj/item/device/electronic_assembly/device))
var/obj/item/device/electronic_assembly/device/device = assembly
device.holder.pulse()

View File

@@ -0,0 +1,238 @@
//These circuits convert one variable to another.
/obj/item/integrated_circuit/converter
complexity = 2
inputs = list("input")
outputs = list("output")
activators = list("convert" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT)
category_text = "Converter"
power_draw_per_use = 10
/obj/item/integrated_circuit/converter/num2text
name = "number to string"
desc = "This circuit can convert a number variable into a string."
extended_desc = "Because of game limitations null/false variables will output a '0' string."
icon_state = "num-string"
inputs = list("input" = IC_PINTYPE_NUMBER)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/num2text/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = num2text(incoming)
else if(!incoming)
result = "0"
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/text2num
name = "string to number"
desc = "This circuit can convert a string variable into a number."
icon_state = "string-num"
inputs = list("input" = IC_PINTYPE_STRING)
outputs = list("output" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/text2num/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = text2num(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/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 = "ref-string"
inputs = list("input" = IC_PINTYPE_REF)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/ref2text/do_work()
var/result = null
pull_data()
var/atom/A = get_pin_data_as_type(IC_INPUT, 1, /atom)
if(A)
result = A.name
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/lowercase
name = "lowercase string converter"
desc = "this will cause a string to come out in all lowercase."
icon_state = "lowercase"
inputs = list("input" = IC_PINTYPE_STRING)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/lowercase/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = lowertext(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/uppercase
name = "uppercase string converter"
desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE."
icon_state = "uppercase"
inputs = list("input" = IC_PINTYPE_STRING)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/uppercase/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = uppertext(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/concatenator
name = "concatenator"
desc = "This joins many strings together to get one big string."
complexity = 4
inputs = list(
"A" = IC_PINTYPE_STRING,
"B" = IC_PINTYPE_STRING,
"C" = IC_PINTYPE_STRING,
"D" = IC_PINTYPE_STRING,
"E" = IC_PINTYPE_STRING,
"F" = IC_PINTYPE_STRING,
"G" = IC_PINTYPE_STRING,
"H" = IC_PINTYPE_STRING
)
outputs = list("result" = IC_PINTYPE_STRING)
activators = list("concatenate" = IC_PINTYPE_PULSE_IN, "on concatenated" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/concatenator/do_work()
var/result = null
for(var/datum/integrated_io/I in inputs)
I.pull_data()
if(!isnull(I.data))
result = result + I.data
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/separator
name = "separator"
desc = "This splits as single string into two at the relative split point."
extended_desc = "This circuits splits a given string into two, based on the string, and the index value. \
The index splits the string <b>after</b> the given index, including spaces. So 'a person' with an index of '3' \
will split into 'a p' and 'erson'."
complexity = 4
inputs = list(
"string to split" = IC_PINTYPE_STRING,
"index" = IC_PINTYPE_NUMBER
)
outputs = list(
"before split" = IC_PINTYPE_STRING,
"after split" = IC_PINTYPE_STRING
)
activators = list("separate" = IC_PINTYPE_PULSE_IN, "on separated" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/separator/do_work()
var/text = get_pin_data(IC_INPUT, 1)
var/index = get_pin_data(IC_INPUT, 2)
var/split = min(index+1, length(text))
var/before_text = copytext(text, 1, split)
var/after_text = copytext(text, split, 0)
set_pin_data(IC_OUTPUT, 1, before_text)
set_pin_data(IC_OUTPUT, 2, after_text)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/radians2degrees
name = "radians to degrees converter"
desc = "Converts radians to degrees."
inputs = list("radian" = IC_PINTYPE_NUMBER)
outputs = list("degrees" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/radians2degrees/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = ToDegrees(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/degrees2radians
name = "degrees to radians converter"
desc = "Converts degrees to radians."
inputs = list("degrees" = IC_PINTYPE_NUMBER)
outputs = list("radians" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/degrees2radians/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = ToRadians(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/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" = IC_PINTYPE_NUMBER,
"Y1" = IC_PINTYPE_NUMBER,
"X2" = IC_PINTYPE_NUMBER,
"Y2" = IC_PINTYPE_NUMBER
)
outputs = list(
"X" = IC_PINTYPE_NUMBER,
"Y" = IC_PINTYPE_NUMBER
)
activators = list("compute rel coordinates" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work()
var/x1 = get_pin_data(IC_INPUT, 1)
var/y1 = get_pin_data(IC_INPUT, 2)
var/x2 = get_pin_data(IC_INPUT, 3)
var/y2 = get_pin_data(IC_INPUT, 4)
if(!isnull(x1) && !isnull(y1) && !isnull(x2) && !isnull(y2))
set_pin_data(IC_OUTPUT, 1, x1 - x2)
set_pin_data(IC_OUTPUT, 2, y1 - y2)
push_data()
activate_pin(2)

View File

@@ -0,0 +1,165 @@
/obj/item/integrated_circuit/transfer
category_text = "Data Transfer"
power_draw_per_use = 2
/obj/item/integrated_circuit/transfer/multiplexer
name = "two multiplexer"
desc = "This is what those in the business tend to refer to as a 'mux' or data selector. It moves data from one of the selected inputs to the output."
extended_desc = "The first input pin is used to select which of the other input pins which has its data moved to the output. \
If the input selection is outside the valid range then no output is given."
complexity = 2
icon_state = "mux2"
inputs = list("input selection" = IC_PINTYPE_NUMBER)
outputs = list("output" = IC_PINTYPE_ANY)
activators = list(
"select" = IC_PINTYPE_PULSE_IN,
"on select" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
var/number_of_inputs = 2
/obj/item/integrated_circuit/transfer/multiplexer/Initialize()
for(var/i = 1 to number_of_inputs)
inputs["input [i]"] = IC_PINTYPE_ANY // This is just a string since pins don't get built until ..() is called.
complexity = number_of_inputs
. = ..()
desc += " It has [number_of_inputs] input pins."
extended_desc += " This multiplexer has a range from 1 to [inputs.len - 1]."
/obj/item/integrated_circuit/transfer/multiplexer/do_work()
var/input_index = get_pin_data(IC_INPUT, 1)
var/output = null
if(!isnull(input_index) && (input_index >= 1 && input_index < inputs.len))
output = get_pin_data(IC_INPUT, input_index + 1)
set_pin_data(IC_OUTPUT, 1, output)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/transfer/multiplexer/medium
name = "four multiplexer"
number_of_inputs = 4
icon_state = "mux4"
/obj/item/integrated_circuit/transfer/multiplexer/large
name = "eight multiplexer"
number_of_inputs = 8
w_class = ITEMSIZE_SMALL
icon_state = "mux8"
/obj/item/integrated_circuit/transfer/multiplexer/huge
name = "sixteen multiplexer"
icon_state = "mux16"
w_class = ITEMSIZE_SMALL
number_of_inputs = 16
/obj/item/integrated_circuit/transfer/demultiplexer
name = "two demultiplexer"
desc = "This is what those in the business tend to refer to as a 'demux'. It moves data from the input to one of the selected outputs."
extended_desc = "The first input pin is used to select which of the output pins is given the data from the second input pin. \
If the output selection is outside the valid range then no output is given."
complexity = 2
icon_state = "dmux2"
inputs = list(
"output selection" = IC_PINTYPE_NUMBER,
"input" = IC_PINTYPE_ANY
)
outputs = list()
activators = list(
"select" = IC_PINTYPE_PULSE_IN,
"on select" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
var/number_of_outputs = 2
/obj/item/integrated_circuit/transfer/demultiplexer/Initialize()
for(var/i = 1 to number_of_outputs)
outputs["output [i]"] = IC_PINTYPE_ANY
complexity = number_of_outputs
. = ..()
desc += " It has [number_of_outputs] output pins."
extended_desc += " This demultiplexer has a range from 1 to [outputs.len]."
/obj/item/integrated_circuit/transfer/demultiplexer/do_work()
var/output_index = get_pin_data(IC_INPUT, 1)
var/output = get_pin_data(IC_INPUT, 2)
for(var/i = 1 to outputs.len)
set_pin_data(IC_OUTPUT, i, i == output_index ? output : null)
activate_pin(2)
/obj/item/integrated_circuit/transfer/demultiplexer/medium
name = "four demultiplexer"
icon_state = "dmux4"
number_of_outputs = 4
/obj/item/integrated_circuit/transfer/demultiplexer/large
name = "eight demultiplexer"
icon_state = "dmux8"
w_class = ITEMSIZE_SMALL
number_of_outputs = 8
/obj/item/integrated_circuit/transfer/demultiplexer/huge
name = "sixteen demultiplexer"
icon_state = "dmux16"
w_class = ITEMSIZE_SMALL
number_of_outputs = 16
/obj/item/integrated_circuit/transfer/wireless
name = "subspace transceiver"
desc = "A wireless transmitter-receiver pair that can transmit data between devices."
extended_desc = "The first input is the data to send to the other device, and the second input is the channel to send it on."
complexity = 12
spawn_flags = IC_SPAWN_RESEARCH
icon_state = "bluespace"
power_draw_per_use = 100 // fancy subspace comms aren't cheap power-wise
w_class = ITEMSIZE_SMALL
inputs = list(
"data" = IC_PINTYPE_ANY,
"channel" = IC_PINTYPE_STRING
)
outputs = list(
"data" = IC_PINTYPE_ANY
)
activators = list(
"send" = IC_PINTYPE_PULSE_IN,
"receive" = IC_PINTYPE_PULSE_OUT
)
var/last_channel
var/listener/listener
/obj/item/integrated_circuit/transfer/wireless/do_work()
pull_data()
var/data = get_pin_data(IC_INPUT, 1)
if (data != null)
var/chan = "[WP_ELECTRONICS][get_pin_data(IC_INPUT, 2) || "default"]"
for (var/thing in GET_LISTENERS(chan))
var/listener/L = thing
var/obj/item/integrated_circuit/transfer/wireless/W = L.target
if (W != src)
W.receive(data)
/obj/item/integrated_circuit/transfer/wireless/proc/receive(datum/data)
set_pin_data(IC_OUTPUT, 1, data)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/transfer/wireless/Destroy()
QDEL_NULL(listener)
return ..()
/obj/item/integrated_circuit/transfer/wireless/on_data_written()
var/chan = "[WP_ELECTRONICS][get_pin_data(IC_INPUT, 2) || "default"]"
if (chan != last_channel)
QDEL_NULL(listener)
listener = new(chan, src)
last_channel = chan

View File

@@ -0,0 +1,381 @@
/obj/item/integrated_circuit/input
var/can_be_asked_input = 0
category_text = "Input"
power_draw_per_use = 5
/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"
complexity = 1
can_be_asked_input = 1
inputs = list()
outputs = list()
activators = list("on pressed" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use.
to_chat(user, "<span class='notice'>You press the button labeled '[src.name]'.</span>")
activate_pin(1)
/obj/item/integrated_circuit/input/toggle_button
name = "toggle button"
desc = "It toggles on, off, on, off..."
icon_state = "toggle_button"
complexity = 1
can_be_asked_input = 1
inputs = list()
outputs = list("on" = IC_PINTYPE_BOOLEAN)
activators = list("on toggle" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto.
set_pin_data(IC_OUTPUT, 1, !get_pin_data(IC_OUTPUT, 1))
push_data()
activate_pin(1)
to_chat(user, "<span class='notice'>You toggle the button labeled '[src.name]' [get_pin_data(IC_OUTPUT, 1) ? "on" : "off"].</span>")
/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"
complexity = 2
can_be_asked_input = 1
inputs = list()
outputs = list("number entered" = IC_PINTYPE_NUMBER)
activators = list("on entered" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user)
var/new_input = input(user, "Enter a number, please.","Number pad") as null|num
if(isnum(new_input) && CanInteract(user, physical_state))
set_pin_data(IC_OUTPUT, 1, new_input)
push_data()
activate_pin(1)
/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 = "textpad"
complexity = 2
can_be_asked_input = 1
inputs = list()
outputs = list("string entered" = IC_PINTYPE_STRING)
activators = list("on entered" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user)
var/new_input = sanitize(input(user, "Enter some words, please.","Number pad") as null|text)
if(istext(new_input) && CanInteract(user, physical_state))
set_pin_data(IC_OUTPUT, 1, new_input)
push_data()
activate_pin(1)
/obj/item/integrated_circuit/input/med_scanner
name = "integrated medical analyser"
desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is."
icon_state = "medscan"
complexity = 4
inputs = list("target" = IC_PINTYPE_REF)
outputs = list(
"total health %" = IC_PINTYPE_NUMBER,
"total missing health" = IC_PINTYPE_NUMBER
)
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
power_draw_per_use = 40
/obj/item/integrated_circuit/input/med_scanner/do_work()
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100
var/missing_health = H.getMaxHealth() - H.health
set_pin_data(IC_OUTPUT, 1, total_health)
set_pin_data(IC_OUTPUT, 2, missing_health)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/adv_med_scanner
name = "integrated advanced medical analyser"
desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is. \
This type is much more precise, allowing the machine to know much more about the target than a normal analyzer."
icon_state = "medscan_adv"
complexity = 12
inputs = list("target" = IC_PINTYPE_REF)
outputs = list(
"total health %" = IC_PINTYPE_NUMBER,
"total missing health" = IC_PINTYPE_NUMBER,
"brute damage" = IC_PINTYPE_NUMBER,
"burn damage" = IC_PINTYPE_NUMBER,
"tox damage" = IC_PINTYPE_NUMBER,
"oxy damage" = IC_PINTYPE_NUMBER,
"clone damage" = IC_PINTYPE_NUMBER
)
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4)
power_draw_per_use = 80
/obj/item/integrated_circuit/input/adv_med_scanner/do_work()
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100
var/missing_health = H.getMaxHealth() - H.health
set_pin_data(IC_OUTPUT, 1, total_health)
set_pin_data(IC_OUTPUT, 2, missing_health)
set_pin_data(IC_OUTPUT, 3, H.getBruteLoss())
set_pin_data(IC_OUTPUT, 4, H.getFireLoss())
set_pin_data(IC_OUTPUT, 5, H.getToxLoss())
set_pin_data(IC_OUTPUT, 6, H.getOxyLoss())
set_pin_data(IC_OUTPUT, 7, H.getCloneLoss())
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/local_locator
name = "local locator"
desc = "This is needed for certain devices that demand a reference for a target to act upon. This type only locates something \
that is holding the machine containing it."
inputs = list()
outputs = list(
"located ref" = IC_PINTYPE_REF
)
activators = list(
"locate" = IC_PINTYPE_PULSE_IN,
"on locate" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 20
/obj/item/integrated_circuit/input/local_locator/do_work()
if(assembly && istype(assembly.loc, /mob/living))
set_pin_data(IC_OUTPUT, 1, assembly.loc)
else
set_pin_data(IC_OUTPUT, 1, null)
activate_pin(2)
/obj/item/integrated_circuit/input/adjacent_locator
name = "adjacent locator"
desc = "This is needed for certain devices that demand a reference for a target to act upon. This type only locates something \
that is standing a meter away from the machine."
extended_desc = "The first pin requires a ref to a kind of object that you want the locator to acquire. This means that it will \
give refs to nearby objects that are similar. If more than one valid object is found nearby, it will choose one of them at \
random."
inputs = list("desired type ref" = IC_PINTYPE_REF)
outputs = list("located ref" = IC_PINTYPE_REF)
activators = list("locate" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 30
/obj/item/integrated_circuit/input/adjacent_locator/do_work()
var/atom/A = get_pin_data_as_type(IC_INPUT, 1, /atom)
if(!A)
set_pin_data(IC_OUTPUT, 1, null)
return
var/desired_type = A.type
var/list/nearby_things = range(1, get_turf(src))
var/list/valid_things = list()
for(var/atom/thing in nearby_things)
if(thing.type != desired_type)
continue
valid_things += thing
if(valid_things.len)
set_pin_data(IC_OUTPUT, 1, pick(valid_things))
/obj/item/integrated_circuit/input/signaler
name = "integrated signaler"
desc = "Signals from a signaler can be received with this, allowing for remote control. Additionally, it can send signals as well."
extended_desc = "When a signal is received from another signaler, the 'on signal received' activator pin will be pulsed. \
The two input pins are to configure the integrated signaler's settings. Note that the frequency should not have a decimal in it. \
Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin."
icon_state = "signal"
complexity = 4
inputs = list(
"frequency" = IC_PINTYPE_NUMBER,
"code" = IC_PINTYPE_NUMBER
)
outputs = list()
activators = list(
"send signal" = IC_PINTYPE_PULSE_IN,
"on signal sent" = IC_PINTYPE_PULSE_OUT,
"on signal received" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2)
power_draw_idle = 5
power_draw_per_use = 40
var/frequency = 1457
var/code = 30
var/datum/radio_frequency/radio_connection
/obj/item/integrated_circuit/input/signaler/Initialize()
..()
set_frequency(frequency)
// Set the pins so when someone sees them, they won't show as null
set_pin_data(IC_INPUT, 1, frequency)
set_pin_data(IC_INPUT, 2, code)
/obj/item/integrated_circuit/input/signaler/Destroy()
SSradio.remove_object(src,frequency)
frequency = 0
. = ..()
/obj/item/integrated_circuit/input/signaler/on_data_written()
var/new_freq = get_pin_data(IC_INPUT, 1)
var/new_code = get_pin_data(IC_INPUT, 2)
if(isnum(new_freq) && new_freq > 0)
set_frequency(new_freq)
if(isnum(new_code))
code = new_code
/obj/item/integrated_circuit/input/signaler/do_work() // Sends a signal.
if(!radio_connection)
return
var/datum/signal/signal = new()
signal.source = src
signal.encryption = code
signal.data["message"] = "ACTIVATE"
radio_connection.post_signal(src, signal)
activate_pin(2)
/obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency)
if(!frequency)
return
SSradio.remove_object(src, frequency)
frequency = new_frequency
radio_connection = SSradio.add_object(src, frequency, RADIO_CHAT)
/obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal)
var/new_code = get_pin_data(IC_INPUT, 2)
var/code = 0
if(isnum(new_code))
code = new_code
if(!signal)
return 0
if(signal.encryption != code)
return 0
if(signal.source == src) // Don't trigger ourselves.
return 0
activate_pin(3)
for(var/mob/O in hearers(1, get_turf(src)))
O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2)
//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."
extended_desc = "The GPS's coordinates it gives is absolute, not relative."
icon_state = "gps"
complexity = 4
inputs = list()
outputs = list(
"X"= IC_PINTYPE_NUMBER,
"Y" = IC_PINTYPE_NUMBER
)
activators = list(
"get coordinates" = IC_PINTYPE_PULSE_IN,
"on get coordinates" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 30
/obj/item/integrated_circuit/input/gps/do_work()
var/turf/T = get_turf(src)
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
if(!T)
return
set_pin_data(IC_OUTPUT, 1, T.x)
set_pin_data(IC_OUTPUT, 2, T.y)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/microphone
name = "microphone"
desc = "Useful for spying on people or for voice activated machines."
extended_desc = "This will automatically translate most languages it hears to Tau Ceti Basic. \
The first activation pin is always pulsed when the circuit hears someone talk, while the second one \
is only triggered if it hears someone speaking a language other than Tau Ceti Basic."
icon_state = "recorder"
complexity = 8
inputs = list()
outputs = list(
"speaker" = IC_PINTYPE_STRING,
"message" = IC_PINTYPE_STRING
)
activators = list(
"on message received" = IC_PINTYPE_PULSE_OUT,
"on translation" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 15
/obj/item/integrated_circuit/input/microphone/Initialize()
. = ..()
listening_objects |= src
/obj/item/integrated_circuit/input/microphone/Destroy()
listening_objects -= src
return ..()
/obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
var/translated = FALSE
if(M && msg)
if(speaking)
if(!istype(speaking, /datum/language/common))
translated = TRUE
set_pin_data(IC_OUTPUT, 1, M.GetVoice())
set_pin_data(IC_OUTPUT, 2, msg)
push_data()
activate_pin(1)
if(translated)
activate_pin(2)
/obj/item/integrated_circuit/input/sensor
name = "sensor"
desc = "Scans and obtains a reference for any objects or persons near you. All you need to do is shove the machine in their face."
extended_desc = "If 'ignore storage' pin is set to true, the sensor will disregard scanning various storage containers such as backpacks."
icon_state = "recorder"
complexity = 12
inputs = list("ignore storage" = IC_PINTYPE_BOOLEAN)
outputs = list("scanned" = IC_PINTYPE_REF)
activators = list("on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A)
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
if(istype(A, /obj/item/weapon/storage))
return FALSE
set_pin_data(IC_OUTPUT, 1, A)
push_data()
activate_pin(1)
return TRUE

View File

@@ -0,0 +1,87 @@
//These circuits do things with lists, and use special list pins for stability.
/obj/item/integrated_circuit/list
complexity = 1
inputs = list(
"input" = IC_PINTYPE_LIST
)
outputs = list("result" = IC_PINTYPE_STRING)
activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT)
category_text = "Lists"
power_draw_per_use = 20
/obj/item/integrated_circuit/list/pick
name = "pick circuit"
desc = "This circuit will randomly 'pick' an element from a list that is inputted."
extended_desc = "Will output null if the list is empty. Input list is unmodified."
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/list/pick/do_work()
var/result = null
var/list/input_list = get_pin_data(IC_INPUT, 1) // List pins guarantee that there is a list inside, even if just an empty one.
if(input_list.len)
result = pick(input_list)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/list/append
name = "append circuit"
desc = "This circuit will add an element to a list."
extended_desc = "The new element will always be at the bottom of the list."
inputs = list(
"list to append" = IC_PINTYPE_LIST,
"input" = IC_PINTYPE_ANY
)
outputs = list(
"appended list" = IC_PINTYPE_LIST
)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/list/append/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
var/list/output_list = list()
var/new_entry = get_pin_data(IC_INPUT, 2)
output_list = input_list + new_entry
set_pin_data(IC_OUTPUT, 1, output_list)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/list/jointext
name = "join text circuit"
desc = "This circuit will add all elements of a list into one string, seperated by a character."
extended_desc = "Default settings will encode the entire list into a string."
inputs = list(
"list to join" = IC_PINTYPE_LIST,
"delimiter" = IC_PINTYPE_CHAR,
"start" = IC_PINTYPE_NUMBER,
"end" = IC_PINTYPE_NUMBER
)
inputs_default = list(
"2" = ",",
"3" = 1,
"4" = 0
)
outputs = list(
"joined text" = IC_PINTYPE_STRING
)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/list/jointext/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
var/delimiter = get_pin_data(IC_INPUT, 2)
var/start = get_pin_data(IC_INPUT, 3)
var/end = get_pin_data(IC_INPUT, 4)
var/result = null
if(input_list.len && delimiter && !isnull(start) && !isnull(end))
result = jointext(input_list, delimiter, start, end)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)

View File

@@ -0,0 +1,135 @@
/obj/item/integrated_circuit/logic
name = "logic gate"
desc = "This tiny chip will decide for you!"
extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE."
complexity = 3
outputs = list("result" = IC_PINTYPE_BOOLEAN)
activators = list("compare" = IC_PINTYPE_PULSE_IN)
category_text = "Logic"
power_draw_per_use = 1
/obj/item/integrated_circuit/logic/binary
inputs = list(
"A" = IC_PINTYPE_ANY,
"B" = IC_PINTYPE_ANY
)
activators = list(
"compare" = IC_PINTYPE_PULSE_IN,
"on true result" = IC_PINTYPE_PULSE_OUT,
"on false result" = IC_PINTYPE_PULSE_OUT
)
/obj/item/integrated_circuit/logic/binary/do_work()
var/data1 = get_pin_data(IC_INPUT, 1)
var/data2 = get_pin_data(IC_INPUT, 2)
var/result = !!do_compare(data1, data2)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
if (result)
activate_pin(2)
else
activate_pin(3)
/obj/item/integrated_circuit/logic/binary/proc/do_compare(A, B)
return FALSE
/obj/item/integrated_circuit/logic/unary
inputs = list(
"A" = IC_PINTYPE_ANY
)
activators = list(
"compare" = IC_PINTYPE_PULSE_IN,
"on compare" = IC_PINTYPE_PULSE_OUT
)
/obj/item/integrated_circuit/logic/unary/do_work()
var/mydata = get_pin_data(IC_INPUT, 1)
set_pin_data(IC_OUTPUT, 1, !!do_check(mydata))
push_data()
activate_pin(2)
/obj/item/integrated_circuit/logic/unary/proc/do_check(A)
return FALSE
/obj/item/integrated_circuit/logic/binary/equals
name = "equal gate"
desc = "This gate compares two values, and outputs the number one if both are the same."
icon_state = "equal"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/equals/do_compare(A, B)
return A == B
/obj/item/integrated_circuit/logic/binary/not_equals
name = "not equal gate"
desc = "This gate compares two values, and outputs the number one if both are different."
icon_state = "not_equal"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/not_equals/do_compare(A, B)
return A != B
/obj/item/integrated_circuit/logic/binary/and
name = "and gate"
desc = "This gate will output 'one' if both inputs evaluate to true."
icon_state = "and"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/and/do_compare(A, B)
return A && B
/obj/item/integrated_circuit/logic/binary/or
name = "or gate"
desc = "This gate will output 'one' if one of the inputs evaluate to true."
icon_state = "or"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/or/do_compare(A, B)
return A || B
/obj/item/integrated_circuit/logic/binary/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"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/less_than/do_compare(A, B)
return A < B
/obj/item/integrated_circuit/logic/binary/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"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/less_than_or_equal/do_compare(A, B)
return A <= B
/obj/item/integrated_circuit/logic/binary/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"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/greater_than/do_compare(A, B)
return A > B
/obj/item/integrated_circuit/logic/binary/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"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/greater_than_or_equal/do_compare(A, B)
return A >= B
/obj/item/integrated_circuit/logic/unary/not
name = "not gate"
desc = "This gate inverts what's fed into it."
icon_state = "not"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
activators = list("invert" = IC_PINTYPE_PULSE_IN, "on inverted" = IC_PINTYPE_PULSE_OUT)
/obj/item/integrated_circuit/logic/unary/not/do_check(A)
return !A

View File

@@ -0,0 +1,188 @@
/obj/item/integrated_circuit/manipulation
category_text = "Manipulation"
/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
w_class = ITEMSIZE_NORMAL
size = 3
inputs = list(
"target X rel" = IC_PINTYPE_NUMBER,
"target Y rel" = IC_PINTYPE_NUMBER
)
outputs = list()
activators = list(
"fire" = IC_PINTYPE_PULSE_IN
)
var/obj/item/weapon/gun/installed_gun
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
power_draw_per_use = 50 // The targeting mechanism uses this. The actual gun uses its own cell for firing if it's an energy weapon.
/obj/item/integrated_circuit/manipulation/weapon_firing/Destroy()
QDEL_NULL(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 << "<span class='warning'>There's already a weapon installed.</span>"
return
user.drop_from_inventory(gun)
installed_gun = gun
size += gun.w_class
gun.forceMove(src)
user << "<span class='notice'>You slide \the [gun] into the firing mechanism.</span>"
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 << "<span class='notice'>You slide \the [installed_gun] out of the firing mechanism.</span>"
size = initial(size)
playsound(loc, 'sound/items/Crowbar.ogg', 50, 1)
installed_gun = null
else
user << "<span class='notice'>There's no weapon to remove from the mechanism.</span>"
/obj/item/integrated_circuit/manipulation/weapon_firing/do_work()
if(!installed_gun)
return
var/target_x = get_pin_data(IC_INPUT, 1)
var/target_y = get_pin_data(IC_INPUT, 2)
if (!isnum(target_x) || !isnum(target_y) || !assembly)
return
target_x = round(target_x)
target_y = round(target_y)
if(target_x == 0 && target_y == 0) // Don't shoot ourselves.
return
var/turf/T = get_turf(assembly)
var/Tx = T.x + target_x
var/Ty = T.y + target_y
if (Tx > world.maxx || Tx < 1 || Ty > world.maxy || Ty < 1)
return // Off the edge of the map.
T = locate(Tx, Ty, T.z)
if(!T)
return
installed_gun.Fire_userless(T)
/obj/item/integrated_circuit/manipulation/locomotion
name = "locomotion circuit"
desc = "This allows a machine to move in a given direction."
icon_state = "locomotion"
extended_desc = "The circuit accepts a 'dir' number as a direction to move towards.<br>\
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 the ability to move is dependant on the type of assembly that this circuit inhabits."
w_class = ITEMSIZE_NORMAL
complexity = 20
// size = 5
inputs = list("direction" = IC_PINTYPE_DIR)
outputs = list()
activators = list("step towards dir" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 100
/obj/item/integrated_circuit/manipulation/locomotion/do_work()
..()
var/turf/T = get_turf(src)
if(T && assembly)
if(assembly.anchored || !assembly.can_move())
return
if(assembly.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]
if(isnum(wanted_dir.data))
step(assembly, wanted_dir.data)
/obj/item/integrated_circuit/manipulation/grenade
name = "grenade primer"
desc = "This circuit comes with the ability to attach most types of grenades at prime them at will."
extended_desc = "Time between priming and detonation is limited to between 1 to 12 seconds but is optional. \
If unset, not a number, or a number less than 1 then the grenade's built-in timing will be used. \
Beware: Once primed there is no aborting the process!"
icon_state = "grenade"
complexity = 30
size = 2
inputs = list("detonation time" = IC_PINTYPE_NUMBER)
outputs = list()
activators = list("prime grenade" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
var/obj/item/weapon/grenade/attached_grenade
var/pre_attached_grenade_type
/obj/item/integrated_circuit/manipulation/grenade/Initialize()
. = ..()
if(pre_attached_grenade_type)
var/grenade = new pre_attached_grenade_type(src)
attach_grenade(grenade)
/obj/item/integrated_circuit/manipulation/grenade/Destroy()
if(attached_grenade && !attached_grenade.active)
attached_grenade.dropInto(loc)
detach_grenade()
. = ..()
/obj/item/integrated_circuit/manipulation/grenade/attackby(var/obj/item/weapon/grenade/G, var/mob/user)
if(istype(G))
if(attached_grenade)
to_chat(user, "<span class='warning'>There is already a grenade attached!</span>")
else if(user.unEquip(G, force=1))
user.visible_message("<span class='warning'>\The [user] attaches \a [G] to \the [src]!</span>", "<span class='notice'>You attach \the [G] to \the [src].</span>")
attach_grenade(G)
G.forceMove(src)
else
..()
/obj/item/integrated_circuit/manipulation/grenade/attack_self(var/mob/user)
if(attached_grenade)
user.visible_message("<span class='warning'>\The [user] removes \an [attached_grenade] from \the [src]!</span>", "<span class='notice'>You remove \the [attached_grenade] from \the [src].</span>")
user.put_in_any_hand_if_possible(attached_grenade) || attached_grenade.dropInto(loc)
detach_grenade()
else
..()
/obj/item/integrated_circuit/manipulation/grenade/do_work()
if(attached_grenade && !attached_grenade.active)
var/datum/integrated_io/detonation_time = inputs[1]
if(isnum(detonation_time.data) && detonation_time.data > 0)
attached_grenade.det_time = between(1, detonation_time.data, 12) SECONDS
attached_grenade.activate()
var/atom/holder = loc
log_and_message_admins("activated a grenade assembly. Last touches: Assembly: [holder.fingerprintslast] Circuit: [fingerprintslast] Grenade: [attached_grenade.fingerprintslast]")
// These procs do not relocate the grenade, that's the callers responsibility
/obj/item/integrated_circuit/manipulation/grenade/proc/attach_grenade(var/obj/item/weapon/grenade/G)
attached_grenade = G
attached_grenade.OnDestroy(CALLBACK(src, .proc/detach_grenade))
size += G.w_class
desc += " \An [attached_grenade] is attached to it!"
/obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade()
if(!attached_grenade)
return
attached_grenade.UnregisterOnDestroy(src)
attached_grenade = null
size = initial(size)
desc = initial(desc)
/obj/item/integrated_circuit/manipulation/grenade/frag
pre_attached_grenade_type = /obj/item/weapon/grenade/frag
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 10)
spawn_flags = null // Used for world initializing, see the #defines above.

View File

@@ -0,0 +1,125 @@
/obj/item/integrated_circuit/memory
complexity = 1
category_text = "Memory"
power_draw_per_use = 1
/obj/item/integrated_circuit/memory/storage
name = "memory chip"
icon_state = "memory"
desc = "This tiny chip can store one piece of data."
inputs = list()
outputs = list()
activators = list(
"set" = IC_PINTYPE_PULSE_IN,
"on set" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/number_of_pins = 1
/obj/item/integrated_circuit/memory/storage/Initialize()
for(var/i = 1 to number_of_pins)
inputs["input [i]"] = IC_PINTYPE_ANY // This is just a string since pins don't get built until ..() is called.
outputs["output [i]"] = IC_PINTYPE_ANY
complexity = number_of_pins
. = ..()
/obj/item/integrated_circuit/memory/storage/examine(mob/user)
..()
var/i
for (i in 1 to outputs.len)
var/datum/integrated_io/O = outputs[i]
var/data = "nothing"
if(isweakref(O.data))
var/datum/d = O.data_as_type(/datum)
if(d)
data = "[d]"
else if(!isnull(O.data))
data = O.data
to_chat(user, "\The [src] has [data] saved to address [i].")
/obj/item/integrated_circuit/memory/storage/do_work()
for(var/i = 1 to inputs.len)
var/data = get_pin_data(IC_INPUT, i)
set_pin_data(IC_OUTPUT, i, data)
activate_pin(2)
/obj/item/integrated_circuit/memory/storage/medium
name = "memory circuit"
desc = "This circuit can store four pieces of data."
icon_state = "memory4"
power_draw_per_use = 2
number_of_pins = 4
/obj/item/integrated_circuit/memory/storage/large
name = "large memory circuit"
desc = "This big circuit can hold eight pieces of data."
icon_state = "memory8"
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
power_draw_per_use = 4
number_of_pins = 8
/obj/item/integrated_circuit/memory/storage/huge
name = "large memory stick"
desc = "This stick of memory can hold up up to sixteen pieces of data."
icon_state = "memory16"
w_class = ITEMSIZE_NORMAL
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4)
power_draw_per_use = 8
number_of_pins = 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"
inputs = list()
outputs = list("output pin" = IC_PINTYPE_ANY)
activators = list(
"push data" = IC_PINTYPE_PULSE_IN,
"on push" = IC_PINTYPE_PULSE_OUT
)
var/accepting_refs = 0
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/data
/obj/item/integrated_circuit/memory/constant/do_work()
set_pin_data(IC_OUTPUT, 1, data)
activate_pin(2)
/obj/item/integrated_circuit/memory/constant/attack_self(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","ref", "null")
if(!CanInteract(user, physical_state))
return
var/new_data = null
switch(type_to_use)
if("string")
accepting_refs = 0
new_data = sanitize(input("Now type in a string.","[src] string writing") as null|text)
if(istext(new_data) && CanInteract(user, physical_state))
data = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [O.display_data(data)].</span>")
if("number")
accepting_refs = 0
new_data = input("Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && CanInteract(user, physical_state))
data = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [O.display_data(data)].</span>")
if("ref")
accepting_refs = 1
to_chat(user, "<span class='notice'>You turn \the [src]'s ref scanner on. Slide it across \
an object for a ref of that object to save it in memory.</span>")
if("null")
data = null
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
/obj/item/integrated_circuit/memory/constant/afterattack(atom/target, mob/living/user, proximity)
if(accepting_refs && proximity)
var/datum/integrated_io/O = outputs[1]
data = WEAKREF(target)
visible_message("<span class='notice'>[user] slides [src]'s ref scanner over \the [target].</span>")
to_chat(user, "<span class='notice'>You set \the [src]'s memory to a reference to [O.display_data(data)]. The ref scanner is \
now off.</span>")
accepting_refs = 0

View File

@@ -0,0 +1,352 @@
/obj/item/integrated_circuit/output
category_text = "Output"
/obj/item/integrated_circuit/output/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" = IC_PINTYPE_ANY)
outputs = list()
activators = list("load data" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 10
var/stuff_to_display = null
/obj/item/integrated_circuit/output/screen/disconnect_all()
..()
stuff_to_display = null
/obj/item/integrated_circuit/output/screen/any_examine(mob/user)
if (displayed_name)
to_chat(user, "There is a little screen labeled '[displayed_name]', which displays [!isnull(stuff_to_display) ? "'[stuff_to_display]'" : "nothing"].")
else
to_chat(user, "There is an unlabelled little screen, which displays [!isnull(stuff_to_display) ? "'[stuff_to_display]'" : "nothing"].")
/obj/item/integrated_circuit/output/screen/do_work()
var/datum/integrated_io/I = inputs[1]
if(isweakref(I.data))
var/datum/d = I.data_as_type(/datum)
if(d)
stuff_to_display = "[d]"
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"
power_draw_per_use = 20
/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 = assembly ? assembly : src
to_chat(M, "<span class='notice'>\icon[O] [stuff_to_display]</span>")
/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"
power_draw_per_use = 40
/obj/item/integrated_circuit/output/screen/large/do_work()
..()
var/obj/O = assembly ? loc : assembly
O.visible_message("<span class='notice'>\icon[O] [stuff_to_display]</span>")
/obj/item/integrated_circuit/output/light
name = "light"
desc = "This light can turn on and off on command."
icon_state = "light"
complexity = 4
inputs = list()
outputs = list()
activators = list("toggle light" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/light_toggled = 0
var/light_brightness = 3
var/light_rgb = "#FFFFFF"
power_draw_idle = 0 // Adjusted based on brightness.
/obj/item/integrated_circuit/output/light/do_work()
light_toggled = !light_toggled
update_lighting()
/obj/item/integrated_circuit/output/light/proc/update_lighting()
if(light_toggled)
if(assembly)
assembly.set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb)
else
if(assembly)
assembly.set_light(0)
power_draw_idle = light_toggled ? light_brightness * 2 : 0
/obj/item/integrated_circuit/output/light/advanced/update_lighting()
var/new_color = get_pin_data(IC_INPUT, 1)
var/brightness = get_pin_data(IC_INPUT, 2)
if(new_color && isnum(brightness))
brightness = Clamp(brightness, 0, 6)
light_rgb = new_color
light_brightness = brightness
..()
/obj/item/integrated_circuit/output/light/power_fail() // Turns off the flashlight if there's no power left.
light_toggled = FALSE
update_lighting()
/obj/item/integrated_circuit/output/light/advanced
name = "advanced light"
desc = "This light can turn on and off on command, in any color, and in various brightness levels."
icon_state = "light_adv"
complexity = 8
inputs = list(
"color" = IC_PINTYPE_COLOR,
"brightness" = IC_PINTYPE_NUMBER
)
outputs = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
/obj/item/integrated_circuit/output/light/advanced/on_data_written()
update_lighting()
/obj/item/integrated_circuit/output/sound
name = "speaker circuit"
desc = "A miniature speaker is attached to this component."
icon_state = "speaker"
complexity = 8
cooldown_per_use = 4 SECONDS
inputs = list(
"sound ID" = IC_PINTYPE_STRING,
"volume" = IC_PINTYPE_NUMBER,
"frequency" = IC_PINTYPE_BOOLEAN
)
outputs = list()
activators = list("play sound" = IC_PINTYPE_PULSE_IN)
power_draw_per_use = 20
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" = IC_PINTYPE_STRING)
outputs = list()
activators = list("to speech" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 60
/obj/item/integrated_circuit/output/text_to_speech/do_work()
text = get_pin_data(IC_INPUT, 1)
if(!isnull(text))
var/obj/O = assembly ? loc : assembly
audible_message("\icon[O] \The [O.name] states, \"[text]\"")
/obj/item/integrated_circuit/output/sound/Initialize()
. = ..()
extended_desc = list()
extended_desc += "The first input pin determines which sound is used. The choices are; "
extended_desc += jointext(sounds, ", ")
extended_desc += ". The second pin determines the volume of sound that is played"
extended_desc += ", and the third determines if the frequency of the sound will vary with each activation."
extended_desc = jointext(extended_desc, null)
/obj/item/integrated_circuit/output/sound/do_work()
var/ID = get_pin_data(IC_INPUT, 1)
var/vol = get_pin_data(IC_INPUT, 2)
var/freq = get_pin_data(IC_INPUT, 3)
if(!isnull(ID) && !isnull(vol))
var/selected_sound = sounds[ID]
if(!selected_sound)
return
vol = between(0, vol, 100)
playsound(get_turf(src), selected_sound, vol, freq, -1)
/obj/item/integrated_circuit/output/sound/beeper
name = "beeper circuit"
desc = "A miniature speaker is attached to this component. This is often used in the construction of motherboards, which use \
the speaker to tell the user if something goes very wrong when booting up. It can also do other similar synthetic sounds such \
as buzzing, pinging, chiming, and more."
sounds = list(
"beep" = 'sound/machines/twobeep.ogg',
"chime" = 'sound/machines/chime.ogg',
"buzz sigh" = 'sound/machines/buzz-sigh.ogg',
"buzz twice" = 'sound/machines/buzz-two.ogg',
"ping" = 'sound/machines/ping.ogg',
"synth yes" = 'sound/machines/synth_yes.ogg',
"synth no" = 'sound/machines/synth_no.ogg',
"warning buzz" = 'sound/machines/warning-buzzer.ogg'
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/output/sound/beepsky
name = "securitron sound circuit"
desc = "A miniature speaker is attached to this component. Considered by some to be the essential component for a securitron."
sounds = list(
"creep" = 'sound/voice/bcreep.ogg',
"criminal" = 'sound/voice/bcriminal.ogg',
"freeze" = 'sound/voice/bfreeze.ogg',
"god" = 'sound/voice/bgod.ogg',
"i am the law" = 'sound/voice/biamthelaw.ogg',
"insult" = 'sound/voice/binsult.ogg',
"radio" = 'sound/voice/bradio.ogg',
"secure day" = 'sound/voice/bsecureday.ogg'
)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 1)
/obj/item/integrated_circuit/output/sound/medbot
name = "medbot sound circuit"
desc = "A miniature speaker is attached to this component, used to annoy patients while they get pricked by a medbot."
sounds = list(
"surgeon" = 'sound/voice/medbot/msurgeon.ogg',
"radar" = 'sound/voice/medbot/mradar.ogg',
"feel better" = 'sound/voice/medbot/mfeelbetter.ogg',
"patched up" = 'sound/voice/medbot/mpatchedup.ogg',
"injured" = 'sound/voice/medbot/minjured.ogg',
"insult" = 'sound/voice/medbot/minsult.ogg',
"coming" = 'sound/voice/medbot/mcoming.ogg',
"help" = 'sound/voice/medbot/mhelp.ogg',
"live" = 'sound/voice/medbot/mlive.ogg',
"lost" = 'sound/voice/medbot/mlost.ogg',
"flies" = 'sound/voice/medbot/mflies.ogg',
"catch" = 'sound/voice/medbot/mcatch.ogg',
"delicious" = 'sound/voice/medbot/mdelicious.ogg',
"apple" = 'sound/voice/medbot/mapple.ogg',
"no" = 'sound/voice/medbot/mno.ogg'
)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 1)
/obj/item/integrated_circuit/output/video_camera
name = "video camera circuit"
desc = "This small camera allows a remote viewer to see what it sees."
extended_desc = "The camera is linked to the Research camera network."
icon_state = "video_camera"
w_class = ITEMSIZE_SMALL
complexity = 10
inputs = list(
"camera name" = IC_PINTYPE_STRING,
"camera active" = IC_PINTYPE_BOOLEAN
)
inputs_default = list("1" = "video camera circuit")
outputs = list()
activators = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_idle = 5 // Raises to 80 when on.
var/obj/machinery/camera/network/research/camera
/obj/item/integrated_circuit/output/video_camera/Initialize()
. = ..()
camera = new(src)
on_data_written()
/obj/item/integrated_circuit/output/video_camera/Destroy()
QDEL_NULL(camera)
return ..()
/obj/item/integrated_circuit/output/video_camera/proc/set_camera_status(var/status)
if(camera)
camera.set_status(status)
power_draw_idle = camera.status ? 80 : 5
if(camera.status) // Ensure that there's actually power.
if(!draw_idle_power())
power_fail()
/obj/item/integrated_circuit/output/video_camera/on_data_written()
if(camera)
var/cam_name = get_pin_data(IC_INPUT, 1)
var/cam_active = get_pin_data(IC_INPUT, 2)
if(!isnull(cam_name))
camera.c_tag = cam_name
set_camera_status(cam_active)
/obj/item/integrated_circuit/output/video_camera/power_fail()
if(camera)
set_camera_status(0)
set_pin_data(IC_INPUT, 2, FALSE)
/obj/item/integrated_circuit/output/led
name = "light-emitting diode"
desc = "This a LED that is lit whenever there is TRUE-equivalent data on its input."
extended_desc = "TRUE-equivalent values are: Non-empty strings, non-zero numbers, and valid refs."
complexity = 0.1
icon_state = "led"
inputs = list("lit" = IC_PINTYPE_BOOLEAN)
outputs = list()
activators = list()
power_draw_idle = 0 // Raises to 1 when lit.
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/led_color
var/color_name
/obj/item/integrated_circuit/output/led/on_data_written()
power_draw_idle = get_pin_data(IC_INPUT, 1) ? 1 : 0
/obj/item/integrated_circuit/output/led/power_fail()
set_pin_data(IC_INPUT, 1, FALSE)
/obj/item/integrated_circuit/output/led/any_examine(mob/user)
var/text_output = list()
var/initial_name = initial(name)
// Doing all this work just to have a color-blind friendly output.
text_output += "There is "
if(name == initial_name)
text_output += "\an [name]"
else
text_output += "\an ["\improper[initial_name]"] labeled '[name]'"
text_output += " which is currently [get_pin_data(IC_INPUT, 1) ? "lit <font color=[led_color]>[color_name]</font>" : "unlit."]"
to_chat(user,jointext(text_output,null))
/obj/item/integrated_circuit/output/led/red
name = "red LED"
led_color = COLOR_RED
color_name = "red"
/obj/item/integrated_circuit/output/led/orange
name = "orange LED"
led_color = COLOR_ORANGE
color_name = "orange"
/obj/item/integrated_circuit/output/led/yellow
name = "yellow LED"
led_color = COLOR_YELLOW
color_name = "yellow"
/obj/item/integrated_circuit/output/led/green
name = "green LED"
led_color = COLOR_GREEN
color_name = "green"
/obj/item/integrated_circuit/output/led/blue
name = "blue LED"
led_color = COLOR_BLUE
color_name = "blue"
/obj/item/integrated_circuit/output/led/purple
name = "purple LED"
led_color = COLOR_PURPLE
color_name = "purple"
/obj/item/integrated_circuit/output/led/cyan
name = "cyan LED"
led_color = COLOR_CYAN
color_name = "cyan"
/obj/item/integrated_circuit/output/led/white
name = "white LED"
led_color = COLOR_WHITE
color_name = "white"
/obj/item/integrated_circuit/output/led/pink
name = "pink LED"
led_color = COLOR_PINK
color_name = "pink"

View File

@@ -0,0 +1,88 @@
/obj/item/integrated_circuit/power/
category_text = "Power - Active"
/obj/item/integrated_circuit/power/transmitter
name = "power transmission circuit"
desc = "This can wirelessly transmit electricity from an assembly's battery towards a nearby machine."
icon_state = "power_transmitter"
extended_desc = "This circuit transmits 5 kJ of electricity every time the activator pin is pulsed. The input pin must be \
a reference to a machine to send electricity to. This can be a battery, or anything containing a battery. The machine can exist \
inside the assembly, or adjacent to it. The power is sourced from the assembly's power cell. If the target is outside of the assembly, \
some power is lost due to ineffiency."
w_class = ITEMSIZE_SMALL
complexity = 16
inputs = list("target" = IC_PINTYPE_REF)
outputs = list(
"target cell charge" = IC_PINTYPE_NUMBER,
"target cell max charge" = IC_PINTYPE_NUMBER,
"target cell percentage" = IC_PINTYPE_NUMBER
)
activators = list("transmit" = IC_PINTYPE_PULSE_IN, "on transmit" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3)
power_draw_per_use = 500 // Inefficency has to come from somewhere.
var/amount_to_move = 5000
/obj/item/integrated_circuit/power/transmitter/large
name = "large power transmission circuit"
desc = "This can wirelessly transmit a lot of electricity from an assembly's battery towards a nearby machine. Warning: Do not operate in flammable enviroments."
extended_desc = "This circuit transmits 20 kJ of electricity every time the activator pin is pulsed. The input pin must be \
a reference to a machine to send electricity to. This can be a battery, or anything containing a battery. The machine can exist \
inside the assembly, or adjacent to it. The power is sourced from the assembly's power cell. If the target is outside of the assembly, \
some power is lost due to ineffiency."
w_class = ITEMSIZE_LARGE
complexity = 32
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 6, TECH_MAGNET = 5)
power_draw_per_use = 2000
amount_to_move = 20000
/obj/item/integrated_circuit/power/transmitter/do_work()
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(AM && assembly)
var/obj/item/weapon/cell/cell = null
if(istype(AM, /obj/item/weapon/cell)) // Is this already a cell?
cell = AM
else // If not, maybe there's a cell inside it?
for(var/obj/item/weapon/cell/C in AM.contents)
if(C) // Find one cell to charge.
cell = C
break
if(cell)
var/transfer_amount = amount_to_move
var/turf/A = get_turf(src)
var/turf/B = get_turf(AM)
if(A.Adjacent(B))
if(AM.loc != assembly)
transfer_amount *= 0.8 // Losses due to distance.
if(cell.fully_charged())
set_pin_data(IC_OUTPUT, 1, cell.charge)
set_pin_data(IC_OUTPUT, 2, cell.maxcharge)
set_pin_data(IC_OUTPUT, 3, cell.percent())
push_data()
return FALSE
if(transfer_amount && assembly.draw_power(amount_to_move)) // CELLRATE is already handled in draw_power()
cell.give(transfer_amount * CELLRATE)
AM.update_icon()
set_pin_data(IC_OUTPUT, 1, cell.charge)
set_pin_data(IC_OUTPUT, 2, cell.maxcharge)
set_pin_data(IC_OUTPUT, 3, cell.percent())
push_data()
activate_pin(2)
return TRUE
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
set_pin_data(IC_OUTPUT, 3, null)
push_data()
return FALSE
/obj/item/integrated_circuit/power/transmitter/large/do_work()
if(..()) // If the above code succeeds, do this below.
if(prob(2))
spark(src, 3)
visible_message("<span class='warning'>\The [assembly] makes some sparks!</span>")

View File

@@ -0,0 +1,160 @@
/obj/item/integrated_circuit/reagent
category_text = "Reagent"
var/volume = 0
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
/obj/item/integrated_circuit/reagent/Initialize()
. = ..()
if(volume)
create_reagents(volume)
/obj/item/integrated_circuit/reagent/smoke
name = "smoke generator"
desc = "Unlike most electronics, creating smoke is completely intentional."
icon_state = "smoke"
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. The reagents are consumed when smoke is made."
flags = OPENCONTAINER
complexity = 20
cooldown_per_use = 30 SECONDS
inputs = list()
outputs = list()
activators = list("create smoke" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3)
volume = 100
power_draw_per_use = 20
/obj/item/integrated_circuit/reagent/smoke/do_work()
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()
/obj/item/integrated_circuit/reagent/injector
name = "integrated hypo-injector"
desc = "This scary looking thing is able to pump liquids into whatever it's pointed at."
icon_state = "injector"
extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine. The target \
must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing."
flags = OPENCONTAINER
complexity = 20
cooldown_per_use = 6 SECONDS
inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER)
inputs_default = list("2" = 5)
outputs = list()
activators = list("inject" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
volume = 30
power_draw_per_use = 15
/obj/item/integrated_circuit/reagent/injector/proc/inject_amount()
var/amount = get_pin_data(IC_INPUT, 2)
if(isnum(amount))
return Clamp(amount, 0, 30)
/obj/item/integrated_circuit/reagent/injector/do_work()
set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(!istype(AM)) //Invalid input
return
if(!reagents.total_volume) // Empty
return
if(AM.can_be_injected_by(src))
if(isliving(AM))
var/mob/living/L = AM
var/turf/T = get_turf(AM)
T.visible_message("<span class='warning'>[src] is trying to inject [L]!</span>")
sleep(3 SECONDS)
if(!L.can_be_injected_by(src))
return
var/contained = reagents.get_reagents()
var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD)
message_admins("[src] injected \the [L] with [trans]u of [contained].")
to_chat(AM, "<span class='notice'>You feel a tiny prick!</span>")
visible_message("<span class='warning'>[src] injects [L]!</span>")
else
reagents.trans_to(AM, inject_amount())
/obj/item/integrated_circuit/reagent/pump
name = "reagent pump"
desc = "Moves liquids safely inside a machine, or even nearby it."
icon_state = "reagent_pump"
extended_desc = "This is a pump, which will move liquids from the source ref to the target ref. The third pin determines \
how much liquid is moved per pulse, between 0 and 50. The pump can move reagents to any open container inside the machine, or \
outside the machine if it is next to the machine. Note that this cannot be used on entities."
flags = OPENCONTAINER
complexity = 8
inputs = list(
"source" = IC_PINTYPE_REF,
"target" = IC_PINTYPE_REF,
"injection amount" = IC_PINTYPE_NUMBER
)
inputs_default = list("3" = 5)
outputs = list()
activators = list(
"transfer reagents" = IC_PINTYPE_PULSE_IN,
"on transfer" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
var/transfer_amount = 10
power_draw_per_use = 10
/obj/item/integrated_circuit/reagent/pump/on_data_written()
var/new_amount = get_pin_data(IC_INPUT, 3)
if(!isnull(new_amount))
new_amount = Clamp(new_amount, 0, 50)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/pump/do_work()
var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable)
if(!istype(source) || !istype(target)) //Invalid input
return
var/turf/T = get_turf(src)
if(source.Adjacent(T) && target.Adjacent(T))
if(!source.reagents || !target.reagents)
return
if(ismob(source) || ismob(target))
return
if(!source.is_open_container() || !target.is_open_container())
return
if(!target.reagents.get_free_space())
return
source.reagents.trans_to(target, transfer_amount)
activate_pin(2)
/obj/item/integrated_circuit/reagent/storage
name = "reagent storage"
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u."
icon_state = "reagent_storage"
extended_desc = "This is effectively an internal beaker."
flags = OPENCONTAINER
complexity = 4
inputs = list()
outputs = list("volume used" = IC_PINTYPE_NUMBER)
activators = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
volume = 60
/obj/item/integrated_circuit/reagent/storage/on_reagent_change()
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
/obj/item/integrated_circuit/reagent/storage/cryo
name = "cryo reagent storage"
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. This will also suppress reactions."
icon_state = "reagent_storage_cryo"
extended_desc = "This is effectively an internal cryo beaker."
flags = OPENCONTAINER | NOREACT
complexity = 8
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_MATERIALS = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)

View File

@@ -0,0 +1,33 @@
/obj/item/integrated_circuit/smart
category_text = "Smart"
/obj/item/integrated_circuit/smart/basic_pathfinder
name = "basic pathfinder"
desc = "This complex circuit is able to determine what direction a given target is."
extended_desc = "This circuit uses a miniturized, integrated camera to determine where the target is. If the machine \
cannot see the target, it will not be able to calculate the correct direction."
icon_state = "numberpad"
complexity = 25
inputs = list("target" = IC_PINTYPE_REF)
outputs = list("dir" = IC_PINTYPE_DIR)
activators = list("calculate dir" = IC_PINTYPE_PULSE_IN, "on calculated" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5)
power_draw_per_use = 40
/obj/item/integrated_circuit/smart/basic_pathfinder/do_work()
var/datum/integrated_io/I = inputs[1]
set_pin_data(IC_OUTPUT, 1, null)
if(!isweakref(I.data))
return
var/atom/A = I.data.resolve()
if(!A)
return
if(!(A in view(get_turf(src))))
return // Can't see the target.
var/desired_dir = get_dir(get_turf(src), A)
set_pin_data(IC_OUTPUT, 1, desired_dir)
push_data()
activate_pin(2)

View File

@@ -0,0 +1,147 @@
/obj/item/integrated_circuit/time
name = "time circuit"
desc = "Now you can build your own clock!"
complexity = 2
inputs = list()
outputs = list()
category_text = "Time"
/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."
icon_state = "delay-20"
var/delay = 2 SECONDS
activators = list("incoming"= IC_PINTYPE_PULSE_IN,"outgoing" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/time/delay/do_work()
addtimer(CALLBACK(src, /obj/item/integrated_circuit/.proc/activate_pin, 2), delay)
/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."
icon_state = "delay-50"
delay = 5 SECONDS
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/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."
icon_state = "delay-10"
delay = 1 SECOND
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/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."
icon_state = "delay-5"
delay = 5
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/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."
icon_state = "delay-1"
delay = 1
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/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."
icon_state = "delay"
inputs = list("delay time" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/custom/do_work()
var/delay_input = get_pin_data(IC_INPUT, 1)
if(delay_input && isnum(delay_input) )
var/new_delay = between(1, delay_input, 1 HOUR)
delay = new_delay
..()
/obj/item/integrated_circuit/time/ticker
name = "ticker circuit"
desc = "This circuit sends an automatic pulse every four seconds."
icon_state = "tick-m"
complexity = 8
var/ticks_to_pulse = 4
var/ticks_completed = 0
var/is_running = FALSE
inputs = list("enable ticking" = IC_PINTYPE_BOOLEAN)
activators = list("outgoing pulse" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/time/ticker/Destroy()
STOP_PROCESSING(SSelectronics, src)
. = ..()
/obj/item/integrated_circuit/time/ticker/on_data_written()
var/do_tick = get_pin_data(IC_INPUT, 1)
if(do_tick && !is_running)
is_running = TRUE
START_PROCESSING(SSelectronics, src)
else if(is_running)
is_running = FALSE
STOP_PROCESSING(SSelectronics, src)
ticks_completed = 0
/obj/item/integrated_circuit/time/ticker/process()
var/process_ticks = SSelectronics.wait
ticks_completed += process_ticks
if(ticks_completed >= ticks_to_pulse)
if(ticks_to_pulse >= process_ticks)
ticks_completed -= ticks_to_pulse
else
ticks_completed = 0
activate_pin(1)
/obj/item/integrated_circuit/time/ticker/fast
name = "fast ticker"
desc = "This advanced circuit sends an automatic pulse every two seconds."
icon_state = "tick-f"
complexity = 12
ticks_to_pulse = 2
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 8
/obj/item/integrated_circuit/time/ticker/slow
name = "slow ticker"
desc = "This simple circuit sends an automatic pulse every six seconds."
icon_state = "tick-s"
complexity = 4
ticks_to_pulse = 6
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/time/clock
name = "integrated clock"
desc = "Tells you what the local time is, specific to your station, planet, or facility."
icon_state = "clock"
inputs = list()
outputs = list(
"time" = IC_PINTYPE_STRING,
"hours" = IC_PINTYPE_NUMBER,
"minutes" = IC_PINTYPE_NUMBER,
"seconds" = IC_PINTYPE_NUMBER
)
activators = list("get time" = IC_PINTYPE_PULSE_IN, "on time got" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/time/clock/do_work()
set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") )
set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) )
set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) )
set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) )
push_data()
activate_pin(2)

View File

@@ -0,0 +1,143 @@
//These circuits do not-so-simple math.
/obj/item/integrated_circuit/trig
complexity = 1
inputs = list(
"A" = IC_PINTYPE_NUMBER,
"B" = IC_PINTYPE_NUMBER,
"C" = IC_PINTYPE_NUMBER,
"D" = IC_PINTYPE_NUMBER,
"E" = IC_PINTYPE_NUMBER,
"F" = IC_PINTYPE_NUMBER,
"G" = IC_PINTYPE_NUMBER,
"H" = IC_PINTYPE_NUMBER
)
outputs = list("result" = IC_PINTYPE_NUMBER)
activators = list(
"compute" = IC_PINTYPE_PULSE_IN,
"on computed" = IC_PINTYPE_PULSE_OUT
)
category_text = "Trig"
extended_desc = "Input and output are in degrees."
power_draw_per_use = 1 // Still cheap math.
// 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" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/sine/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = sin(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cosine //
/obj/item/integrated_circuit/trig/cosine
name = "cos circuit"
desc = "Outputs the cosine of A."
icon_state = "cosine"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cosine/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = cos(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// 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" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/tangent/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = Tan(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cosecant //
/obj/item/integrated_circuit/trig/cosecant
name = "csc circuit"
desc = "Outputs the cosecant of A."
icon_state = "cosecant"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cosecant/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = Csc(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// 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" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/secant/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = Sec(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cotangent //
/obj/item/integrated_circuit/trig/cotangent
name = "cot circuit"
desc = "Outputs the cotangent of A."
icon_state = "cotangent"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cotangent/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = Cot(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)

View File

@@ -0,0 +1,36 @@
#undef IC_INPUT
#undef IC_OUTPUT
#undef IC_ACTIVATOR
#undef DATA_CHANNEL
#undef PULSE_CHANNEL
#undef IC_SPAWN_DEFAULT
//#undef IC_SPAWN_RESEARCH // Research designs depend on this unfortunately.
#undef IC_FORMAT_ANY
#undef IC_FORMAT_STRING
#undef IC_FORMAT_CHAR
#undef IC_FORMAT_COLOR
#undef IC_FORMAT_NUMBER
#undef IC_FORMAT_DIR
#undef IC_FORMAT_BOOLEAN
#undef IC_FORMAT_REF
#undef IC_FORMAT_LIST
#undef IC_FORMAT_PULSE
#undef IC_PINTYPE_ANY
#undef IC_PINTYPE_STRING
#undef IC_PINTYPE_CHAR
#undef IC_PINTYPE_COLOR
#undef IC_PINTYPE_NUMBER
#undef IC_PINTYPE_DIR
#undef IC_PINTYPE_BOOLEAN
#undef IC_PINTYPE_REF
#undef IC_PINTYPE_LIST
#undef IC_PINTYPE_PULSE_IN
#undef IC_PINTYPE_PULSE_OUT
#undef IC_MAX_LIST_LENGTH

View File

@@ -201,6 +201,59 @@
user.setMoveCooldown(move_delay)
next_fire_time = world.time + fire_delay
// 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)
addtimer(CALLBACK(src, /atom/.proc/set_light, 0), 2, TIMER_UNIQUE | TIMER_OVERRIDE)
update_icon()
if(i < burst)
sleep(burst_delay)
if(!(target && target.loc))
target = targloc
//update timing
next_fire_time = world.time + fire_delay
accuracy = initial(accuracy) //Reset the gun's accuracy
//obtains the next projectile to fire
/obj/item/weapon/gun/proc/consume_next_projectile()
return null

View File

@@ -0,0 +1,14 @@
/atom/movable/proc/can_be_injected_by(var/atom/injector)
if(!Adjacent(get_turf(injector)))
return FALSE
if(!reagents)
return FALSE
if(!reagents.get_free_space())
return FALSE
return TRUE
/obj/can_be_injected_by(var/atom/injector)
return is_open_container() && ..()
/mob/living/can_be_injected_by(var/atom/injector)
return ..() && (can_inject(null, 0, "chest") || can_inject(null, 0, "groin"))

View File

@@ -345,3 +345,92 @@ other types of metals and chemistry for reagents).
id = "cart_captain"
build_path = /obj/item/weapon/cartridge/captain
sort_string = "VBAAO"
// Integrated Electronics stuff.
/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/debugger
name = "Custom circuit debugger tool"
id = "debugger"
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500)
build_path = /obj/item/device/integrated_electronics/debugger
sort_string = "VBVAB"
/datum/design/item/custom_circuit_assembly
name = "Small custom assembly"
desc = "A 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 = "A 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
sort_string = "VCAAB"
/datum/design/item/custom_circuit_assembly/drone
name = "Drone custom assembly"
desc = "A customizable assembly optimized for autonomous devices."
id = "assembly-drone"
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"
desc = "A 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
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"
/datum/design/item/custom_circuit_assembly/device
name = "Device custom assembly"
desc = "An customizable assembly designed to interface with other devices."
id = "assembly-device"
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2)
materials = list(DEFAULT_WALL_MATERIAL = 5000)
build_path = /obj/item/device/assembly/electronic_assembly
sort_string = "VCAAF"
/datum/design/item/custom_circuit_printer
name = "Portable integrated circuit printer"
desc = "A portable(ish) printer for modular machines."
id = "ic_printer"
req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4, TECH_DATA = 5)
materials = list(DEFAULT_WALL_MATERIAL = 10000)
build_path = /obj/item/device/integrated_circuit_printer
sort_string = "VCAAG"
/datum/design/item/custom_circuit_printer_upgrade
name = "Integrated circuit printer upgrade - advanced designs"
desc = "Allows the integrated circuit printer to create advanced circuits"
id = "ic_printer_upgrade_adv"
req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4)
materials = list(DEFAULT_WALL_MATERIAL = 2000)
build_path = /obj/item/weapon/disk/integrated_circuit/upgrade/advanced
sort_string = "VCAAH"