mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-26 01:52:15 +00:00
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:
67
code/modules/integrated_electronics/_defines.dm
Normal file
67
code/modules/integrated_electronics/_defines.dm
Normal 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).
|
||||
336
code/modules/integrated_electronics/core/assemblies.dm
Normal file
336
code/modules/integrated_electronics/core/assemblies.dm
Normal 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
|
||||
81
code/modules/integrated_electronics/core/device.dm
Normal file
81
code/modules/integrated_electronics/core/device.dm
Normal 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
|
||||
78
code/modules/integrated_electronics/core/helpers.dm
Normal file
78
code/modules/integrated_electronics/core/helpers.dm
Normal 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
|
||||
355
code/modules/integrated_electronics/core/integrated_circuit.dm
Normal file
355
code/modules/integrated_electronics/core/integrated_circuit.dm
Normal 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()
|
||||
188
code/modules/integrated_electronics/core/pins.dm
Normal file
188
code/modules/integrated_electronics/core/pins.dm
Normal 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
|
||||
159
code/modules/integrated_electronics/core/printer.dm
Normal file
159
code/modules/integrated_electronics/core/printer.dm
Normal 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)
|
||||
@@ -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)"
|
||||
@@ -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
|
||||
@@ -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 ..()
|
||||
@@ -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 ..()
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
461
code/modules/integrated_electronics/core/tools.dm
Normal file
461
code/modules/integrated_electronics/core/tools.dm
Normal 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
|
||||
7
code/modules/integrated_electronics/passive/passive.dm
Normal file
7
code/modules/integrated_electronics/passive/passive.dm
Normal 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
|
||||
106
code/modules/integrated_electronics/passive/power.dm
Normal file
106
code/modules/integrated_electronics/passive/power.dm
Normal 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
|
||||
314
code/modules/integrated_electronics/subtypes/arithmetic.dm
Normal file
314
code/modules/integrated_electronics/subtypes/arithmetic.dm
Normal 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)
|
||||
|
||||
28
code/modules/integrated_electronics/subtypes/built_in.dm
Normal file
28
code/modules/integrated_electronics/subtypes/built_in.dm
Normal 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()
|
||||
238
code/modules/integrated_electronics/subtypes/converters.dm
Normal file
238
code/modules/integrated_electronics/subtypes/converters.dm
Normal 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)
|
||||
165
code/modules/integrated_electronics/subtypes/data_transfer.dm
Normal file
165
code/modules/integrated_electronics/subtypes/data_transfer.dm
Normal 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
|
||||
381
code/modules/integrated_electronics/subtypes/input.dm
Normal file
381
code/modules/integrated_electronics/subtypes/input.dm
Normal 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
|
||||
87
code/modules/integrated_electronics/subtypes/lists.dm
Normal file
87
code/modules/integrated_electronics/subtypes/lists.dm
Normal 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)
|
||||
135
code/modules/integrated_electronics/subtypes/logic.dm
Normal file
135
code/modules/integrated_electronics/subtypes/logic.dm
Normal 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
|
||||
188
code/modules/integrated_electronics/subtypes/manipulation.dm
Normal file
188
code/modules/integrated_electronics/subtypes/manipulation.dm
Normal 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.
|
||||
125
code/modules/integrated_electronics/subtypes/memory.dm
Normal file
125
code/modules/integrated_electronics/subtypes/memory.dm
Normal 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
|
||||
352
code/modules/integrated_electronics/subtypes/output.dm
Normal file
352
code/modules/integrated_electronics/subtypes/output.dm
Normal 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"
|
||||
88
code/modules/integrated_electronics/subtypes/power.dm
Normal file
88
code/modules/integrated_electronics/subtypes/power.dm
Normal 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>")
|
||||
160
code/modules/integrated_electronics/subtypes/reagents.dm
Normal file
160
code/modules/integrated_electronics/subtypes/reagents.dm
Normal 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)
|
||||
33
code/modules/integrated_electronics/subtypes/smart.dm
Normal file
33
code/modules/integrated_electronics/subtypes/smart.dm
Normal 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)
|
||||
147
code/modules/integrated_electronics/subtypes/time.dm
Normal file
147
code/modules/integrated_electronics/subtypes/time.dm
Normal 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)
|
||||
143
code/modules/integrated_electronics/subtypes/trig.dm
Normal file
143
code/modules/integrated_electronics/subtypes/trig.dm
Normal 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)
|
||||
36
code/modules/integrated_electronics/~defines/~defines.dm
Normal file
36
code/modules/integrated_electronics/~defines/~defines.dm
Normal 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
|
||||
@@ -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
|
||||
|
||||
14
code/modules/reagents/Chemistry-Reagents-Helpers.dm
Normal file
14
code/modules/reagents/Chemistry-Reagents-Helpers.dm
Normal 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"))
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user