[READY]integrated circuitry port+upgrade.

This commit is contained in:
arsserpentarium
2017-11-14 12:05:22 +03:00
committed by CitadelStationBot
parent 4afc4f5b39
commit d8847ea167
61 changed files with 6933 additions and 9 deletions

View File

@@ -0,0 +1,41 @@
#define IC_INPUT "input"
#define IC_OUTPUT "output"
#define IC_ACTIVATOR "activator"
// Pin functionality.
#define DATA_CHANNEL "data channel"
#define PULSE_CHANNEL "pulse channel"
// Methods of obtaining a circuit.
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
// Displayed along with the pin name to show what type of pin it is.
#define IC_FORMAT_ANY "\<ANY\>"
#define IC_FORMAT_STRING "\<TEXT\>"
#define IC_FORMAT_CHAR "\<CHAR\>"
#define IC_FORMAT_COLOR "\<COLOR\>"
#define IC_FORMAT_NUMBER "\<NUM\>"
#define IC_FORMAT_DIR "\<DIR\>"
#define IC_FORMAT_BOOLEAN "\<BOOL\>"
#define IC_FORMAT_REF "\<REF\>"
#define IC_FORMAT_LIST "\<LIST\>"
#define IC_FORMAT_PULSE "\<PULSE\>"
// Used inside input/output list to tell the constructor what pin to make.
#define IC_PINTYPE_ANY /datum/integrated_io
#define IC_PINTYPE_STRING /datum/integrated_io/string
#define IC_PINTYPE_CHAR /datum/integrated_io/char
#define IC_PINTYPE_COLOR /datum/integrated_io/color
#define IC_PINTYPE_NUMBER /datum/integrated_io/number
#define IC_PINTYPE_DIR /datum/integrated_io/dir
#define IC_PINTYPE_BOOLEAN /datum/integrated_io/boolean
#define IC_PINTYPE_REF /datum/integrated_io/ref
#define IC_PINTYPE_LIST /datum/integrated_io/lists
#define IC_PINTYPE_PULSE_IN /datum/integrated_io/activate
#define IC_PINTYPE_PULSE_OUT /datum/integrated_io/activate/out
// Data limits.
#define IC_MAX_LIST_LENGTH 500

View File

@@ -12,6 +12,7 @@
#define INVESTIGATE_PORTAL "portals"
#define INVESTIGATE_HALLUCINATIONS "hallucinations"
#define INVESTIGATE_RADIATION "radiation"
#define INVESTIGATE_EXONET "exonet"
//Individual logging defines
#define INDIVIDUAL_ATTACK_LOG "Attack log"

View File

@@ -475,3 +475,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define MAX_PROC_DEPTH 195 // 200 proc calls deep and shit breaks, this is a bit lower to give some safety room
#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
#define SYRINGE_DRAW 0
#define SYRINGE_INJECT 1

View File

@@ -53,6 +53,7 @@
#define INIT_ORDER_ATOMS 11
#define INIT_ORDER_LANGUAGE 10
#define INIT_ORDER_MACHINES 9
#define INIT_ORDER_CIRCUIT 8
#define INIT_ORDER_TIMER 1
#define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_AIR -1

View File

@@ -578,3 +578,23 @@
return "turf"
else //regex everything else (works for /proc too)
return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", ""))
/proc/strtohex(str)
if(!istext(str)||!str)
return
var/r
var/c
for(var/i = 1 to length(str))
c= text2ascii(str,i)
r+= num2hex(c)
return r
/proc/hextostr(str)
if(!istext(str)||!str)
return
var/r
var/c
for(var/i = 1 to length(str)/2)
c= hex2num(copytext(str,i*2-1,i*2+1))
r+= ascii2text(c)
return r

View File

@@ -506,6 +506,7 @@ Turf and target are separate in case you want to teleport some distance from a t
/*
Gets all contents of contents and returns them all in a list.
*/
/atom/proc/GetAllContents()
var/list/processing_list = list(src)
var/list/assembled = list()
@@ -1425,6 +1426,46 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/proc/turf_z_is_planet(turf/T)
return GLOB.z_is_planet["[T.z]"]
//same as do_mob except for movables and it allows both to drift and doesn't draw progressbar
/proc/do_atom(atom/movable/user , atom/movable/target, time = 30, uninterruptible = 0,datum/callback/extra_checks = null)
if(!user || !target)
return TRUE
var/user_loc = user.loc
var/drifting = FALSE
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = TRUE
var/target_drifting = FALSE
if(!target.Process_Spacemove(0) && target.inertia_dir)
target_drifting = TRUE
var/target_loc = target.loc
var/endtime = world.time+time
// var/starttime = world.time
. = TRUE
while (world.time < endtime)
stoplag(1)
if(QDELETED(user) || QDELETED(target))
. = 0
break
if(uninterruptible)
continue
if(drifting && !user.inertia_dir)
drifting = FALSE
user_loc = user.loc
if(target_drifting && !target.inertia_dir)
target_drifting = FALSE
target_loc = target.loc
if((!drifting && user.loc != user_loc) || (!target_drifting && target.loc != target_loc) || (extra_checks && !extra_checks.Invoke()))
. = FALSE
break
//returns a GUID like identifier (using a mostly made up record format)
//guids are not on their own suitable for access or security tokens, as most of their bits are predictable.
// (But may make a nice salt to one)

View File

@@ -262,3 +262,5 @@ CONFIG_DEF(number/emergency_shuttle_autocall_threshold)
min_val = 0
max_val = 1
integer = FALSE
CONFIG_DEF(flag/ic_printing)

View File

@@ -0,0 +1,70 @@
PROCESSING_SUBSYSTEM_DEF(circuit)
name = "Circuit"
stat_tag = "CIR"
init_order = INIT_ORDER_CIRCUIT
flags = NONE
var/cipherkey
var/list/all_exonet_connections = list() //Address = connection datum.
var/list/obj/machinery/exonet_node/all_exonet_nodes = list()
var/list/all_circuits = list() // Associative list of [circuit_name]:[circuit_path] pairs
var/list/circuit_fabricator_recipe_list = list() // Associative list of [category_name]:[list_of_circuit_paths] pairs
/datum/controller/subsystem/processing/circuit/Initialize(start_timeofday)
SScircuit.cipherkey = random_string(2000+rand(0,10), GLOB.alphabet)
circuits_init()
return ..()
/datum/controller/subsystem/processing/circuit/proc/circuits_init()
//Cached lists for free performance
var/list/all_circuits = src.all_circuits
var/list/circuit_fabricator_recipe_list = src.circuit_fabricator_recipe_list
for(var/path in typesof(/obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = path
var/name = initial(IC.name)
all_circuits[name] = IC // Populating the complete list
if(!(initial(IC.spawn_flags) & (IC_SPAWN_DEFAULT | IC_SPAWN_RESEARCH)))
continue
var/category = initial(IC.category_text)
if(!circuit_fabricator_recipe_list[category])
circuit_fabricator_recipe_list[category] = list()
var/list/category_list = circuit_fabricator_recipe_list[category]
category_list += IC // Populating the fabricator categories
circuit_fabricator_recipe_list["Assemblies"] = list(
/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone
//new /obj/item/weapon/implant/integrated_circuit,
//new /obj/item/device/assembly/electronic_assembly
)
circuit_fabricator_recipe_list["Tools"] = list(
/obj/item/device/integrated_electronics/wirer,
/obj/item/device/integrated_electronics/debugger,
/obj/item/device/integrated_electronics/analyzer
)
/datum/controller/subsystem/processing/circuit/proc/get_exonet_node()
for(var/i in 1 to all_exonet_nodes.len)
var/obj/machinery/exonet_node/E = all_exonet_nodes[i]
if(E.is_operating())
return E
/datum/controller/subsystem/processing/circuit/proc/get_exonet_address(addr)
return all_exonet_connections[addr]
// Proc: get_atom_from_address()
// Parameters: 1 (target_address - the desired address to find)
// Description: Searches an address for the atom it is attached for, otherwise returns null.
/datum/controller/subsystem/processing/circuit/proc/get_atom_from_address(var/target_address)
var/datum/exonet_protocol/exonet = SScircuit.get_exonet_address(target_address)
if(exonet)
return exonet.holder

113
code/datums/EPv2.dm Normal file
View File

@@ -0,0 +1,113 @@
/*
Exonet Protocol Version 2
This is designed to be a fairly simple fake-networking system, allowing you to send and receive messages
between the exonet_protocol datums, and for atoms to react to those messages, based on the contents of the message.
Hopefully, this can evolve to be a more robust fake-networking system and allow for some devious network hacking in the future.
Version 1 never existed.
*Setting up*
To set up the exonet link, define a variable on your desired atom it is like this;
var/datum/exonet_protocol/exonet = null
Afterwards, before you want to do networking, call exonet = New(src), then exonet.make_address(string), and give it a string to hash into the new IP.
The reason it needs a string is so you can have the addresses be persistant, assuming no-one already took it first.
When you're no longer wanting to use the address and want to free it up, like when you want to Destroy() it, you need to call remove_address()
Destroy() also automatically calls remove_address().
*Sending messages*
To send a message to another datum, you need to know it's EPv2 (fake IP) address. Once you know that, call send_message(), place your
intended address in the first argument, then the message in the second. For example, send_message(exonet.address, "ping") will make you
ping yourself.
*Receiving messages*
You don't need to do anything special to receive the messages, other than give your target exonet datum an address as well. Once something hits
your datum with send_message(), receive_message() is called, and the default action is to call receive_exonet_message() on the datum's holder.
You'll want to override receive_exonet_message() on your atom, and define what will occur when the message is received.
The receiving atom will receive the origin atom (the atom that sent the message), the origin address, and finally the message itself.
It's suggested to start with an if or switch statement for the message, to determine what to do.
*/
/datum/exonet_protocol
var/address = "" //Resembles IPv6, but with only five 'groups', e.g. XXXX:XXXX:XXXX:XXXX:XXXX
var/atom/holder
/datum/exonet_protocol/New(var/atom/H)
holder = H
/datum/exonet_protocol/Destroy()
remove_address()
holder = null
return ..()
// Proc: make_address()
// Parameters: 1 (string - used to make into a hash that will be part of the new address)
// Description: Allocates a new address based on the string supplied. It results in consistant addresses for each round assuming it is not already taken..
/datum/exonet_protocol/proc/make_address(var/string)
if(!string)
return
var/hex = copytext(md5(string),1,25)
if(!hex)
return
var/addr_1 = copytext(hex,1,5)
var/addr_2 = copytext(hex,5,9)
var/addr_3 = copytext(hex,9,13)
var/addr_4 = copytext(hex,13,17)
address = "fc00:[addr_1]:[addr_2]:[addr_3]:[addr_4]"
if(SScircuit.all_exonet_connections[address])
stack_trace("WARNING: Exonet address collision in make_address. Holder type if applicable is [holder? holder.type : "NO HOLDER"]!")
SScircuit.all_exonet_connections[address] = src
// Proc: make_arbitrary_address()
// Parameters: 1 (new_address - the desired address)
// Description: Allocates that specific address, if it is available.
/datum/exonet_protocol/proc/make_arbitrary_address(var/new_address)
if(new_address)
if(new_address == SScircuit.get_exonet_address(new_address) ) //Collision test.
return FALSE
address = new_address
SScircuit.all_exonet_connections[address] = src
return TRUE
// Proc: remove_address()
// Parameters: None
// Description: Deallocates the address, freeing it for use.
/datum/exonet_protocol/proc/remove_address()
SScircuit.all_exonet_connections -= address
address = ""
// Proc: send_message()
// Parameters: 3 (target_address - the desired address to send the message to, data_type - text stating what the content is meant to be used for,
// content - the actual 'message' being sent to the address)
// Description: Sends the message to target_address, by calling receive_message() on the desired datum. Returns true if the message is recieved.
/datum/exonet_protocol/proc/send_message(var/target_address, var/data_type, var/content)
if(!address)
return FALSE
var/obj/machinery/exonet_node/node = SScircuit.get_exonet_node()
if(!node) // Telecomms went boom, ion storm, etc.
return FALSE
var/datum/exonet_protocol/exonet = SScircuit.get_exonet_address(target_address)
if(exonet)
node.write_log(address, target_address, data_type, content)
return exonet.receive_message(holder, address, data_type, content)
// Proc: receive_message()
// Parameters: 4 (origin_atom - the origin datum's holder, origin_address - the address the message originated from,
// data_type - text stating what the content is meant to be used for, content - the actual 'message' being sent from origin_atom)
// Description: Called when send_message() successfully reaches the intended datum. By default, calls receive_exonet_message() on the holder atom.
/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/data_type, var/content)
holder.receive_exonet_message(origin_atom, origin_address, data_type, content)
return TRUE // for send_message()
// Proc: receive_exonet_message()
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
// Description: Override this to make your atom do something when a message is received.
/atom/proc/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
return

View File

@@ -1,4 +1,3 @@
/proc/WEAKREF(datum/input)
if(istype(input) && !QDELETED(input))
if(!input.weak_reference)
@@ -16,4 +15,9 @@
/datum/weakref/proc/resolve()
var/datum/D = locate(reference)
<<<<<<< HEAD
return D.weak_reference == src? D : null
=======
return (!QDELETED(D) && D.weak_reference == src) ? D : null
>>>>>>> bdfbafd... [READY]integrated circuitry port+upgrade. (#32481)

View File

@@ -69,5 +69,4 @@
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
if (!area_motion)
if(isliving(AM))
newTarget(AM)
newTarget(AM)

View File

@@ -0,0 +1,106 @@
/obj/machinery/exonet_node
name = "exonet node"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "exonet_node"
idle_power_usage = 25
var/on = TRUE
var/toggle = TRUE
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/machine/exonet_node
max_integrity = 300
integrity_failure = 100
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
desc = "This machine is exonet node."
var/list/logs = list() // Gets written to by exonet's send_message() function.
var/opened = FALSE
/obj/machinery/exonet_node/Initialize()
. = ..()
SScircuit.all_exonet_nodes += src
/obj/machinery/exonet_node/Destroy()
SScircuit.all_exonet_nodes -= src
return ..()
/obj/machinery/exonet_node/proc/is_operating()
return on && !stat
// Proc: update_icon()
// Parameters: None
// Description: Self explanatory.
/obj/machinery/exonet_node/update_icon()
icon_state = "[initial(icon_state)][on? "" : "_off"]"
// Proc: update_power()
// Parameters: None
// Description: Sets the device on/off and adjusts power draw based on stat and toggle variables.
/obj/machinery/exonet_node/proc/update_power()
on = is_operational() && toggle
use_power = on
update_icon()
// Proc: emp_act()
// Parameters: 1 (severity - how strong the EMP is, with lower numbers being stronger)
// Description: Shuts off the machine for awhile if an EMP hits it. Ion anomalies also call this to turn it off.
/obj/machinery/exonet_node/emp_act(severity)
if(!(stat & EMPED))
stat |= EMPED
var/duration = (300 * 10)/severity
addtimer(CALLBACK(src, /obj/machinery/exonet_node/proc/unemp_act), rand(duration - 20, duration + 20))
update_icon()
..()
/obj/machinery/exonet_node/proc/unemp_act(severity)
stat &= ~EMPED
// Proc: attackby()
// Parameters: 2 (I - the item being whacked against the machine, user - the person doing the whacking)
// Description: Handles deconstruction.
/obj/machinery/exonet_node/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/screwdriver))
default_deconstruction_screwdriver(user, I)
else if(istype(I, /obj/item/crowbar))
default_deconstruction_crowbar(user, I)
else
return ..()
// Proc: attack_ai()
// Parameters: 1 (user - the AI clicking on the machine)
// Description: Redirects to attack_hand()
/obj/machinery/exonet_node/attack_ai(mob/user)
ui_interact(user)
/obj/machinery/exonet_node/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, var/force_open = 1,datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "exonet_node", name, 600, 300, master_ui, state)
ui.open()
/obj/machinery/exonet_node/ui_data(mob/user)
var/list/data = list()
data["toggle"] = toggle
data["logs"] = logs
return data
/obj/machinery/exonet_node/ui_act(action, params)
if(..())
return
switch(action)
if("toggle_power")
toggle = !toggle
update_power()
if(!toggle)
investigate_log("has been turned off by [key_name(usr)].", INVESTIGATE_EXONET)
. = TRUE
update_icon()
add_fingerprint(usr)
// Proc: get_exonet_node()
// Parameters: None
// Description: Helper proc to get a reference to an Exonet node.
/obj/machinery/exonet_node/proc/write_log(var/origin_address, var/target_address, var/data_type, var/content)
var/msg = "[time2text(world.time, "hh:mm:ss")] | FROM [origin_address] TO [target_address] | TYPE: [data_type] | CONTENT: [content]"
logs.Add(msg)

View File

@@ -193,6 +193,19 @@
/obj/item/stack/cable_coil = 1,
/obj/item/stock_parts/subspace/filter = 1)
/obj/item/circuitboard/machine/exonet_node
name = "Exonet Node(machine board)"
build_path = /obj/machinery/exonet_node
origin_tech = "programming=3;engineering=4;bluespace=3;materials=3"
req_components = list(
/obj/item/stock_parts/subspace/ansible = 1,
/obj/item/stock_parts/subspace/filter = 1,
/obj/item/stock_parts/manipulator = 2,
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stock_parts/subspace/crystal = 1,
/obj/item/stock_parts/subspace/treatment = 2,
/obj/item/stack/cable_coil = 2)
/obj/item/circuitboard/machine/teleporter_hub
name = "Teleporter Hub (Machine Board)"
build_path = /obj/machinery/teleport/hub

View File

@@ -1,3 +1,4 @@
<<<<<<< HEAD
#define PROXIMITY_NONE ""
#define PROXIMITY_ON_SCREEN "_red"
#define PROXIMITY_NEAR "_yellow"
@@ -99,3 +100,172 @@
icon_state = "multitool"
toolspeed = 0.1
origin_tech = "magnets=5;engineering=5;abductor=3"
=======
#define PROXIMITY_NONE ""
#define PROXIMITY_ON_SCREEN "_red"
#define PROXIMITY_NEAR "_yellow"
/**
* Multitool -- A multitool is used for hacking electronic devices.
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
*
*/
/obj/item/device/multitool
name = "multitool"
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors."
icon_state = "multitool"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
force = 5
w_class = WEIGHT_CLASS_SMALL
throwforce = 0
throw_range = 7
throw_speed = 3
materials = list(MAT_METAL=50, MAT_GLASS=20)
origin_tech = "magnets=1;engineering=2"
var/obj/machinery/buffer // simple machine buffer for device linkage
hitsound = 'sound/weapons/tap.ogg'
toolspeed = 1
var/datum/integrated_io/selected_io = null //functional for integrated circuits.
var/mode = 0
/obj/item/device/multitool/attack_self(mob/user)
if(selected_io)
selected_io = null
to_chat(user, "<span class='notice'>You clear the wired connection from the multitool.</span>")
else
..()
update_icon()
/obj/item/device/multitool/update_icon()
if(selected_io)
icon_state = "multitool_red"
else
icon_state = "multitool"
/obj/item/device/multitool/proc/wire(var/datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
return
if(selected_io)
if(io == selected_io)
to_chat(user, "<span class='warning'>Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless.</span>")
return
if(io.io_type != selected_io.io_type)
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
while the second is a [io.io_type].</span>")
return
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
return
selected_io.linked |= io
io.linked |= selected_io
to_chat(user, "<span class='notice'>You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name].</span>")
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
else
selected_io = io
to_chat(user, "<span class='notice'>You link \the multitool to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
update_icon()
/obj/item/device/multitool/proc/unwire(var/datum/integrated_io/io1, var/datum/integrated_io/io2, mob/user)
if(!io1.linked.len || !io2.linked.len)
to_chat(user, "<span class='warning'>There is nothing connected to the data channel.</span>")
return
if(!(io1 in io2.linked) || !(io2 in io1.linked) )
to_chat(user, "<span class='warning'>These data pins aren't connected!</span>")
return
else
io1.linked.Remove(io2)
io2.linked.Remove(io1)
to_chat(user, "<span class='notice'>You clip the data connection between the [io1.holder.displayed_name]'s \
[io1.name] and the [io2.holder.displayed_name]'s [io2.name].</span>")
io1.holder.interact(user) // This is to update the UI.
update_icon()
// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby.
/obj/item/device/multitool/ai_detect
var/track_cooldown = 0
var/track_delay = 10 //How often it checks for proximity
var/detect_state = PROXIMITY_NONE
var/rangealert = 8 //Glows red when inside
var/rangewarning = 20 //Glows yellow when inside
origin_tech = "magnets=1;engineering=2;syndicate=1"
/obj/item/device/multitool/ai_detect/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/device/multitool/ai_detect/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/device/multitool/ai_detect/process()
if(track_cooldown > world.time)
return
detect_state = PROXIMITY_NONE
multitool_detect()
icon_state = "[initial(icon_state)][detect_state]"
track_cooldown = world.time + track_delay
/obj/item/device/multitool/ai_detect/proc/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/living/silicon/ai/AI in GLOB.ai_list)
if(AI.cameraFollow == src)
detect_state = PROXIMITY_ON_SCREEN
break
if(!detect_state && GLOB.cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z))
var/datum/camerachunk/chunk = GLOB.cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z)
if(chunk)
if(chunk.seenby.len)
for(var/mob/camera/aiEye/A in chunk.seenby)
var/turf/detect_turf = get_turf(A)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
break
if(get_dist(our_turf, detect_turf) < rangewarning)
detect_state = PROXIMITY_NEAR
break
/obj/item/device/multitool/ai_detect/admin
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors. Has a strange tag that says 'Grief in Safety'." //What else should I say for a meme item?
track_delay = 5
/obj/item/device/multitool/ai_detect/admin/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/J in urange(rangewarning,our_turf))
if(GLOB.admin_datums[J.ckey])
detect_state = PROXIMITY_NEAR
var/turf/detect_turf = get_turf(J)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
break
/obj/item/device/multitool/cyborg
name = "multitool"
desc = "Optimised and stripped-down version of a regular multitool."
toolspeed = 0.5
/obj/item/device/multitool/abductor
name = "alien multitool"
desc = "An omni-technological interface."
icon = 'icons/obj/abductor.dmi'
icon_state = "multitool"
toolspeed = 0.1
origin_tech = "magnets=5;engineering=5;abductor=3"
>>>>>>> bdfbafd... [READY]integrated circuitry port+upgrade. (#32481)

View File

@@ -4,8 +4,7 @@
var/F = file("[GLOB.log_directory]/[subject].html")
WRITE_FILE(F, "<small>[time_stamp()] [REF(src)] ([x],[y],[z])</small> || [src] [message]<br>")
/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION) )
/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION) )
set name = "Investigate"
set category = "Admin"
if(!holder)

View File

@@ -0,0 +1,103 @@
/obj/item/device/integrated_electronics/analyzer
name = "circuit analyzer"
desc = "This tool can scan an assembly and generate code necessary to recreate it in a circuit printer."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "analyzer"
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_SMALL
var/list/circuit_list = list()
var/list/assembly_list = list(/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone)
/obj/item/device/integrated_electronics/analyzer/afterattack(var/atom/A, var/mob/living/user)
visible_message( "<span class='notice'>attempt to scan</span>")
if(ispath(A.type,/obj/item/device/electronic_assembly))
var/i = 0
var/j = 0
var/HTML ="start.assembly{{*}}" //1-st in chapters.1-st block is just to secure start of program from excess symbols.{{*}} is delimeter for chapters.
visible_message( "<span class='notice'>start of scan</span>")
for(var/ix in 1 to assembly_list.len)
var/obj/item/I = assembly_list[ix]
if( A.type == I )
HTML += initial(I.name) +"=-="+A.name //2-nd block.assembly type and name. Maybe in future there will also be color and accesories.
break
/*
If(I.name == "electronic implant")
var/obj/item/weapon/implant/integrated_circuit/PI = PA //now it can't recreate electronic implants.and devices maybe I'll fix it later.
var/obj/item/device/electronic_assembly/implant/PIC = PI.IC
A = PIC
*/
HTML += "{{*}}components" //3-rd block.components. First element is useless.delimeter for elements is ^%^.In element first circuit's default name.Second is user given name.delimiter is =-=
for(var/obj/item/integrated_circuit/IC in A.contents)
i =i + 1
HTML += "^%^"+IC.name+"=-="+IC.displayed_name
if(i == 0)
return
HTML += "{{*}}values" //4-th block.values. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second is data type.third is value.delimiter is :+:
i = 0
var/val
var/list/inp=list()
var/list/out=list()
var/list/act=list()
var/list/ioa=list()
for(var/obj/item/integrated_circuit/IC in A.contents)
i += 1
if(IC.inputs && IC.inputs.len)
for(j in 1 to IC.inputs.len)
var/datum/integrated_io/IN =IC.inputs[j]
inp[IN] = "[i]i[j]"
if(islist(IN.data))
val = list2params(IN.data)
HTML += "^%^"+"[i]i[j]:+:list:+:[val]"
else if(isnum(IN.data))
val= IN.data
HTML += "^%^"+"[i]i[j]:+:num:+:[val]"
else if(istext(IN.data))
val = IN.data
HTML += "^%^"+"[i]i[j]:+:text:+:[val]"
if(IC.outputs && IC.outputs.len)
for(j in 1 to IC.outputs.len) //Also this block uses for setting all i/o id's
var/datum/integrated_io/OUT = IC.outputs[j]
out[OUT] = "[i]o[j]"
if(IC.activators && IC.activators.len)
for(j in 1 to IC.activators.len)
var/datum/integrated_io/ACT = IC.activators[j]
act[ACT] = "[i]a[j]"
ioa.Add(inp)
ioa.Add(out)
ioa.Add(act)
HTML += "{{*}}wires"
if(inp && inp.len)
for(i in 1 to inp.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-=
var/datum/integrated_io/P = inp[i]
for(j in 1 to P.linked.len)
var/datum/integrated_io/C = P.linked[j]
HTML += "^%^"+inp[P]+"=-="+ioa[C]
if(out && out.len)
for(i in 1 to out.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-=
var/datum/integrated_io/P = out[i]
for(j in 1 to P.linked.len)
var/datum/integrated_io/C = P.linked[j]
HTML += "^%^"+out[P]+"=-="+ioa[C]
if(act && act.len)
for(i in 1 to act.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-=
var/datum/integrated_io/P = act[i]
for(j in 1 to P.linked.len)
var/datum/integrated_io/C = P.linked[j]
HTML += "^%^"+act[P]+"=-="+ioa[C]
HTML += "{{*}}end" //6 block.like 1.
visible_message( "<span class='notice'>[A] has been scanned,</span>")
user << browse(jointext(HTML, null), "window=analyzer;size=[500]x[600];border=1;can_resize=1;can_close=1;can_minimize=1")
else
..()

View File

@@ -0,0 +1,342 @@
#define IC_MAX_SIZE_BASE 25
#define IC_COMPLEXITY_BASE 75
/obj/item/device/electronic_assembly
name = "electronic assembly"
desc = "It's a case, for building small electronics with."
w_class = WEIGHT_CLASS_SMALL
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "setup_small"
flags_1 = NOBLUDGEON_1
var/max_components = IC_MAX_SIZE_BASE
var/max_complexity = IC_COMPLEXITY_BASE
var/opened = FALSE
var/obj/item/stock_parts/cell/battery // Internal cell which most circuits need to work.
var/cell_type = /obj/item/stock_parts/cell
var/can_charge = TRUE //Can it be charged in a recharger?
var/charge_sections = 4
var/charge_tick = FALSE
var/charge_delay = 4
var/use_cyborg_cell = TRUE
/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user)
return user.canUseTopic(src,be_close = TRUE)
/obj/item/device/electronic_assembly/medium
name = "electronic mechanism"
icon_state = "setup_medium"
desc = "It's a case, for building medium-sized electronics with."
w_class = WEIGHT_CLASS_NORMAL
max_components = IC_MAX_SIZE_BASE * 2
max_complexity = IC_COMPLEXITY_BASE * 2
/obj/item/device/electronic_assembly/large
name = "electronic machine"
icon_state = "setup_large"
desc = "It's a case, for building large electronics with."
w_class = WEIGHT_CLASS_BULKY
max_components = IC_MAX_SIZE_BASE * 4
max_complexity = IC_COMPLEXITY_BASE * 4
anchored = FALSE
/obj/item/device/electronic_assembly/large/attackby(var/obj/item/O, var/mob/user)
if(default_unfasten_wrench(user, O, 20))
return
..()
/obj/item/device/electronic_assembly/large/attack_tk(mob/user)
if(anchored)
return
..()
/obj/item/device/electronic_assembly/large/attack_hand(mob/user)
if(anchored)
attack_self(user)
return
..()
/obj/item/device/electronic_assembly/drone
name = "electronic drone"
icon_state = "setup_drone"
desc = "It's a case, for building mobile electronics with."
w_class = WEIGHT_CLASS_SMALL
max_components = IC_MAX_SIZE_BASE * 3
max_complexity = IC_COMPLEXITY_BASE * 3
/obj/item/device/electronic_assembly/Initialize()
.=..()
START_PROCESSING(SScircuit, src)
/obj/item/device/electronic_assembly/Destroy()
STOP_PROCESSING(SScircuit, src)
return ..()
/obj/item/device/electronic_assembly/process()
handle_idle_power()
/obj/item/device/electronic_assembly/proc/handle_idle_power()
// First we generate power.
for(var/obj/item/integrated_circuit/passive/power/P in contents)
P.make_energy()
// Now spend it.
for(var/obj/item/integrated_circuit/IC in contents)
if(IC.power_draw_idle)
if(!draw_power(IC.power_draw_idle))
IC.power_fail()
/obj/item/device/electronic_assembly/interact(mob/user)
if(!check_interactivity(user))
return
var/total_part_size = return_total_size()
var/total_complexity = return_total_complexity()
var/HTML = list()
HTML += "<html><head><title>[name]</title></head><body>"
HTML += "<br><a href='?src=[REF(src)]'>\[Refresh\]</a> | "
HTML += "<a href='?src=[REF(src)];rename=1'>\[Rename\]</a><br>"
HTML += "[total_part_size]/[max_components] ([round((total_part_size / max_components) * 100, 0.1)]%) space taken up in the assembly.<br>"
HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.<br>"
if(battery)
HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. <a href='?src=[REF(src)];remove_cell=1'>\[Remove\]</a>"
else
HTML += "<span class='danger'>No powercell detected!</span>"
HTML += "<br><br>"
HTML += "Components:<hr>"
HTML += "Built in:<br>"
//Put removable circuits in separate categories from non-removable
for(var/obj/item/integrated_circuit/circuit in contents)
if(!circuit.removable)
HTML += "<a href=?src=[REF(circuit)];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
HTML += "<a href=?src=[REF(circuit)];rename=1;from_assembly=1>\[Rename\]</a> | "
HTML += "<a href=?src=[REF(circuit)];scan=1;from_assembly=1>\[Scan with Debugger\]</a> | "
HTML += "<a href=?src=[REF(circuit)];bottom=[REF(circuit)];from_assembly=1>\[Move to Bottom\]</a>"
HTML += "<br>"
HTML += "<hr>"
HTML += "Removable:<br>"
for(var/obj/item/integrated_circuit/circuit in contents)
if(circuit.removable)
HTML += "<a href=?src=[REF(circuit)];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
HTML += "<a href=?src=[REF(circuit)];rename=1;from_assembly=1>\[Rename\]</a> | "
HTML += "<a href=?src=[REF(circuit)];scan=1;from_assembly=1>\[Scan with Debugger\]</a> | "
HTML += "<a href=?src=[REF(circuit)];remove=1;from_assembly=1>\[Remove\]</a> | "
HTML += "<a href=?src=[REF(circuit)];bottom=[REF(circuit)];from_assembly=1>\[Move to Bottom\]</a>"
HTML += "<br>"
HTML += "</body></html>"
user << browse(jointext(HTML,null), "window=assembly-\[REF(src)];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1")
/obj/item/device/electronic_assembly/Topic(href, href_list[])
if(..())
return 1
if(href_list["rename"])
rename(usr)
if(href_list["remove_cell"])
if(!battery)
to_chat(usr, "<span class='warning'>There's no power cell to remove from \the [src].</span>")
else
var/turf/T = get_turf(src)
battery.forceMove(T)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pull \the [battery] out of \the [src]'s power supplier.</span>")
battery = null
interact(usr) // To refresh the UI.
/obj/item/device/electronic_assembly/proc/rename()
var/mob/M = usr
if(!check_interactivity(M))
return
var/input = reject_bad_name(input("What do you want to name this?", "Rename", src.name) as null|text,1)
if(!check_interactivity(M))
return
if(src && input)
to_chat(M, "<span class='notice'>The machine now has a label reading '[input]'.</span>")
name = input
/obj/item/device/electronic_assembly/proc/can_move()
return FALSE
/obj/item/device/electronic_assembly/drone/can_move()
return TRUE
/obj/item/device/electronic_assembly/update_icon()
if(opened)
icon_state = initial(icon_state) + "-open"
else
icon_state = initial(icon_state)
/obj/item/device/electronic_assembly/examine(mob/user)
..()
for(var/obj/item/integrated_circuit/IC in contents)
IC.external_examine(user)
if(istype(IC,/obj/item/integrated_circuit/output/screen))
var/obj/item/integrated_circuit/output/screen/S
if(S.stuff_to_display)
to_chat(user, "There's a little screen labeled '[S]', which displays '[S.stuff_to_display]'.")
if(opened)
interact(user)
/obj/item/device/electronic_assembly/proc/return_total_complexity()
. = 0
for(var/obj/item/integrated_circuit/part in contents)
. += part.complexity
/obj/item/device/electronic_assembly/proc/return_total_size()
. = 0
for(var/obj/item/integrated_circuit/part in contents)
. += part.size
// Returns true if the circuit made it inside.
/obj/item/device/electronic_assembly/proc/add_circuit(var/obj/item/integrated_circuit/IC, var/mob/user)
if(!opened)
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
return FALSE
if(IC.w_class > w_class)
to_chat(user, "<span class='warning'>\The [IC] is way too big to fit into \the [src].</span>")
return FALSE
var/total_part_size = return_total_size()
var/total_complexity = return_total_complexity()
if((total_part_size + IC.size) > max_components)
to_chat(user, "<span class='warning'>You can't seem to add the '[IC]', as there's insufficient space.</span>")
return FALSE
if((total_complexity + IC.complexity) > max_complexity)
to_chat(user, "<span class='warning'>You can't seem to add the '[IC]', since this setup's too complicated for the case.</span>")
return FALSE
if(!user.transferItemToLoc(IC, src))
return FALSE
IC.assembly = src
return TRUE
/obj/item/device/electronic_assembly/afterattack(atom/target, mob/user, proximity)
for(var/obj/item/integrated_circuit/input/sensor/S in contents)
if(!proximity)
if(istype(S,/obj/item/integrated_circuit/input/sensor/ranged)||(!user))
if(user.client)
if(!(target in view(user.client)))
continue
else
if(!(target in view(user)))
continue
else
continue
S.set_pin_data(IC_OUTPUT, 1, WEAKREF(target))
S.check_then_do_work()
S.scan(target)
visible_message("<span class='notice'> [user] waves [src] around [target].</span>")
/obj/item/device/electronic_assembly/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/integrated_circuit))
if(!user.canUnEquip(I))
return FALSE
if(add_circuit(I, user))
to_chat(user, "<span class='notice'>You slide [I] inside [src].</span>")
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
interact(user)
return TRUE
else if(istype(I, /obj/item/crowbar))
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
opened = !opened
to_chat(user, "<span class='notice'>You [opened ? "opened" : "closed"] [src].</span>")
update_icon()
return TRUE
else if(istype(I, /obj/item/device/integrated_electronics/wirer) || istype(I, /obj/item/device/integrated_electronics/debugger) || istype(I, /obj/item/screwdriver))
if(opened)
interact(user)
else
to_chat(user, "<span class='warning'> [src] isn't opened, so you can't fiddle with the internal components. \
Try using a crowbar.</span>")
else if(istype(I, /obj/item/stock_parts/cell))
if(!opened)
to_chat(user, "<span class='warning'> [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
return FALSE
if(battery)
to_chat(user, "<span class='warning'> [src] already has \a [battery] inside. Remove it first if you want to replace it.</span>")
return FALSE
var/obj/item/stock_parts/cell = I
user.transferItemToLoc(I, loc)
cell.forceMove(src)
battery = cell
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "<span class='notice'>You slot \the [cell] inside \the [src]'s power supplier.</span>")
interact(user)
return TRUE
else
return ..()
/obj/item/device/electronic_assembly/attack_self(mob/user)
if(!check_interactivity(user))
return
if(opened)
interact(user)
var/list/input_selection = list()
var/list/available_inputs = list()
for(var/obj/item/integrated_circuit/input/input in contents)
if(input.can_be_asked_input)
available_inputs.Add(input)
var/i = 0
for(var/obj/item/integrated_circuit/s in available_inputs)
if(s.name == input.name && s.displayed_name == input.displayed_name && s != input)
i++
var/disp_name= "[input.displayed_name] \[[input]\]"
if(i)
disp_name += " ([i+1])"
input_selection.Add(disp_name)
var/obj/item/integrated_circuit/input/choice
if(available_inputs)
if(available_inputs.len ==1)
choice = available_inputs[1]
else
var/selection = input(user, "What do you want to interact with?", "Interaction") as null|anything in input_selection
if(!check_interactivity(user))
return
if(selection)
var/index = input_selection.Find(selection)
choice = available_inputs[index]
if(choice)
choice.ask_for_input(user)
/obj/item/device/electronic_assembly/emp_act(severity)
..()
for(var/i in 1 to contents.len)
var/atom/movable/AM = contents[i]
AM.emp_act(severity)
// Returns true if power was successfully drawn.
/obj/item/device/electronic_assembly/proc/draw_power(amount)
if(battery && battery.use(amount * GLOB.CELLRATE))
return TRUE
return FALSE
// Ditto for giving.
/obj/item/device/electronic_assembly/proc/give_power(amount)
if(battery && battery.give(amount * GLOB.CELLRATE))
return TRUE
return FALSE
/obj/item/device/electronic_assembly/Moved(oldLoc, dir)
for(var/obj/item/integrated_circuit/IC in contents)
IC.ext_moved(oldLoc, dir)

View File

@@ -0,0 +1,64 @@
/obj/item/device/integrated_electronics/debugger
name = "circuit debugger"
desc = "This small tool allows one working with custom machinery to directly set data to a specific pin, useful for writing \
settings to specific circuits, or for debugging purposes. It can also pulse activation pins."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "debugger"
flags_1 = CONDUCT_1 | NOBLUDGEON_1
w_class = WEIGHT_CLASS_SMALL
var/data_to_write = null
var/accepting_refs = FALSE
/obj/item/device/integrated_electronics/debugger/attack_self(mob/user)
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null")
if(!user.IsAdvancedToolUser())
return
var/new_data = null
switch(type_to_use)
if("string")
accepting_refs = FALSE
new_data = input("Now type in a string.","[src] string writing") as null|text
if(istext(new_data) && user.IsAdvancedToolUser())
data_to_write = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to \"[new_data]\".</span>")
if("number")
accepting_refs = FALSE
new_data = input("Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && user.IsAdvancedToolUser())
data_to_write = new_data
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [new_data].</span>")
if("ref")
accepting_refs = TRUE
to_chat(user, "<span class='notice'>You turn \the [src]'s ref scanner on. Slide it across \
an object for a ref of that object to save it in memory.</span>")
if("null")
data_to_write = null
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
/obj/item/device/integrated_electronics/debugger/afterattack(atom/target, mob/living/user, proximity)
if(accepting_refs && proximity)
data_to_write = WEAKREF(target)
visible_message("<span class='notice'>[user] slides \a [src]'s over \the [target].</span>")
to_chat(user, "<span class='notice'>You set \the [src]'s memory to a reference to [target.name] \[Ref\]. The ref scanner is \
now off.</span>")
accepting_refs = FALSE
else
return ..()
/obj/item/device/integrated_electronics/debugger/proc/write_data(var/datum/integrated_io/io, mob/user)
if(io.io_type == DATA_CHANNEL)
io.write_data_to_pin(data_to_write)
var/data_to_show = data_to_write
if(isweakref(data_to_write))
var/datum/weakref/w = data_to_write
var/atom/A = w.resolve()
data_to_show = A.name
to_chat(user, "<span class='notice'>You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].</span>")
else if(io.io_type == PULSE_CHANNEL)
io.holder.check_then_do_work(ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [io.holder]'s [io].</span>")
io.holder.interact(user) // This is to update the UI.

View File

@@ -0,0 +1,136 @@
/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type, var/list/io_default_list)
var/list/io_list_copy = io_list.Copy()
io_list.Cut()
for(var/i in 1 to io_list_copy.len)
var/io_entry = io_list_copy[i]
var/default_data = null
var/io_type_override = null
// Override the default data.
if(io_default_list && io_default_list.len) // List containing special pin types that need to be added.
default_data = io_default_list["[i]"] // This is deliberately text because the index is a number in text form.
// Override the pin type.
if(io_list_copy[io_entry])
io_type_override = io_list_copy[io_entry]
if(io_type_override)
// world << "io_type_override is now [io_type_override] on [src]."
io_list.Add(new io_type_override(src, io_entry, default_data))
else
io_list.Add(new io_type(src, io_entry, default_data))
/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, datum/new_data)
if (istype(new_data) && !isweakref(new_data))
new_data = WEAKREF(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(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
return inputs[pin_number]
if(IC_OUTPUT)
if(pin_number > outputs.len)
return
return outputs[pin_number]
if(IC_ACTIVATOR)
if(pin_number > activators.len)
return
return activators[pin_number]
return
/obj/item/integrated_circuit/proc/handle_wire(var/datum/integrated_io/pin, var/obj/item/device/integrated_electronics/tool)
if(istype(tool, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = tool
if(pin)
wirer.wire(pin, usr)
return TRUE
else if(istype(tool, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = tool
if(pin)
debugger.write_data(pin, usr)
return TRUE
return FALSE
/obj/item/integrated_circuit/proc/asc2b64(var/S)
var/static/list/b64 = list(
"A"=0,"B"=1,"C"=2,"D"=3,
"E"=4,"F"=5,"G"=6,"H"=7,
"I"=8,"J"=9,"K"=10,"L"=11,
"M"=12,"N"=13,"O"=14,"P"=15,
"Q"=16,"R"=17,"S"=18,"T"=19,
"U"=20,"V"=21,"W"=22,"X"=23,
"Y"=24,"Z"=25,"a"=26,"b"=27,
"c"=28,"d"=29,"e"=30,"f"=31,
"g"=32,"h"=33,"i"=34,"j"=35,
"k"=36,"l"=37,"m"=38,"n"=39,
"o"=40,"p"=41,"q"=42,"r"=43,
"s"=44,"t"=45,"u"=46,"v"=47,
"w"=48,"x"=49,"y"=50,"z"=51,
"0"=52,"1"=53,"2"=54,"3"=55,
"4"=56,"5"=57,"6"=58,"7"=59,
"8"=60,"9"=61,","=62,"."=63
)
var/ls = lentext(S)
var/c
var/i=1
while(i <= ls)
var/sb1=text2ascii(S,i)
var/sb2=text2ascii(S,i+1)
var/sb3=text2ascii(S,i+2)
var/cb1 = (sb1 & 252)>>2
var/cb2 = ((sb1 & 3)<<6 | (sb2 & 240)>>2)>>2
var/cb3 = (sb2 & 15)<<2 | (sb3 & 192)>>6
var/cb4 = (sb3 & 63)
c=c+b64[cb1+1]+b64[cb2+1]+b64[cb3+1]+b64[cb4+1]
i=i+3
return c
/obj/item/integrated_circuit/proc/b642asc(var/S)
var/static/list/b64 = list("A"=1,"B"=2,"C"=3,"D"=4,"E"=5,"F"=6,"G"=7,"H"=8,"I"=9,"J"=10,"K"=11,"L"=12,"M"=13,"N"=14,"O"=15,"P"=16,"Q"=17,"R"=18,
"S"=19,"T"=20,"U"=21,"V"=22,"W"=23,"X"=24,"Y"=25,"Z"=26,"a"=27,"b"=28,"c"=29,"d"=30,"e"=31,"f"=32,"g"=33,"h"=34,"i"=35,"j"=36,"k"=37,"l"=38,"m"=39,"n"=40,"o"=41,
"p"=42,"q"=43,"r"=44,"s"=45,"t"=46,"u"=47,"v"=48,"w"=49,"x"=50,"y"=51,"z"=52,"0"=53,"1"=54,"2"=55,"3"=56,"4"=57,"5"=58,"6"=59,"7"=60,"8"=61,"9"=62,","=63,"."=64)
var/ls = lentext(S)
var/c
var/i=1
while(i<=ls)
var/cb1=b64[copytext(S,i,i+1)]-1
var/cb2=b64[copytext(S,i+1,i+2)]-1
var/cb3=b64[copytext(S,i+2,i+3)]-1
var/cb4=b64[copytext(S,i+3,i+4)]-1
var/sb1=cb1<<2 | (cb2 & 48)>>4
var/sb2=(cb2 & 15) <<4 | (cb3 & 60)>>2
var/sb3=(cb3 & 3)<<6 | cb4
c=c+ascii2text(sb1)+ascii2text(sb2)+ascii2text(sb3)
i=i+4
return c
/proc/XorEncrypt(string,key)
if(!string || !key ||!istext(string)||!istext(key))
return
var/r
for(var/i = 1 to length(string))
r += ascii2text(text2ascii(string,i) ^ text2ascii(key,(i-1)%length(string)+1))
return r

View File

@@ -0,0 +1,437 @@
/obj/item/integrated_circuit
name = "integrated circuit"
desc = "It's a tiny chip! This one doesn't seem to do much, however."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "template"
w_class = WEIGHT_CLASS_TINY
var/obj/item/device/electronic_assembly/assembly // Reference to the assembly holding this circuit, if any.
var/extended_desc
var/list/inputs = list()
var/list/inputs_default = list()// Assoc list which will fill a pin with data upon creation. e.g. "2" = 0 will set input pin 2 to equal 0 instead of null.
var/list/outputs = list()
var/list/outputs_default =list()// Ditto, for output.
var/list/activators = list()
var/next_use = 0 // Uses world.time
var/complexity = 1 // This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
var/size = 1 // This acts as a limitation on building machines, bigger components cost more 'space'. -1 for size 0
var/cooldown_per_use = 9 // Circuits are limited in how many times they can be work()'d by this variable.
var/power_draw_per_use = 0 // How much power is drawn when work()'d.
var/power_draw_idle = 0 // How much power is drawn when doing nothing.
var/spawn_flags // Used for world initializing, see the #defines above.
var/category_text = "NO CATEGORY THIS IS A BUG" // To show up on circuit printer, and perhaps other places.
var/removable = TRUE // Determines if a circuit is removable from the assembly.
var/displayed_name = ""
var/allow_multitool = TRUE // Allows additional multitool functionality
// Used as a global var, (Do not set manually in children).
/*
Integrated circuits are essentially modular machines. Each circuit has a specific function, and combining them inside Electronic Assemblies allows
a creative player the means to solve many problems. Circuits are held inside an electronic assembly, and are wired using special tools.
*/
/obj/item/integrated_circuit/examine(mob/user)
interact(user)
external_examine(user)
. = ..()
// This should be used when someone is examining while the case is opened.
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
to_chat(user, "This board has [inputs.len] input pin\s, [outputs.len] output pin\s and [activators.len] activation pin\s.")
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
if(I.linked.len)
to_chat(user, "The '[I]' is connected to [I.get_linked_to_desc()].")
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
if(O.linked.len)
to_chat(user, "The '[O]' is connected to [O.get_linked_to_desc()].")
for(var/k in 1 to activators.len)
var/datum/integrated_io/activate/A = activators[k]
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/proc/check_interactivity(mob/user)
if(assembly)
return assembly.check_interactivity(user)
else
return user.canUseTopic(src,be_close = TRUE)
/obj/item/integrated_circuit/Initialize()
displayed_name = name
setup_io(inputs, /datum/integrated_io, inputs_default)
setup_io(outputs, /datum/integrated_io, outputs_default)
setup_io(activators, /datum/integrated_io/activate)
..()
/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit.
return
/obj/item/integrated_circuit/Destroy()
QDEL_LIST(inputs)
QDEL_LIST(outputs)
QDEL_LIST(activators)
. = ..()
/*
/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/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
I.scramble()
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
O.scramble()
for(var/k in 1 to activators.len)
var/datum/integrated_io/activate/A = activators[k]
A.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(!check_interactivity(M))
return
var/input = reject_bad_name(input("What do you want to name this?", "Rename", src.name) as null|text,1)
if(src && input && check_interactivity(M))
to_chat(M, "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>")
displayed_name = input
/obj/item/integrated_circuit/interact(mob/user)
if(!check_interactivity(user))
return
// if(!assembly)
// 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 += "<html><head><title>[src.displayed_name]</title></head><body>"
HTML += "<div align='center'>"
HTML += "<table border='1' style='undefined;table-layout: fixed; width: 80%'>"
HTML += "<br><a href='?src=[REF(src)];return=1'>\[Return to Assembly\]</a>"
HTML += "<br><a href='?src=[REF(src)];'>\[Refresh\]</a> | "
HTML += "<a href='?src=[REF(src)];rename=1'>\[Rename\]</a> | "
HTML += "<a href='?src=[REF(src)];scan=1'>\[Scan with Device\]</a> | "
if(src.removable)
HTML += "<a href='?src=[REF(src)];remove=1'>\[Remove\]</a><br>"
HTML += "<colgroup>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "<col style='width: [table_middle_width]'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "</colgroup>"
var/column_width = 3
var/row_height = max(inputs.len, outputs.len, 1)
for(var/i = 1 to row_height)
HTML += "<tr>"
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = list()
var/height = 1
switch(j)
if(1)
io = get_pin_ref(IC_INPUT, i)
if(io)
words += "<b><a href=?src=[REF(src)];pin_name=1;pin=[REF(io)]>[io.display_pin_type()] [io.name]</a> <a href=?src=[REF(src)];pin_data=1;pin=[REF(io)]>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
// words += "<a href=?src=[REF(linked.holder)];pin_name=1;pin=[REF(linked)];link=[REF(io)]>\[[linked]\]</a>
words += "<a href=?src=[REF(src)];pin_unwire=1;pin=[REF(io)];link=[REF(linked)]>[linked]</a> \
@ <a href=?src=[REF(linked.holder)];examine=1;>[linked.holder.displayed_name]</a><br>"
if(outputs.len > inputs.len)
height = 1
if(2)
if(i == 1)
words += "[src.displayed_name]<br>[src.name != src.displayed_name ? "([src.name])":""]<hr>[src.desc]"
height = row_height
else
continue
if(3)
io = get_pin_ref(IC_OUTPUT, i)
if(io)
words += "<b><a href=?src=[REF(src)];pin_name=1;pin=[REF(io)]>[io.display_pin_type()] [io.name]</a> <a href=?src=[REF(src)];pin_data=1;pin=[REF(io)]>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
// words += "<a href=?src=[REF(linked.holder)];pin_name=1;pin=[REF(linked)];link=[REF(io)]>\[[linked]\]</a>
words += "<a href=?src=[REF(src)];pin_unwire=1;pin=[REF(io)];link=[REF(linked)]>[linked]</a> \
@ <a href=?src=[REF(linked.holder)];examine=1;>[linked.holder.displayed_name]</a><br>"
if(inputs.len > outputs.len)
height = 1
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
HTML += "</tr>"
for(var/activator in activators)
var/datum/integrated_io/io = activator
var/words = list()
words += "<b><a href=?src=[REF(src)];pin_name=1;pin=[REF(io)]><font color='FF0000'>[io]</font></a> <a href=?src=[REF(src)];pin_data=1;pin=[REF(io)]><font color='FF0000'>[io.data?"\<PULSE OUT\>":"\<PULSE IN\>"]</font></a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
// words += "<a href=?src=[REF(linked.holder)];pin_name=1;pin=[REF(linked)];link=[REF(io)]>\[[linked]\]</a>
words += "<a href=?src=[REF(src)];pin_unwire=1;pin=[REF(io)];link=[REF(linked)]><font color='FF0000'>[linked]</font></a> \
@ <a href=?src=[REF(linked.holder)];examine=1;><font color='FF0000'>[linked.holder.displayed_name]</font></a><br>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
HTML += "</tr>"
HTML += "</table>"
HTML += "</div>"
// HTML += "<br><font color='33CC33'>Meta Variables;</font>" // If more meta vars get introduced, uncomment this.
// HTML += "<br>"
HTML += "<br><font color='0000AA'>Complexity: [complexity]</font>"
if(power_draw_idle)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_idle] W (Idle)</font>"
if(power_draw_per_use)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_per_use] W (Active)</font>" // Borgcode says that powercells' checked_use() takes joules as input.
HTML += "<br><font color='0000AA'>[extended_desc]</font>"
HTML += "</body></html>"
if(src.assembly)
user << browse(jointext(HTML, null), "window=assembly-[REF(src.assembly)];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
else
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, "assembly-[REF(src.assembly)]")
/obj/item/integrated_circuit/Topic(href, href_list)
if(!check_interactivity(usr))
return
if(..())
return TRUE
var/update = TRUE
var/obj/item/device/electronic_assembly/A = src.assembly
var/update_to_assembly = FALSE
var/datum/integrated_io/pin = locate(href_list["pin"]) in inputs + outputs + activators
var/datum/integrated_io/linked = null
if(href_list["link"])
linked = locate(href_list["link"]) in pin.linked
var/obj/held_item = usr.get_active_held_item()
if(href_list["rename"])
rename_component(usr)
if(href_list["from_assembly"])
update = FALSE
var/obj/item/device/electronic_assembly/ea = loc
if(istype(ea))
ea.interact(usr)
if(href_list["pin_name"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = TRUE
else
var/obj/item/device/multitool/M = held_item
M.wire(pin,usr)
if(href_list["pin_data"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = TRUE
else
var/datum/integrated_io/io = pin
io.ask_for_pin_data(usr) // The pins themselves will determine how to ask for data, and will validate the data.
/*
if(io.io_type == DATA_CHANNEL)
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number", "null")
if(!check_interactivity(usr))
return
var/new_data = null
switch(type_to_use)
if("string")
new_data = input("Now type in a string.","[src] string writing") as null|text
to_chat(usr, "<span class='notice'>You input [new_data] into the pin.</span>")
//to_chat(user, "<span class='notice'>You write '[new_data]' to the '[io]' pin of \the [io.holder].</span>")
if("number")
new_data = input("Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && check_interactivity(usr) )
to_chat(usr, "<span class='notice'>You input [new_data] into the pin.</span>")
if("null")
if(check_interactivity(usr))
to_chat(usr, "<span class='notice'>You clear the pin's memory.</span>")
io.write_data_to_pin(new_data)
else if(io.io_type == PULSE_CHANNEL)
io.holder.check_then_do_work(ignore_power = TRUE)
to_chat(usr, "<span class='notice'>You pulse \the [io.holder]'s [io] pin.</span>")
*/
if(href_list["pin_unwire"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = TRUE
else
var/obj/item/device/multitool/M = held_item
M.unwire(pin, linked, usr)
if(href_list["wire"])
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(linked)
wirer.wire(linked, usr)
else if(pin)
wirer.wire(pin, usr)
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, usr)
else
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
if(href_list["examine"])
var/obj/item/integrated_circuit/examined
if(href_list["examined"])
examined = href_list["examined"]
else
examined = src
examined.interact(usr)
update = FALSE
if(href_list["bottom"])
var/obj/item/integrated_circuit/circuit = locate(href_list["bottom"]) in src.assembly.contents
var/assy = circuit.assembly
if(!circuit)
return
circuit.loc = null
circuit.loc = assy
. = TRUE
update_to_assembly = TRUE
if(href_list["scan"])
if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/D = held_item
if(D.accepting_refs)
D.afterattack(src, usr, TRUE)
else
to_chat(usr, "<span class='warning'>The Debugger's 'ref scanner' needs to be on.</span>")
else
to_chat(usr, "<span class='warning'>You need a multitool/debugger set to 'ref' mode to do that.</span>")
if(href_list["return"])
if(A)
update_to_assembly = TRUE
usr << browse(null, "window=circuit-[REF(src)];border=1;can_resize=1;can_close=1;can_minimize=1")
else
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
if(href_list["remove"])
if(!A)
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
return
if(!removable)
to_chat(usr, "<span class='warning'>\The [src] seems to be permanently attached to the case.</span>")
return
var/obj/item/device/electronic_assembly/ea = loc
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
assembly = null
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
if(istype(ea))
ea.interact(usr)
update = FALSE
return
if(update)
if(A && istype(A) && update_to_assembly)
A.interact(usr)
else
interact(usr) // To refresh the UI.
/obj/item/integrated_circuit/proc/push_data()
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
O.push_data()
/obj/item/integrated_circuit/proc/pull_data()
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
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(var/ignore_power = FALSE)
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
if(power_draw_per_use && !ignore_power)
if(!check_power())
power_fail()
return
next_use = world.time + cooldown_per_use
do_work()
/obj/item/integrated_circuit/proc/do_work()
return
/obj/item/integrated_circuit/proc/disconnect_all()
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
I.disconnect()
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
O.disconnect()
for(var/k in 1 to activators.len)
var/datum/integrated_io/activate/A = activators[k]
A.disconnect()
/obj/item/integrated_circuit/proc/ext_moved(oldLoc, dir)
return

View File

@@ -0,0 +1,197 @@
/*
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
var/datum/weakref/data // 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(newloc, name1, new_data)
name = name1
if(new_data)
data = new_data
holder = newloc
if(!istype(holder))
message_admins("ERROR: An integrated_io ([name]) spawned without a valid holder! This is a bug.")
/datum/integrated_io/Destroy()
disconnect()
data = null
holder = null
return ..()
/*
/datum/integrated_io/nano_host()
return holder.nano_host()
*/
/datum/integrated_io/proc/data_as_type(var/as_type)
if(!isweakref(data))
return
var/datum/weakref/w = data
var/output = w.resolve()
return istype(output, as_type) ? output : null
/datum/integrated_io/proc/display_data(var/input)
if(isnull(input))
return "(null)" // Empty data means nothing to show.
if(istext(input))
return "(\"[input]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'.
/*
list[](
"A",
"B",
"C"
)
*/
if(islist(input))
var/list/my_list = input
var/result = "list\[[my_list.len]\]("
if(my_list.len)
result += "<br>"
var/pos = 0
for(var/line in my_list)
result += "[display_data(line)]"
pos++
if(pos != my_list.len)
result += ",<br>"
result += "<br>"
result += ")"
return result
if(isweakref(input))
var/datum/weakref/w = input
var/atom/A = w.resolve()
return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed.
//return A ? "([REF(A)] \[Ref\])" : "(null)"
return "([input])" // Nothing special needed for numbers or other stuff.
/datum/integrated_io/activate/display_data()
return "(\[pulse\])"
/datum/integrated_io/proc/display_pin_type()
return IC_FORMAT_ANY
/datum/integrated_io/activate/display_pin_type()
return IC_FORMAT_PULSE
/datum/integrated_io/proc/scramble()
if(isnull(data))
return
if(isnum(data))
write_data_to_pin(rand(-10000, 10000))
if(istext(data))
write_data_to_pin("ERROR")
push_data()
/datum/integrated_io/activate/scramble()
push_data()
/datum/integrated_io/proc/write_data_to_pin(var/new_data)
if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data))
data = new_data
holder.on_data_written()
else if(islist(new_data))
var/list/new_list = new_data
data = new_list.Copy(1,min( IC_MAX_LIST_LENGTH+1, new_list.len ))
holder.on_data_written()
/datum/integrated_io/proc/push_data()
for(var/k in 1 to linked.len)
var/datum/integrated_io/io = linked[k]
io.write_data_to_pin(data)
/datum/integrated_io/activate/push_data()
for(var/k in 1 to linked.len)
var/datum/integrated_io/io = linked[k]
io.holder.check_then_do_work()
/datum/integrated_io/proc/pull_data()
for(var/k in 1 to linked.len)
var/datum/integrated_io/io = linked[k]
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.
if(linked && linked.len)
for(var/i in 1 to linked.len)
var/datum/integrated_io/their_io = linked[i]
//While doing that, we iterate them as well, and disconnect ourselves from them.
if(their_io.linked.len && their_io.linked)
for(var/j in 1 to their_io.linked.len)
var/datum/integrated_io/their_linked_io = their_io.linked[j]
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.
linked.Remove(their_io)
/datum/integrated_io/proc/ask_for_data_type(mob/user, var/default, var/list/allowed_data_types = list("string","number","null"))
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in allowed_data_types
if(!holder.check_interactivity(user))
return
var/new_data = null
switch(type_to_use)
if("string")
new_data = input("Now type in a string.","[src] string writing", istext(default) ? default : null) as null|text
if(istext(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input "+new_data+" into the pin.</span>")
return new_data
if("number")
new_data = input("Now type in a number.","[src] number writing", isnum(default) ? default : null) as null|num
if(isnum(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
return new_data
if("null")
if(holder.check_interactivity(user))
to_chat(user, "<span class='notice'>You clear the pin's memory.</span>")
return new_data
// Basically a null check
/datum/integrated_io/proc/is_valid()
return !isnull(data)
// This proc asks for the data to write, then writes it.
/datum/integrated_io/proc/ask_for_pin_data(mob/user)
var/new_data = ask_for_data_type(user)
write_data_to_pin(new_data)
/datum/integrated_io/activate/ask_for_pin_data(mob/user) // This just pulses the pin.
holder.check_then_do_work(ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [holder]'s [src] pin.</span>")
/datum/integrated_io/activate
name = "activation pin"
io_type = PULSE_CHANNEL
/datum/integrated_io/activate/out // All this does is just make the UI say 'out' instead of 'in'
data = 1

View File

@@ -0,0 +1,156 @@
/obj/item/device/integrated_electronics/prefab
var/debug = FALSE
name = "prefab"
desc = "new machine in package"
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "box_template"
w_class = WEIGHT_CLASS_BULKY
var/program="blank"
var/list/as_names = list()
/obj/item/device/integrated_electronics/prefab/attack_self(var/mob/user)
if(program && program != "blank")
assemble(program)
else
return ..()
/obj/item/device/integrated_electronics/prefab/Initialize()
. = ..()
var/list/assembly_list = list(
/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone,
)
for(var/k in 1 to assembly_list.len)
var/obj/item/I = assembly_list[k]
as_names[initial(I.name)] = I
addtimer(CALLBACK(src, .proc/attack_self), 2) //IDK, why it's need dely,but otherwise it doesn't work.
/obj/item/device/integrated_electronics/prefab/proc/assemble(var/program)
var/list/all_circuits = SScircuit.all_circuits //cached lists = free performance
var/list/chap = splittext( program ,"{{*}}")
var/list/elements = list()
var/list/elements_input = list()
var/list/element = list()
var/obj/item/AS
var/PA
var/i = 0
var/list/ioa = list()
var/datum/integrated_io/IO
var/datum/integrated_io/IO2
if(debug)
visible_message( "<span class='notice'>started successful</span>")
if(chap[2] != "")
if(debug)
visible_message( "<span class='notice'>assembly</span>")
element = splittext( chap[2] ,"=-=")
PA = as_names[element[1]]
AS = new PA(null)
AS.loc = src
AS.name = element[2]
else
return //what's the point if there is no assembly?
if(chap[3] != "components") //if there is only one word,there is no components.
elements_input = splittext( chap[3] ,"^%^")
if(debug)
visible_message( "<span class='notice'>components[elements_input.len]</span>")
i = 0
elements = list()
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem) //I don't know,why Cut or copy don't works. If somebody can fix it, it should be fixed.
if(debug)
visible_message( "<span class='notice'>components[elements.len]</span>")
if(!length(elements_input))
return
if(debug)
visible_message( "<span class='notice'>inserting components[elements.len]</span>")
var/obj/item/integrated_circuit/comp
i=0
for(var/E in elements)
i=i+1
element = splittext( E ,"=-=")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
var/path_to_use = all_circuits[element[1]]
comp = new path_to_use(null)
comp.loc = AS
comp.displayed_name = element[2]
comp.assembly = AS
if(comp.inputs && comp.inputs.len)
for(var/j in 1 to comp.inputs.len)
var/datum/integrated_io/IN = comp.inputs[j]
ioa["[i]i[j]"] = IN
if(debug)
visible_message( "<span class='notice'>[i]i[j]</span>")
if(comp.outputs && comp.outputs.len)
for(var/j in 1 to comp.outputs.len) //Also this block uses for setting all i/o id's
var/datum/integrated_io/OUT = comp.outputs[j]
ioa["[i]o[j]"] = OUT
if(debug)
visible_message( "<span class='notice'>[i]o[j]</span>")
if(comp.activators && comp.activators.len)
for(var/j in 1 to comp.activators.len)
var/datum/integrated_io/ACT = comp.activators[j]
ioa["[i]a[j]"] = ACT
if(debug)
visible_message( "<span class='notice'>[i]a[j]</span>")
else
return
if(!AS.contents.len)
return
if(chap[4] != "values") //if there is only one word,there is no values
elements_input = splittext( chap[4] ,"^%^")
if(debug)
visible_message( "<span class='notice'>values[elements_input.len]</span>")
i=0
elements = list()
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>values[elements.len]</span>")
if(elements.len>0)
if(debug)
visible_message( "<span class='notice'>setting values[elements.len]</span>")
for(var/E in elements)
element = splittext( E ,":+:")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
IO = ioa[element[1]]
if(element[2]=="text")
IO.write_data_to_pin(element[3])
else if(element[2]=="num")
IO.write_data_to_pin(text2num(element[3]))
else if(element[2]=="list")
IO.write_data_to_pin(params2list(element[3]))
if(chap[5] != "wires") //if there is only one word,there is no wires
elements_input = splittext( chap[5] ,"^%^")
i=0
elements = list()
if(debug)
visible_message( "<span class='notice'>wires[elements_input.len]</span>")
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>wires[elements.len]</span>")
if(elements.len>0)
if(debug)
visible_message( "<span class='notice'>setting wires[elements.len]</span>")
for(var/E in elements)
element = splittext( E ,"=-=")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
IO = ioa[element[1]]
IO2 = ioa[element[2]]
IO.linked |= IO2
AS.forceMove(loc)
qdel(src)

View File

@@ -0,0 +1,413 @@
/obj/item/device/integrated_circuit_printer
name = "integrated circuit printer"
desc = "A portable(ish) machine made to print tiny modular circuitry out of metal."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "circuit_printer"
w_class = WEIGHT_CLASS_BULKY
var/metal = 0
var/init_max_metal = 100
var/max_metal = 100
var/metal_per_sheet = 10 // One sheet equals this much metal.
var/debug = FALSE
var/upgraded = FALSE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits.
var/can_clone = FALSE // Same for above, but will allow the printer to duplicate a specific assembly.
var/static/list/recipe_list //category = list(paths in category)
var/current_category = null
var/as_printing = FALSE
var/as_needs = 0
var/program ="blank"
var/obj/item/device/integrated_electronics/prefab/PR = null
/obj/item/device/integrated_circuit_printer/proc/check_interactivity(mob/user)
return user.canUseTopic(src,be_close = TRUE)
/obj/item/device/integrated_circuit_printer/upgraded
upgraded = TRUE
can_clone = TRUE
/obj/item/device/integrated_circuit_printer/Initialize()
. = ..()
if(!recipe_list)
recipe_list = SScircuit.circuit_fabricator_recipe_list
/obj/item/device/integrated_circuit_printer/attackby(var/obj/item/O, var/mob/user)
if(istype(O,/obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/stack = O
var/num = min((max_metal - metal) / metal_per_sheet, stack.amount)
if(num < 1)
to_chat(user, "<span class='warning'>\The [src] is too full to add more metal.</span>")
return
if(stack.use(num))
to_chat(user, "<span class='notice'>You add [num] sheet\s to \the [src].</span>")
metal += num * metal_per_sheet
if(as_printing)
if(as_needs <= metal)
PR = new/obj/item/device/integrated_electronics/prefab(get_turf(loc))
PR.program = program
metal = metal - as_needs
to_chat(user, "<span class='notice'>Assembly has been printed.</span>")
as_printing = FALSE
as_needs = 0
max_metal = init_max_metal
else
to_chat(user, "<span class='notice'>Please insert [(as_needs-metal)/10] more metal!</span>")
interact(user)
return TRUE
if(istype(O,/obj/item/integrated_circuit))
to_chat(user, "<span class='notice'>You insert the circuit into \the [src]. </span>")
user.temporarilyRemoveItemFromInventory(O)
metal = min(metal + O.w_class, max_metal)
qdel(O)
interact(user)
return TRUE
if(istype(O,/obj/item/disk/integrated_circuit/upgrade/advanced))
if(upgraded)
to_chat(user, "<span class='warning'>\The [src] already has this upgrade. </span>")
return TRUE
to_chat(user, "<span class='notice'>You install \the [O] into \the [src]. </span>")
upgraded = TRUE
interact(user)
return TRUE
if(istype(O,/obj/item/disk/integrated_circuit/upgrade/clone))
if(can_clone)
to_chat(user, "<span class='warning'>\The [src] already has this upgrade. </span>")
return TRUE
to_chat(user, "<span class='notice'>You install \the [O] into \the [src]. </span>")
can_clone = TRUE
interact(user)
return TRUE
return ..()
/obj/item/device/integrated_circuit_printer/attack_self(var/mob/user)
interact(user)
/obj/item/device/integrated_circuit_printer/interact(mob/user)
var/window_height = 600
var/window_width = 500
if(isnull(current_category))
current_category = recipe_list[1]
var/HTML = "<center><h2>Integrated Circuit Printer</h2></center><br>"
HTML += "Metal: [metal/metal_per_sheet]/[max_metal/metal_per_sheet] sheets.<br>"
HTML += "Circuits available: [upgraded ? "Advanced":"Regular"]."
HTML += "Assembly Cloning: [can_clone ? "Available": "Unavailable"]."
HTML += "Crossed out circuits mean that the printer is not sufficiently upgraded to create that circuit.<br>"
HTML += "<hr>"
if(can_clone)
HTML += "Here you can load script for your assembly.<br>"
if(as_printing)
HTML += " {Load Program} "
else
HTML += " <A href='?src=[REF(src)];print=load'>{Load Program}</a> "
if(program == "blank")
HTML += " {Check Program} "
else
HTML += " <A href='?src=[REF(src)];print=check'>{Check Program}</a> "
if((program == "blank")|as_printing)
HTML += " {Print assembly} "
else
HTML += " <A href='?src=[REF(src)];print=print'>{Print assembly}</a> "
if(as_printing)
HTML += "<br> printing in process. Please insert more metal. "
HTML += "<br><hr>"
HTML += "Categories:"
for(var/category in recipe_list)
if(category != current_category)
HTML += " <a href='?src=[REF(src)];category=[category]'>\[[category]\]</a> "
else // Bold the button if it's already selected.
HTML += " <b>\[[category]\]</b> "
HTML += "<hr>"
HTML += "<center><h4>[current_category]</h4></center>"
var/list/current_list = recipe_list[current_category]
for(var/k in 1 to current_list.len)
var/obj/O = current_list[k]
var/can_build = TRUE
if(istype(O, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = current_list[k]
if((initial(IC.spawn_flags) & IC_SPAWN_RESEARCH) && (!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT)) && !upgraded)
can_build = FALSE
if(can_build)
HTML += "<A href='?src=[REF(src)];build=[current_list[k]]'>\[[initial(O.name)]\]</A>: [initial(O.desc)]<br>"
else
HTML += "<s>\[[initial(O.name)]\]: [initial(O.desc)]</s><br>"
user << browse(jointext(HTML, null), "window=integrated_printer;size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
/obj/item/device/integrated_circuit_printer/Topic(href, href_list)
if(!check_interactivity(usr))
return
if(..())
return TRUE
var/sc = 0
add_fingerprint(usr)
if(href_list["category"])
current_category = href_list["category"]
if(href_list["build"])
var/build_type = text2path(href_list["build"])
if(!build_type || !ispath(build_type))
return TRUE
var/cost = 1
if(ispath(build_type, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/E = build_type
cost = round( (initial(E.max_complexity) + initial(E.max_components) ) / 4)
else if(ispath(build_type, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = build_type
cost = initial(IC.w_class)
if(metal - cost < 0)
to_chat(usr, "<span class='warning'>You need [cost] metal to build that!.</span>")
return TRUE
metal -= cost
new build_type(get_turf(loc))
if(href_list["print"])
if(!CONFIG_GET(flag/ic_printing))
to_chat(usr, "<span class='warning'>CentCom has disabled printing of custom circuitry due to recent allegations of copyright infringement.</span>")
return
switch(href_list["print"])
if("load")
program = input("Put your code there:", "loading", null, null)
if("check")
sc = sanity_check(program,usr)
if(sc == 0)
to_chat(usr, "<span class='warning'>Invalid program.</span>")
else if(sc == -1)
to_chat(usr, "<span class='warning'>Unknown circuits found. Upgrades required to process this design.</span>")
else if(sc == null)
to_chat(usr, "<span class='warning'>Invalid program.</span>")
else
to_chat(usr, "<span class='notice'>Program is correct.You'll need [sc/10] sheets of metal</span>")
if("print")
sc = sanity_check(program,usr)
if(sc == 0 || sc == null)
to_chat(usr, "<span class='warning'>Invalid program.</span>")
else if(sc == -1)
to_chat(usr, "<span class='warning'>Unknown circuits found. Upgrades required to process this design.</span>")
else
as_printing = TRUE
if(sc <= metal)
PR = new/obj/item/device/integrated_electronics/prefab(get_turf(loc))
PR.program = program
metal = metal - sc
to_chat(usr, "<span class='notice'>Assembly has been printed.</span>")
as_printing = FALSE
as_needs = 0
max_metal=init_max_metal
else
max_metal = sc + metal_per_sheet
as_needs = sc
to_chat(usr, "<span class='notice'>Please insert [(as_needs-metal)/10] more metal!</span>")
interact(usr)
// FUKKEN UPGRADE DISKS
/obj/item/disk/integrated_circuit/upgrade
name = "integrated circuit printer upgrade disk"
desc = "Install this into your integrated circuit printer to enhance it."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "upgrade_disk"
item_state = "card-id"
w_class = WEIGHT_CLASS_SMALL
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4)
/obj/item/disk/integrated_circuit/upgrade/advanced
name = "integrated circuit printer upgrade disk - advanced designs"
desc = "Install this into your integrated circuit printer to enhance it. This one adds new, advanced designs to the printer."
// To be implemented later.
/obj/item/disk/integrated_circuit/upgrade/clone
name = "integrated circuit printer upgrade disk - circuit cloner"
desc = "Install this into your integrated circuit printer to enhance it. This one allows the printer to duplicate assemblies."
icon_state = "upgrade_disk_clone"
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5)
/obj/item/device/integrated_circuit_printer/proc/sanity_check(var/program,var/mob/user)
var/list/chap = splittext( program ,"{{*}}")
if(chap.len != 6)
return 0 //splitting incorrect
var/list/elements = list()
var/list/elements_input = list()
var/list/element = list()
var/obj/item/PA
var/obj/item/device/electronic_assembly/PF
var/datum/integrated_io/IO
var/datum/integrated_io/IO2
var/i = 0
var/obj/item/integrated_circuit/comp
var/list/ioa = list()
var/list/as_samp = list()
var/list/all_circuits = SScircuit.all_circuits // It's free. Performance. We're giving you cpu time. It's free. We're giving you time. It's performance, free. It's free cpu time for you jim!
var/list/assembly_list = list(
/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone,
)
var/compl = 0
var/maxcomp = 0
var/cap = 0
var/maxcap = 0
var/metalcost = 0
for(var/k in 1 to assembly_list.len)
var/obj/item/I = assembly_list[k]
as_samp[initial(I.name)] = I
if(debug)
visible_message( "<span class='notice'>started successful</span>")
if(chap[2] != "")
if(debug)
visible_message( "<span class='notice'>assembly</span>")
element = splittext( chap[2] ,"=-=")
PA = as_samp[element[1]]
if(ispath(PA,/obj/item/device/electronic_assembly))
PF = PA
maxcap = initial(PF.max_components)
maxcomp = initial(PF.max_complexity)
metalcost = metalcost + round( (initial(PF.max_complexity) + initial(PF.max_components) ) / 4)
if(debug)
visible_message( "<span class='notice'>maxcap[maxcap]maxcomp[maxcomp]</span>")
else
return 0
to_chat(usr, "<span class='notice'>This is program for [element[2]]</span>")
/*
else if(istype(PA,/obj/item/weapon/implant/integrated_circuit))
var/obj/item/weapon/implant/integrated_circuit/PI = PA
var/obj/item/device/electronic_assembly/implant/PIC = PI.IC
maxcap = PIC.max_components
maxcomp = PIC.max_complexity
metalcost = metalcost + round( (initial(PIC.max_complexity) + initial(PIC.max_components) ) / 4)*/
else
return 0 //what's the point if there is no assembly?
if(chap[3] != "components") //if there is only one word,there is no components.
elements_input = splittext( chap[3] ,"^%^")
if(debug)
visible_message( "<span class='notice'>components[elements_input.len]</span>")
i = 0
elements = list()
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>components[elements.len]</span>")
if(elements_input.len<1)
return 0
if(debug)
visible_message( "<span class='notice'>inserting components[elements.len]</span>")
i=0
for(var/E in elements)
i=i+1
element = splittext( E ,"=-=")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
comp = all_circuits[element[1]]
if(!comp)
break
if(!upgraded)
var/obj/item/integrated_circuit/IC = comp
if(!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT))
return -1
compl = compl + initial(comp.complexity)
cap = cap + initial(comp.size)
metalcost = metalcost + initial(initial(comp.w_class))
var/obj/item/integrated_circuit/circuit = new comp
var/list/ini = circuit.inputs
if(length(ini))
for(var/j in 1 to ini.len)
var/datum/integrated_io/IN = ini[j]
ioa["[i]i[j]"] = IN
if(debug)
visible_message( "<span class='notice'>[i]i[j]</span>")
ini = circuit.outputs
if(length(ini))
for(var/j in 1 to ini.len) //Also this block uses for setting all i/o id's
var/datum/integrated_io/OUT = ini[j]
ioa["[i]o[j]"] = OUT
if(debug)
visible_message( "<span class='notice'>[i]o[j]</span>")
ini = circuit.activators
if(length(ini))
for(var/j in 1 to ini.len)
var/datum/integrated_io/ACT = ini.[j]
ioa["[i]a[j]"] = ACT
if(debug)
visible_message( "<span class='notice'>[i]a[j]</span>")
if(i<elements.len)
return 0
else
return 0
if(debug)
visible_message( "<span class='notice'>cap[cap]compl[compl]maxcompl[maxcomp]maxcap[maxcap]</span>")
if(cap == 0)
return 0
if(cap>maxcap)
return 0
if(compl>maxcomp)
return 0
if(chap[4] != "values") //if there is only one word,there is no values
elements_input = splittext( chap[4] ,"^%^")
if(debug)
visible_message( "<span class='notice'>values[elements_input.len]</span>")
i=0
elements = list()
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>values[elements.len]</span>")
if(elements.len>0)
if(debug)
visible_message( "<span class='notice'>setting values[elements.len]</span>")
for(var/E in elements)
element = splittext( E ,":+:")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
if(!ioa[element[1]])
return 0
if(element[2]=="text")
continue
else if(element[2]=="num")
continue
else if(element[2]=="list")
continue
else
return 0
if(chap[5] != "wires") //if there is only one word,there is no wires
elements_input = splittext( chap[5] ,"^%^")
i=0
elements = list()
if(debug)
visible_message( "<span class='notice'>wires[elements_input.len]</span>")
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>wires[elements.len]</span>")
if(elements.len>0)
if(debug)
visible_message( "<span class='notice'>setting wires[elements.len]</span>")
for(var/E in elements)
element = splittext( E ,"=-=")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
IO = ioa[element[1]]
IO2 = ioa[element[2]]
if(!((element[2]+"=-="+element[1]) in elements))
return 0
if(!IO)
return 0
if(!IO2)
return 0
if(initial(IO.io_type) != initial(IO2.io_type))
return 0
return metalcost

View File

@@ -0,0 +1,26 @@
// These pins only contain 0 or 1. Null is not allowed.
/datum/integrated_io/boolean
name = "boolean pin"
data = FALSE
/datum/integrated_io/boolean/ask_for_pin_data(mob/user) // 'Ask' is a bit misleading, acts more like a toggle.
var/new_data = !data
to_chat(user, "<span class='notice'>You switch the data bit to [data? "true" : "false"].</span>")
write_data_to_pin(new_data)
/datum/integrated_io/boolean/write_data_to_pin(var/new_data)
if(new_data == FALSE || new_data == TRUE)
data = new_data
holder.on_data_written()
/datum/integrated_io/boolean/scramble()
write_data_to_pin(rand(FALSE,TRUE))
push_data()
/datum/integrated_io/boolean/display_pin_type()
return IC_FORMAT_BOOLEAN
/datum/integrated_io/boolean/display_data(var/input)
if(data == TRUE)
return "(True)"
return "(False)"

View File

@@ -0,0 +1,27 @@
// These pins can only contain a 1 character string or null.
/datum/integrated_io/char
name = "char pin"
/datum/integrated_io/char/ask_for_pin_data(mob/user)
var/new_data = input("Please type in one character.","[src] char writing") as null|text
if(holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data ? "new_data" : "NULL"] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/char/write_data_to_pin(var/new_data)
if(isnull(new_data) || istext(new_data))
if(length(new_data) > 1)
return
data = new_data
holder.on_data_written()
// This makes the text go from "A" to "%".
/datum/integrated_io/char/scramble()
if(!is_valid())
return
var/list/options = list("!","@","#","$","%","^","&","*","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
data = pick(options)
push_data()
/datum/integrated_io/char/display_pin_type()
return IC_FORMAT_CHAR

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,27 @@
// These pins can only contain text and null.
/datum/integrated_io/string
name = "string pin"
/datum/integrated_io/string/ask_for_pin_data(mob/user)
var/new_data = input("Please type in a string.","[src] string writing") as null|text
if(holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data ? "[new_data]" : "NULL"] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/string/write_data_to_pin(var/new_data)
if(isnull(new_data) || istext(new_data))
data = new_data
holder.on_data_written()
// This makes the text go "from this" to "#G&*!HD$%L"
/datum/integrated_io/string/scramble()
if(!is_valid())
return
var/list/options = list("!","@","#","$","%","^","&","*","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
var/new_data = ""
for(var/i in 1 to length(data))
new_data += pick(options)
push_data()
/datum/integrated_io/string/display_pin_type()
return IC_FORMAT_STRING

View File

@@ -0,0 +1,102 @@
#define WIRE "wire"
#define WIRING "wiring"
#define UNWIRE "unwire"
#define UNWIRING "unwiring"
/obj/item/device/integrated_electronics/wirer
name = "circuit wirer"
desc = "It's a small wiring tool, with a wire roll, electric soldering iron, wire cutter, and more in one package. \
The wires used are generally useful for small electronics, such as circuitboards and breadboards, as opposed to larger wires \
used for power or data transmission."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "wirer-wire"
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_SMALL
var/datum/integrated_io/selected_io = null
var/mode = WIRE
/obj/item/device/integrated_electronics/wirer/update_icon()
icon_state = "wirer-[mode]"
/obj/item/device/integrated_electronics/wirer/proc/wire(var/datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
return
if(mode == WIRE)
selected_io = io
to_chat(user, "<span class='notice'>You attach a data wire to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
mode = WIRING
update_icon()
else if(mode == WIRING)
if(io == selected_io)
to_chat(user, "<span class='warning'>Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless.</span>")
return
if(io.io_type != selected_io.io_type)
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
while the second is a [io.io_type].</span>")
return
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
return
selected_io.linked |= io
io.linked |= selected_io
to_chat(user, "<span class='notice'>You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name].</span>")
mode = WIRE
update_icon()
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
else if(mode == UNWIRE)
selected_io = io
if(!io.linked.len)
to_chat(user, "<span class='warning'>There is nothing connected to \the [selected_io] data channel.</span>")
selected_io = null
return
to_chat(user, "<span class='notice'>You prepare to detach a data wire from \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
mode = UNWIRING
update_icon()
return
else if(mode == UNWIRING)
if(io == selected_io)
to_chat(user, "<span class='warning'>You can't wire a pin into each other, so unwiring \the [selected_io.holder] from \
the same pin is rather moot.</span>")
return
if(selected_io in io.linked)
io.linked.Remove(selected_io)
selected_io.linked.Remove(io)
to_chat(user, "<span class='notice'>You disconnect \the [selected_io.holder]'s [selected_io.name] from \
\the [io.holder]'s [io.name].</span>")
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
mode = UNWIRE
update_icon()
else
to_chat(user, "<span class='warning'>\The [selected_io.holder]'s [selected_io.name] and \the [io.holder]'s \
[io.name] are not connected.</span>")
return
/obj/item/device/integrated_electronics/wirer/attack_self(mob/user)
switch(mode)
if(WIRE)
mode = UNWIRE
if(WIRING)
if(selected_io)
to_chat(user, "<span class='notice'>You decide not to wire the data channel.</span>")
selected_io = null
mode = WIRE
if(UNWIRE)
mode = WIRE
if(UNWIRING)
if(selected_io)
to_chat(user, "<span class='notice'>You decide not to disconnect the data channel.</span>")
selected_io = null
mode = UNWIRE
update_icon()
to_chat(user, "<span class='notice'>You set \the [src] to [mode].</span>")
#undef WIRE
#undef WIRING
#undef UNWIRE
#undef UNWIRING

View File

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

View File

@@ -0,0 +1,126 @@
/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 = 30
/obj/item/integrated_circuit/passive/power/solar_cell/make_energy()
var/turf/T = get_turf(src)
var/light_amount = T ? T.get_lumcount() : 0
var/adjusted_power = max(max_power * light_amount, 0)
adjusted_power = round(adjusted_power, 0.1)
if(adjusted_power)
if(assembly)
assembly.give_power(adjusted_power)
/obj/item/integrated_circuit/passive/power/starter
name = "starter"
desc = "This tiny circuit will send pulse right after device is turned on. Or when power is restored."
icon_state = "led"
complexity = 1
activators = list("pulse out" = IC_PINTYPE_PULSE_OUT)
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/is_charge = FALSE
/obj/item/integrated_circuit/passive/power/starter/make_energy()
if(assembly.battery)
if(assembly.battery.charge)
if(!is_charge)
activate_pin(1)
is_charge = TRUE
else
is_charge = FALSE
else
is_charge=FALSE
return FALSE
// 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 = WEIGHT_CLASS_SMALL
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 = 150
//fuel cell
/obj/item/integrated_circuit/passive/power/chemical_cell
name = "fuel cell"
desc = "Produces electricity from chemicals."
icon_state = "chemical_cell"
extended_desc = "This is effectively an internal beaker.It will consume and produce power from phoron, slime jelly, welding fuel, carbon,\
ethanol, nutriments and blood , in order of decreasing efficiency. It will consume fuel only if the battery can take more energy."
container_type = OPENCONTAINER_1
complexity = 4
inputs = list()
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
activators = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
var/volume = 60
var/list/fuel = list("plasma" = 10000, "welding_fuel" = 3000, "carbon" = 2000, "ethanol"= 2000, "nutriment" =1600, "blood" = 1000)
/obj/item/integrated_circuit/passive/power/chemical_cell/New()
..()
create_reagents(volume)
/obj/item/integrated_circuit/passive/power/chemical_cell/interact(mob/user)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
..()
/obj/item/integrated_circuit/passive/power/chemical_cell/on_reagent_change()
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
/obj/item/integrated_circuit/passive/power/chemical_cell/make_energy()
if(assembly)
if(assembly.battery)
for(var/I in fuel)
if((assembly.battery.maxcharge-assembly.battery.charge) / GLOB.CELLRATE > fuel[I])
if(reagents.remove_reagent(I, 1))
assembly.give_power(fuel[I])
// 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 = WEIGHT_CLASS_BULKY
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 = 1000
/obj/item/integrated_circuit/passive/power/relay/make_energy()
if(!assembly)
return
var/area/A = get_area(src)
if(A)
if(A.powered(EQUIP) && assembly.give_power(power_amount))
A.use_power(power_amount, EQUIP)
// give_power() handles CELLRATE on its own.

View File

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

View File

@@ -0,0 +1,320 @@
//These circuits convert one variable to another.
/obj/item/integrated_circuit/converter
complexity = 2
inputs = list("input")
outputs = list("output")
activators = list("convert" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT)
category_text = "Converter"
power_draw_per_use = 10
/obj/item/integrated_circuit/converter/num2text
name = "number to string"
desc = "This circuit can convert a number variable into a string."
extended_desc = "Because of game limitations null/false variables will output a '0' string."
icon_state = "num-string"
inputs = list("input" = IC_PINTYPE_NUMBER)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/num2text/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = num2text(incoming)
else if(!incoming)
result = "0"
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/text2num
name = "string to number"
desc = "This circuit can convert a string variable into a number."
icon_state = "string-num"
inputs = list("input" = IC_PINTYPE_STRING)
outputs = list("output" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/text2num/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = text2num(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/ref2text
name = "reference to string"
desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference."
icon_state = "ref-string"
inputs = list("input" = IC_PINTYPE_REF)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/ref2text/do_work()
var/result = null
pull_data()
var/atom/A = get_pin_data(IC_INPUT, 1)
if(A && istype(A))
result = A.name
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/refcode
name = "reference encoder"
desc = "This circuit can encode a reference into a string, which can then be read by an EPV2 circuit."
icon_state = "ref-string"
inputs = list("input" = IC_PINTYPE_REF)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/refcode/do_work()
var/result = null
pull_data()
var/atom/A = get_pin_data(IC_INPUT, 1)
if(A && istype(A))
result = strtohex(XorEncrypt(REF(A),SScircuit.cipherkey))
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/refdecode
name = "reference decoder"
desc = "This circuit can convert a encoded reference to actual reference."
icon_state = "ref-string"
inputs = list("input" = IC_PINTYPE_STRING)
outputs = list("output" = IC_PINTYPE_REF)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/dec
/obj/item/integrated_circuit/converter/refdecode/do_work()
pull_data()
dec=XorEncrypt(hextostr(get_pin_data(IC_INPUT, 1)),SScircuit.cipherkey)
set_pin_data(IC_OUTPUT, 1, WEAKREF(locate( dec )))
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/lowercase
name = "lowercase string converter"
desc = "this will cause a string to come out in all lowercase."
icon_state = "lowercase"
inputs = list("input" = IC_PINTYPE_STRING)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/lowercase/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = lowertext(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/uppercase
name = "uppercase string converter"
desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE."
icon_state = "uppercase"
inputs = list("input" = IC_PINTYPE_STRING)
outputs = list("output" = IC_PINTYPE_STRING)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/uppercase/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = uppertext(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/concatenator
name = "concatenator"
desc = "This joins many strings together to get one big string."
complexity = 4
inputs = list(
"A" = IC_PINTYPE_STRING,
"B" = IC_PINTYPE_STRING,
"C" = IC_PINTYPE_STRING,
"D" = IC_PINTYPE_STRING,
"E" = IC_PINTYPE_STRING,
"F" = IC_PINTYPE_STRING,
"G" = IC_PINTYPE_STRING,
"H" = IC_PINTYPE_STRING
)
outputs = list("result" = IC_PINTYPE_STRING)
activators = list("concatenate" = IC_PINTYPE_PULSE_IN, "on concatenated" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/concatenator/do_work()
var/result = null
for(var/datum/integrated_io/I in inputs)
I.pull_data()
if(!isnull(I.data))
result = result + I.data
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/separator
name = "separator"
desc = "This splits as single string into two at the relative split point."
extended_desc = "This circuits splits a given string into two, based on the string, and the index value. \
The index splits the string <b>after</b> the given index, including spaces. So 'a person' with an index of '3' \
will split into 'a p' and 'erson'."
complexity = 4
inputs = list(
"string to split" = IC_PINTYPE_STRING,
"index" = IC_PINTYPE_NUMBER,
)
outputs = list(
"before split" = IC_PINTYPE_STRING,
"after split" = IC_PINTYPE_STRING
)
activators = list("separate" = IC_PINTYPE_PULSE_IN, "on separated" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/separator/do_work()
var/text = get_pin_data(IC_INPUT, 1)
var/index = get_pin_data(IC_INPUT, 2)
var/split = min(index+1, length(text))
var/before_text = copytext(text, 1, split)
var/after_text = copytext(text, split, 0)
set_pin_data(IC_OUTPUT, 1, before_text)
set_pin_data(IC_OUTPUT, 2, after_text)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/findstring
name = "find text"
desc = "This gives position of sample in the string. Or returns 0."
extended_desc = "The first pin is the string to be examined. The second pin is the sample to be found. \
For example, 'eat this burger',' ' will give you position 4. This circuit isn't case sensitive."
complexity = 4
inputs = list(
"string" = IC_PINTYPE_STRING,
"sample" = IC_PINTYPE_STRING,
)
outputs = list(
"position" = IC_PINTYPE_NUMBER
)
activators = list("search" = IC_PINTYPE_PULSE_IN, "after search" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/findstring/do_work()
set_pin_data(IC_OUTPUT, 1, findtext(get_pin_data(IC_INPUT, 1),get_pin_data(IC_INPUT, 2)) )
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/exploders
name = "string exploder"
desc = "This splits a single string into a list of strings."
extended_desc = "This circuit splits a given string into a list of strings based on the string and given delimiter. \
For example, 'eat this burger',' ' will be converted to list('eat','this','burger')."
complexity = 4
inputs = list(
"string to split" = IC_PINTYPE_STRING,
"delimiter" = IC_PINTYPE_STRING,
)
outputs = list(
"list" = IC_PINTYPE_LIST
)
activators = list("separate" = IC_PINTYPE_PULSE_IN, "on separated" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/exploders/do_work()
var/strin = get_pin_data(IC_INPUT, 1)
var/sample = get_pin_data(IC_INPUT, 2)
set_pin_data(IC_OUTPUT, 1, splittext( strin ,sample ))
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/radians2degrees
name = "radians to degrees converter"
desc = "Converts radians to degrees."
inputs = list("radian" = IC_PINTYPE_NUMBER)
outputs = list("degrees" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/radians2degrees/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = ToDegrees(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/degrees2radians
name = "degrees to radians converter"
desc = "Converts degrees to radians."
inputs = list("degrees" = IC_PINTYPE_NUMBER)
outputs = list("radians" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/degrees2radians/do_work()
var/result = null
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
result = ToRadians(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/abs_to_rel_coords
name = "abs to rel coordinate converter"
desc = "Easily convert absolute coordinates to relative coordinates with this."
complexity = 4
inputs = list(
"X1" = IC_PINTYPE_NUMBER,
"Y1" = IC_PINTYPE_NUMBER,
"X2" = IC_PINTYPE_NUMBER,
"Y2" = IC_PINTYPE_NUMBER
)
outputs = list(
"X" = IC_PINTYPE_NUMBER,
"Y" = IC_PINTYPE_NUMBER
)
activators = list("compute rel coordinates" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work()
var/x1 = get_pin_data(IC_INPUT, 1)
var/y1 = get_pin_data(IC_INPUT, 2)
var/x2 = get_pin_data(IC_INPUT, 3)
var/y2 = get_pin_data(IC_INPUT, 4)
if(!isnull(x1) && !isnull(y1) && !isnull(x2) && !isnull(y2))
set_pin_data(IC_OUTPUT, 1, x1 - x2)
set_pin_data(IC_OUTPUT, 2, y1 - y2)
push_data()
activate_pin(2)

View File

@@ -0,0 +1,146 @@
/obj/item/integrated_circuit/transfer
category_text = "Data Transfer"
power_draw_per_use = 2
/obj/item/integrated_circuit/transfer/multiplexer
name = "two multiplexer"
desc = "This is what those in the business tend to refer to as a 'mux' or data selector. It moves data from one of the selected inputs to the output."
extended_desc = "The first input pin is used to select which of the other input pins which has its data moved to the output. \
If the input selection is outside the valid range then no output is given."
complexity = 2
icon_state = "mux2"
inputs = list("input selection" = IC_PINTYPE_NUMBER)
outputs = list("output" = IC_PINTYPE_ANY)
activators = list("select" = IC_PINTYPE_PULSE_IN, "on select" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
var/number_of_inputs = 2
/obj/item/integrated_circuit/transfer/multiplexer/New()
for(var/i = 1 to number_of_inputs)
inputs["input [i]"] = IC_PINTYPE_ANY // This is just a string since pins don't get built until ..() is called.
// 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)
if(!isnull(input_index) && (input_index >= 1 && input_index < inputs.len))
set_pin_data(IC_OUTPUT, 1,get_pin_data(IC_INPUT, input_index + 1))
push_data()
activate_pin(2)
/obj/item/integrated_circuit/transfer/multiplexer/medium
name = "four multiplexer"
number_of_inputs = 4
icon_state = "mux4"
/obj/item/integrated_circuit/transfer/multiplexer/large
name = "eight multiplexer"
number_of_inputs = 8
w_class = WEIGHT_CLASS_SMALL
icon_state = "mux8"
/obj/item/integrated_circuit/transfer/multiplexer/huge
name = "sixteen multiplexer"
icon_state = "mux16"
w_class = WEIGHT_CLASS_SMALL
number_of_inputs = 16
/obj/item/integrated_circuit/transfer/demultiplexer
name = "two demultiplexer"
desc = "This is what those in the business tend to refer to as a 'demux'. It moves data from the input to one of the selected outputs."
extended_desc = "The first input pin is used to select which of the output pins is given the data from the second input pin. \
If the output selection is outside the valid range then no output is given."
complexity = 2
icon_state = "dmux2"
inputs = list("output selection" = IC_PINTYPE_NUMBER, "input" = IC_PINTYPE_ANY)
outputs = list()
activators = list("select" = IC_PINTYPE_PULSE_IN, "on select" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
var/number_of_outputs = 2
/obj/item/integrated_circuit/transfer/demultiplexer/New()
for(var/i = 1 to number_of_outputs)
// outputs += "output [i]"
outputs["output [i]"] = IC_PINTYPE_ANY
complexity = number_of_outputs
..()
desc += " It has [number_of_outputs] output pins."
extended_desc += " This demultiplexer has a range from 1 to [outputs.len]."
/obj/item/integrated_circuit/transfer/demultiplexer/do_work()
var/output_index = get_pin_data(IC_INPUT, 1)
for(var/i = 1 to outputs.len)
set_pin_data(IC_OUTPUT, i, i == output_index ? get_pin_data(IC_INPUT, 2) : null)
activate_pin(2)
/obj/item/integrated_circuit/transfer/demultiplexer/medium
name = "four demultiplexer"
icon_state = "dmux4"
number_of_outputs = 4
/obj/item/integrated_circuit/transfer/demultiplexer/large
name = "eight demultiplexer"
icon_state = "dmux8"
w_class = WEIGHT_CLASS_SMALL
number_of_outputs = 8
/obj/item/integrated_circuit/transfer/demultiplexer/huge
name = "sixteen demultiplexer"
icon_state = "dmux16"
w_class = WEIGHT_CLASS_SMALL
number_of_outputs = 16
/obj/item/integrated_circuit/transfer/pulsedemultiplexer
name = "two pulse demultiplexer"
desc = "Selector switch to choose the pin to be activated by number."
extended_desc = "The first input pin is used to select which of the pulse out pins will be activated after activation of the circuit. \
If the output selection is outside the valid range then no output is given."
complexity = 2
icon_state = "dmux2"
inputs = list("output selection" = IC_PINTYPE_NUMBER)
outputs = list()
activators = list("select" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
var/number_of_outputs = 2
/obj/item/integrated_circuit/transfer/pulsedemultiplexer/New()
for(var/i = 1 to number_of_outputs)
// outputs += "output [i]"
activators["output [i]"] = IC_PINTYPE_PULSE_OUT
complexity = number_of_outputs
..()
desc += " It has [number_of_outputs] output pins."
extended_desc += " This pulse demultiplexer has a range from 1 to [activators.len - 1]."
/obj/item/integrated_circuit/transfer/pulsedemultiplexer/do_work()
var/output_index = get_pin_data(IC_INPUT, 1)
if(output_index == Clamp(output_index, 1, number_of_outputs))
activate_pin(round(output_index + 1 ,1))
/obj/item/integrated_circuit/transfer/pulsedemultiplexer/medium
name = "four pulse demultiplexer"
icon_state = "dmux4"
number_of_outputs = 4
/obj/item/integrated_circuit/transfer/pulsedemultiplexer/large
name = "eight pulse demultiplexer"
icon_state = "dmux8"
w_class = WEIGHT_CLASS_SMALL
number_of_outputs = 8
/obj/item/integrated_circuit/transfer/pulsedemultiplexer/huge
name = "sixteen pulse demultiplexer"
icon_state = "dmux16"
w_class = WEIGHT_CLASS_SMALL
number_of_outputs = 16

View File

@@ -0,0 +1,806 @@
/obj/item/integrated_circuit/input
var/can_be_asked_input = 0
category_text = "Input"
power_draw_per_use = 5
/obj/item/integrated_circuit/input/proc/ask_for_input(mob/user)
return
/obj/item/integrated_circuit/input/button
name = "button"
desc = "This tiny button must do something, right?"
icon_state = "button"
complexity = 1
can_be_asked_input = 1
inputs = list()
outputs = list()
activators = list("on pressed" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use.
to_chat(user, "<span class='notice'>You press the button labeled '[src]'.</span>")
activate_pin(1)
/obj/item/integrated_circuit/input/toggle_button
name = "toggle button"
desc = "It toggles on, off, on, off..."
icon_state = "toggle_button"
complexity = 1
can_be_asked_input = 1
inputs = list()
outputs = list("on" = IC_PINTYPE_BOOLEAN)
activators = list("on toggle" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto.
set_pin_data(IC_OUTPUT, 1, !get_pin_data(IC_OUTPUT, 1))
push_data()
activate_pin(1)
to_chat(user, "<span class='notice'>You toggle the button labeled '[src]' [get_pin_data(IC_OUTPUT, 1) ? "on" : "off"].</span>")
/obj/item/integrated_circuit/input/numberpad
name = "number pad"
desc = "This small number pad allows someone to input a number into the system."
icon_state = "numberpad"
complexity = 2
can_be_asked_input = 1
inputs = list()
outputs = list("number entered" = IC_PINTYPE_NUMBER)
activators = list("on entered" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user)
var/new_input = input(user, "Enter a number, please.","Number pad") as null|num
if(isnum(new_input) && user.IsAdvancedToolUser())
set_pin_data(IC_OUTPUT, 1, new_input)
push_data()
activate_pin(1)
/obj/item/integrated_circuit/input/textpad
name = "text pad"
desc = "This small text pad allows someone to input a string into the system."
icon_state = "textpad"
complexity = 2
can_be_asked_input = 1
inputs = list()
outputs = list("string entered" = IC_PINTYPE_STRING)
activators = list("on entered" = IC_PINTYPE_PULSE_IN)
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
if(istext(new_input) && user.IsAdvancedToolUser())
set_pin_data(IC_OUTPUT, 1, new_input)
push_data()
activate_pin(1)
/obj/item/integrated_circuit/input/med_scanner
name = "integrated medical analyser"
desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is."
icon_state = "medscan"
complexity = 4
inputs = list("\<REF\> target")
outputs = list(
"total health %" = IC_PINTYPE_NUMBER,
"total missing health" = IC_PINTYPE_NUMBER
)
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
power_draw_per_use = 40
/obj/item/integrated_circuit/input/med_scanner/do_work()
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100
var/missing_health = H.getMaxHealth() - H.health
set_pin_data(IC_OUTPUT, 1, total_health)
set_pin_data(IC_OUTPUT, 2, missing_health)
push_data()
activate_pin(2)
/*
/obj/item/integrated_circuit/input/pressure_plate
name = "pressure plate"
desc = "Electronic plate with a scanner, that could retrieve references to things,that was put onto the machine"
icon_state = "pressure_plate"
complexity = 4
inputs = list()
outputs = list("laid" = IC_PINTYPE_REF, "removed" = IC_PINTYPE_REF)
activators = list("laid" = IC_PINTYPE_PULSE_OUT, "removed" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
power_draw_per_use = 40
var/list/cont
/obj/item/integrated_circuit/input/pressure_plate/New()
..()
processing_objects |= src
/obj/item/integrated_circuit/input/pressure_plate/Destroy()
processing_objects -= src
/obj/item/integrated_circuit/input/pressure_plate/process()
var/list/newcont
var/turf/T = get_turf(src)
newcont = T.contents
var/list/U = cont & newcont
for(var/laid in U)
if(!(laid in cont))
var/datum/integrated_io/O = outputs[1]
O.data = WEAKREF(laid)
O.push_data()
activate_pin(1)
break
for(var/removed in U)
if(!(removed in newcont))
var/datum/integrated_io/O = outputs[2]
O.data = WEAKREF(removed)
O.push_data()
activate_pin(2)
break
cont = newcont
*/
/obj/item/integrated_circuit/input/adv_med_scanner
name = "integrated advanced medical analyser"
desc = "A very small version of the medbot's medical analyser. This allows the machine to know how healthy someone is. \
This type is much more precise, allowing the machine to know much more about the target than a normal analyzer."
icon_state = "medscan_adv"
complexity = 12
inputs = list("\<REF\> target")
outputs = list(
"total health %" = IC_PINTYPE_NUMBER,
"total missing health" = IC_PINTYPE_NUMBER,
"brute damage" = IC_PINTYPE_NUMBER,
"burn damage" = IC_PINTYPE_NUMBER,
"tox damage" = IC_PINTYPE_NUMBER,
"oxy damage" = IC_PINTYPE_NUMBER,
"clone damage" = IC_PINTYPE_NUMBER
)
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4)
power_draw_per_use = 80
/obj/item/integrated_circuit/input/adv_med_scanner/do_work()
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100
var/missing_health = H.getMaxHealth() - H.health
set_pin_data(IC_OUTPUT, 1, total_health)
set_pin_data(IC_OUTPUT, 2, missing_health)
set_pin_data(IC_OUTPUT, 3, H.getBruteLoss())
set_pin_data(IC_OUTPUT, 4, H.getFireLoss())
set_pin_data(IC_OUTPUT, 5, H.getToxLoss())
set_pin_data(IC_OUTPUT, 6, H.getOxyLoss())
set_pin_data(IC_OUTPUT, 7, H.getCloneLoss())
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/plant_scanner
name = "integrated plant analyzer"
desc = "A very small version of the plant analyser. This allows the machine to know all valuable params of plants in trays. \
it can't scan seeds and fruits.only plants."
icon_state = "medscan_adv"
complexity = 12
inputs = list("\<REF\> target")
outputs = list(
"plant type" = IC_PINTYPE_STRING,
"age" = IC_PINTYPE_NUMBER,
"potency" = IC_PINTYPE_NUMBER,
"yield" = IC_PINTYPE_NUMBER,
"Maturation speed" = IC_PINTYPE_NUMBER,
"Production speed" = IC_PINTYPE_NUMBER,
"Endurance" = IC_PINTYPE_NUMBER,
"Lifespan" = IC_PINTYPE_NUMBER,
"Weed Growth Rate" = IC_PINTYPE_NUMBER,
"Weed Vulnerability" = IC_PINTYPE_NUMBER,
"Weed level" = IC_PINTYPE_NUMBER,
"Pest level" = IC_PINTYPE_NUMBER,
"Toxicity level" = IC_PINTYPE_NUMBER,
"Water level" = IC_PINTYPE_NUMBER,
"Nutrition level" = IC_PINTYPE_NUMBER,
"harvest" = IC_PINTYPE_NUMBER,
"dead" = IC_PINTYPE_NUMBER ,
"plant health" = IC_PINTYPE_NUMBER
)
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4)
power_draw_per_use = 10
/obj/item/integrated_circuit/input/plant_scanner/do_work()
var/obj/machinery/hydroponics/H = get_pin_data_as_type(IC_INPUT, 1, /obj/machinery/hydroponics)
if(!istype(H)) //Invalid input
return
for(var/i=1, i<=outputs.len, i++)
set_pin_data(IC_OUTPUT, i, null)
if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
if(H.myseed)
set_pin_data(IC_OUTPUT, 1, H.myseed.plantname)
set_pin_data(IC_OUTPUT, 2, H.age)
set_pin_data(IC_OUTPUT, 3, H.myseed.potency)
set_pin_data(IC_OUTPUT, 4, H.myseed.yield)
set_pin_data(IC_OUTPUT, 5, H.myseed.maturation)
set_pin_data(IC_OUTPUT, 6, H.myseed.production)
set_pin_data(IC_OUTPUT, 7, H.myseed.endurance)
set_pin_data(IC_OUTPUT, 8, H.myseed.lifespan)
set_pin_data(IC_OUTPUT, 9, H.myseed.weed_rate)
set_pin_data(IC_OUTPUT, 10, H.myseed.weed_chance)
set_pin_data(IC_OUTPUT, 11, H.weedlevel)
set_pin_data(IC_OUTPUT, 12, H.pestlevel)
set_pin_data(IC_OUTPUT, 13, H.toxic)
set_pin_data(IC_OUTPUT, 14, H.waterlevel)
set_pin_data(IC_OUTPUT, 15, H.nutrilevel)
set_pin_data(IC_OUTPUT, 16, H.harvest)
set_pin_data(IC_OUTPUT, 17, H.dead)
set_pin_data(IC_OUTPUT, 18, H.plant_health)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/gene_scanner
name = "gene scanner"
desc = "This circuit will scan plant for traits and reagent genes."
extended_desc = "This allows the machine to scan plants in trays for reagent and trait genes. \
it can't scan seeds and fruits.only plants."
inputs = list(
"\<REF\> target" = IC_PINTYPE_REF
)
outputs = list(
"traits" = IC_PINTYPE_LIST,
"reagents" = IC_PINTYPE_LIST
)
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
icon_state = "medscan_adv"
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/gene_scanner/do_work()
var/list/gtraits = list()
var/list/greagents = list()
var/obj/machinery/hydroponics/H = get_pin_data_as_type(IC_INPUT, 1, /obj/machinery/hydroponics)
if(!istype(H)) //Invalid input
return
for(var/i=1, i<=outputs.len, i++)
set_pin_data(IC_OUTPUT, i, null)
if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range..
if(H.myseed)
for(var/datum/plant_gene/reagent/G in H.myseed.genes)
greagents.Add(G.get_name())
for(var/datum/plant_gene/trait/G in H.myseed.genes)
gtraits.Add(G.get_name())
set_pin_data(IC_OUTPUT, 1, gtraits)
set_pin_data(IC_OUTPUT, 2, greagents)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/examiner
name = "examiner"
desc = "It' s a little machine vision system. It can return the name, description, distance, \
relative coordinates, total amount of reagents, and maximum amount of reagents of the referenced object."
icon_state = "video_camera"
complexity = 6
inputs = list("\<REF\> target" = IC_PINTYPE_REF)
outputs = list(
"name" = IC_PINTYPE_STRING,
"description" = IC_PINTYPE_STRING,
"X" = IC_PINTYPE_NUMBER,
"Y" = IC_PINTYPE_NUMBER,
"distance" = IC_PINTYPE_NUMBER,
"max reagents" = IC_PINTYPE_NUMBER,
"amount of reagents" = IC_PINTYPE_NUMBER,
)
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT, "not scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4)
power_draw_per_use = 80
/obj/item/integrated_circuit/input/examiner/do_work()
var/atom/movable/H = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
var/turf/T = get_turf(src)
if(!istype(H)) //Invalid input
return
if(H in view(T)) // This is a camera. It can't examine thngs,that it can't see.
set_pin_data(IC_OUTPUT, 1, H.name)
set_pin_data(IC_OUTPUT, 2, H.desc)
set_pin_data(IC_OUTPUT, 3, H.x-T.x)
set_pin_data(IC_OUTPUT, 4, H.y-T.y)
set_pin_data(IC_OUTPUT, 5, sqrt((H.x-T.x)*(H.x-T.x)+ (H.y-T.y)*(H.y-T.y)))
var/mr = 0
var/tr = 0
if(H.reagents)
mr = H.reagents.maximum_volume
tr = H.reagents.total_volume
set_pin_data(IC_OUTPUT, 6, mr)
set_pin_data(IC_OUTPUT, 7, tr)
push_data()
activate_pin(2)
else
activate_pin(3)
/obj/item/integrated_circuit/input/local_locator
name = "local locator"
desc = "This is needed for certain devices that demand a reference for a target to act upon. This type only locates something \
that is holding the machine containing it."
inputs = list()
outputs = list("located ref")
activators = list("locate" = IC_PINTYPE_PULSE_IN)
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(assembly)
if(istype(assembly.loc, /mob/living)) // Now check if someone's holding us.
O.data = WEAKREF(assembly.loc)
O.push_data()
/obj/item/integrated_circuit/input/adjacent_locator
name = "adjacent locator"
desc = "This is needed for certain devices that demand a reference for a target to act upon. This type only locates something \
that is standing a meter away from the machine."
extended_desc = "The first pin requires a ref to a kind of object that you want the locator to acquire. This means that it will \
give refs to nearby objects that are similar. If more than one valid object is found nearby, it will choose one of them at \
random."
inputs = list("desired type ref")
outputs = list("located ref")
activators = list("locate" = IC_PINTYPE_PULSE_IN,"found" = IC_PINTYPE_PULSE_OUT,
"not found" = IC_PINTYPE_PULSE_OUT)
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]
var/datum/integrated_io/O = outputs[1]
O.data = null
if(!isweakref(I.data))
return
var/atom/A = I.data.resolve()
if(!A)
return
var/desired_type = A.type
var/list/nearby_things = range(1, get_turf(src))
var/list/valid_things = list()
for(var/atom/thing in nearby_things)
if(thing.type != desired_type)
continue
valid_things.Add(thing)
if(valid_things.len)
O.data = WEAKREF(pick(valid_things))
activate_pin(2)
else
activate_pin(3)
O.push_data()
/obj/item/integrated_circuit/input/advanced_locator_list
complexity = 6
name = "list advanced locator"
desc = "This is needed for certain devices that demand list of names for a targets to act upon. This type locates something \
that is standing in given radius up to 8 meters"
extended_desc = "The first pin requires list a kinds of object that you want the locator to acquire. If This means that it will \
give refs to nearby objects that are similar. It will locate objects by given names and description,given in list. It will give list of all found objects.\
.The second pin is a radius"
inputs = list("desired type ref" = IC_PINTYPE_LIST, "radius" = IC_PINTYPE_NUMBER)
outputs = list("located ref" = IC_PINTYPE_LIST)
activators = list("locate" = IC_PINTYPE_PULSE_IN,"found" = IC_PINTYPE_PULSE_OUT,"not found" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 30
var/radius = 1
/obj/item/integrated_circuit/input/advanced_locator_list/on_data_written()
var/rad = get_pin_data(IC_INPUT, 2)
if(isnum(rad))
rad = Clamp(rad, 0, 8)
radius = rad
/obj/item/integrated_circuit/input/advanced_locator_list/do_work()
var/datum/integrated_io/I = inputs[1]
var/datum/integrated_io/O = outputs[1]
O.data = null
var/turf/T = get_turf(src)
var/list/nearby_things = view(radius,T)
var/list/valid_things = list()
var/list/GI = list()
GI = I.data
for(var/G in GI)
if(isweakref(G)) //It should search by refs. But don't want.will fix it later.
var/datum/integrated_io/G1
G1.data = G
var/atom/A = G1.data.resolve()
var/desired_type = A.type
for(var/atom/thing in nearby_things)
if(thing.type != desired_type)
continue
valid_things.Add(WEAKREF(thing))
else if(istext(G))
for(var/atom/thing in nearby_things)
if(findtext(addtext(thing.name," ",thing.desc), G, 1, 0) )
valid_things.Add(WEAKREF(thing))
if(valid_things.len)
O.data = valid_things
O.push_data()
activate_pin(2)
else
O.push_data()
activate_pin(3)
/obj/item/integrated_circuit/input/advanced_locator
complexity = 6
name = "advanced locator"
desc = "This is needed for certain devices that demand a reference for a target to act upon. This type locates something \
that is standing in given radius up to 8 meters"
extended_desc = "The first pin requires a ref to a kind of object that you want the locator to acquire. If This means that it will \
give refs to nearby objects that are similar. If this pin is string, locator will search\
item by matching desired text in name + description. If more than one valid object is found nearby, it will choose one of them at \
random. The second pin is a radius."
inputs = list("desired type" = IC_PINTYPE_ANY, "radius" = IC_PINTYPE_NUMBER)
outputs = list("located ref")
activators = list("locate" = IC_PINTYPE_PULSE_IN,"found" = IC_PINTYPE_PULSE_OUT,"not found" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 30
var/radius = 1
/obj/item/integrated_circuit/input/advanced_locator/on_data_written()
var/rad = get_pin_data(IC_INPUT, 2)
if(isnum(rad))
rad = Clamp(rad, 0, 8)
radius = rad
/obj/item/integrated_circuit/input/advanced_locator/do_work()
var/datum/integrated_io/I = inputs[1]
var/datum/integrated_io/O = outputs[1]
O.data = null
var/turf/T = get_turf(src)
var/list/nearby_things = view(radius,T)
var/list/valid_things = list()
if(isweakref(I.data))
var/atom/A = I.data.resolve()
var/desired_type = A.type
if(desired_type)
for(var/atom/thing in nearby_things)
if(thing.type == desired_type)
valid_things.Add(thing)
else if(istext(I.data))
var/DT = I.data
for(var/atom/thing in nearby_things)
if(findtext(addtext(thing.name," ",thing.desc), DT, 1, 0) )
valid_things.Add(thing)
if(valid_things.len)
O.data = WEAKREF(pick(valid_things))
O.push_data()
activate_pin(2)
else
O.push_data()
activate_pin(3)
/obj/item/integrated_circuit/input/signaler
name = "integrated signaler"
desc = "Signals from a signaler can be received with this, allowing for remote control. Additionally, it can send signals as well."
extended_desc = "When a signal is received from another signaler, the 'on signal received' activator pin will be pulsed. \
The two input pins are to configure the integrated signaler's settings. Note that the frequency should not have a decimal in it. \
Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin."
icon_state = "signal"
complexity = 4
inputs = list("frequency" = IC_PINTYPE_NUMBER,"code" = IC_PINTYPE_NUMBER)
outputs = list()
activators = list(
"send signal" = IC_PINTYPE_PULSE_IN,
"on signal sent" = IC_PINTYPE_PULSE_OUT,
"on signal received" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2)
power_draw_idle = 5
power_draw_per_use = 40
var/frequency = 1457
var/code = 30
var/datum/radio_frequency/radio_connection
/obj/item/integrated_circuit/input/signaler/Initialize()
..()
spawn(40)
set_frequency(frequency)
// Set the pins so when someone sees them, they won't show as null
set_pin_data(IC_INPUT, 1, frequency)
set_pin_data(IC_INPUT, 2, code)
/obj/item/integrated_circuit/input/signaler/Destroy()
SSradio.remove_object(src,frequency)
frequency = 0
return ..()
/obj/item/integrated_circuit/input/signaler/on_data_written()
var/new_freq = get_pin_data(IC_INPUT, 1)
var/new_code = get_pin_data(IC_INPUT, 2)
if(isnum(new_freq) && new_freq > 0)
set_frequency(new_freq)
if(isnum(new_code))
code = new_code
/obj/item/integrated_circuit/input/signaler/do_work() // Sends a signal.
if(!radio_connection)
return
var/datum/signal/signal = new
signal.source = src
signal.encryption = code
signal.data["message"] = "ACTIVATE"
radio_connection.post_signal(src, signal)
activate_pin(2)
/obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency)
if(!frequency)
return
if(!SSradio)
sleep(20)
if(!SSradio)
return
SSradio.remove_object(src, frequency)
frequency = new_frequency
radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_CHAT)
/obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal)
var/new_code = get_pin_data(IC_INPUT, 2)
var/code = 0
if(isnum(new_code))
code = new_code
if(!signal)
return 0
if(signal.encryption != code)
return 0
if(signal.source == src) // Don't trigger ourselves.
return 0
activate_pin(3)
for(var/mob/O in hearers(1, get_turf(src)))
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 1)
/obj/item/integrated_circuit/input/EPv2
name = "EPv2 circuit"
desc = "Enables the sending and receiving of messages on the Exonet with the EPv2 protocol."
extended_desc = "An EPv2 address is a string with the format of XXXX:XXXX:XXXX:XXXX. Data can be send or received using the \
second pin on each side, with additonal data reserved for the third pin. When a message is received, the second activation pin \
will pulse whatever's connected to it. Pulsing the first activation pin will send a message."
icon_state = "signal"
complexity = 4
inputs = list(
"target EPv2 address" = IC_PINTYPE_STRING,
"data to send" = IC_PINTYPE_STRING,
"secondary text" = IC_PINTYPE_STRING
)
outputs = list(
"address received" = IC_PINTYPE_STRING,
"data received" = IC_PINTYPE_STRING,
"secondary text received" = IC_PINTYPE_STRING
)
activators = list("send data" = IC_PINTYPE_PULSE_IN, "on data received" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2)
power_draw_per_use = 50
var/datum/exonet_protocol/exonet = null
/obj/item/integrated_circuit/input/EPv2/New()
..()
exonet = new(src)
exonet.make_address("EPv2_circuit-[REF(src)]")
desc += "<br>This circuit's EPv2 address is: [exonet.address]"
/obj/item/integrated_circuit/input/EPv2/Destroy()
if(exonet)
exonet.remove_address()
qdel(exonet)
exonet = null
return ..()
/obj/item/integrated_circuit/input/EPv2/do_work()
var/target_address = get_pin_data(IC_INPUT, 1)
var/message = get_pin_data(IC_INPUT, 2)
var/text = get_pin_data(IC_INPUT, 3)
if(target_address && istext(target_address))
exonet.send_message(target_address, message, text)
/obj/item/integrated_circuit/input/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
set_pin_data(IC_OUTPUT, 1, origin_address)
set_pin_data(IC_OUTPUT, 2, message)
set_pin_data(IC_OUTPUT, 3, text)
push_data()
activate_pin(2)
//This circuit gives information on where the machine is.
/obj/item/integrated_circuit/input/gps
name = "global positioning system"
desc = "This allows you to easily know the position of a machine containing this device."
extended_desc = "The GPS's coordinates it gives is absolute, not relative."
icon_state = "gps"
complexity = 4
inputs = list()
outputs = list("X"= IC_PINTYPE_NUMBER, "Y" = IC_PINTYPE_NUMBER, "Z" = IC_PINTYPE_NUMBER)
activators = list("get coordinates" = IC_PINTYPE_PULSE_IN, "on get coordinates" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 30
/obj/item/integrated_circuit/input/gps/do_work()
var/turf/T = get_turf(src)
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
set_pin_data(IC_OUTPUT, 3, null)
if(!T)
return
set_pin_data(IC_OUTPUT, 1, T.x)
set_pin_data(IC_OUTPUT, 2, T.y)
set_pin_data(IC_OUTPUT, 3, T.z)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/microphone
name = "microphone"
desc = "Useful for spying on people or for voice activated machines."
extended_desc = "This will automatically translate most languages it hears to Galactic Common. \
The first activation pin is always pulsed when the circuit hears someone talk, while the second one \
is only triggered if it hears someone speaking a language other than Galactic Common."
icon_state = "recorder"
complexity = 8
inputs = list()
flags_1 = CONDUCT_1 | HEAR_1
outputs = list(
"speaker" = IC_PINTYPE_STRING,
"message" = IC_PINTYPE_STRING
)
activators = list("on message received" = IC_PINTYPE_PULSE_OUT, "on translation" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 5
/obj/item/integrated_circuit/input/microphone/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
var/translated = FALSE
if(speaker && message)
if(raw_message)
if(message_langs != get_default_language())
translated = TRUE
set_pin_data(IC_OUTPUT, 1, speaker.GetVoice())
set_pin_data(IC_OUTPUT, 2, raw_message)
push_data()
activate_pin(1)
if(translated)
activate_pin(2)
/obj/item/integrated_circuit/input/sensor
name = "sensor"
desc = "Scans and obtains a reference for any objects or persons near you. All you need to do is shove the machine in their face."
extended_desc = "If 'ignore storage' pin is set to true, the sensor will disregard scanning various storage containers such as backpacks."
icon_state = "recorder"
complexity = 12
inputs = list("ignore storage" = IC_PINTYPE_BOOLEAN)
outputs = list("scanned" = IC_PINTYPE_REF)
activators = list("on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A)
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
if(istype(A, /obj/item/storage))
return FALSE
set_pin_data(IC_OUTPUT, 1, WEAKREF(A))
push_data()
activate_pin(1)
return TRUE
/obj/item/integrated_circuit/input/sensor/ranged
name = "Ranged sensor"
desc = "Scans and obtains a reference for any objects or persons in range. All you need to do is point the machine towards target."
extended_desc = "If 'ignore storage' pin is set to true, the sensor will disregard scanning various storage containers such as backpacks."
icon_state = "recorder"
complexity = 36
inputs = list("ignore storage" = IC_PINTYPE_BOOLEAN)
outputs = list("scanned" = IC_PINTYPE_REF)
activators = list("on scanned" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
/obj/item/integrated_circuit/input/internalbm
name = "internal battery monitor"
desc = "This monitors the charge level of an internal battery."
icon_state = "internalbm"
extended_desc = "This circuit will give you values of charge, max charge and percentage of the internal battery on demand."
w_class = WEIGHT_CLASS_TINY
complexity = 1
inputs = list()
outputs = list(
"cell charge" = IC_PINTYPE_NUMBER,
"max charge" = IC_PINTYPE_NUMBER,
"percentage" = IC_PINTYPE_NUMBER,
"refference to assembly" = IC_PINTYPE_REF
)
activators = list("read" = IC_PINTYPE_PULSE_IN, "on read" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3)
power_draw_per_use = 1
/obj/item/integrated_circuit/input/internalbm/do_work()
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
set_pin_data(IC_OUTPUT, 3, null)
set_pin_data(IC_OUTPUT, 4, WEAKREF(assembly))
if(assembly)
if(assembly.battery)
set_pin_data(IC_OUTPUT, 1, assembly.battery.charge)
set_pin_data(IC_OUTPUT, 2, assembly.battery.maxcharge)
set_pin_data(IC_OUTPUT, 3, 100*assembly.battery.charge/assembly.battery.maxcharge)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/externalbm
name = "external battery monitor"
desc = "This can help to watch battery state of any device in view"
icon_state = "externalbm"
extended_desc = "This circuit will give you values of charge, max charge and percentage of any device or battery in view"
w_class = WEIGHT_CLASS_TINY
complexity = 2
inputs = list("target" = IC_PINTYPE_REF)
outputs = list(
"cell charge" = IC_PINTYPE_NUMBER,
"max charge" = IC_PINTYPE_NUMBER,
"percentage" = IC_PINTYPE_NUMBER
)
activators = list("read" = IC_PINTYPE_PULSE_IN, "on read" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3)
power_draw_per_use = 1
/obj/item/integrated_circuit/input/externalbm/do_work()
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
set_pin_data(IC_OUTPUT, 3, null)
if(AM)
var/obj/item/stock_parts/cell/cell = get_cell(AM)
if(cell)
var/turf/A = get_turf(src)
if(AM in view(A))
push_data()
set_pin_data(IC_OUTPUT, 1, cell.charge)
set_pin_data(IC_OUTPUT, 2, cell.maxcharge)
set_pin_data(IC_OUTPUT, 3, cell.percent())
push_data()
activate_pin(2)

View File

@@ -0,0 +1,200 @@
//These circuits do things with lists, and use special list pins for stability.
/obj/item/integrated_circuit/lists
complexity = 1
inputs = list(
"input" = IC_PINTYPE_LIST
)
outputs = list("result" = IC_PINTYPE_STRING)
activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT)
category_text = "Lists"
power_draw_per_use = 20
/obj/item/integrated_circuit/lists/pick
name = "pick circuit"
desc = "This circuit will randomly 'pick' an element from a list that is inputted."
extended_desc = "Will output null if the list is empty. Input list is unmodified."
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/lists/pick/do_work()
var/result = null
var/list/input_list = get_pin_data(IC_INPUT, 1) // List pins guarantee that there is a list inside, even if just an empty one.
if(input_list.len)
result = pick(input_list)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/lists/append
name = "append circuit"
desc = "This circuit will add an element to a list."
extended_desc = "The new element will always be at the bottom of the list."
inputs = list(
"list to append" = IC_PINTYPE_LIST,
"input" = IC_PINTYPE_ANY
)
outputs = list(
"appended list" = IC_PINTYPE_LIST
)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/lists/append/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
var/list/output_list = list()
var/new_entry = get_pin_data(IC_INPUT, 2)
output_list = input_list.Copy()
output_list.Add(new_entry)
set_pin_data(IC_OUTPUT, 1, output_list)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/lists/search
name = "search circuit"
desc = "This circuit will give index of desired element in the list."
extended_desc = "Search will start at 1 position and will return first matching position."
inputs = list(
"list" = IC_PINTYPE_LIST,
"item" = IC_PINTYPE_ANY
)
outputs = list(
"index" = IC_PINTYPE_NUMBER
)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/lists/search/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
var/item = get_pin_data(IC_INPUT, 2)
set_pin_data(IC_OUTPUT, 1, input_list.Find(item))
push_data()
activate_pin(2)
/obj/item/integrated_circuit/lists/at
name = "at circuit"
desc = "This circuit will pick an element from a list by index."
extended_desc = "If there is no element with such index, result will be null."
inputs = list(
"list" = IC_PINTYPE_LIST,
"index" = IC_PINTYPE_NUMBER
)
outputs = list("item" = IC_PINTYPE_ANY)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/lists/at/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
var/index = get_pin_data(IC_INPUT, 2)
var/item = input_list[index]
set_pin_data(IC_OUTPUT, 1, item)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/lists/delete
name = "delete circuit"
desc = "This circuit will delete the element from a list by index."
extended_desc = "If there is no element with such index, result list will be unchanged."
inputs = list(
"list" = IC_PINTYPE_LIST,
"index" = IC_PINTYPE_NUMBER
)
outputs = list(
"item" = IC_PINTYPE_LIST
)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/lists/delete/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
var/list/red_list = list()
var/index = get_pin_data(IC_INPUT, 2)
for(var/j in 1 to input_list.len)
var/I = input_list[j]
if(j != index)
red_list.Add(I)
set_pin_data(IC_OUTPUT, 1, red_list)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/lists/write
name = "write circuit"
desc = "This circuit will write element in list with given index."
extended_desc = "If there is no element with such index, it will give the same list, as before."
inputs = list(
"list" = IC_PINTYPE_LIST,
"index" = IC_PINTYPE_NUMBER,
"item" = IC_PINTYPE_ANY
)
outputs = list(
"redacted list" = IC_PINTYPE_LIST
)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/lists/write/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
var/index = get_pin_data(IC_INPUT, 2)
var/item = get_pin_data(IC_INPUT, 3)
if(!islist(item)) //crh proof
input_list[index] = item
set_pin_data(IC_OUTPUT, 1, input_list)
push_data()
activate_pin(2)
obj/item/integrated_circuit/lists/len
name = "len circuit"
desc = "This circuit will give lenght of the list."
inputs = list(
"list" = IC_PINTYPE_LIST,
)
outputs = list(
"item" = IC_PINTYPE_NUMBER
)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/lists/len/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
set_pin_data(IC_OUTPUT, 1, input_list.len)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/lists/jointext
name = "join text circuit"
desc = "This circuit will add all elements of a list into one string, seperated by a character."
extended_desc = "Default settings will encode the entire list into a string."
inputs = list(
"list to join" = IC_PINTYPE_LIST,//
"delimiter" = IC_PINTYPE_CHAR,
"start" = IC_PINTYPE_NUMBER,
"end" = IC_PINTYPE_NUMBER
)
inputs_default = list(
"2" = ",",
"3" = 1,
"4" = 0
)
outputs = list(
"joined text" = IC_PINTYPE_STRING
)
icon_state = "addition"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/lists/jointext/do_work()
var/list/input_list = get_pin_data(IC_INPUT, 1)
var/delimiter = get_pin_data(IC_INPUT, 2)
var/start = get_pin_data(IC_INPUT, 3)
var/end = get_pin_data(IC_INPUT, 4)
var/result = null
if(input_list.len && delimiter && !isnull(start) && !isnull(end))
result = jointext(input_list, delimiter, start, end)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)

View File

@@ -0,0 +1,221 @@
/obj/item/integrated_circuit/logic
name = "logic gate"
desc = "This tiny chip will decide for you!"
extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE."
complexity = 3
outputs = list("result")
activators = list("compare" = IC_PINTYPE_PULSE_IN)
category_text = "Logic"
power_draw_per_use = 1
/obj/item/integrated_circuit/logic/do_work()
push_data()
/obj/item/integrated_circuit/logic/binary
inputs = list("A","B")
activators = list("compare" = IC_PINTYPE_PULSE_IN, "on true result" = IC_PINTYPE_PULSE_OUT, "on false result" = IC_PINTYPE_PULSE_OUT)
/obj/item/integrated_circuit/logic/binary/do_work()
pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
var/datum/integrated_io/O = outputs[1]
O.data = do_compare(A, B) ? TRUE : FALSE
if(get_pin_data(IC_OUTPUT, 1))
activate_pin(2)
else
activate_pin(3)
..()
/obj/item/integrated_circuit/logic/binary/proc/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return FALSE
/obj/item/integrated_circuit/logic/unary
inputs = list("A")
activators = list("compare" = IC_PINTYPE_PULSE_IN, "on compare" = IC_PINTYPE_PULSE_OUT)
/obj/item/integrated_circuit/logic/unary/do_work()
pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/O = outputs[1]
O.data = do_check(A) ? TRUE : FALSE
..()
activate_pin(2)
/obj/item/integrated_circuit/logic/unary/proc/do_check(var/datum/integrated_io/A)
return FALSE
/obj/item/integrated_circuit/logic/binary/equals
name = "equal gate"
desc = "This gate compares two values, and outputs the number one if both are the same."
icon_state = "equal"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/equals/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data == B.data
/obj/item/integrated_circuit/logic/binary/jklatch
name = "JK latch"
desc = "This gate is synchronysed JK latch."
icon_state = "jklatch"
inputs = list("J","K")
outputs = list("Q","!Q")
activators = list("pulse in C" = IC_PINTYPE_PULSE_IN, "pulse out Q" = IC_PINTYPE_PULSE_OUT, "pulse out !Q" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/lstate=FALSE
/obj/item/integrated_circuit/logic/binary/jklatch/do_work()
pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
var/datum/integrated_io/O = outputs[1]
var/datum/integrated_io/Q = outputs[2]
if(A.data)
if(B.data)
lstate=!lstate
else
lstate = TRUE
else
if(B.data)
lstate=FALSE
O.data = lstate ? TRUE : FALSE
Q.data = !lstate ? TRUE : FALSE
if(get_pin_data(IC_OUTPUT, 1))
activate_pin(2)
else
activate_pin(3)
push_data()
/obj/item/integrated_circuit/logic/binary/rslatch
name = "RS latch"
desc = "This gate is synchronysed RS latch. If both R and S are true, state will not change."
icon_state = "sr_nor"
inputs = list("S","R")
outputs = list("Q","!Q")
activators = list("pulse in C" = IC_PINTYPE_PULSE_IN, "pulse out Q" = IC_PINTYPE_PULSE_OUT, "pulse out !Q" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/lstate=FALSE
/obj/item/integrated_circuit/logic/binary/rslatch/do_work()
pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
var/datum/integrated_io/O = outputs[1]
var/datum/integrated_io/Q = outputs[2]
if(A.data)
if(!B.data)
lstate=TRUE
else
if(B.data)
lstate=FALSE
O.data = lstate ? TRUE : FALSE
Q.data = !lstate ? TRUE : FALSE
if(get_pin_data(IC_OUTPUT, 1))
activate_pin(2)
else
activate_pin(3)
push_data()
/obj/item/integrated_circuit/logic/binary/gdlatch
name = "gated D latch"
desc = "This gate is synchronysed gated D latch."
icon_state = "gated_d"
inputs = list("D","E")
outputs = list("Q","!Q")
activators = list("pulse in C" = IC_PINTYPE_PULSE_IN, "pulse out Q" = IC_PINTYPE_PULSE_OUT, "pulse out !Q" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/lstate=FALSE
/obj/item/integrated_circuit/logic/binary/gdlatch/do_work()
pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
var/datum/integrated_io/O = outputs[1]
var/datum/integrated_io/Q = outputs[2]
if(B.data)
if(A.data)
lstate=TRUE
else
lstate=FALSE
O.data = lstate ? TRUE : FALSE
Q.data = !lstate ? TRUE : FALSE
if(get_pin_data(IC_OUTPUT, 1))
activate_pin(2)
else
activate_pin(3)
push_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."
icon_state = "and"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/and/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data && B.data
/obj/item/integrated_circuit/logic/binary/or
name = "or gate"
desc = "This gate will output 'one' if one of the inputs evaluate to true."
icon_state = "or"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/or/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data || B.data
/obj/item/integrated_circuit/logic/binary/less_than
name = "less than gate"
desc = "This will output 'one' if the first input is less than the second input."
icon_state = "less_than"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/less_than/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data < B.data
/obj/item/integrated_circuit/logic/binary/less_than_or_equal
name = "less than or equal gate"
desc = "This will output 'one' if the first input is less than, or equal to the second input."
icon_state = "less_than_or_equal"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/less_than_or_equal/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data <= B.data
/obj/item/integrated_circuit/logic/binary/greater_than
name = "greater than gate"
desc = "This will output 'one' if the first input is greater than the second input."
icon_state = "greater_than"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/greater_than/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data > B.data
/obj/item/integrated_circuit/logic/binary/greater_than_or_equal
name = "greater_than or equal gate"
desc = "This will output 'one' if the first input is greater than, or equal to the second input."
icon_state = "greater_than_or_equal"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/greater_than_or_equal/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data >= B.data
/obj/item/integrated_circuit/logic/unary/not
name = "not gate"
desc = "This gate inverts what's fed into it."
icon_state = "not"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
activators = list("invert" = IC_PINTYPE_PULSE_IN, "on inverted" = IC_PINTYPE_PULSE_OUT)
/obj/item/integrated_circuit/logic/unary/not/do_check(var/datum/integrated_io/A)
return !A.data

View File

@@ -0,0 +1,443 @@
/obj/item/integrated_circuit/manipulation
category_text = "Manipulation"
/obj/item/integrated_circuit/manipulation/weapon_firing
name = "weapon firing mechanism"
desc = "This somewhat complicated system allows one to slot in a gun, direct it towards a position, and remotely fire it."
extended_desc = "The firing mechanism can slot in any energy weapon. \
The first and second inputs need to be numbers. They are coordinates for the gun to fire at, relative to the machine itself. \
The 'fire' activator will cause the mechanism to attempt to fire the weapon at the coordinates, if possible. Mode is switch between\
letal(TRUE) or stun(FALSE) modes.It uses internal battery of weapon."
complexity = 20
w_class = WEIGHT_CLASS_SMALL
size = 3
inputs = list(
"target X rel" = IC_PINTYPE_NUMBER,
"target Y rel" = IC_PINTYPE_NUMBER,
"mode" = IC_PINTYPE_BOOLEAN
)
outputs = list("reference to gun" = IC_PINTYPE_REF)
activators = list(
"fire" = IC_PINTYPE_PULSE_IN
)
var/obj/item/gun/energy/installed_gun = null
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
power_draw_per_use = 0
var/mode = FALSE
var/stun_projectile = null //stun mode projectile type
var/stun_projectile_sound
var/lethal_projectile = null //lethal mode projectile type
var/lethal_projectile_sound
/obj/item/integrated_circuit/manipulation/weapon_firing/Destroy()
qdel(installed_gun)
..()
/obj/item/integrated_circuit/manipulation/weapon_firing/attackby(var/obj/O, var/mob/user)
if(istype(O, /obj/item/gun/energy))
var/obj/item/gun/gun = O
if(installed_gun)
to_chat(user, "<span class='warning'>There's already a weapon installed.</span>")
return
user.transferItemToLoc(gun,src)
installed_gun = gun
var/list/gun_properties = gun.get_turret_properties()
to_chat(user, "<span class='notice'>You slide \the [gun] into the firing mechanism.</span>")
playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
stun_projectile = gun_properties["stun_projectile"]
stun_projectile_sound = gun_properties["stun_projectile_sound"]
lethal_projectile = gun_properties["lethal_projectile"]
lethal_projectile_sound = gun_properties["lethal_projectile_sound"]
if(gun_properties["shot_delay"])
cooldown_per_use = gun_properties["shot_delay"]*10
if(cooldown_per_use<30)
cooldown_per_use = 40
if(gun_properties["reqpower"])
power_draw_per_use = gun_properties["reqpower"]
set_pin_data(IC_OUTPUT, 1, WEAKREF(installed_gun))
push_data()
else
..()
/obj/item/integrated_circuit/manipulation/weapon_firing/attack_self(var/mob/user)
if(installed_gun)
installed_gun.forceMove(drop_location())
to_chat(user, "<span class='notice'>You slide \the [installed_gun] out of the firing mechanism.</span>")
size = initial(size)
playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
installed_gun = null
set_pin_data(IC_OUTPUT, 1, WEAKREF(null))
push_data()
else
to_chat(user, "<span class='notice'>There's no weapon to remove from the mechanism.</span>")
/obj/item/integrated_circuit/manipulation/weapon_firing/do_work()
if(!installed_gun)
return
set_pin_data(IC_OUTPUT, 1, WEAKREF(installed_gun))
push_data()
var/datum/integrated_io/xo = inputs[1]
var/datum/integrated_io/yo = inputs[2]
var/datum/integrated_io/mode1 = inputs[3]
mode = mode1.data
if(assembly)
if(isnum(xo.data))
xo.data = round(xo.data, 1)
if(isnum(yo.data))
yo.data = round(yo.data, 1)
var/turf/T = get_turf(assembly)
var/target_x = Clamp(T.x + xo.data, 0, world.maxx)
var/target_y = Clamp(T.y + yo.data, 0, world.maxy)
shootAt(locate(target_x, target_y, T.z))
/obj/item/integrated_circuit/manipulation/weapon_firing/proc/shootAt(turf/target)
var/turf/T = get_turf(src)
var/turf/U = target
if(!istype(T) || !istype(U))
return
if(!installed_gun.cell)
return
if(!installed_gun.cell.charge)
return
var/obj/item/ammo_casing/energy/shot = installed_gun.ammo_type[mode?2:1]
if(installed_gun.cell.charge < shot.e_cost)
return
if(!shot)
return
update_icon()
var/obj/item/projectile/A
if(!mode)
A = new stun_projectile(T)
playsound(loc, stun_projectile_sound, 75, 1)
else
A = new lethal_projectile(T)
playsound(loc, lethal_projectile_sound, 75, 1)
installed_gun.cell.use(shot.e_cost)
//Shooting Code:
A.preparePixelProjectile(target, src)
A.fire()
return A
/obj/item/integrated_circuit/manipulation/locomotion
name = "locomotion circuit"
desc = "This allows a machine to move in a given direction."
icon_state = "locomotion"
extended_desc = "The circuit accepts a 'dir' number as a direction to move towards.<br>\
Pulsing the 'step towards dir' activator pin will cause the machine to move a meter in that direction, assuming it is not \
being held, or anchored in some way. It should be noted that the ability to move is dependant on the type of assembly that this circuit inhabits."
w_class = WEIGHT_CLASS_SMALL
complexity = 20
// size = 5
inputs = list("direction" = IC_PINTYPE_DIR)
outputs = list()
activators = list("step towards dir" = IC_PINTYPE_PULSE_IN,"on step"=IC_PINTYPE_PULSE_OUT,"blocked"=IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 100
/obj/item/integrated_circuit/manipulation/locomotion/do_work()
..()
var/turf/T = get_turf(src)
if(T && assembly)
if(assembly.anchored || !assembly.can_move())
return
if(assembly.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held.
var/datum/integrated_io/wanted_dir = inputs[1]
if(isnum(wanted_dir.data))
if(step(assembly, wanted_dir.data))
activate_pin(2)
else
activate_pin(3)
return FALSE
/obj/item/integrated_circuit/manipulation/grenade
name = "grenade primer"
desc = "This circuit comes with the ability to attach most types of grenades at prime them at will."
extended_desc = "Time between priming and detonation is limited to between 1 to 12 seconds but is optional. \
If unset, not a number, or a number less than 1 then the grenade's built-in timing will be used. \
Beware: Once primed there is no aborting the process!"
icon_state = "grenade"
complexity = 30
inputs = list("detonation time" = IC_PINTYPE_NUMBER)
outputs = list()
activators = list("prime grenade" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
var/obj/item/grenade/attached_grenade
var/pre_attached_grenade_type
/obj/item/integrated_circuit/manipulation/grenade/Initialize()
. = ..()
if(pre_attached_grenade_type)
var/grenade = new pre_attached_grenade_type(src)
attach_grenade(grenade)
/obj/item/integrated_circuit/manipulation/grenade/Destroy()
if(attached_grenade && !attached_grenade.active)
attached_grenade.forceMove(loc)
detach_grenade()
return ..()
/obj/item/integrated_circuit/manipulation/grenade/attackby(var/obj/item/grenade/G, var/mob/user)
if(istype(G))
if(attached_grenade)
to_chat(user, "<span class='warning'>There is already a grenade attached!</span>")
else if(user.transferItemToLoc(G,src))
user.visible_message("<span class='warning'>\The [user] attaches \a [G] to \the [src]!</span>", "<span class='notice'>You attach \the [G] to \the [src].</span>")
attach_grenade(G)
G.forceMove(src)
else
return ..()
/obj/item/integrated_circuit/manipulation/grenade/attack_self(var/mob/user)
if(attached_grenade)
user.visible_message("<span class='warning'>\The [user] removes \an [attached_grenade] from \the [src]!</span>", "<span class='notice'>You remove \the [attached_grenade] from \the [src].</span>")
user.put_in_hands(attached_grenade)
detach_grenade()
else
return ..()
/obj/item/integrated_circuit/manipulation/grenade/do_work()
if(attached_grenade && !attached_grenade.active)
var/datum/integrated_io/detonation_time = inputs[1]
var/dt
if(isnum(detonation_time.data) && detonation_time.data > 0)
dt = Clamp(detonation_time.data, 1, 12)*10
else
dt = 15
addtimer(CALLBACK(attached_grenade, /obj/item/grenade.proc/prime), dt)
var/atom/holder = loc
message_admins("activated a grenade assembly. Last touches: Assembly: [holder.fingerprintslast] Circuit: [fingerprintslast] Grenade: [attached_grenade.fingerprintslast]")
// These procs do not relocate the grenade, that's the callers responsibility
/obj/item/integrated_circuit/manipulation/grenade/proc/attach_grenade(var/obj/item/grenade/G)
attached_grenade = G
G.forceMove(src)
desc += " \An [attached_grenade] is attached to it!"
/obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade()
if(!attached_grenade)
return
attached_grenade.forceMove(drop_location())
attached_grenade = null
desc = initial(desc)
/*
/obj/item/integrated_circuit/manipulation/grenade/frag
pre_attached_grenade_type = /obj/item/weapon/grenade/explosive
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 10)
spawn_flags = null // Used for world initializing, see the #defines above.
*/
/obj/item/integrated_circuit/manipulation/shocker
name = "shocker circuit"
desc = "Used to shock adjacent creatures with electricity."
icon_state = "shocker"
extended_desc = "The circuit accepts a reference to creature,who needs to be shocked. It can shock target on adjacent tiles. \
Severity determines hardness of shock and it's power consumption. It's given between 0 and 60."
w_class = WEIGHT_CLASS_TINY
complexity = 10
inputs = list("target" = IC_PINTYPE_REF,"severity" = IC_PINTYPE_NUMBER)
outputs = list()
activators = list("shock" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 0
/obj/item/integrated_circuit/manipulation/shocker/on_data_written()
var/s = get_pin_data(IC_INPUT, 2)
power_draw_per_use = Clamp(s,0,60)*1200/60
/obj/item/integrated_circuit/manipulation/shocker/do_work()
..()
var/turf/T = get_turf(src)
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /mob/living)
if(!istype(AM,/mob/living)) //Invalid input
return
var/mob/living/M = AM
if(!M.Adjacent(T))
return //Can't reach
to_chat(M, "<span class='danger'>You feel a sharp shock!</span>")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(12, 1, src)
s.start()
var/stf=Clamp(get_pin_data(IC_INPUT, 2),0,60)
M.Knockdown(stf)
M.apply_effect(STUTTER, stf)
/obj/item/integrated_circuit/manipulation/plant_module
name = "plant manipulation module"
desc = "Used to uproot weeds or harvest plants in trays."
icon_state = "plant_m"
extended_desc = "The circuit accepts a reference to hydroponic tray. It work from adjacent tiles. \
Mode(0- harvest, 1-uproot weeds, 2-uproot plant) determinies action."
w_class = WEIGHT_CLASS_TINY
complexity = 10
inputs = list("target" = IC_PINTYPE_REF,"mode" = IC_PINTYPE_NUMBER)
outputs = list()
activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out"=IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 50
/obj/item/integrated_circuit/manipulation/plant_module/do_work()
..()
var/turf/T = get_turf(src)
var/obj/machinery/hydroponics/AM = get_pin_data_as_type(IC_INPUT, 1, /obj/machinery/hydroponics)
if(!istype(AM)) //Invalid input
return
var/mob/living/M = get_turf(AM)
if(!M.Adjacent(T))
return //Can't reach
switch(get_pin_data(IC_INPUT, 2))
if(0)
if(AM.myseed)
if(AM.harvest)
AM.myseed.harvest()
AM.harvest = 0
AM.lastproduce = AM.age
if(!AM.myseed.get_gene(/datum/plant_gene/trait/repeated_harvest))
qdel(AM.myseed)
AM.myseed = null
AM.dead = 0
AM.update_icon()
if(1)
AM.weedlevel = 0
if(2)
if(AM.myseed) //Could be that they're just using it as a de-weeder
AM.age = 0
AM.plant_health = 0
if(AM.harvest)
AM.harvest = FALSE //To make sure they can't just put in another seed and insta-harvest it
qdel(AM.myseed)
AM.myseed = null
AM.weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
AM.update_icon()
else
activate_pin(2)
return FALSE
activate_pin(2)
/obj/item/integrated_circuit/manipulation/grabber
name = "grabber"
desc = "A circuit with it's own inventory for small/medium items, used to grab and store things."
icon_state = "grabber"
extended_desc = "The circuit accepts a reference to thing to be grabbed. It can store up to 10 things. Modes: 1 for grab. 0 for eject the first thing. -1 for eject all."
w_class = WEIGHT_CLASS_SMALL
size = 3
complexity = 10
inputs = list("target" = IC_PINTYPE_REF,"mode" = IC_PINTYPE_NUMBER)
outputs = list("first" = IC_PINTYPE_REF, "last" = IC_PINTYPE_REF, "amount" = IC_PINTYPE_NUMBER,"contents" = IC_PINTYPE_LIST)
activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 50
var/max_w_class = WEIGHT_CLASS_NORMAL
var/max_items = 10
/*
/obj/item/integrated_circuit/manipulation/thrower/New()
processing_objects |= src
/obj/item/integrated_circuit/manipulation/thrower/Destroy()
processing_objects -= src
/obj/item/integrated_circuit/manipulation/thrower/process()
set_pin_data(IC_OUTPUT, 1, WEAKREF(contents[1]))
set_pin_data(IC_OUTPUT, 2, WEAKREF(contents[contents.len]))
set_pin_data(IC_OUTPUT, 3, contents.len)
push_data()
*/
/obj/item/integrated_circuit/manipulation/grabber/do_work()
var/turf/T = get_turf(src)
var/obj/item/AM = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
if(AM)
var/turf/P = get_turf(AM)
var/mode = get_pin_data(IC_INPUT, 2)
if(mode == 1)
if(P.Adjacent(T))
if((contents.len < max_items) && AM && (AM.w_class <= max_w_class))
AM.forceMove(src)
if(mode == 0)
if(contents.len)
var/obj/item/U = contents[1]
U.forceMove(T)
if(mode == -1)
if(contents.len)
var/obj/item/U
for(U in contents)
U.forceMove(T)
if(contents.len)
set_pin_data(IC_OUTPUT, 1, WEAKREF(contents[1]))
set_pin_data(IC_OUTPUT, 2, WEAKREF(contents[contents.len]))
else
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
set_pin_data(IC_OUTPUT, 3, contents.len)
set_pin_data(IC_OUTPUT, 4, contents)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/manipulation/grabber/attack_self(var/mob/user)
if(contents.len)
var/turf/T = get_turf(src)
var/obj/item/U
for(U in contents)
U.forceMove(T)
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
set_pin_data(IC_OUTPUT, 3, contents.len)
push_data()
/obj/item/integrated_circuit/manipulation/thrower
name = "thrower"
desc = "A compact launcher to throw things from inside or nearby tiles"
extended_desc = "The first and second inputs need to be numbers. They are coordinates to throw thing at, relative to the machine itself. \
The 'fire' activator will cause the mechanism to attempt to throw thing at the coordinates, if possible. Note that the \
projectile need to be inside the machine, or to be on an adjacent tile, and to be up to medium size."
complexity = 15
w_class = WEIGHT_CLASS_SMALL
size = 2
inputs = list(
"target X rel" = IC_PINTYPE_NUMBER,
"target Y rel" = IC_PINTYPE_NUMBER,
"projectile" = IC_PINTYPE_REF
)
outputs = list()
activators = list(
"fire" = IC_PINTYPE_PULSE_IN
)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
power_draw_per_use = 50
/obj/item/integrated_circuit/manipulation/thrower/do_work()
var/datum/integrated_io/target_x = inputs[1]
var/datum/integrated_io/target_y = inputs[2]
var/datum/integrated_io/projectile = inputs[3]
if(!isweakref(projectile.data))
return
var/obj/item/A = projectile.data.resolve()
if(A.anchored || (A.w_class > WEIGHT_CLASS_NORMAL))
return
var/turf/T = get_turf(assembly)
if(!(A.Adjacent(T) || (A in assembly.GetAllContents())))
return
if(assembly)
if(isnum(target_x.data))
target_x.data = round(target_x.data, 1)
if(isnum(target_y.data))
target_y.data = round(target_y.data, 1)
var/_x = Clamp(T.x + target_x.data, 0, world.maxx)
var/_y = Clamp(T.y + target_y.data, 0, world.maxy)
A.forceMove(drop_location())
A.throw_at(locate(_x, _y, T.z), round(Clamp(sqrt(target_x.data*target_x.data+target_y.data*target_y.data),0,8),1), 3)

View File

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

View File

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

View File

@@ -0,0 +1,81 @@
/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 = WEIGHT_CLASS_SMALL
complexity = 16
inputs = list("target" = IC_PINTYPE_REF)
outputs = list(
"target cell charge" = IC_PINTYPE_NUMBER,
"target cell max charge" = IC_PINTYPE_NUMBER,
"target cell percentage" = IC_PINTYPE_NUMBER
)
activators = list("transmit" = IC_PINTYPE_PULSE_IN, "on transmit" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3)
power_draw_per_use = 500 // Inefficency has to come from somewhere.
var/amount_to_move = 5000
/obj/item/integrated_circuit/power/transmitter/large
name = "large power transmission circuit"
desc = "This can wirelessly transmit a lot of electricity from an assembly's battery towards a nearby machine. Warning: Do not operate in flammable enviroments."
extended_desc = "This circuit transmits 20 kJ of electricity every time the activator pin is pulsed. The input pin must be \
a reference to a machine to send electricity to. This can be a battery, or anything containing a battery. The machine can exist \
inside the assembly, or adjacent to it. The power is sourced from the assembly's power cell. If the target is outside of the assembly, \
some power is lost due to ineffiency."
w_class = WEIGHT_CLASS_BULKY
complexity = 32
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 6, TECH_MAGNET = 5)
power_draw_per_use = 2000
amount_to_move = 20000
/obj/item/integrated_circuit/power/transmitter/do_work()
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(AM)
if(!assembly)
return FALSE // Pointless to do everything else if there's no battery to draw from.
var/obj/item/stock_parts/cell/cell = AM.get_cell()
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.charge == cell.maxcharge)
return FALSE
if(transfer_amount && assembly.draw_power(amount_to_move)) // CELLRATE is already handled in draw_power()
cell.give(transfer_amount * GLOB.CELLRATE)
set_pin_data(IC_OUTPUT, 1, cell.charge)
set_pin_data(IC_OUTPUT, 2, cell.maxcharge)
set_pin_data(IC_OUTPUT, 3, cell.percent())
activate_pin(2)
push_data()
return TRUE
else
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
set_pin_data(IC_OUTPUT, 3, null)
activate_pin(2)
push_data()
return FALSE
return FALSE
/obj/item/integrated_circuit/power/transmitter/large/do_work()
if(..()) // If the above code succeeds, do this below.
if(prob(20))
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(12, 1, src)
s.start()
visible_message("<span class='warning'>\The [assembly] makes some sparks!</span>")

View File

@@ -0,0 +1,365 @@
/obj/item/integrated_circuit/reagent
category_text = "Reagent"
var/volume = 0
resistance_flags = UNACIDABLE | FIRE_PROOF
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
/obj/item/integrated_circuit/reagent/New()
..()
if(volume)
create_reagents(volume)
/obj/item/integrated_circuit/reagent/smoke
name = "smoke generator"
desc = "Unlike most electronics, creating smoke is completely intentional."
icon_state = "smoke"
extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \
into the smoke clouds when activated. The reagents are consumed when smoke is made."
container_type = OPENCONTAINER_1
complexity = 20
cooldown_per_use = 1 SECONDS
inputs = list()
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
activators = list("create smoke" = IC_PINTYPE_PULSE_IN,"on smoked" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3)
volume = 100
power_draw_per_use = 20
var/smoke_radius = 5
/obj/item/integrated_circuit/reagent/smoke/on_reagent_change()
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
/obj/item/integrated_circuit/reagent/smoke/interact(mob/user)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
..()
/obj/item/integrated_circuit/reagent/smoke/do_work()
var/location = get_turf(src)
var/datum/effect_system/smoke_spread/chem/S = new
S.attach(location)
playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
if(S)
S.set_up(reagents, smoke_radius, location, 0)
S.start()
if(reagents)
reagents.clear_reagents()
activate_pin(2)
/obj/item/integrated_circuit/reagent/injector
name = "integrated hypo-injector"
desc = "This scary looking thing is able to pump liquids into whatever it's pointed at."
icon_state = "injector"
extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine. The target \
must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing. Negative given amount makes injector suck out reagents."
container_type = OPENCONTAINER_1
complexity = 20
cooldown_per_use = 6 SECONDS
inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER)
inputs_default = list("2" = 5)
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
activators = list("inject" = IC_PINTYPE_PULSE_IN, "on injected" = IC_PINTYPE_PULSE_OUT, "on fail" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
volume = 30
power_draw_per_use = 15
var/direction_mode = SYRINGE_INJECT
var/transfer_amount = 10
var/busy = FALSE
/obj/item/integrated_circuit/reagent/injector/interact(mob/user)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
..()
/obj/item/integrated_circuit/reagent/injector/on_reagent_change()
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
/obj/item/integrated_circuit/reagent/injector/on_data_written()
var/new_amount = get_pin_data(IC_INPUT, 2)
if(new_amount < 0)
new_amount = -new_amount
direction_mode = SYRINGE_DRAW
else
direction_mode = SYRINGE_INJECT
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, volume)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/proc/inject_tray(var/obj/machinery/hydroponics/H,var/atom/movable/SO,var/A)
var/datum/reagents/S = new /datum/reagents() //This is a strange way, but I don't know of a better one so I can't fix it at the moment...
S.my_atom = H
SO.reagents.trans_to(S,A)
H.applyChemicals(S)
S.clear_reagents()
qdel(S)
/obj/item/integrated_circuit/reagent/injector/do_work()
set waitfor = FALSE // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(!istype(AM)||!Adjacent(AM)||busy)
activate_pin(3)
return
if(istype(AM,/obj/machinery/hydroponics)&&(direction_mode==SYRINGE_INJECT)&&(reagents.total_volume))//injection into tray.
inject_tray(AM,src,transfer_amount)
activate_pin(2)
return
if(!AM.reagents)
activate_pin(3)
return
if(direction_mode == SYRINGE_INJECT)
if(!reagents.total_volume) // Empty
activate_pin(3)
return
if(AM.is_injectable())
if(AM.reagents.total_volume>=AM.reagents.maximum_volume)
activate_pin(3)
return
if(isliving(AM))
var/mob/living/L = AM
if(!L.can_inject(null, 0))
activate_pin(3)
return
//Always log attemped injections for admins
var/list/rinject = list()
for(var/datum/reagent/R in reagents.reagent_list)
rinject += R.name
var/contained = english_list(rinject)
add_logs(src, L, "attemped to inject", addition="which had [contained]") //TODO: proper logging (maybe last touched and assembled)
L.visible_message("<span class='danger'>[src] is trying to inject [L]!</span>", \
"<span class='userdanger'>[src] is trying to inject you!</span>")
busy = TRUE
if(do_atom(src, L, extra_checks=CALLBACK(L, /mob/living/proc/can_inject,null,0)))
var/fraction = min(transfer_amount/reagents.total_volume, 1)
reagents.reaction(L, INJECT, fraction)
reagents.trans_to(L, transfer_amount)
L.visible_message("<span class='danger'>[src] injects [L] with it's needle!</span>", \
"<span class='userdanger'>[src] injects you with it's needle!</span>")
else
busy = FALSE
activate_pin(3)
return
busy = FALSE
else
reagents.trans_to(AM, transfer_amount)
else
activate_pin(3)
return
else
if(reagents.total_volume >= reagents.maximum_volume) // Full
activate_pin(3)
return
var/tramount = Clamp(min(transfer_amount, reagents.maximum_volume - reagents.total_volume), 0, reagents.maximum_volume)
if(isliving(AM))
var/mob/living/L = AM
L.visible_message("<span class='danger'>[src] is trying to take a blood sample from [L]!</span>", \
"<span class='userdanger'>[src] is trying to take a blood sample from you!</span>")
busy = TRUE
if(do_atom(src, L, extra_checks=CALLBACK(L, /mob/living/proc/can_inject,null,0)))
if(L.transfer_blood_to(src, tramount))
L.visible_message("[src] takes a blood sample from [L].")
else
busy = FALSE
activate_pin(3)
return
busy = FALSE
else
if(!AM.reagents.total_volume || !AM.is_drawable())
activate_pin(3)
return
AM.reagents.trans_to(src, tramount)
activate_pin(2)
/obj/item/integrated_circuit/reagent/pump
name = "reagent pump"
desc = "Moves liquids safely inside a machine, or even nearby it."
icon_state = "reagent_pump"
extended_desc = "This is a pump, which will move liquids from the source ref to the target ref. The third pin determines \
how much liquid is moved per pulse, between 0 and 50. The pump can move reagents to any open container inside the machine, or \
outside the machine if it is next to the machine. Note that this cannot be used on entities."
container_type = OPENCONTAINER_1
complexity = 8
inputs = list("source" = IC_PINTYPE_REF, "target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER)
inputs_default = list("3" = 5)
outputs = list()
activators = list("transfer reagents" = IC_PINTYPE_PULSE_IN, "on transfer" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
var/transfer_amount = 10
var/direction_mode = SYRINGE_INJECT
power_draw_per_use = 10
/obj/item/integrated_circuit/reagent/pump/on_data_written()
var/new_amount = get_pin_data(IC_INPUT, 3)
if(new_amount < 0)
new_amount = -new_amount
direction_mode = SYRINGE_DRAW
else
direction_mode = SYRINGE_INJECT
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, 50)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/pump/do_work()
var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable)
if(!istype(source) || !istype(target) || !source.reagents) //Invalid input
return
if(Adjacent(source) && Adjacent(target))
if(istype(target,/obj/machinery/hydroponics)&&(source.reagents.total_volume))//injection into tray.
inject_tray(target,source,transfer_amount)
activate_pin(2)
return
if(!target.reagents)
return
if(ismob(source) || ismob(target))
return
if(!source.is_open_container() || !target.is_open_container())
return
if(direction_mode)
if(target.reagents.maximum_volume - target.reagents.total_volume <= 0) //full
return
source.reagents.trans_to(target, transfer_amount)
else
if(source.reagents.maximum_volume - source.reagents.total_volume <= 0)
return
target.reagents.trans_to(source, transfer_amount)
activate_pin(2)
/obj/item/integrated_circuit/reagent/storage
name = "reagent storage"
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u."
icon_state = "reagent_storage"
extended_desc = "This is effectively an internal beaker."
container_type = OPENCONTAINER_1
complexity = 4
inputs = list()
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
activators = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
volume = 60
/obj/item/integrated_circuit/reagent/storage/interact(mob/user)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
..()
/obj/item/integrated_circuit/reagent/storage/on_reagent_change()
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
/obj/item/integrated_circuit/reagent/storage/cryo
name = "cryo reagent storage"
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. This will also suppress reactions."
icon_state = "reagent_storage_cryo"
extended_desc = "This is effectively an internal cryo beaker."
container_type = OPENCONTAINER_1
complexity = 8
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_MATERIALS = 4, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
/obj/item/integrated_circuit/reagent/storage/cryo/New()
. = ..()
reagents.set_reacting(FALSE)
/obj/item/integrated_circuit/reagent/storage/big
name = "big reagent storage"
desc = "Stores liquid inside, and away from electrical components. Can store up to 180u."
icon_state = "reagent_storage_big"
extended_desc = "This is effectively an internal beaker."
container_type = OPENCONTAINER_1
complexity = 16
volume = 180
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_MATERIALS = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
/obj/item/integrated_circuit/reagent/storage/scan
name = "reagent scanner"
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. On pulse this beaker will send list of contained reagents."
icon_state = "reagent_scan"
extended_desc = "Mostly useful for reagent filter."
container_type = OPENCONTAINER_1
complexity = 8
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF,"list of reagents" = IC_PINTYPE_LIST)
activators = list("scan" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_MATERIALS = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
/obj/item/integrated_circuit/reagent/storage/scan/do_work()
var/cont[0]
for(var/datum/reagent/RE in reagents.reagent_list)
cont += RE.id
set_pin_data(IC_OUTPUT, 3, cont)
push_data()
/obj/item/integrated_circuit/reagent/filter
name = "reagent filter"
desc = "Filtering liquids by list of desired or unwanted reagents."
icon_state = "reagent_filter"
extended_desc = "This is a filter, which will move liquids from the source ref to the target ref. \
It will move all reagents, except list, given in fourth pin if amount value is positive.\
Or it will move only desired reagents if amount is negative, The third pin determines \
how much reagent is moved per pulse, between 0 and 50. Amount is given for each separate reagent."
container_type = OPENCONTAINER_1
complexity = 8
inputs = list("source" = IC_PINTYPE_REF, "target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER, "list of reagents" = IC_PINTYPE_LIST)
inputs_default = list("3" = 5)
outputs = list()
activators = list("transfer reagents" = IC_PINTYPE_PULSE_IN, "on transfer" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
var/transfer_amount = 10
var/direction_mode = SYRINGE_INJECT
power_draw_per_use = 10
/obj/item/integrated_circuit/reagent/filter/on_data_written()
var/new_amount = get_pin_data(IC_INPUT, 3)
if(new_amount < 0)
new_amount = -new_amount
direction_mode = SYRINGE_DRAW
else
direction_mode = SYRINGE_INJECT
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, 50)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/filter/do_work()
var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable)
var/list/demand = get_pin_data(IC_INPUT, 4)
if(!istype(source) || !istype(target)) //Invalid input
return
var/turf/T = get_turf(src)
if(source.Adjacent(T) && target.Adjacent(T))
if(!source.reagents || !target.reagents)
return
if(ismob(source) || ismob(target))
return
if(!source.is_open_container() || !target.is_open_container())
return
if(target.reagents.maximum_volume - target.reagents.total_volume <= 0)
return
for(var/datum/reagent/G in source.reagents.reagent_list)
if (!direction_mode)
if(G.id in demand)
source.reagents.trans_id_to(target, G.id, transfer_amount)
else
if(!(G.id in demand))
source.reagents.trans_id_to(target, G.id, transfer_amount)
activate_pin(2)
push_data()

View File

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

View File

@@ -0,0 +1,145 @@
/obj/item/integrated_circuit/time
name = "time circuit"
desc = "Now you can build your own clock!"
complexity = 2
inputs = list()
outputs = list()
category_text = "Time"
/obj/item/integrated_circuit/time/delay
name = "two-sec delay circuit"
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
This circuit is set to send a pulse after a delay of two seconds."
icon_state = "delay-20"
var/delay = 20
activators = list("incoming"= IC_PINTYPE_PULSE_IN,"outgoing" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/time/delay/do_work()
addtimer(CALLBACK(src, .proc/activate_pin, 2), delay)
/obj/item/integrated_circuit/time/delay/five_sec
name = "five-sec delay circuit"
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
This circuit is set to send a pulse after a delay of five seconds."
icon_state = "delay-50"
delay = 50
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/one_sec
name = "one-sec delay circuit"
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
This circuit is set to send a pulse after a delay of one second."
icon_state = "delay-10"
delay = 10
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/half_sec
name = "half-sec delay circuit"
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
This circuit is set to send a pulse after a delay of half a second."
icon_state = "delay-5"
delay = 5
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/tenth_sec
name = "tenth-sec delay circuit"
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
This circuit is set to send a pulse after a delay of 1/10th of a second."
icon_state = "delay-1"
delay = 1
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/custom
name = "custom delay circuit"
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse."
icon_state = "delay"
inputs = list("delay time" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/custom/do_work()
var/delay_input = get_pin_data(IC_INPUT, 1)
if(delay_input && isnum(delay_input) )
var/new_delay = Clamp(delay_input ,1 ,36000) //An hour.
delay = new_delay
..()
/obj/item/integrated_circuit/time/ticker
name = "ticker circuit"
desc = "This circuit sends an automatic pulse every four seconds."
icon_state = "tick-m"
complexity = 8
var/delay = 4 SECONDS
var/next_fire = 0
var/is_running = FALSE
inputs = list("enable ticking" = IC_PINTYPE_BOOLEAN)
activators = list("outgoing pulse" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/time/ticker/Destroy()
if(is_running)
STOP_PROCESSING(SSfastprocess, src)
return ..()
/obj/item/integrated_circuit/time/ticker/on_data_written()
var/do_tick = get_pin_data(IC_INPUT, 1)
if(do_tick && !is_running)
is_running = TRUE
tick()
else if(is_running)
is_running = FALSE
/obj/item/integrated_circuit/time/ticker/proc/tick()
if(is_running)
addtimer(CALLBACK(src, .proc/tick), delay)
if(world.time > next_fire)
next_fire = world.time + delay
activate_pin(1)
/obj/item/integrated_circuit/time/ticker/fast
name = "fast ticker"
desc = "This advanced circuit sends an automatic pulse every two seconds."
icon_state = "tick-f"
complexity = 12
delay = 2 SECONDS
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 8
/obj/item/integrated_circuit/time/ticker/slow
name = "slow ticker"
desc = "This simple circuit sends an automatic pulse every six seconds."
icon_state = "tick-s"
complexity = 4
delay = 6 SECONDS
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/time/clock
name = "integrated clock"
desc = "Tells you what the local time is, specific to your station or planet."
icon_state = "clock"
inputs = list()
outputs = list(
"time" = IC_PINTYPE_STRING,
"hours" = IC_PINTYPE_NUMBER,
"minutes" = IC_PINTYPE_NUMBER,
"seconds" = IC_PINTYPE_NUMBER
)
activators = list("get time" = IC_PINTYPE_PULSE_IN, "on time got" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/time/clock/do_work()
var/wtime = world.time
set_pin_data(IC_OUTPUT, 1, time2text(wtime, "hh:mm:ss") )
set_pin_data(IC_OUTPUT, 2, text2num(time2text(wtime, "hh") ) )
set_pin_data(IC_OUTPUT, 3, text2num(time2text(wtime, "mm") ) )
set_pin_data(IC_OUTPUT, 4, text2num(time2text(wtime, "ss") ) )
push_data()
activate_pin(2)

View File

@@ -0,0 +1,138 @@
//These circuits do not-so-simple math.
/obj/item/integrated_circuit/trig
complexity = 1
inputs = list(
"A" = IC_PINTYPE_NUMBER,
"B" = IC_PINTYPE_NUMBER,
"C" = IC_PINTYPE_NUMBER,
"D" = IC_PINTYPE_NUMBER,
"E" = IC_PINTYPE_NUMBER,
"F" = IC_PINTYPE_NUMBER,
"G" = IC_PINTYPE_NUMBER,
"H" = IC_PINTYPE_NUMBER
)
outputs = list("result" = IC_PINTYPE_NUMBER)
activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT)
category_text = "Trig"
extended_desc = "Input and output are in degrees."
power_draw_per_use = 1 // Still cheap math.
// Sine //
/obj/item/integrated_circuit/trig/sine
name = "sin circuit"
desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A."
icon_state = "sine"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/sine/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = sin(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cosine //
/obj/item/integrated_circuit/trig/cosine
name = "cos circuit"
desc = "Outputs the cosine of A."
icon_state = "cosine"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cosine/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = cos(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Tangent //
/obj/item/integrated_circuit/trig/tangent
name = "tan circuit"
desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance."
icon_state = "tangent"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/tangent/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = Tan(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cosecant //
/obj/item/integrated_circuit/trig/cosecant
name = "csc circuit"
desc = "Outputs the cosecant of A."
icon_state = "cosecant"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cosecant/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = Csc(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Secant //
/obj/item/integrated_circuit/trig/secant
name = "sec circuit"
desc = "Outputs the secant of A. Has nothing to do with the security department."
icon_state = "secant"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/secant/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = Sec(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cotangent //
/obj/item/integrated_circuit/trig/cotangent
name = "cot circuit"
desc = "Outputs the cotangent of A."
icon_state = "cotangent"
inputs = list("A" = IC_PINTYPE_NUMBER)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cotangent/do_work()
pull_data()
var/result = null
var/A = get_pin_data(IC_INPUT, 1)
if(!isnull(A))
result = Cot(A)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)

View File

@@ -1,6 +1,3 @@
#define SYRINGE_DRAW 0
#define SYRINGE_INJECT 1
/obj/item/reagent_containers/syringe
name = "syringe"
desc = "A syringe that can hold up to 15 units."

View File

@@ -91,6 +91,35 @@ other types of metals and chemistry for reagents).
build_path = /obj/item/device/paicard
category = list("Electronics")
/datum/design/integrated_printer
name = "Integrated circuits printer"
desc = "This machine provides all neccesary things for circuitry."
id = "icprinter"
req_tech = list("programming" = 2,"materials" = 2, "engineering" = 3)
build_type = PROTOLATHE
materials = list(MAT_GLASS = 5000, MAT_METAL = 5000)
build_path = /obj/item/device/integrated_circuit_printer
category = list("Electronics")
/datum/design/advupdisk
name = "Upgrade disk-advanced circuits"
desc = "Upgrade disk for integrated circuits printer.Allows advanced designs."
id = "udiskadv"
req_tech = list("programming" = 3, "engineering" = 3)
build_type = PROTOLATHE
materials = list(MAT_GLASS = 500, MAT_METAL = 500)
build_path = /obj/item/disk/integrated_circuit/upgrade/advanced
category = list("Electronics")
/datum/design/cloneupisk
name = "Upgrade disk-assembly cloning"
desc = "Upgrade disk for integrated circuits printer.Allows assembly cloning."
id = "udiskclone"
req_tech = list("programming" = 4, "engineering" = 4)
build_type = PROTOLATHE
materials = list(MAT_GLASS = 500, MAT_METAL = 500)
build_path = /obj/item/disk/integrated_circuit/upgrade/clone
category = list("Electronics")
////////////////////////////////////////
//////////Disk Construction Disks///////

View File

@@ -10,6 +10,14 @@
build_path = /obj/item/circuitboard/machine/telecomms/receiver
category = list("Subspace Telecomms")
/datum/design/board/exonet_node
name = "Machine Design (Exonet Node)"
desc = "Allows for the construction of Exonet Node."
id = "e-node"
req_tech = list("programming" = 2, "engineering" = 3, "bluespace" = 1)
build_path = /obj/item/circuitboard/machine/exonet_node
category = list("Subspace Telecomms")
/datum/design/board/telecomms_bus
name = "Machine Design (Bus Mainframe)"
desc = "Allows for the construction of Telecommunications Bus Mainframes."

View File

@@ -7,5 +7,133 @@
# NOTE: if the rank-name cannot be found in admin_ranks.txt, they will not be adminned! ~Carn #
# NOTE: syntax was changed to allow hyphenation of ranknames, since spaces are stripped. #
###############################################################################################
<<<<<<< HEAD
Jayehh = Host
Jayehh = Host
=======
Optimumtact = Host
NewSta = Game Master
Expletives = Game Master
kingofkosmos = Game Master
MrStonedOne = Game Master
microscopics = Game Master
Gun Hog = Game Master
KorPhaeron = Game Master
razharas = Game Master
Lordpidey = Game Master
Niknakflak = Game Master
rolan7 = Game Master
quarxink = Game Master
adrix89 = Game Master
tle = Game Master
xsi = Game Master
scaredofshadows = Game Master
neofite = Game Master
trubblebass = Game Master
mport2004 = Game Master
deuryn = Game Master
agouri = Game Master
errorage = Game Master
superxpdude = Game Master
petethegoat = Game Master
korphaeron = Game Master
nodrak = Game Master
carnwennan = Game Master
ikarrus = Game Master
cheridan = Game Master
giacomand = Game Master
rockdtben = Game Master
sieve = Game Master
aranclanos = Game Master
intigracy = Game Master
dumpdavidson = Game Master
kazeespada = Game Master
malkevin = Game Master
incoming = Game Master
demas = Game Master
fleure = Game Master
ricotez = Game Master
misterperson = Game Master
crimsonvision = Game Master
iamgoofball = Game Master
zelacks = Game Master
androidsfv = Game Master
miggles = Game Master
jordie0608 = Game Master
s0ldi3rkr4s0 = Game Master
ergovisavi = Game Master
vistapowa = Game Master
miauw62 = Game Master
kazeespada = Game Master
rumia29 = Game Master
bobylein = Game Master
sirbayer = Game Master
hornygranny = Game Master
yota = Game Master
firecage = Game Master
donkieyo = Game Master
argoneus = Game Master
paprka = Game Master
cookingboy3 = Game Master
limeliz = Game Master
steelpoint = Game Master
phil235 = Game Master
CorruptComputer = Game Master
xxnoob = Game Master
tkdrg = Game Master
Cuboos = Game Master
thunder12345 = Game Master
wjohnston = Game Master
mandurrh = Game Master
thurgatar = Game Master
xerux = Game Master
dannno = Game Master
lo6a4evskiy = Game Master
vekter = Game Master
Ahammer18 = Game Master
ACCount12 = Game Master
fayrik = Game Master
shadowlight213 = Game Master
drovidicorv = Game Master
Dunc = Game Master
MMMiracles = Game Master
bear1ake = Game Master
CoreOverload = Game Master
Jalleo = Game Master
ChangelingRain = Game Master
FoxPMcCloud = Game Master
Xhuis = Game Master
Astralenigma = Game Master
Tokiko1 = Game Master
SuperSayu = Game Master
Lzimann = Game Master
As334 = Game Master
neersighted = Game Master
Swankcookie = Game Master
Ressler = Game Master
Folix = Game Master
Bawhoppennn = Game Master
Anturke = Host
Lumipharon = Game Master
bgobandit = Game Master
coiax = Game Master
RandomMarine = Game Master
PKPenguin321 = Game Master
TechnoAlchemist = Game Master
Aloraydrel = Game Master
Quiltyquilty = Game Master
SnipeDragon = Game Master
Fjeld = Game Master
kevinz000 = Game Master
Tacolizard = Game Master
TrustyGun = Game Master
Cyberboss = Game Master
PJB3005 = Game Master
Sweaterkittens = Game Master
Feemjmeem = Game Master
JStheguy = Game Master
excessiveuseofcobby = Game Master
Plizzard = Game Master
octareenroon91 = Game Master
Serpentarium = Game Master
>>>>>>> bdfbafd... [READY]integrated circuitry port+upgrade. (#32481)

View File

@@ -504,6 +504,7 @@ MICE_ROUNDSTART 10
## If the percentage of players alive (doesn't count conversions) drops below this threshold the emergency shuttle will be forcefully called (provided it can be)
#EMERGENCY_SHUTTLE_AUTOCALL_THRESHOLD 0.2
<<<<<<< HEAD
## CREW OBJECTIVES ##
## Comment to disable objectives for innocent crew members.
ALLOW_CREW_OBJECTIVES
@@ -514,3 +515,7 @@ ALLOW_MISCREANTS
## Uncomment to let miscreants spawn during Extended. I hold no responsibility for fun that may occur while this is enabled.
#ALLOW_EXTENDED_MISCREANTS
=======
## Determines if players are allowed to print integrated circuits, uncomment to allow.
#IC_PRINTING
>>>>>>> bdfbafd... [READY]integrated circuitry port+upgrade. (#32481)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 59 KiB

BIN
sound/machines/synth_no.ogg Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -44,6 +44,7 @@
#include "code\__DEFINES\flags.dm"
#include "code\__DEFINES\food.dm"
#include "code\__DEFINES\hud.dm"
#include "code\__DEFINES\integrated_electronics.dm"
#include "code\__DEFINES\inventory.dm"
#include "code\__DEFINES\is_helpers.dm"
#include "code\__DEFINES\jobs.dm"
@@ -265,6 +266,7 @@
#include "code\controllers\subsystem\title.dm"
#include "code\controllers\subsystem\vote.dm"
#include "code\controllers\subsystem\weather.dm"
#include "code\controllers\subsystem\processing\circuit.dm"
#include "code\controllers\subsystem\processing\fastprocess.dm"
#include "code\controllers\subsystem\processing\fields.dm"
#include "code\controllers\subsystem\processing\flightpacks.dm"
@@ -285,6 +287,7 @@
#include "code\datums\dna.dm"
#include "code\datums\dog_fashion.dm"
#include "code\datums\emotes.dm"
#include "code\datums\EPv2.dm"
#include "code\datums\explosion.dm"
#include "code\datums\forced_movement.dm"
#include "code\datums\holocall.dm"
@@ -628,6 +631,7 @@
#include "code\game\machinery\dna_scanner.dm"
#include "code\game\machinery\doppler_array.dm"
#include "code\game\machinery\droneDispenser.dm"
#include "code\game\machinery\exonet_node.dm"
#include "code\game\machinery\firealarm.dm"
#include "code\game\machinery\flasher.dm"
#include "code\game\machinery\gulag_item_reclaimer.dm"
@@ -1538,6 +1542,39 @@
#include "code\modules\hydroponics\grown\tobacco.dm"
#include "code\modules\hydroponics\grown\tomato.dm"
#include "code\modules\hydroponics\grown\towercap.dm"
#include "code\modules\integrated_electronics\core\analyzer.dm"
#include "code\modules\integrated_electronics\core\assemblies.dm"
#include "code\modules\integrated_electronics\core\debugger.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\prefab.dm"
#include "code\modules\integrated_electronics\core\printer.dm"
#include "code\modules\integrated_electronics\core\wirer.dm"
#include "code\modules\integrated_electronics\core\special_pins\boolean_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\char_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\color_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\dir_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\list_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\number_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\ref_pin.dm"
#include "code\modules\integrated_electronics\core\special_pins\string_pin.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.dm"
#include "code\modules\integrated_electronics\subtypes\lists.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\output.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\jobs\access.dm"
#include "code\modules\jobs\job_exp.dm"
#include "code\modules\jobs\jobs.dm"

View File

@@ -0,0 +1,14 @@
<ui-display>
<ui-section label='Status'>
<ui-button
action='toggle_power'
style='{{data.toggle ? "selected" : null}}' >
Turn {{data.toggle ? "off" : "on"}}
</ui-button>
</ui-section>
<ui-display title='Logging'>
{{#each data.logs}}
<ui-section label='>'>{{.}}<ui-section>
{{/each}}
</ui-display>
</ui-display>