diff --git a/code/game/gamemodes/technomancer/devices/gloves_of_regen.dm b/code/game/gamemodes/technomancer/devices/gloves_of_regen.dm index 9c18e774ed6..a4761c847a3 100644 --- a/code/game/gamemodes/technomancer/devices/gloves_of_regen.dm +++ b/code/game/gamemodes/technomancer/devices/gloves_of_regen.dm @@ -47,7 +47,7 @@ ..() /obj/item/clothing/gloves/regen/process() - if(!wearer || wearer.isSynthetic() || wearer.stat == DEAD || wearer.nutrition >= 10) + if(!wearer || wearer.isSynthetic() || wearer.stat == DEAD || wearer.nutrition <= 10) return // Robots and dead people don't have a metabolism. if(wearer.getBruteLoss()) diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index f9bbeb8f33a..c354d655765 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -14,8 +14,12 @@ return check_access(id) return 0 -/obj/item/proc/GetAccess() - return list() +///obj/item/proc/GetAccess() +// return list() + +/atom/movable/proc/GetAccess() + var/obj/item/weapon/card/id/id = GetIdCard() + return id ? id.GetAccess() : list() /obj/proc/GetID() return null @@ -197,7 +201,7 @@ "Emergency Response Team", "Emergency Response Team Leader") -/mob/proc/GetIdCard() +/atom/movable/proc/GetIdCard() return null /mob/living/bot/GetIdCard() diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 13168e19f46..43497523708 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -8,7 +8,7 @@ obj/machinery/recharger idle_power_usage = 4 active_power_usage = 40000 //40 kW var/obj/item/charging = null - var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/laptop, /obj/item/weapon/cell, /obj/item/device/flashlight) + var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/laptop, /obj/item/weapon/cell, /obj/item/device/flashlight, /obj/item/device/electronic_assembly) var/icon_state_charged = "recharger2" var/icon_state_charging = "recharger1" var/icon_state_idle = "recharger0" //also when unpowered @@ -60,6 +60,11 @@ obj/machinery/recharger if(!L.stored_computer.battery) user << "There's no battery in it!" return + if(istype(G, /obj/item/device/electronic_assembly)) + var/obj/item/device/electronic_assembly/assembly = G + if(!assembly.battery) + to_chat(user, "The assembly doesn't have a power cell.") + return user.drop_item() G.loc = src charging = G @@ -161,6 +166,21 @@ obj/machinery/recharger update_use_power(1) return + if(istype(charging, /obj/item/device/electronic_assembly)) + var/obj/item/device/electronic_assembly/assembly = charging + if(assembly.battery) + if(!assembly.battery.fully_charged()) + icon_state = icon_state_charging + assembly.battery.give(active_power_usage*CELLRATE) + update_use_power(2) + else + icon_state = icon_state_charged + update_use_power(1) + else + icon_state = icon_state_idle + update_use_power(1) + return + /obj/machinery/recharger/emp_act(severity) if(stat & (NOPOWER|BROKEN) || !anchored) ..(severity) diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm index d9daa035d54..c404f615812 100644 --- a/code/modules/integrated_electronics/_defines.dm +++ b/code/modules/integrated_electronics/_defines.dm @@ -8,6 +8,13 @@ #define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box. #define IC_SPAWN_RESEARCH 2 // If the circuit design will be autogenerated for RnD. +#define IC_FORMAT_STRING "\" +#define IC_FORMAT_NUMBER "\" +#define IC_FORMAT_REF "\" +#define IC_FORMAT_LIST "\" +#define IC_FORMAT_ANY "\" +#define IC_FORMAT_PULSE "\" + var/list/all_integrated_circuits = list() /proc/initialize_integrated_circuits_list() @@ -20,377 +27,19 @@ var/list/all_integrated_circuits = list() icon = 'icons/obj/electronic_assemblies.dmi' icon_state = "template" w_class = ITEMSIZE_TINY + var/obj/item/device/electronic_assembly/assembly = null // Reference to the assembly holding this circuit, if any. var/extended_desc = null var/list/inputs = list() var/list/outputs = list() var/list/activators = list() var/next_use = 0 //Uses world.time - var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'. - var/cooldown_per_use = 1 SECOND - var/spawn_flags = null // Used for world initializing, see the #defines above. - var/category_text = "NO CATEGORY" // To show up on circuit printer, and perhaps other places. - var/autopulse = -1 // When input is received, the circuit will pulse itself if set to 1. 0 means it won't. -1 means it is permanently off. - -/obj/item/integrated_circuit/examine(mob/user) - ..() - to_chat(user, "This board has [inputs.len] input pin\s and [outputs.len] output pin\s.") - for(var/datum/integrated_io/input/I in inputs) - if(I.linked.len) - to_chat(user, "The [I] is connected to [I.get_linked_to_desc()].") - for(var/datum/integrated_io/output/O in outputs) - if(O.linked.len) - to_chat(user, "The [O] is connected to [O.get_linked_to_desc()].") - for(var/datum/integrated_io/activate/A in activators) - if(A.linked.len) - to_chat(user, "The [A] is connected to [A.get_linked_to_desc()].") - - interact(user) - -/obj/item/integrated_circuit/New() - setup_io(inputs, /datum/integrated_io/input) - setup_io(outputs, /datum/integrated_io/output) - setup_io(activators, /datum/integrated_io/activate) - ..() - -/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type) - var/list/io_list_copy = io_list.Copy() - io_list.Cut() - for(var/io_entry in io_list_copy) - io_list.Add(new io_type(src, io_entry, io_list_copy[io_entry])) - -/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit. - return - -/obj/item/integrated_circuit/Destroy() - for(var/datum/integrated_io/I in inputs) - qdel(I) - for(var/datum/integrated_io/O in outputs) - qdel(O) - for(var/datum/integrated_io/A in activators) - qdel(A) - . = ..() - -/obj/item/integrated_circuit/nano_host() - if(istype(src.loc, /obj/item/device/electronic_assembly)) - 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/verb/rename_component() - set name = "Rename Circuit" - set category = "Object" - set desc = "Rename your circuit, useful to stay organized." - - var/mob/M = usr - if(!CanInteract(M, physical_state)) - return - - var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name) as null|text, MAX_NAME_LEN) - if(src && input && CanInteract(M, physical_state)) - to_chat(M, "The circuit '[src.name]' is now labeled '[input]'.") - name = input - -/obj/item/integrated_circuit/proc/get_pin_ref(var/pin_type, var/pin_number) - switch(pin_type) - if(IC_INPUT) - if(pin_number > inputs.len) - return null - return inputs[pin_number] - if(IC_OUTPUT) - if(pin_number > outputs.len) - return null - return outputs[pin_number] - if(IC_ACTIVATOR) - if(pin_number > activators.len) - return null - return activators[pin_number] - return null - -/obj/item/integrated_circuit/interact(mob/user) - if(!CanInteract(user, physical_state)) - return - - var/window_height = 350 - var/window_width = 600 - - //var/table_edge_width = "[(window_width - window_width * 0.1) / 4]px" - //var/table_middle_width = "[(window_width - window_width * 0.1) - (table_edge_width * 2)]px" - var/table_edge_width = "30%" - var/table_middle_width = "40%" - - var/HTML = list() - HTML += "[src.name]" - HTML += "
" - HTML += "" - - HTML += "
\[Refresh\] | " - HTML += "\[Rename\] | " - HTML += "\[Remove\]
" - - HTML += "" - //HTML += "" - //HTML += "" - //HTML += "" - HTML += "" - HTML += "" - HTML += "" - HTML += "" - - var/column_width = 3 - var/row_height = max(inputs.len, outputs.len, 1) - - for(var/i = 1 to row_height) - HTML += "" - 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) - if(io.linked.len) - words += "[io.name] [io.display_data()]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - else - words += "[io.name] [io.display_data()]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - if(outputs.len > inputs.len) - height = 1 - if(2) - if(i == 1) - words += "[src.name]

[src.desc]" - height = row_height - else - continue - if(3) - io = get_pin_ref(IC_OUTPUT, i) - if(io) - if(io.linked.len) - words += "[io.name] [io.display_data()]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - else - words += "[io.name] [io.display_data()]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - if(inputs.len > outputs.len) - height = 1 - HTML += "" - HTML += "" - - for(var/activator in activators) - var/datum/integrated_io/io = activator - var/words = list() - if(io.linked.len) - words += "[io.name]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - else - words += "[io.name]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - HTML += "" - HTML += "" - HTML += "" - - HTML += "
[jointext(words, null)]
[jointext(words, null)]
" - HTML += "
" - - if(autopulse != -1) - HTML += "
Meta Variables;" - HTML += "
\[Autopulse\] = [autopulse ? "ON" : "OFF"]" - HTML += "
" - - HTML += "
Complexity: [complexity]" - HTML += "
[extended_desc]" - - HTML += "" - user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") - - onclose(user, "circuit-\ref[src]") - -/obj/item/integrated_circuit/Topic(href, href_list, state = physical_state) - if(..()) - return 1 - var/pin = locate(href_list["pin"]) in inputs + outputs + activators - - var/obj/held_item = usr.get_active_hand() - if(href_list["wire"]) - if(istype(held_item, /obj/item/device/integrated_electronics/wirer)) - var/obj/item/device/integrated_electronics/wirer/wirer = held_item - if(pin) - wirer.wire(pin, usr) - - else if(istype(held_item, /obj/item/device/integrated_electronics/debugger)) - var/obj/item/device/integrated_electronics/debugger/debugger = held_item - if(pin) - debugger.write_data(pin, usr) - else - to_chat(usr, "You can't do a whole lot without the proper tools.") - - if(href_list["examine"]) - examine(usr) - - if(href_list["rename"]) - rename_component(usr) - - if(href_list["autopulse"]) - if(autopulse != -1) - autopulse = !autopulse - - if(href_list["remove"]) - if(istype(held_item, /obj/item/weapon/screwdriver)) - disconnect_all() - var/turf/T = get_turf(src) - forceMove(T) - playsound(T, 'sound/items/Crowbar.ogg', 50, 1) - to_chat(usr, "You pop \the [src] out of the case, and slide it out.") - else - to_chat(usr, "You need a screwdriver to remove components.") - var/obj/item/device/electronic_assembly/ea = loc - if(istype(ea)) - ea.interact(usr) - return - - interact(usr) // To refresh the UI. - -/datum/integrated_io - var/name = "input/output" - var/obj/item/integrated_circuit/holder = null - var/weakref/data = null // This is a weakref, to reduce typecasts. Note that oftentimes numbers and text may also occupy this. - var/list/linked = list() - var/io_type = DATA_CHANNEL - -/datum/integrated_io/New(var/newloc, var/name, var/data) - ..() - src.name = name - src.data = data - holder = newloc - if(!istype(holder)) - message_admins("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.") - -/datum/integrated_io/Destroy() - disconnect() - data = null - holder = null - . = ..() - -/datum/integrated_io/nano_host() - return holder.nano_host() + var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'. + 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 = null // 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/autopulse = -1 // When input is received, the circuit will pulse itself if set to 1. 0 means it won't. -1 means it is permanently off. + var/removable = TRUE // Determines if a circuit is removable from the assembly. -/datum/integrated_io/proc/data_as_type(var/as_type) - if(!isweakref(data)) - return - var/weakref/w = data - var/output = w.resolve() - return istype(output, as_type) ? output : null - -/datum/integrated_io/proc/display_data() - if(isnull(data)) - return "(null)" // Empty data means nothing to show. - if(istext(data)) - return "(\"[data]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'. - if(isweakref(data)) - var/weakref/w = data - var/atom/A = w.resolve() - //return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed. - return A ? "(\ref[A] \[Ref\])" : "(null)" - return "([data])" // Nothing special needed for numbers or other stuff. - -/datum/integrated_io/activate/display_data() - return "(\[pulse\])" - -/datum/integrated_io/proc/scramble() - if(isnull(data)) - return - if(isnum(data)) - write_data_to_pin(rand(-10000, 10000)) - if(istext(data)) - write_data_to_pin("ERROR") - push_data() - -/datum/integrated_io/activate/scramble() - push_data() - -/datum/integrated_io/proc/write_data_to_pin(var/new_data) - if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data)) // Anything else is a type we don't want. - data = new_data - holder.on_data_written() - -/datum/integrated_io/proc/push_data() - for(var/datum/integrated_io/io in linked) - io.write_data_to_pin(data) - -/datum/integrated_io/activate/push_data() - for(var/datum/integrated_io/io in linked) - io.holder.check_then_do_work() - -/datum/integrated_io/proc/pull_data() - for(var/datum/integrated_io/io in linked) - write_data_to_pin(io.data) - -/datum/integrated_io/proc/get_linked_to_desc() - if(linked.len) - return "the [english_list(linked)]" - return "nothing" - -/datum/integrated_io/proc/disconnect() - //First we iterate over everything we are linked to. - for(var/datum/integrated_io/their_io in linked) - //While doing that, we iterate them as well, and disconnect ourselves from them. - for(var/datum/integrated_io/their_linked_io in their_io.linked) - if(their_linked_io == src) - their_io.linked.Remove(src) - else - continue - //Now that we're removed from them, we gotta remove them from us. - src.linked.Remove(their_io) - -/datum/integrated_io/input - name = "input pin" - -/datum/integrated_io/output - name = "output pin" - -/datum/integrated_io/activate - name = "activation pin" - io_type = PULSE_CHANNEL - -/obj/item/integrated_circuit/proc/push_data() - for(var/datum/integrated_io/output/O in outputs) - O.push_data() - -/obj/item/integrated_circuit/proc/pull_data() - for(var/datum/integrated_io/input/I in inputs) - I.push_data() - -/obj/item/integrated_circuit/proc/check_then_do_work() - if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam. - return - next_use = world.time + cooldown_per_use - do_work() - -/obj/item/integrated_circuit/proc/do_work() - return - -/obj/item/integrated_circuit/proc/disconnect_all() - for(var/datum/integrated_io/input/I in inputs) - I.disconnect() - for(var/datum/integrated_io/output/O in outputs) - O.disconnect() - for(var/datum/integrated_io/activate/A in activators) - A.disconnect() \ No newline at end of file diff --git a/code/modules/integrated_electronics/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm similarity index 51% rename from code/modules/integrated_electronics/assemblies.dm rename to code/modules/integrated_electronics/core/assemblies.dm index ff994aa43c4..88b804f80a3 100644 --- a/code/modules/integrated_electronics/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -11,6 +11,7 @@ var/max_components = IC_COMPONENTS_BASE var/max_complexity = IC_COMPLEXITY_BASE var/opened = 0 + var/obj/item/weapon/cell/device/battery = null // Internal cell which most circuits need to work. /obj/item/device/electronic_assembly/medium name = "electronic mechanism" @@ -23,8 +24,8 @@ name = "electronic machine" icon_state = "setup_large" w_class = ITEMSIZE_LARGE - max_components = IC_COMPONENTS_BASE * 3 - max_complexity = IC_COMPLEXITY_BASE * 3 + max_components = IC_COMPONENTS_BASE * 4 + max_complexity = IC_COMPLEXITY_BASE * 4 /obj/item/device/electronic_assembly/drone name = "electronic drone" @@ -41,6 +42,32 @@ max_complexity = IC_COMPLEXITY_BASE / 2 var/obj/item/weapon/implant/integrated_circuit/implant = null +/obj/item/device/electronic_assembly/New() + ..() + battery = new(src) + processing_objects |= src + +/obj/item/device/electronic_assembly/Destroy() + battery = null + processing_objects -= src + for(var/atom/movable/AM in contents) + qdel(AM) + ..() + +/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) + if(!draw_power(IC.power_draw_idle)) + IC.power_fail() + /obj/item/device/electronic_assembly/implant/update_icon() ..() implant.icon_state = icon_state @@ -70,13 +97,18 @@ HTML += "
\[Refresh\] | " HTML += "\[Rename\]
" HTML += "[total_parts]/[max_components] ([round((total_parts / max_components) * 100, 0.1)]%) space taken up in the assembly.
" - HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity." + HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.
" + if(battery) + HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. \[Remove\]" + else + HTML += "No powercell detected!" HTML += "

" HTML += "Components;
" for(var/obj/item/integrated_circuit/circuit in contents) HTML += "[circuit.name] | " HTML += "\[Rename\] | " - HTML += "\[Remove\]" + if(circuit.removable) + HTML += "\[Remove\]" HTML += "
" HTML += "" @@ -89,6 +121,16 @@ if(href_list["rename"]) rename(usr) + if(href_list["remove_cell"]) + if(!battery) + to_chat(usr, "There's no power cell to remove from \the [src].") + else + var/turf/T = get_turf(src) + battery.forceMove(T) + playsound(T, 'sound/items/Crowbar.ogg', 50, 1) + to_chat(usr, "You pull \the [battery] out of \the [src]'s power supplier.") + battery = null + interact(usr) // To refresh the UI. /obj/item/device/electronic_assembly/verb/rename() @@ -117,39 +159,84 @@ 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/GetIdCard() + . = list() + for(var/obj/item/integrated_circuit/part in contents) + var/id_card = part.GetIdCard() + if(id_card) + return id_card + /obj/item/device/electronic_assembly/examine(mob/user) . = ..(user, 1) if(.) - for(var/obj/item/integrated_circuit/output/screen/S in contents) - if(S.stuff_to_display) - to_chat(user, "There's a little screen labeled '[S.name]', which displays '[S.stuff_to_display]'.") + for(var/obj/item/integrated_circuit/IC in contents) + IC.external_examine(user) + // for(var/obj/item/integrated_circuit/output/screen/S in contents) + // if(S.stuff_to_display) + // to_chat(user, "There's a little screen labeled '[S.name]', which displays '[S.stuff_to_display]'.") 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.w_class + +// Returns true if the circuit made it inside. +/obj/item/device/electronic_assembly/proc/add_circuit(var/obj/item/integrated_circuit/IC, var/mob/user) + if(!opened) + to_chat(user, "\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.") + return FALSE + + if(IC.w_class > src.w_class) + to_chat(user, "\The [IC] is way too big to fit into \the [src].") + return FALSE + + var/total_part_size = get_part_size() + var/total_complexity = get_part_complexity() + + if((total_part_size + IC.w_class) > max_components) + to_chat(user, "You can't seem to add the '[IC.name]', as there's insufficient space.") + return FALSE + if((total_complexity + IC.complexity) > max_complexity) + to_chat(user, "You can't seem to add the '[IC.name]', since this setup's too complicated for the case.") + 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) + S.set_pin_data(IC_OUTPUT, 1, weakref(target)) + S.check_then_do_work() + scanned = TRUE + if(scanned) + visible_message("\The [user] waves \the [src] around [target].") + /obj/item/device/electronic_assembly/attackby(var/obj/item/I, var/mob/user) if(istype(I, /obj/item/integrated_circuit)) - if(!opened) - to_chat(user, "\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.") + if(!user.unEquip(I)) return 0 - var/obj/item/integrated_circuit/IC = I - var/total_parts = 0 - var/total_complexity = 0 - for(var/obj/item/integrated_circuit/part in contents) - total_parts++ - total_complexity = total_complexity + part.complexity - - if( (total_parts + 1) > max_components) - to_chat(user, "You can't seem to add this [IC.name], since there's no more room.") - return 0 - if( (total_complexity + IC.complexity) > max_complexity) - to_chat(user, "You can't seem to add this [IC.name], since this setup's too complicated for the case.") - return 0 - - to_chat(user, "You slide \the [IC] inside \the [src].") - user.drop_item() - IC.forceMove(src) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - interact(user) + if(add_circuit(I, user)) + to_chat(user, "You slide \the [I] inside \the [src].") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + interact(user) else if(istype(I, /obj/item/weapon/crowbar)) playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) opened = !opened @@ -161,6 +248,21 @@ else to_chat(user, "\The [src] isn't opened, so you can't fiddle with the internal components. \ Try using a crowbar.") + else if(istype(I, /obj/item/weapon/cell/device)) + if(!opened) + to_chat(user, "\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.") + return FALSE + if(battery) + to_chat(user, "\The [src] already has \a [battery] inside. Remove it first if you want to replace it.") + 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, "You slot \the [cell] inside \the [src]'s power supplier.") + interact(user) + else return ..() @@ -179,4 +281,16 @@ /obj/item/device/electronic_assembly/emp_act(severity) ..() for(var/atom/movable/AM in contents) - AM.emp_act(severity) \ No newline at end of file + 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 \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm new file mode 100644 index 00000000000..c98d74e79f4 --- /dev/null +++ b/code/modules/integrated_electronics/core/helpers.dm @@ -0,0 +1,44 @@ +/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type) + var/list/io_list_copy = io_list.Copy() + io_list.Cut() + for(var/io_entry in io_list_copy) + io_list.Add(new io_type(src, io_entry, io_list_copy[io_entry])) + +/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, var/new_data) + var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number) + return pin.write_data_to_pin(new_data) + +/obj/item/integrated_circuit/proc/get_pin_data(var/pin_type, var/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(var/pin_type, var/pin_number, var/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(var/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(var/pin_type, var/pin_number) + switch(pin_type) + if(IC_INPUT) + if(pin_number > inputs.len) + return null + return inputs[pin_number] + if(IC_OUTPUT) + if(pin_number > outputs.len) + return null + return outputs[pin_number] + if(IC_ACTIVATOR) + if(pin_number > activators.len) + return null + return activators[pin_number] + return null diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm new file mode 100644 index 00000000000..87bb4cd182f --- /dev/null +++ b/code/modules/integrated_electronics/core/integrated_circuit.dm @@ -0,0 +1,282 @@ +/* + 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) + . = ..() + 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/input/I in inputs) + if(I.linked.len) + to_chat(user, "The '[I]' is connected to [I.get_linked_to_desc()].") + for(var/datum/integrated_io/output/O in outputs) + if(O.linked.len) + to_chat(user, "The '[O]' is connected to [O.get_linked_to_desc()].") + for(var/datum/integrated_io/activate/A in activators) + if(A.linked.len) + to_chat(user, "The '[A]' is connected to [A.get_linked_to_desc()].") + 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/New() + setup_io(inputs, /datum/integrated_io/input) + setup_io(outputs, /datum/integrated_io/output) + setup_io(activators, /datum/integrated_io/activate) + ..() + +/obj/item/integrated_circuit/proc/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/verb/rename_component() + set name = "Rename Circuit" + set category = "Object" + set desc = "Rename your circuit, useful to stay organized." + + var/mob/M = usr + if(!CanInteract(M, physical_state)) + return + + var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name) as null|text, MAX_NAME_LEN) + if(src && input && CanInteract(M, physical_state)) + to_chat(M, "The circuit '[src.name]' is now labeled '[input]'.") + name = input + +/obj/item/integrated_circuit/interact(mob/user) + if(!CanInteract(user, physical_state)) + return + + var/window_height = 350 + var/window_width = 600 + + //var/table_edge_width = "[(window_width - window_width * 0.1) / 4]px" + //var/table_middle_width = "[(window_width - window_width * 0.1) - (table_edge_width * 2)]px" + var/table_edge_width = "30%" + var/table_middle_width = "40%" + + var/HTML = list() + HTML += "[src.name]" + HTML += "
" + HTML += "" + + HTML += "
\[Refresh\] | " + HTML += "\[Rename\] | " + HTML += "\[Remove\]
" + + HTML += "" + //HTML += "" + //HTML += "" + //HTML += "" + HTML += "" + HTML += "" + HTML += "" + HTML += "" + + var/column_width = 3 + var/row_height = max(inputs.len, outputs.len, 1) + + for(var/i = 1 to row_height) + HTML += "" + 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) + if(io.linked.len) + words += "[io.name] [io.display_data()]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + else + words += "[io.name] [io.display_data()]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + if(outputs.len > inputs.len) + height = 1 + if(2) + if(i == 1) + words += "[src.name]

[src.desc]" + height = row_height + else + continue + if(3) + io = get_pin_ref(IC_OUTPUT, i) + if(io) + if(io.linked.len) + words += "[io.name] [io.display_data()]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + else + words += "[io.name] [io.display_data()]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + if(inputs.len > outputs.len) + height = 1 + HTML += "" + HTML += "" + + for(var/activator in activators) + var/datum/integrated_io/io = activator + var/words = list() + if(io.linked.len) + words += "[io.name]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + else + words += "[io.name]
" + for(var/datum/integrated_io/linked in io.linked) + words += "\[[linked.name]\] \ + @ [linked.holder]
" + HTML += "" + HTML += "" + HTML += "" + + HTML += "
[jointext(words, null)]
[jointext(words, null)]
" + HTML += "
" + + if(autopulse != -1) + HTML += "
Meta Variables;" + HTML += "
\[Autopulse\] = [autopulse ? "ON" : "OFF"]" + HTML += "
" + + HTML += "
Complexity: [complexity]" + if(power_draw_idle) + HTML += "
Power Draw: [power_draw_idle] W (Idle)" + if(power_draw_per_use) + HTML += "
Power Draw: [power_draw_per_use] W (Active)" // Borgcode says that powercells' checked_use() takes joules as input. + HTML += "
[extended_desc]" + + HTML += "" + user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") + + onclose(user, "circuit-\ref[src]") + +/obj/item/integrated_circuit/Topic(href, href_list, state = physical_state) + if(..()) + return 1 + var/pin = locate(href_list["pin"]) in inputs + outputs + activators + + var/obj/held_item = usr.get_active_hand() + if(href_list["wire"]) + if(istype(held_item, /obj/item/device/integrated_electronics/wirer)) + var/obj/item/device/integrated_electronics/wirer/wirer = held_item + if(pin) + wirer.wire(pin, usr) + + else if(istype(held_item, /obj/item/device/integrated_electronics/debugger)) + var/obj/item/device/integrated_electronics/debugger/debugger = held_item + if(pin) + debugger.write_data(pin, usr) + else + to_chat(usr, "You can't do a whole lot without the proper tools.") + + if(href_list["examine"]) + examine(usr) + + if(href_list["rename"]) + rename_component(usr) + + if(href_list["autopulse"]) + if(autopulse != -1) + autopulse = !autopulse + + if(href_list["remove"]) + if(istype(held_item, /obj/item/weapon/screwdriver)) + if(!removable) + to_chat(usr, "\The [src] seems to be permanently attached to the case.") + return + disconnect_all() + var/turf/T = get_turf(src) + forceMove(T) + assembly = null + playsound(T, 'sound/items/Crowbar.ogg', 50, 1) + to_chat(usr, "You pop \the [src] out of the case, and slide it out.") + else + to_chat(usr, "You need a screwdriver to remove components.") + var/obj/item/device/electronic_assembly/ea = loc + if(istype(ea)) + ea.interact(usr) + return + + interact(usr) // To refresh the UI. + +/obj/item/integrated_circuit/proc/push_data() + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + +/obj/item/integrated_circuit/proc/pull_data() + for(var/datum/integrated_io/input/I in inputs) + I.push_data() + +/obj/item/integrated_circuit/proc/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() + if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam. + return + if(power_draw_per_use) + 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/input/I in inputs) + I.disconnect() + for(var/datum/integrated_io/output/O in outputs) + O.disconnect() + for(var/datum/integrated_io/activate/A in activators) + A.disconnect() diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm new file mode 100644 index 00000000000..dc6d48e3034 --- /dev/null +++ b/code/modules/integrated_electronics/core/pins.dm @@ -0,0 +1,139 @@ +/* + 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/weakref/data = null // This is a weakref, to reduce typecasts. Note that oftentimes numbers and text may also occupy this. + var/list/linked = list() + var/io_type = DATA_CHANNEL + +/datum/integrated_io/New(var/newloc, var/name, var/data) + ..() + src.name = name + src.data = data + holder = newloc + if(!istype(holder)) + message_admins("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.") + +/datum/integrated_io/Destroy() + disconnect() + data = null + holder = null + . = ..() + +/datum/integrated_io/nano_host() + return holder.nano_host() + + +/datum/integrated_io/proc/data_as_type(var/as_type) + if(!isweakref(data)) + return + var/weakref/w = data + var/output = w.resolve() + return istype(output, as_type) ? output : null + +/datum/integrated_io/proc/display_data() + if(isnull(data)) + return "(null)" // Empty data means nothing to show. + if(istext(data)) + return "(\"[data]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'. + if(isweakref(data)) + var/weakref/w = data + var/atom/A = w.resolve() + //return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed. + return A ? "(\ref[A] \[Ref\])" : "(null)" + return "([data])" // 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.Remove(src) + else + continue + //Now that we're removed from them, we gotta remove them from us. + src.linked.Remove(their_io) + +/datum/integrated_io/input + name = "input pin" + +/datum/integrated_io/output + name = "output pin" + +/datum/integrated_io/activate + name = "activation pin" + io_type = PULSE_CHANNEL + +/datum/integrated_io/list + name = "list pin" + +/datum/integrated_io/list/write_data_to_pin(var/new_data) + if(islist(new_data)) + data = new_data + holder.on_data_written() + +/datum/integrated_io/list/display_pin_type() + return IC_FORMAT_LIST \ No newline at end of file diff --git a/code/modules/integrated_electronics/tools.dm b/code/modules/integrated_electronics/core/tools.dm similarity index 71% rename from code/modules/integrated_electronics/tools.dm rename to code/modules/integrated_electronics/core/tools.dm index 6c76b9b4ffe..21a56f014dd 100644 --- a/code/modules/integrated_electronics/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -20,6 +20,9 @@ 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, "\The [io.holder] needs to be secured inside an assembly first.") + return if(mode == WIRE) selected_io = io to_chat(user, "You attach a data wire to \the [selected_io.holder]'s [selected_io.name] data channel.") @@ -33,6 +36,9 @@ to_chat(user, "Those two types of channels are incompatable. The first is a [selected_io.io_type], \ while the second is a [io.io_type].") return + if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly) + to_chat(user, "Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.") + return selected_io.linked |= io io.linked |= selected_io @@ -191,6 +197,7 @@ 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/integrated_electronics/wirer(src) @@ -202,11 +209,24 @@ /obj/item/weapon/storage/bag/circuits/all/New() ..() spawn(2 SECONDS) // So the list has time to initialize. - for(var/obj/item/integrated_circuit/IC in all_integrated_circuits) - for(var/i = 1 to 10) - new IC.type(src) + 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) @@ -219,16 +239,20 @@ w_class = 2 display_contents_with_number = 1 can_hold = list(/obj/item/integrated_circuit) + var/spawn_flags_to_use = IC_SPAWN_DEFAULT /obj/item/weapon/storage/bag/circuits/mini/arithmetic name = "arithmetic circuit box" desc = "Warning: Contains math." icon_state = "box_arithmetic" +/obj/item/weapon/storage/bag/circuits/mini/arithmetic/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/arithmetic/New() ..() for(var/obj/item/integrated_circuit/arithmetic/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() @@ -239,10 +263,13 @@ desc = "Danger: Contains more math." icon_state = "box_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/trig/New() ..() for(var/obj/item/integrated_circuit/trig/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() @@ -253,10 +280,13 @@ desc = "Tell these circuits everything you know." icon_state = "box_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/input/New() ..() for(var/obj/item/integrated_circuit/input/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() @@ -267,10 +297,13 @@ desc = "Circuits to interface with the world beyond itself." icon_state = "box_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/output/New() ..() for(var/obj/item/integrated_circuit/output/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() @@ -281,25 +314,30 @@ desc = "Machines can be quite forgetful without these." icon_state = "box_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/memory/New() ..() for(var/obj/item/integrated_circuit/memory/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() - /obj/item/weapon/storage/bag/circuits/mini/logic name = "logic circuit box" desc = "May or may not be Turing complete." icon_state = "box_logic" +/obj/item/weapon/storage/bag/circuits/mini/logic/all + spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + /obj/item/weapon/storage/bag/circuits/mini/logic/New() ..() for(var/obj/item/integrated_circuit/logic/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() @@ -310,10 +348,13 @@ desc = "No time machine parts, sadly." icon_state = "box_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/time/New() ..() for(var/obj/item/integrated_circuit/time/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() @@ -324,10 +365,13 @@ desc = "Unlike most electronics, these circuits are supposed to come in contact with liquids." icon_state = "box_reagents" +/obj/item/weapon/storage/bag/circuits/mini/reagents/all + spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + /obj/item/weapon/storage/bag/circuits/mini/reagents/New() ..() for(var/obj/item/integrated_circuit/reagent/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() @@ -338,10 +382,13 @@ desc = "Useful for moving data representing something arbitrary to another arbitrary virtual place." icon_state = "box_transfer" +/obj/item/weapon/storage/bag/circuits/mini/transfer/all + spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + /obj/item/weapon/storage/bag/circuits/mini/transfer/New() ..() for(var/obj/item/integrated_circuit/transfer/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() @@ -352,10 +399,66 @@ desc = "Transform one piece of data to another type of data with these." icon_state = "box_converter" +/obj/item/weapon/storage/bag/circuits/mini/converter/all + spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + /obj/item/weapon/storage/bag/circuits/mini/converter/New() ..() for(var/obj/item/integrated_circuit/converter/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) + if(IC.spawn_flags & spawn_flags_to_use) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + +/obj/item/weapon/storage/bag/circuits/mini/smart + name = "smart box" + desc = "Sentience not included." + icon_state = "box_ai" + +/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/smart/New() + ..() + for(var/obj/item/integrated_circuit/smart/IC in all_integrated_circuits) + if(IC.spawn_flags & spawn_flags_to_use) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + +/obj/item/weapon/storage/bag/circuits/mini/manipulation + name = "manipulation box" + desc = "Make your machines actually useful with these." + icon_state = "box_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/manipulation/New() + ..() + for(var/obj/item/integrated_circuit/manipulation/IC in all_integrated_circuits) + if(IC.spawn_flags & spawn_flags_to_use) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/power + name = "power circuit box" + desc = "Electronics generally require electricity." + icon_state = "box_power" + +/obj/item/weapon/storage/bag/circuits/mini/power/all + spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/weapon/storage/bag/circuits/mini/power/New() + ..() + for(var/obj/item/integrated_circuit/passive/power/IC in all_integrated_circuits) + if(IC.spawn_flags & spawn_flags_to_use) + for(var/i = 1 to 3) + new IC.type(src) + for(var/obj/item/integrated_circuit/power/IC in all_integrated_circuits) + if(IC.spawn_flags & spawn_flags_to_use) for(var/i = 1 to 3) new IC.type(src) make_exact_fit() \ No newline at end of file diff --git a/code/modules/integrated_electronics/data_transfer.dm b/code/modules/integrated_electronics/data_transfer.dm deleted file mode 100644 index 7e37995df5b..00000000000 --- a/code/modules/integrated_electronics/data_transfer.dm +++ /dev/null @@ -1,85 +0,0 @@ -/obj/item/integrated_circuit/transfer - category_text = "Data Transfer" - autopulse = 1 - -/obj/item/integrated_circuit/transfer/on_data_written() - if(autopulse == 1) - check_then_do_work() - -/obj/item/integrated_circuit/transfer/splitter - name = "splitter" - desc = "Splits incoming data into all of the output pins." - icon_state = "splitter" - complexity = 3 - inputs = list("data to split") - outputs = list("A","B") - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - -/obj/item/integrated_circuit/transfer/splitter/medium - name = "four splitter" - icon_state = "splitter4" - complexity = 5 - outputs = list("A","B","C","D") - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - -/obj/item/integrated_circuit/transfer/splitter/large - name = "eight splitter" - icon_state = "splitter8" - complexity = 9 - outputs = list("A","B","C","D","E","F","G","H") - spawn_flags = IC_SPAWN_RESEARCH - -/obj/item/integrated_circuit/transfer/splitter/do_work() - var/datum/integrated_io/I = inputs[1] - for(var/datum/integrated_io/output/O in outputs) - O.data = I.data - -/obj/item/integrated_circuit/transfer/activator_splitter - name = "activator splitter" - desc = "Splits incoming activation pulses into all of the output pins." - icon_state = "splitter" - complexity = 3 - activators = list( - "incoming pulse", - "outgoing pulse A", - "outgoing pulse B" - ) - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - -/obj/item/integrated_circuit/transfer/activator_splitter/do_work() - for(var/datum/integrated_io/activate/A in outputs) - if(A == activators[1]) - continue - if(A.linked.len) - for(var/datum/integrated_io/activate/target in A.linked) - target.holder.check_then_do_work() - -/obj/item/integrated_circuit/transfer/activator_splitter/medium - name = "four activator splitter" - icon_state = "splitter4" - complexity = 5 - activators = list( - "incoming pulse", - "outgoing pulse A", - "outgoing pulse B", - "outgoing pulse C", - "outgoing pulse D" - ) - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - -/obj/item/integrated_circuit/transfer/activator_splitter/large - name = "eight activator splitter" - icon_state = "splitter4" - complexity = 9 - activators = list( - "incoming pulse", - "outgoing pulse A", - "outgoing pulse B", - "outgoing pulse C", - "outgoing pulse D", - "outgoing pulse E", - "outgoing pulse F", - "outgoing pulse G", - "outgoing pulse H" - ) - spawn_flags = IC_SPAWN_RESEARCH \ No newline at end of file diff --git a/code/modules/integrated_electronics/passive/passive.dm b/code/modules/integrated_electronics/passive/passive.dm new file mode 100644 index 00000000000..02f03d48d7c --- /dev/null +++ b/code/modules/integrated_electronics/passive/passive.dm @@ -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 \ No newline at end of file diff --git a/code/modules/integrated_electronics/passive/power.dm b/code/modules/integrated_electronics/passive/power.dm new file mode 100644 index 00000000000..9e08a96d24f --- /dev/null +++ b/code/modules/integrated_electronics/passive/power.dm @@ -0,0 +1,109 @@ + +/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/atom/movable/lighting_overlay/light = locate(/atom/movable/lighting_overlay) in get_turf(src) + var/light_amount = 1 // Unsimulated tiles are pretend-lit, so we need to be pretend too if that somehow happens. + if(light) + light_amount = (light.lum_r + light.lum_g + light.lum_b) / 3 + + var/adjusted_power = max(max_power * light_amount, 0) + adjusted_power = round(adjusted_power, 0.1) + if(adjusted_power) + if(assembly) + assembly.give_power(adjusted_power) + +// 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 = null + 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(host && test_validity(host)) + assembly.give_power(10) + host.nutrition = max(host.nutrition - DEFAULT_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 + +// 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)) + A.use_power(power_amount, EQUIP) + assembly.give_power(power_amount) // give_power() handles CELLRATE on its own. diff --git a/code/modules/integrated_electronics/arithmetic.dm b/code/modules/integrated_electronics/subtypes/arithmetic.dm similarity index 99% rename from code/modules/integrated_electronics/arithmetic.dm rename to code/modules/integrated_electronics/subtypes/arithmetic.dm index 37eabf20270..c6134f9bd1d 100644 --- a/code/modules/integrated_electronics/arithmetic.dm +++ b/code/modules/integrated_electronics/subtypes/arithmetic.dm @@ -6,6 +6,7 @@ activators = list("compute") category_text = "Arithmetic" autopulse = 1 + power_draw_per_use = 5 // Math is pretty cheap. /obj/item/integrated_circuit/arithmetic/on_data_written() if(autopulse == 1) diff --git a/code/modules/integrated_electronics/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm similarity index 99% rename from code/modules/integrated_electronics/converters.dm rename to code/modules/integrated_electronics/subtypes/converters.dm index 96494ba469f..9e04e24db51 100644 --- a/code/modules/integrated_electronics/converters.dm +++ b/code/modules/integrated_electronics/subtypes/converters.dm @@ -6,6 +6,7 @@ activators = list("convert") category_text = "Converter" autopulse = 1 + power_draw_per_use = 10 /obj/item/integrated_circuit/converter/on_data_written() if(autopulse == 1) diff --git a/code/modules/integrated_electronics/subtypes/data_transfer.dm b/code/modules/integrated_electronics/subtypes/data_transfer.dm new file mode 100644 index 00000000000..c5fe9741be1 --- /dev/null +++ b/code/modules/integrated_electronics/subtypes/data_transfer.dm @@ -0,0 +1,186 @@ +/obj/item/integrated_circuit/transfer + category_text = "Data Transfer" + autopulse = 1 + power_draw_per_use = 2 + +/obj/item/integrated_circuit/transfer/on_data_written() + if(autopulse == 1) + check_then_do_work() + +/obj/item/integrated_circuit/transfer/splitter + name = "splitter" + desc = "Splits incoming data into all of the output pins." + icon_state = "splitter" + complexity = 3 + inputs = list("data to split") + outputs = list("A","B") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/transfer/splitter/medium + name = "four splitter" + icon_state = "splitter4" + complexity = 5 + outputs = list("A","B","C","D") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 4 + +/obj/item/integrated_circuit/transfer/splitter/large + name = "eight splitter" + icon_state = "splitter8" + w_class = ITEMSIZE_SMALL + complexity = 9 + outputs = list("A","B","C","D","E","F","G","H") + spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 8 + +/obj/item/integrated_circuit/transfer/splitter/do_work() + var/datum/integrated_io/I = inputs[1] + for(var/datum/integrated_io/output/O in outputs) + O.data = I.data + +/obj/item/integrated_circuit/transfer/activator_splitter + name = "activator splitter" + desc = "Splits incoming activation pulses into all of the output pins." + icon_state = "splitter" + complexity = 3 + activators = list( + "incoming pulse", + "outgoing pulse A", + "outgoing pulse B" + ) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 2 + +/obj/item/integrated_circuit/transfer/activator_splitter/do_work() + for(var/datum/integrated_io/activate/A in outputs) + if(A == activators[1]) + continue + if(A.linked.len) + for(var/datum/integrated_io/activate/target in A.linked) + target.holder.check_then_do_work() + +/obj/item/integrated_circuit/transfer/activator_splitter/medium + name = "four activator splitter" + icon_state = "splitter4" + complexity = 5 + activators = list( + "incoming pulse", + "outgoing pulse A", + "outgoing pulse B", + "outgoing pulse C", + "outgoing pulse D" + ) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 4 + +/obj/item/integrated_circuit/transfer/activator_splitter/large + name = "eight activator splitter" + icon_state = "splitter4" + w_class = ITEMSIZE_SMALL + complexity = 9 + activators = list( + "incoming pulse", + "outgoing pulse A", + "outgoing pulse B", + "outgoing pulse C", + "outgoing pulse D", + "outgoing pulse E", + "outgoing pulse F", + "outgoing pulse G", + "outgoing pulse H" + ) + spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 8 + + +/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") + outputs = list("output") + activators = list("select") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 4 + var/number_of_inputs = 2 + +/obj/item/integrated_circuit/transfer/multiplexer/New() + for(var/i = 1 to number_of_inputs) + inputs += "input [i]" + 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(isnum(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) + +/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","input") + outputs = list() + activators = list("select") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 4 + var/number_of_outputs = 2 + +/obj/item/integrated_circuit/transfer/demultiplexer/New() + for(var/i = 1 to number_of_outputs) + outputs += "output [i]" + 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) + +/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 \ No newline at end of file diff --git a/code/modules/integrated_electronics/input_output.dm b/code/modules/integrated_electronics/subtypes/input_output.dm similarity index 76% rename from code/modules/integrated_electronics/input_output.dm rename to code/modules/integrated_electronics/subtypes/input_output.dm index c77ad3dc69c..753c092974f 100644 --- a/code/modules/integrated_electronics/input_output.dm +++ b/code/modules/integrated_electronics/subtypes/input_output.dm @@ -1,6 +1,7 @@ /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 @@ -23,6 +24,21 @@ target.holder.check_then_do_work() to_chat(user, "You press the button labeled '[src.name]'.") +/obj/item/integrated_circuit/input/toggle_button + name = "toggle button" + desc = "It toggles on, off, on, off..." + icon_state = "toggle_button" + complexity = 1 + inputs = list() + outputs = list("on" = 0) + activators = list("on toggle") + 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)) + activate_pin(1) + to_chat(user, "You toggle the button labeled '[src.name]' [get_pin_data(IC_OUTPUT, 1) ? "on" : "off"].") + /obj/item/integrated_circuit/input/numberpad name = "number pad" desc = "This small number pad allows someone to input a number into the system." @@ -33,6 +49,7 @@ outputs = list("number entered") activators = list("on entered") 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 @@ -53,6 +70,7 @@ outputs = list("string entered") activators = list("on entered") 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 = input(user, "Enter some words, please.","Number pad") as null|text @@ -73,6 +91,7 @@ activators = list("scan") 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/datum/integrated_io/I = inputs[1] @@ -111,6 +130,7 @@ activators = list("scan") 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/datum/integrated_io/I = inputs[1] @@ -148,12 +168,12 @@ outputs = list("located ref") activators = list("locate") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 20 /obj/item/integrated_circuit/input/local_locator/do_work() var/datum/integrated_io/O = outputs[1] O.data = null - if(istype(src.loc, /obj/item/device/electronic_assembly)) // Check to make sure we're actually in a machine. - var/obj/item/device/electronic_assembly/assembly = src.loc + if(assembly) if(istype(assembly.loc, /mob/living)) // Now check if someone's holding us. O.data = weakref(assembly.loc) @@ -170,6 +190,7 @@ outputs = list("located ref") activators = list("locate") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 30 /obj/item/integrated_circuit/input/adjacent_locator/do_work() var/datum/integrated_io/I = inputs[1] @@ -206,6 +227,8 @@ activators = list("send signal","on signal received") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNETS = 2) + power_draw_idle = 5 + power_draw_per_use = 40 var/frequency = 1457 var/code = 30 @@ -288,6 +311,7 @@ activators = list("send data", "on data received") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNETS = 2, TECH_BLUESPACE = 2) + power_draw_per_use = 50 var/datum/exonet_protocol/exonet = null /obj/item/integrated_circuit/input/EPv2/New() @@ -334,6 +358,7 @@ outputs = list("X (abs)", "Y (abs)") activators = list("get coordinates") 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) @@ -361,6 +386,7 @@ outputs = list("speaker \", "message \") activators = list("on message received") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 15 /obj/item/integrated_circuit/input/microphone/New() ..() @@ -385,9 +411,27 @@ for(var/datum/integrated_io/output/out in outputs) out.push_data() + A.push_data() +/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." + icon_state = "recorder" + complexity = 12 + inputs = list() + outputs = list("scanned ref \") + activators = list("on scanned") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 120 + +/obj/item/integrated_circuit/input/sensor/do_work() + // Because this gets called by attack(), all this needs to do is pulse the activator. + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + var/datum/integrated_io/activate/A = activators[1] + A.push_data() /obj/item/integrated_circuit/output @@ -401,8 +445,18 @@ outputs = list() activators = list("load data") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 10 + autopulse = 1 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) + to_chat(user, "There is a little screen labeled '[name]', which displays [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)) @@ -416,22 +470,24 @@ 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 = istype(loc, /obj/item/device/electronic_assembly) ? loc : src + var/obj/O = assembly ? assembly : src visible_message("\icon[O] [stuff_to_display]") /obj/item/integrated_circuit/output/screen/large name = "large screen" desc = "This screen allows for people able to see the device to see a piece of data." icon_state = "screen_large" + power_draw_per_use = 40 /obj/item/integrated_circuit/output/screen/large/do_work() ..() - var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src + var/obj/O = assembly ? loc : assembly O.visible_message("\icon[O] [stuff_to_display]") /obj/item/integrated_circuit/output/light @@ -446,6 +502,10 @@ 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/Destroy() + ..() /obj/item/integrated_circuit/output/light/do_work() light_toggled = !light_toggled @@ -456,6 +516,7 @@ set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb) else set_light(0) + power_draw_idle = light_toggled ? light_brightness * 2 : 0 /obj/item/integrated_circuit/output/light/advanced/update_lighting() var/datum/integrated_io/R = inputs[1] @@ -473,6 +534,10 @@ ..() +/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." @@ -504,6 +569,7 @@ ) outputs = list() activators = list("play sound") + power_draw_per_use = 20 var/list/sounds = list() /obj/item/integrated_circuit/output/text_to_speech @@ -517,11 +583,12 @@ outputs = list() activators = list("to speech") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 60 /obj/item/integrated_circuit/output/text_to_speech/do_work() var/datum/integrated_io/text = inputs[1] if(istext(text.data)) - var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src + var/obj/O = assembly ? loc : assembly audible_message("\icon[O] \The [O.name] states, \"[text.data]\"") /obj/item/integrated_circuit/output/sound/New() @@ -576,4 +643,118 @@ "secure day" = 'sound/voice/bsecureday.ogg', ) spawn_flags = IC_SPAWN_RESEARCH - origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 1) \ No newline at end of file + origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 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" = "video camera circuit", "camera active" = 0) + 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/New() + ..() + camera = new(src) + on_data_written() + +/obj/item/integrated_circuit/output/video_camera/Destroy() + qdel(camera) + ..() + +/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/datum/integrated_io/cam_name = inputs[1] + var/datum/integrated_io/cam_active = inputs[2] + if(istext(cam_name.data)) + camera.c_tag = cam_name.data + if(isnum(cam_active.data)) + set_camera_status(cam_active.data) + +/obj/item/integrated_circuit/output/video_camera/power_fail() + if(camera) + set_camera_status(0) + var/datum/integrated_io/cam_active = inputs[2] + cam_active.data = 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") + outputs = list() + activators = list() + power_draw_idle = 0 // Raises to 1 when lit. + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + var/led_color + +/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 ¤" : "unlit."]" + to_chat(user,jointext(text_output,null)) + +/obj/item/integrated_circuit/output/led/red + name = "red LED" + led_color = COLOR_RED + +/obj/item/integrated_circuit/output/led/orange + name = "orange LED" + led_color = COLOR_ORANGE + +/obj/item/integrated_circuit/output/led/yellow + name = "yellow LED" + led_color = COLOR_YELLOW + +/obj/item/integrated_circuit/output/led/green + name = "green LED" + led_color = COLOR_GREEN + +/obj/item/integrated_circuit/output/led/blue + name = "blue LED" + led_color = COLOR_BLUE + +/obj/item/integrated_circuit/output/led/purple + name = "purple LED" + led_color = COLOR_PURPLE + +/obj/item/integrated_circuit/output/led/cyan + name = "cyan LED" + led_color = COLOR_CYAN + +/obj/item/integrated_circuit/output/led/white + name = "white LED" + led_color = COLOR_WHITE + +/obj/item/integrated_circuit/output/led/pink + name = "pink LED" + led_color = COLOR_PINK diff --git a/code/modules/integrated_electronics/logic.dm b/code/modules/integrated_electronics/subtypes/logic.dm similarity index 87% rename from code/modules/integrated_electronics/logic.dm rename to code/modules/integrated_electronics/subtypes/logic.dm index d477be3cbe1..8feed0457c9 100644 --- a/code/modules/integrated_electronics/logic.dm +++ b/code/modules/integrated_electronics/subtypes/logic.dm @@ -4,9 +4,10 @@ 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") - activators = list("compare", "on true result") + activators = list("compare", "on true result", "on false result") category_text = "Logic" autopulse = 1 + power_draw_per_use = 1 /obj/item/integrated_circuit/logic/on_data_written() if(autopulse == 1) @@ -14,10 +15,13 @@ /obj/item/integrated_circuit/logic/do_work() var/datum/integrated_io/O = outputs[1] - var/datum/integrated_io/P = activators[2] + var/datum/integrated_io/T = activators[2] + var/datum/integrated_io/F = activators[3] O.push_data() if(O.data) - P.push_data() + T.push_data() + else + F.push_data() /obj/item/integrated_circuit/logic/binary inputs = list("A","B") @@ -53,6 +57,15 @@ /obj/item/integrated_circuit/logic/binary/equals/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B) return A.data == B.data +/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(var/datum/integrated_io/A, var/datum/integrated_io/B) + return A.data != B.data + /obj/item/integrated_circuit/logic/binary/and name = "and gate" desc = "This gate will output 'one' if both inputs evaluate to true." @@ -114,4 +127,4 @@ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/logic/unary/not/do_check(var/datum/integrated_io/A) - return !A.data \ No newline at end of file + return !A.data diff --git a/code/modules/integrated_electronics/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm similarity index 90% rename from code/modules/integrated_electronics/manipulation.dm rename to code/modules/integrated_electronics/subtypes/manipulation.dm index f49b96d16c6..65bae751e00 100644 --- a/code/modules/integrated_electronics/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -9,6 +9,7 @@ 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 inputs = list( "target X rel", "target Y rel" @@ -20,6 +21,7 @@ var/obj/item/weapon/gun/installed_gun = null 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(installed_gun) @@ -106,20 +108,21 @@
\ 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 inputs = list("dir num") outputs = list() activators = list("step towards dir") 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 && istype(loc, /obj/item/device/electronic_assembly)) - var/obj/item/device/electronic_assembly/machine = loc - if(machine.anchored || !machine.can_move()) + if(T && assembly) + if(assembly.anchored || !assembly.can_move()) return - if(machine.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held. + 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(machine, wanted_dir.data) \ No newline at end of file + step(assembly, wanted_dir.data) \ No newline at end of file diff --git a/code/modules/integrated_electronics/memory.dm b/code/modules/integrated_electronics/subtypes/memory.dm similarity index 96% rename from code/modules/integrated_electronics/memory.dm rename to code/modules/integrated_electronics/subtypes/memory.dm index f9cd109dce5..49a049a9827 100644 --- a/code/modules/integrated_electronics/memory.dm +++ b/code/modules/integrated_electronics/subtypes/memory.dm @@ -8,6 +8,7 @@ activators = list("set") category_text = "Memory" spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 1 /obj/item/integrated_circuit/memory/examine(mob/user) ..() @@ -33,15 +34,18 @@ name = "memory circuit" desc = "This circuit can store four pieces of data." icon_state = "memory4" + w_class = ITEMSIZE_SMALL complexity = 4 inputs = list("input pin 1","input pin 2","input pin 3","input pin 4") outputs = list("output pin 1","output pin 2","output pin 3","output pin 4") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 2 /obj/item/integrated_circuit/memory/large name = "large memory circuit" desc = "This big circuit can hold eight pieces of data." icon_state = "memory8" + w_class = ITEMSIZE_SMALL complexity = 8 inputs = list( "input pin 1", @@ -63,11 +67,13 @@ "output pin 8") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 4 /obj/item/integrated_circuit/memory/huge name = "large memory stick" desc = "This stick of memory can hold up up to sixteen pieces of data." icon_state = "memory16" + w_class = ITEMSIZE_NORMAL complexity = 16 inputs = list( "input pin 1", @@ -106,6 +112,7 @@ "output pin 16") spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4) + power_draw_per_use = 8 /obj/item/integrated_circuit/memory/constant name = "constant chip" diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm new file mode 100644 index 00000000000..013a35c0588 --- /dev/null +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -0,0 +1,80 @@ +/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 ref") + outputs = list("target cell charge", "target cell max charge", "target cell percentage") + activators = list("transmit") + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNETS = 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_MAGNETS = 5) + power_draw_per_use = 2000 + amount_to_move = 20000 + +/obj/item/integrated_circuit/power/transmitter/do_work() + set_pin_data(IC_OUTPUT, 1, null) + set_pin_data(IC_OUTPUT, 2, null) + set_pin_data(IC_OUTPUT, 3, null) + var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) + if(AM) + if(!assembly) + return FALSE // Pointless to do everything else if there's no battery to draw from. + + 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()) + 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()) + return TRUE + return FALSE + +/obj/item/integrated_circuit/power/transmitter/large/do_work() + if(..()) // If the above code succeeds, do this below. + if(prob(2)) + var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() + sparks.set_up(3, 0, get_turf(src)) + sparks.start() + visible_message("\The [assembly] makes some sparks!") + qdel(sparks) \ No newline at end of file diff --git a/code/modules/integrated_electronics/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm similarity index 98% rename from code/modules/integrated_electronics/reagents.dm rename to code/modules/integrated_electronics/subtypes/reagents.dm index bd6cd1d9333..d0c26baf663 100644 --- a/code/modules/integrated_electronics/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -23,6 +23,7 @@ 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) @@ -47,6 +48,7 @@ activators = list("inject") 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/datum/integrated_io/amount = inputs[2] @@ -92,6 +94,7 @@ 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/datum/integrated_io/amount = inputs[3] diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm new file mode 100644 index 00000000000..c159522e974 --- /dev/null +++ b/code/modules/integrated_electronics/subtypes/smart.dm @@ -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 ref") + outputs = list("dir") + activators = list("calculate dir") + 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] + var/datum/integrated_io/O = outputs[1] + O.data = 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) + if(desired_dir) + O.data = desired_dir + O.push_data() \ No newline at end of file diff --git a/code/modules/integrated_electronics/time.dm b/code/modules/integrated_electronics/subtypes/time.dm similarity index 97% rename from code/modules/integrated_electronics/time.dm rename to code/modules/integrated_electronics/subtypes/time.dm index 50bcc5e3867..72766c0c48c 100644 --- a/code/modules/integrated_electronics/time.dm +++ b/code/modules/integrated_electronics/subtypes/time.dm @@ -14,6 +14,7 @@ var/delay = 2 SECONDS activators = list("incoming pulse","outgoing pulse") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 2 /obj/item/integrated_circuit/time/delay/do_work() set waitfor = 0 // Don't sleep in a proc that is called by a processor. It'll delay the entire thing @@ -82,6 +83,7 @@ inputs = list("enable ticking") activators = list("outgoing pulse") spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 4 /obj/item/integrated_circuit/time/ticker/Destroy() if(is_running) @@ -116,6 +118,7 @@ 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" @@ -124,6 +127,7 @@ 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" @@ -132,6 +136,7 @@ inputs = list() outputs = list("time (string)", "hours (number)", "minutes (number)", "seconds (number)") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 4 /obj/item/integrated_circuit/time/clock/do_work() var/datum/integrated_io/time = outputs[1] diff --git a/code/modules/integrated_electronics/trig.dm b/code/modules/integrated_electronics/subtypes/trig.dm similarity index 97% rename from code/modules/integrated_electronics/trig.dm rename to code/modules/integrated_electronics/subtypes/trig.dm index e8e2e09ca9e..b1a19f4a406 100644 --- a/code/modules/integrated_electronics/trig.dm +++ b/code/modules/integrated_electronics/subtypes/trig.dm @@ -7,6 +7,7 @@ category_text = "Trig" extended_desc = "Input and output are in degrees." autopulse = 1 + power_draw_per_use = 1 // Still cheap math. /obj/item/integrated_circuit/trig/on_data_written() if(autopulse == 1) @@ -118,7 +119,7 @@ /obj/item/integrated_circuit/trig/cotangent name = "cot circuit" - desc = "Outputs the cotangent of A. Has nothing to do with the security department." + desc = "Outputs the cotangent of A." icon_state = "cotangent" inputs = list("A") spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH diff --git a/code/modules/integrated_electronics/~defines.dm b/code/modules/integrated_electronics/~defines.dm deleted file mode 100644 index 7aea6dabbb9..00000000000 --- a/code/modules/integrated_electronics/~defines.dm +++ /dev/null @@ -1,6 +0,0 @@ -#undef IC_INPUT -#undef IC_OUTPUT -#undef IC_ACTIVATOR - -#undef DATA_CHANNEL -#undef PULSE_CHANNEL \ No newline at end of file diff --git a/code/modules/integrated_electronics/~defines/~defines.dm b/code/modules/integrated_electronics/~defines/~defines.dm new file mode 100644 index 00000000000..78ce72f3655 --- /dev/null +++ b/code/modules/integrated_electronics/~defines/~defines.dm @@ -0,0 +1,16 @@ +#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_STRING +#undef IC_FORMAT_NUMBER +#undef IC_FORMAT_REF +#undef IC_FORMAT_LIST +#undef IC_FORMAT_ANY +#undef IC_FORMAT_PULSE \ No newline at end of file diff --git a/code/unit_tests/integrated_circuits/logic.dm b/code/unit_tests/integrated_circuits/logic.dm index 314150f3b4d..a022078c070 100644 --- a/code/unit_tests/integrated_circuits/logic.dm +++ b/code/unit_tests/integrated_circuits/logic.dm @@ -65,6 +65,32 @@ +/datum/unit_test/integrated_circuits/not_equals_1 + name = "Logic Circuits: Not Equals - String True" + circuit_type = /obj/item/integrated_circuit/logic/binary/not_equals + inputs_to_give = list("Test", "Nope") + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/not_equals_2 + name = "Logic Circuits: Not Equals - String False" + circuit_type = /obj/item/integrated_circuit/logic/binary/not_equals + inputs_to_give = list("Test", "Test") + expected_outputs = list(FALSE) + +/datum/unit_test/integrated_circuits/not_equals_3 + name = "Logic Circuits: Not Equals - Number True" + circuit_type = /obj/item/integrated_circuit/logic/binary/not_equals + inputs_to_give = list(150, 20) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/not_equals_4 + name = "Logic Circuits: Not Equals - Number False" + circuit_type = /obj/item/integrated_circuit/logic/binary/not_equals + inputs_to_give = list(100, 100) + expected_outputs = list(FALSE) + + + /datum/unit_test/integrated_circuits/and_1 name = "Logic Circuits: And - True" circuit_type = /obj/item/integrated_circuit/logic/binary/and diff --git a/icons/obj/electronic_assemblies.dmi b/icons/obj/electronic_assemblies.dmi index 8fd1c4f5e10..81aa71eac77 100644 Binary files a/icons/obj/electronic_assemblies.dmi and b/icons/obj/electronic_assemblies.dmi differ diff --git a/polaris.dme b/polaris.dme index c05f4a6db31..f16f2b25842 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1394,19 +1394,26 @@ #include "code\modules\hydroponics\trays\tray_tools.dm" #include "code\modules\hydroponics\trays\tray_update_icons.dm" #include "code\modules\integrated_electronics\_defines.dm" -#include "code\modules\integrated_electronics\arithmetic.dm" -#include "code\modules\integrated_electronics\assemblies.dm" -#include "code\modules\integrated_electronics\converters.dm" -#include "code\modules\integrated_electronics\data_transfer.dm" -#include "code\modules\integrated_electronics\input_output.dm" -#include "code\modules\integrated_electronics\logic.dm" -#include "code\modules\integrated_electronics\manipulation.dm" -#include "code\modules\integrated_electronics\memory.dm" -#include "code\modules\integrated_electronics\reagents.dm" -#include "code\modules\integrated_electronics\time.dm" -#include "code\modules\integrated_electronics\tools.dm" -#include "code\modules\integrated_electronics\trig.dm" -#include "code\modules\integrated_electronics\~defines.dm" +#include "code\modules\integrated_electronics\core\assemblies.dm" +#include "code\modules\integrated_electronics\core\helpers.dm" +#include "code\modules\integrated_electronics\core\integrated_circuit.dm" +#include "code\modules\integrated_electronics\core\pins.dm" +#include "code\modules\integrated_electronics\core\tools.dm" +#include "code\modules\integrated_electronics\passive\passive.dm" +#include "code\modules\integrated_electronics\passive\power.dm" +#include "code\modules\integrated_electronics\subtypes\arithmetic.dm" +#include "code\modules\integrated_electronics\subtypes\converters.dm" +#include "code\modules\integrated_electronics\subtypes\data_transfer.dm" +#include "code\modules\integrated_electronics\subtypes\input_output.dm" +#include "code\modules\integrated_electronics\subtypes\logic.dm" +#include "code\modules\integrated_electronics\subtypes\manipulation.dm" +#include "code\modules\integrated_electronics\subtypes\memory.dm" +#include "code\modules\integrated_electronics\subtypes\power.dm" +#include "code\modules\integrated_electronics\subtypes\reagents.dm" +#include "code\modules\integrated_electronics\subtypes\smart.dm" +#include "code\modules\integrated_electronics\subtypes\time.dm" +#include "code\modules\integrated_electronics\subtypes\trig.dm" +#include "code\modules\integrated_electronics\~defines\~defines.dm" #include "code\modules\library\lib_items.dm" #include "code\modules\library\lib_machines.dm" #include "code\modules\library\lib_readme.dm"