Circuits Update One (#6852)

Ports a buuuuunch of circuits from Polaris.
Allows metabolic siphons and internal energy siphons to consume power to feed their host.
Ports /tg/ circuits too while I'm at it.
Increases base size and complexity for circuits. You're all adults. Hopefully. Don't abuse it.
Ports the integrated circuit detailer.
This commit is contained in:
MarinaGryphon
2019-08-25 13:44:42 -05:00
committed by Erki
parent 4481646713
commit bd5884c89a
56 changed files with 2067 additions and 134 deletions

View File

@@ -43,7 +43,7 @@
/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 = 'icons/obj/assemblies/electronic_components.dmi'
icon_state = "template"
w_class = ITEMSIZE_TINY
var/obj/item/device/electronic_assembly/assembly // Reference to the assembly holding this circuit, if any.

View File

@@ -1,40 +1,19 @@
#define IC_COMPONENTS_BASE 20
#define IC_COMPLEXITY_BASE 60
#define IC_COMPONENTS_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 = ITEMSIZE_SMALL
icon = 'icons/obj/electronic_assemblies.dmi'
icon = 'icons/obj/assemblies/electronic_setups.dmi'
icon_state = "setup_small"
var/max_components = IC_COMPONENTS_BASE
var/max_complexity = IC_COMPLEXITY_BASE
var/opened = 0
var/can_anchor = FALSE // If true, wrenching it will anchor it.
var/obj/item/weapon/cell/device/battery // Internal cell which most circuits need to work.
/obj/item/device/electronic_assembly/medium
name = "electronic mechanism"
icon_state = "setup_medium"
desc = "It's a case, for building medium-sized electronics with."
w_class = ITEMSIZE_NORMAL
max_components = IC_COMPONENTS_BASE * 2
max_complexity = IC_COMPLEXITY_BASE * 2
/obj/item/device/electronic_assembly/large
name = "electronic machine"
icon_state = "setup_large"
desc = "It's a case, for building large electronics with."
w_class = ITEMSIZE_LARGE
max_components = IC_COMPONENTS_BASE * 4
max_complexity = IC_COMPLEXITY_BASE * 4
/obj/item/device/electronic_assembly/drone
name = "electronic drone"
icon_state = "setup_drone"
desc = "It's a case, for building mobile electronics with."
w_class = ITEMSIZE_NORMAL
max_components = IC_COMPONENTS_BASE * 1.5
max_complexity = IC_COMPLEXITY_BASE * 1.5
var/detail_color = COLOR_ASSEMBLY_BLACK
var/obj/item/weapon/card/id/access_card
/obj/item/device/electronic_assembly/implant
name = "electronic implant"
@@ -50,12 +29,22 @@
if (!printed)
battery = new(src)
START_PROCESSING(SSelectronics, src)
access_card = new /obj/item/weapon/card/id(src)
/obj/item/device/electronic_assembly/Destroy()
QDEL_NULL(battery)
STOP_PROCESSING(SSelectronics, src)
QDEL_NULL(access_card)
return ..()
/obj/item/device/electronic_assembly/Collide(atom/AM)
var/collw = AM
.=..()
if((istype(collw, /obj/machinery/door/airlock) || istype(collw, /obj/machinery/door/window)) && (!isnull(access_card)))
var/obj/machinery/door/D = collw
if(D.check_access(access_card))
D.open()
/obj/item/device/electronic_assembly/process()
handle_idle_power()
@@ -175,14 +164,17 @@
/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)
cut_overlays()
if(detail_color == COLOR_ASSEMBLY_BLACK) //Black colored overlay looks almost but not exactly like the base sprite, so just cut the overlay and avoid it looking kinda off.
return
var/image/detail_overlay = image('icons/obj/assemblies/electronic_setups.dmi', "[icon_state]-color")
detail_overlay.color = detail_color
add_overlay(detail_overlay)
/obj/item/device/electronic_assembly/GetAccess()
. = list()
@@ -234,14 +226,18 @@
return TRUE
// Non-interactive version of above that always succeeds, intended for build-in circuits that get added on assembly initialization.
/obj/item/device/electronic_assembly/proc/force_add_circuit(var/obj/item/integrated_circuit/IC)
IC.forceMove(src)
IC.assembly = src
/obj/item/device/electronic_assembly/afterattack(atom/target, mob/user, proximity)
if(proximity)
var/scanned = FALSE
for(var/obj/item/integrated_circuit/input/sensor/S in contents)
if(S.scan(target))
scanned = TRUE
if(scanned)
visible_message("<span class='notice'>\The [user] waves \the [src] around [target].</span>")
var/scanned = FALSE
for(var/obj/item/integrated_circuit/input/sensor/S in contents)
if(S.sense(target))
scanned = TRUE
if(scanned)
visible_message("<span class='notice'>\The [user] waves \the [src] around [target].</span>")
/obj/item/device/electronic_assembly/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/integrated_circuit))
@@ -254,7 +250,17 @@
interact(user)
return TRUE
else if(istype(I, /obj/item/weapon/crowbar))
else if(I.iswrench() && can_anchor)
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
anchored = !anchored
if(anchored)
on_anchored()
else
on_unanchored()
user.visible_message("[user] has wrenched [src]'s anchoring bolts [anchored ? "into" : "out of"] place.", "You wrench [src]'s anchoring bolts [anchored ? "into" : "out of"] place.", "You hear the sound of a ratcheting wrench turning.")
return TRUE
else if(I.iscrowbar())
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
opened = !opened
to_chat(user, "<span class='notice'>You [opened ? "open" : "close"] \the [src].</span>")
@@ -271,10 +277,14 @@
else if(istype(I, /obj/item/weapon/cell/device))
if(!opened)
to_chat(user, "<span class='warning'>\The [src] isn't open, so you can't put anything inside. Try using a crowbar.</span>")
for(var/obj/item/integrated_circuit/input/S in contents)
S.attackby_react(I,user,user.a_intent)
return FALSE
if(battery)
to_chat(user, "<span class='warning'>\The [src] already has \a [battery] inside. Remove it first if you want to replace it.</span>")
for(var/obj/item/integrated_circuit/input/S in contents)
S.attackby_react(I,user,user.a_intent)
return FALSE
var/obj/item/weapon/cell/device/cell = I
@@ -284,12 +294,18 @@
to_chat(user, "<span class='notice'>You slot \the [cell] inside \the [src]'s power supply.</span>")
interact(user)
return TRUE
else if(istype(I, /obj/item/device/integrated_electronics/detailer))
var/obj/item/device/integrated_electronics/detailer/D = I
detail_color = D.detail_color
update_icon()
else //Attempt to insert the item into any contained insert_slots
for(var/obj/item/integrated_circuit/insert_slot/S in contents)
else
for(var/obj/item/integrated_circuit/insert_slot/S in contents) //Attempt to insert the item into any contained insert_slots
if(S.insert(I, user))
return TRUE
for(var/obj/item/integrated_circuit/input/S in contents) // Attempt to swipe on scanners
if(S.attackby_react(I,user,user.a_intent))
return TRUE
return ..()
/obj/item/device/electronic_assembly/attack_self(mob/user)
@@ -338,3 +354,11 @@
if(battery && battery.give(amount * CELLRATE))
return TRUE
return FALSE
/obj/item/device/electronic_assembly/proc/on_anchored()
for(var/obj/item/integrated_circuit/IC in contents)
IC.on_anchored()
/obj/item/device/electronic_assembly/proc/on_unanchored()
for(var/obj/item/integrated_circuit/IC in contents)
IC.on_unanchored()

View File

@@ -0,0 +1,192 @@
// The base subtype for assemblies that can be worn. Certain pieces will have more or less capabilities
// E.g. Glasses have less room than something worn over the chest.
// Note that the electronic assembly is INSIDE the object that actually gets worn, in a similar way to implants.
/obj/item/device/electronic_assembly/clothing
name = "electronic clothing"
icon_state = "circuitry" // Needs to match the clothing's base icon_state.
desc = "It's a case, for building machines attached to clothing."
w_class = ITEMSIZE_SMALL
max_components = IC_COMPONENTS_BASE
max_complexity = IC_COMPLEXITY_BASE
var/obj/item/clothing/clothing = null
/obj/item/device/electronic_assembly/clothing/ui_host()
return clothing
/obj/item/device/electronic_assembly/clothing/resolve_ui_host()
return clothing
/obj/item/device/electronic_assembly/clothing/update_icon()
..()
clothing.icon_state = icon_state
// We don't need to update the mob sprite since it won't (and shouldn't) actually get changed.
// This is 'small' relative to the size of regular clothing assemblies.
/obj/item/device/electronic_assembly/clothing/small
max_components = IC_COMPONENTS_BASE / 2
max_complexity = IC_COMPLEXITY_BASE / 2
w_class = ITEMSIZE_TINY
// Ditto.
/obj/item/device/electronic_assembly/clothing/large
max_components = IC_COMPONENTS_BASE * 2
max_complexity = IC_COMPLEXITY_BASE * 2
w_class = ITEMSIZE_NORMAL
// This is defined higher up, in /clothing to avoid lots of copypasta.
/obj/item/clothing
var/obj/item/device/electronic_assembly/clothing/IC = null
var/obj/item/integrated_circuit/built_in/action_button/action_circuit = null // This gets pulsed when someone clicks the button on the hud, OR when certain interactions are performed (such as clicking on something with gloves worn)
/obj/item/clothing/emp_act(severity)
if(IC)
IC.emp_act(severity)
..()
/obj/item/clothing/examine(mob/user)
if(IC)
IC.examine(user)
..()
/obj/item/clothing/attackby(obj/item/I, mob/user)
if(IC)
// This needs to be done in a better way...
if(I.iscrowbar() || I.isscrewdriver() || istype(I, /obj/item/integrated_circuit) || istype(I, /obj/item/weapon/cell) || istype(I, /obj/item/device/integrated_electronics))
IC.attackby(I, user)
else
..()
/obj/item/clothing/attack_self(mob/user)
if(IC)
if(IC.opened)
IC.attack_self(user)
else
action_circuit.do_work()
else
..()
// Does most of the repeatative setup.
/obj/item/clothing/proc/setup_integrated_circuit(new_type)
// Set up the internal circuit holder.
IC = new new_type(src)
IC.clothing = src
IC.name = name
// Clothing assemblies can be triggered by clicking on the HUD. This allows that to occur.
action_circuit = new(src.IC)
IC.force_add_circuit(action_circuit)
action_button_name = "Activate [name]"
/obj/item/clothing/Destroy()
if(IC)
IC.clothing = null
action_circuit = null // Will get deleted by qdel-ing the IC assembly.
qdel(IC)
return ..()
// Specific subtypes.
// Jumpsuit.
/obj/item/clothing/under/circuitry
name = "electronic jumpsuit"
desc = "It's a wearable case for electronics. This on is a black jumpsuit with wiring weaved into the fabric."
icon_state = "circuitry"
worn_state = "circuitry"
/obj/item/clothing/under/circuitry/Initialize()
setup_integrated_circuit(/obj/item/device/electronic_assembly/clothing)
return ..()
// Gloves.
/obj/item/clothing/gloves/circuitry
name = "electronic gloves"
desc = "It's a wearable case for electronics. This one is a pair of black gloves, with wires woven into them. A small \
device with a screen is attached to the left glove."
icon_state = "circuitry"
item_state = "circuitry"
/obj/item/clothing/gloves/circuitry/Initialize()
setup_integrated_circuit(/obj/item/device/electronic_assembly/clothing/small)
return ..()
/obj/item/clothing/gloves/circuitry/Touch(var/atom/A, var/mob/user, var/proximity)
if(!A || !proximity)
return 0
if(istype(action_circuit) && action_circuit.check_then_do_work())
action_circuit.set_pin_data(IC_OUTPUT, 1, A)
action_circuit.push_data() // we have to not return 1 so we can still do normal stuff like picking things up, etc.
return 0
// Glasses.
/obj/item/clothing/glasses/circuitry
name = "electronic goggles"
desc = "It's a wearable case for electronics. This one is a pair of goggles, with wiring sticking out. \
Could this augment your vision?" // Sadly it won't, or at least not yet.
icon_state = "circuitry"
item_state = "night" // The on-mob sprite would be identical anyways.
/obj/item/clothing/glasses/circuitry/Initialize()
setup_integrated_circuit(/obj/item/device/electronic_assembly/clothing/small)
return ..()
/obj/item/clothing/glasses/circuitry/Look(var/atom/A, mob/user, var/proximity)
if(!A)
return 0
if(istype(action_circuit) && action_circuit.check_then_do_work())
action_circuit.set_pin_data(IC_OUTPUT, 1, A)
action_circuit.push_data() // we have to not return 1 so we can still do normal stuff like picking things up, etc.
return 0
// Shoes
/obj/item/clothing/shoes/circuitry
name = "electronic boots"
desc = "It's a wearable case for electronics. This one is a pair of boots, with wires attached to a small \
cover."
icon_state = "circuitry"
item_state = "circuitry"
/obj/item/clothing/shoes/circuitry/Initialize()
setup_integrated_circuit(/obj/item/device/electronic_assembly/clothing/small)
return ..()
// Head
/obj/item/clothing/head/circuitry
name = "electronic headwear"
desc = "It's a wearable case for electronics. This one appears to be a very technical-looking piece that \
goes around the collar, with a heads-up-display attached on the right."
icon_state = "circuitry"
item_state = "circuitry"
/obj/item/clothing/head/circuitry/Initialize()
setup_integrated_circuit(/obj/item/device/electronic_assembly/clothing/small)
return ..()
// Ear
/obj/item/clothing/ears/circuitry
name = "electronic earwear"
desc = "It's a wearable case for electronics. This one appears to be a technical-looking headset."
icon = 'icons/obj/clothing/ears.dmi'
icon_state = "circuitry"
item_state = "circuitry"
/obj/item/clothing/ears/circuitry/Initialize()
setup_integrated_circuit(/obj/item/device/electronic_assembly/clothing/small)
return ..()
// Exo-slot
/obj/item/clothing/suit/circuitry
name = "electronic chestpiece"
desc = "It's a wearable case for electronics. This one appears to be a very technical-looking vest, that \
almost looks professionally made, however the wiring popping out betrays that idea."
icon_state = "circuitry"
item_state = "circuitry"
/obj/item/clothing/suit/circuitry/Initialize()
setup_integrated_circuit(/obj/item/device/electronic_assembly/clothing/large)
return ..()

View File

@@ -0,0 +1,255 @@
// Generic subtypes without a lot of special code.
// Small assemblies.
/obj/item/device/electronic_assembly/default
name = "type-a electronic assembly"
/obj/item/device/electronic_assembly/calc
name = "type-b electronic assembly"
icon_state = "setup_small_calc"
desc = "It's a case, for building small electronics with. This one resembles a pocket calculator."
/obj/item/device/electronic_assembly/clam
name = "type-c electronic assembly"
icon_state = "setup_small_clam"
desc = "It's a case, for building small electronics with. This one has a clamshell design."
/obj/item/device/electronic_assembly/simple
name = "type-d electronic assembly"
icon_state = "setup_small_simple"
desc = "It's a case, for building small electronics with. This one has a simple design."
/obj/item/device/electronic_assembly/hook
name = "type-e electronic assembly"
icon_state = "setup_small_hook"
desc = "It's a case, for building small electronics with. This one looks like it has a belt clip, but it's purely decorative."
/obj/item/device/electronic_assembly/pda
name = "type-f electronic assembly"
icon_state = "setup_small_pda"
desc = "It's a case, for building small electronics with. This one resembles a PDA."
// Tiny assemblies.
/obj/item/device/electronic_assembly/tiny
name = "electronic device"
icon_state = "setup_device"
desc = "It's a case, for building tiny-sized electronics with."
w_class = ITEMSIZE_TINY
max_components = IC_COMPONENTS_BASE / 2
max_complexity = IC_COMPLEXITY_BASE / 2
/obj/item/device/electronic_assembly/tiny/default
name = "type-a electronic device"
/obj/item/device/electronic_assembly/tiny/cylinder
name = "type-b electronic device"
icon_state = "setup_device_cylinder"
desc = "It's a case, for building tiny-sized electronics with. This one has a cylindrical design."
/obj/item/device/electronic_assembly/tiny/scanner
name = "type-c electronic device"
icon_state = "setup_device_scanner"
desc = "It's a case, for building tiny-sized electronics with. This one has a scanner-like design."
/obj/item/device/electronic_assembly/tiny/hook
name = "type-d electronic device"
icon_state = "setup_device_hook"
desc = "It's a case, for building tiny-sized electronics with. This one looks like it has a belt clip, but it's purely decorative."
/obj/item/device/electronic_assembly/tiny/box
name = "type-e electronic device"
icon_state = "setup_device_box"
desc = "It's a case, for building tiny-sized electronics with. This one has a boxy design."
// Medium assemblies.
/obj/item/device/electronic_assembly/medium
name = "electronic mechanism"
icon_state = "setup_medium"
desc = "It's a case, for building medium-sized electronics with."
w_class = ITEMSIZE_NORMAL
max_components = IC_COMPONENTS_BASE * 2
max_complexity = IC_COMPLEXITY_BASE * 2
/obj/item/device/electronic_assembly/medium/default
name = "type-a electronic mechanism"
/obj/item/device/electronic_assembly/medium/box
name = "type-b electronic mechanism"
icon_state = "setup_medium_box"
desc = "It's a case, for building medium-sized electronics with. This one has a boxy design."
/obj/item/device/electronic_assembly/medium/clam
name = "type-c electronic mechanism"
icon_state = "setup_medium_clam"
desc = "It's a case, for building medium-sized electronics with. This one has a clamshell design."
/obj/item/device/electronic_assembly/medium/medical
name = "type-d electronic mechanism"
icon_state = "setup_medium_med"
desc = "It's a case, for building medium-sized electronics with. This one resembles some type of medical apparatus."
/obj/item/device/electronic_assembly/medium/gun
name = "type-e electronic mechanism"
icon_state = "setup_medium_gun"
item_state = "circuitgun"
desc = "It's a case, for building medium-sized electronics with. This one resembles a gun, or some type of tool, \
if you're feeling optimistic."
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi',
)
/obj/item/device/electronic_assembly/medium/radio
name = "type-f electronic mechanism"
icon_state = "setup_medium_radio"
desc = "It's a case, for building medium-sized electronics with. This one resembles an old radio."
// Large assemblies.
/obj/item/device/electronic_assembly/large
name = "electronic machine"
icon_state = "setup_large"
desc = "It's a case, for building large electronics with."
w_class = ITEMSIZE_LARGE
max_components = IC_COMPONENTS_BASE * 4
max_complexity = IC_COMPLEXITY_BASE * 4
can_anchor = TRUE
/obj/item/device/electronic_assembly/large/default
name = "type-a electronic machine"
/obj/item/device/electronic_assembly/large/scope
name = "type-b electronic machine"
icon_state = "setup_large_scope"
desc = "It's a case, for building large electronics with. This one resembles an oscilloscope."
/obj/item/device/electronic_assembly/large/terminal
name = "type-c electronic machine"
icon_state = "setup_large_terminal"
desc = "It's a case, for building large electronics with. This one resembles a computer terminal."
/obj/item/device/electronic_assembly/large/arm
name = "type-d electronic machine"
icon_state = "setup_large_arm"
desc = "It's a case, for building large electronics with. This one resembles a robotic arm."
/obj/item/device/electronic_assembly/large/tall
name = "type-e electronic machine"
icon_state = "setup_large_tall"
desc = "It's a case, for building large electronics with. This one has a tall design."
/obj/item/device/electronic_assembly/large/industrial
name = "type-f electronic machine"
icon_state = "setup_large_industrial"
desc = "It's a case, for building large electronics with. This one resembles some kind of industrial machinery."
// Drone assemblies, which can move with the locomotion circuit.
/obj/item/device/electronic_assembly/drone
name = "electronic drone"
icon_state = "setup_drone"
desc = "It's a case, for building mobile electronics with."
w_class = ITEMSIZE_NORMAL
max_components = IC_COMPONENTS_BASE * 1.5
max_complexity = IC_COMPLEXITY_BASE * 1.5
can_anchor = FALSE
/obj/item/device/electronic_assembly/drone/can_move()
return TRUE
/obj/item/device/electronic_assembly/drone/default
name = "type-a electronic drone"
/obj/item/device/electronic_assembly/drone/arms
name = "type-b electronic drone"
icon_state = "setup_drone_arms"
desc = "It's a case, for building mobile electronics with. This one is armed and dangerous."
/obj/item/device/electronic_assembly/drone/secbot
name = "type-c electronic drone"
icon_state = "setup_drone_secbot"
desc = "It's a case, for building mobile electronics with. This one resembles a Securitron."
/obj/item/device/electronic_assembly/drone/medbot
name = "type-d electronic drone"
icon_state = "setup_drone_medbot"
desc = "It's a case, for building mobile electronics with. This one resembles a Medibot."
/obj/item/device/electronic_assembly/drone/genbot
name = "type-e electronic drone"
icon_state = "setup_drone_genbot"
desc = "It's a case, for building mobile electronics with. This one has a generic bot design."
/obj/item/device/electronic_assembly/drone/android
name = "type-f electronic drone"
icon_state = "setup_drone_android"
desc = "It's a case, for building mobile electronics with. This one has a hominoid design."
// Wall mounted assemblies.
/obj/item/device/electronic_assembly/wallmount
name = "wall-mounted electronic assembly"
icon_state = "setup_wallmount_medium"
desc = "It's a case, for building medium-sized electronics with. It has a magnetized \
backing to allow it to stick to walls."
w_class = ITEMSIZE_NORMAL
max_components = IC_COMPONENTS_BASE * 2
max_complexity = IC_COMPLEXITY_BASE * 2
can_anchor = TRUE
/obj/item/device/electronic_assembly/wallmount/proc/mount_assembly(turf/on_wall, mob/user)
if(get_dist(on_wall,user) > 1)
return
var/ndir = get_dir(on_wall, user)
if(!(ndir in cardinal))
return
var/turf/T = get_turf(user)
if(!istype(T, /turf/simulated/floor))
to_chat(user, "<span class='warning'>You cannot place \the [src] on this spot!</span>")
return
playsound(src.loc, 'sound/machines/click.ogg', 75, 1)
user.visible_message("\The [user] attaches \the [src] to the wall.",
"<span class='notice'>You attach \the [src] to the wall.</span>",
"<span class='italics'>You hear clicking.</span>")
if(isrobot(user)) //Robots cannot unequip/drop items, for Safety Reasons.
forceMove(T)
user.drop_item(T)
anchored = TRUE
on_anchored()
pixel_x = DIR2PIXEL_X(ndir)
pixel_y = DIR2PIXEL_Y(ndir)
/obj/item/device/electronic_assembly/wallmount/on_unanchored()
pixel_x = 0
pixel_y = 0
..()
/obj/item/device/electronic_assembly/wallmount/heavy
name = "heavy wall-mounted electronic assembly"
icon_state = "setup_wallmount_large"
desc = "It's a case, for building large electronics with. It has a magnetized backing \
to allow it to stick to walls."
w_class = ITEMSIZE_LARGE
max_components = IC_COMPONENTS_BASE * 4
max_complexity = IC_COMPLEXITY_BASE * 4
/obj/item/device/electronic_assembly/wallmount/light
name = "light wall-mounted electronic assembly"
icon_state = "setup_wallmount_small"
desc = "It's a case, for building small electronics with. It has a magnetized backing \
to allow it to stick to walls."
w_class = ITEMSIZE_SMALL
max_components = IC_COMPONENTS_BASE
max_complexity = IC_COMPLEXITY_BASE
/obj/item/device/electronic_assembly/wallmount/tiny
name = "tiny wall-mounted electronic assembly"
icon_state = "setup_wallmount_tiny"
desc = "It's a case, for building tiny electronics with. It has a magnetized backing \
to allow it to stick to walls."
w_class = ITEMSIZE_TINY
max_components = IC_COMPONENTS_BASE / 2
max_complexity = IC_COMPLEXITY_BASE / 2

View File

@@ -37,7 +37,7 @@
/obj/item/integrated_circuit/proc/activate_pin(pin_number)
var/datum/integrated_io/activate/A = activators[pin_number]
A.push_data()
A.push_data(pin_number)
/datum/integrated_io/proc/get_data()
if(isweakref(data))
@@ -73,3 +73,11 @@
debugger.write_data(pin, usr)
return 1
return 0
/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

@@ -333,17 +333,18 @@ a creative player the means to solve many problems. Circuits are held inside an
return TRUE // Battery has enough.
return FALSE // Not enough power.
/obj/item/integrated_circuit/proc/check_then_do_work(ignore_power = FALSE)
/obj/item/integrated_circuit/proc/check_then_do_work(ignore_power = FALSE, activator_id)
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
return 0
if(power_draw_per_use && !ignore_power)
if(!check_power())
power_fail()
return
return 0
next_use = world.time + cooldown_per_use
do_work()
do_work(activator_id)
return 1
/obj/item/integrated_circuit/proc/do_work()
/obj/item/integrated_circuit/proc/do_work(activator_id)
return
/obj/item/integrated_circuit/proc/disconnect_all()
@@ -353,3 +354,12 @@ a creative player the means to solve many problems. Circuits are held inside an
O.disconnect()
for(var/datum/integrated_io/activate/A in activators)
A.disconnect()
/obj/item/integrated_circuit/proc/attackby_react(var/atom/movable/A,mob/user)
return
/obj/item/integrated_circuit/proc/on_anchored()
return
/obj/item/integrated_circuit/proc/on_unanchored()
return

View File

@@ -121,7 +121,7 @@ list[](
/datum/integrated_io/activate/push_data()
for(var/datum/integrated_io/io in linked)
io.holder.check_then_do_work()
io.holder.check_then_do_work(FALSE)
/datum/integrated_io/proc/pull_data()
for(var/datum/integrated_io/io in linked)

View File

@@ -1,7 +1,7 @@
/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 = 'icons/obj/assemblies/electronic_tools.dmi'
icon_state = "circuit_printer"
w_class = ITEMSIZE_LARGE
var/metal = 0
@@ -154,7 +154,7 @@
/obj/item/weapon/disk/integrated_circuit/upgrade
name = "integrated circuit printer upgrade disk"
desc = "Install this into your integrated circuit printer to enhance it."
icon = 'icons/obj/electronic_assemblies.dmi'
icon = 'icons/obj/assemblies/electronic_tools.dmi'
icon_state = "upgrade_disk"
item_state = "card-id"
w_class = ITEMSIZE_SMALL

View File

@@ -8,7 +8,7 @@
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 = 'icons/obj/assemblies/electronic_tools.dmi'
icon_state = "wirer-wire"
item_state = "wirer"
flags = CONDUCT
@@ -60,7 +60,7 @@
to_chat(user, "<span class='notice'>You prepare to detach a data wire from \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
mode = UNWIRING
update_icon()
if (UNWIRING)
if(io == selected_io)
to_chat(user, "<span class='warning'>You can't wire a pin into each other, so unwiring \the [selected_io.holder] from \
@@ -107,7 +107,7 @@
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 = 'icons/obj/assemblies/electronic_tools.dmi'
icon_state = "debugger"
flags = CONDUCT
w_class = 2
@@ -234,10 +234,56 @@
io1.holder.interact(user) // This is to update the UI.
update_icon()
/obj/item/device/integrated_electronics/detailer
name = "assembly detailer"
desc = "A combination autopainter and flash anodizer designed to give electronic assemblies a colorful, wear-resistant finish."
icon = 'icons/obj/assemblies/electronic_tools.dmi'
icon_state = "detailer"
item_flags = NOBLUDGEON
w_class = ITEMSIZE_SMALL
var/detail_color = COLOR_ASSEMBLY_WHITE
var/list/color_list = list(
"black" = COLOR_ASSEMBLY_BLACK,
"machine gray" = COLOR_ASSEMBLY_BGRAY,
"white" = COLOR_ASSEMBLY_WHITE,
"red" = COLOR_ASSEMBLY_RED,
"orange" = COLOR_ASSEMBLY_ORANGE,
"beige" = COLOR_ASSEMBLY_BEIGE,
"brown" = COLOR_ASSEMBLY_BROWN,
"gold" = COLOR_ASSEMBLY_GOLD,
"yellow" = COLOR_ASSEMBLY_YELLOW,
"gurkha" = COLOR_ASSEMBLY_GURKHA,
"light green" = COLOR_ASSEMBLY_LGREEN,
"green" = COLOR_ASSEMBLY_GREEN,
"light blue" = COLOR_ASSEMBLY_LBLUE,
"blue" = COLOR_ASSEMBLY_BLUE,
"purple" = COLOR_ASSEMBLY_PURPLE,
"hot pink" = COLOR_ASSEMBLY_HOT_PINK
)
/obj/item/device/integrated_electronics/detailer/Initialize()
update_icon()
return ..()
/obj/item/device/integrated_electronics/detailer/update_icon()
cut_overlays()
var/image/detail_overlay = image('icons/obj/assemblies/electronic_tools.dmi', "detailer-color")
detail_overlay.color = detail_color
add_overlay(detail_overlay)
/obj/item/device/integrated_electronics/detailer/attack_self(mob/user)
var/color_choice = input(user, "Select color.", "Assembly Detailer", detail_color) as null|anything in color_list
if(!color_list[color_choice])
return
if(!in_range(src, user))
return
detail_color = color_list[color_choice]
update_icon()
/obj/item/weapon/storage/bag/circuits
name = "circuit kit"
desc = "This kit's essential for any circuitry projects."
icon = 'icons/obj/electronic_assemblies.dmi'
desc = "This kit is essential for any circuitry projects."
icon = 'icons/obj/assemblies/electronic_tools.dmi'
icon_state = "circuit_kit"
w_class = 3
display_contents_with_number = 0

View File

@@ -66,13 +66,18 @@
// For implants.
/obj/item/integrated_circuit/passive/power/metabolic_siphon
name = "metabolic siphon"
desc = "A complicated piece of technology which converts bodily nutriments of a host into electricity."
desc = "A complicated piece of technology which converts bodily nutriments of a host into electricity, or vice versa."
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a biological entity. The entity will feel an increased \
appetite and will need to eat more often due to this. This device will fail if used inside synthetic entities."
appetite and will need to eat more often due to this. This device will fail if used inside synthetic entities.\
If the polarity is reversed, it will instead generate chemical energy with electricity, continuously consuming power from the assembly.\
It is slightly less efficient than generating power."
icon_state = "setup_implant"
complexity = 10
origin_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_BIO = 5)
spawn_flags = IC_SPAWN_RESEARCH
inputs = list("reverse" = IC_PINTYPE_BOOLEAN)
outputs = list("nutrition" = IC_PINTYPE_NUMBER)
var/inefficiency = 1.2
/obj/item/integrated_circuit/passive/power/metabolic_siphon/proc/test_validity(var/mob/living/carbon/human/host)
if(!host || host.isSynthetic() || host.stat == DEAD || host.nutrition <= 10)
@@ -85,22 +90,139 @@
var/obj/item/device/electronic_assembly/implant/implant_assembly = assembly
if(implant_assembly.implant.imp_in)
host = implant_assembly.implant.imp_in
if(test_validity(host))
assembly.give_power(10)
host.adjustNutritionLoss(HUNGER_FACTOR)
if(!get_pin_data(IC_INPUT, 1))
if(test_validity(host))
assembly.give_power(10)
host.adjustNutritionLoss(HUNGER_FACTOR)
else
if(assembly.draw_power(10*inefficiency)) // slightly less efficient the other way around
host.adjustNutritionLoss(-HUNGER_FACTOR)
set_pin_data(IC_OUTPUT, 1, host.nutrition)
/obj/item/integrated_circuit/passive/power/metabolic_siphon/synthetic
name = "internal energy siphon"
desc = "A small circuit designed to be connected to an internal power wire inside a synthetic entity."
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a synthetic entity. The entity need to recharge \
more often due to this. This device will fail if used inside organic entities."
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a synthetic entity. The entity needs to recharge \
more often due to this. If the polarity is reversed, it will instead transfer electricity back to the entity, continuously consuming power from \
the assembly. This device will fail if used inside organic entities."
icon_state = "setup_implant"
complexity = 10
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 4, TECH_DATA = 3)
spawn_flags = IC_SPAWN_RESEARCH
inefficiency = 1 // it's not converting anything, just transferring power
/obj/item/integrated_circuit/passive/power/metabolic_siphon/synthetic/test_validity(var/mob/living/carbon/human/host)
if(!host || !host.isSynthetic() || host.stat == DEAD || host.nutrition <= 10)
return FALSE // This time we don't want a metabolism.
return TRUE
/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."
flags = OPENCONTAINER
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("phoron" = 50000, "slimejelly" = 25000, "fuel" = 15000, "carbon" = 10000, "ethanol"= 10000, "nutriment" =8000, "blood" = 5000)
/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, 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)
for(var/I in fuel)
if((assembly.battery.maxcharge - assembly.battery.charge) / CELLRATE > fuel[I])
if(reagents.remove_reagent(I, 1))
assembly.give_power(fuel[I])
// Interacts with the powernet.
// Now you can make your own power generation (or poor man's powersink).
/obj/item/integrated_circuit/passive/power/powernet
name = "power network interface"
desc = "Gives or takes power from a wire underneath the machine."
icon_state = "powernet"
extended_desc = "The assembly must be anchored, with a wrench, and a wire node must be avaiable directly underneath.<br>\
The first pin determines if power is moved at all. The second pin, if true, will draw from the powernet to charge the assembly's \
cell, otherwise it will give power from the cell to the powernet."
complexity = 20
inputs = list(
"active" = IC_PINTYPE_BOOLEAN,
"draw power" = IC_PINTYPE_BOOLEAN
)
outputs = list(
"power in grid" = IC_PINTYPE_NUMBER,
"surplus power" = IC_PINTYPE_NUMBER,
"load" = IC_PINTYPE_NUMBER
)
activators = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 2)
var/obj/machinery/power/circuit_io/IO = null // Dummy power machine to move energy in/out without a bunch of code duplication.
var/throughput = 10000 // Give/take up to 10kW.
/obj/item/integrated_circuit/passive/power/powernet/Initialize()
IO = new(src)
return ..()
/obj/item/integrated_circuit/passive/power/powernet/Destroy()
qdel(IO)
return ..()
/obj/item/integrated_circuit/passive/power/powernet/on_anchored()
IO.connect_to_network()
/obj/item/integrated_circuit/passive/power/powernet/on_unanchored()
IO.disconnect_from_network()
/obj/item/integrated_circuit/passive/power/powernet/make_energy()
if(assembly && assembly.anchored && assembly.battery)
var/should_act = get_pin_data(IC_INPUT, 1) // Even if this is false, we still need to update the output pins with powernet information.
var/drawing = get_pin_data(IC_INPUT, 2)
if(should_act) // We're gonna give or take from the net.
if(drawing)
var/to_transfer = min(throughput, (assembly.battery.maxcharge - assembly.battery.charge) / CELLRATE) // So we don't need to draw 10kW if the cell needs much less.
var/amount = IO.draw_power(to_transfer)
assembly.give_power(amount)
else
var/amount = assembly.draw_power(throughput)
IO.add_avail(amount)
set_pin_data(IC_OUTPUT, 1, IO.avail())
set_pin_data(IC_OUTPUT, 2, IO.surplus())
set_pin_data(IC_OUTPUT, 3, -IO.surplus()-IO.avail()) // we don't have a viewload() proc on machines and i'm lazy
// Internal power machine for interacting with the powernet.
// It needs a bit of special code since base /machinery/power assumes loc will be a tile.
/obj/machinery/power/circuit_io
name = "embedded electrical I/O"
/obj/machinery/power/circuit_io/connect_to_network()
var/turf/T = get_turf(src)
if(!istype(T))
return FALSE
var/obj/structure/cable/C = T.get_cable_node()
if(!C?.powernet)
return FALSE
C.powernet.add_machine(src)
return TRUE

View File

@@ -1,7 +1,7 @@
/obj/item/integrated_circuit/built_in
name = "integrated circuit"
desc = "It's a tiny chip! This one doesn't seem to do much, however."
icon = 'icons/obj/electronic_assemblies.dmi'
icon = 'icons/obj/assemblies/electronic_components.dmi'
icon_state = "template"
size = -1
w_class = ITEMSIZE_TINY
@@ -26,3 +26,15 @@
if(istype(assembly, /obj/item/device/electronic_assembly/device))
var/obj/item/device/electronic_assembly/device/device = assembly
device.holder.pulse()
// Triggered when clothing assembly's hud button is clicked, used in-hand, or when another clothing-specific interaction occurs (like touching something with gloves on).
/obj/item/integrated_circuit/built_in/action_button
name = "external trigger circuit"
desc = "A built in chip that outputs a pulse when an external control event occurs. It also provides additional data depending on the nature of the event and device."
extended_desc = "This outputs a pulse if the assembly's HUD button is clicked while the assembly is closed."
complexity = 0
activators = list("on activation" = IC_PINTYPE_PULSE_OUT)
outputs = list("output" = IC_PINTYPE_ANY)
/obj/item/integrated_circuit/built_in/action_button/do_work()
activate_pin(1)

View File

@@ -168,6 +168,52 @@
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"
@@ -236,3 +282,75 @@
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/stringlength
name = "len circuit"
desc = "This circuit will return the number of characters in a string."
complexity = 1
inputs = list(
"string" = IC_PINTYPE_STRING
)
outputs = list(
"length" = IC_PINTYPE_NUMBER
)
activators = list("get length" = IC_PINTYPE_PULSE_IN, "on acquisition" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/stringlength/do_work()
set_pin_data(IC_OUTPUT, 1, length(get_pin_data(IC_INPUT, 1)))
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/hsv2hex
name = "hsv to hexadecimal converter"
desc = "This circuit can convert a HSV (Hue, Saturation, and Value) color to a Hexadecimal RGB color."
extended_desc = "The first pin controls tint (0-359), the second pin controls how intense the tint is (0-255), \
and the third controls how bright the tint is (0 for black, 127 for normal, 255 for white)."
icon_state = "hsv-hex"
inputs = list(
"hue" = IC_PINTYPE_NUMBER,
"saturation" = IC_PINTYPE_NUMBER,
"value" = IC_PINTYPE_NUMBER
)
outputs = list("hexadecimal rgb" = IC_PINTYPE_COLOR)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/hsv2hex/do_work()
var/result = null
pull_data()
var/hue = get_pin_data(IC_INPUT, 1)
var/saturation = get_pin_data(IC_INPUT, 2)
var/value = get_pin_data(IC_INPUT, 3)
if(isnum(hue) && isnum(saturation) && isnum(value))
result = HSVtoRGB(hsv(AngleToHue(hue),saturation,value))
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/rgb2hex
name = "rgb to hexadecimal converter"
desc = "This circuit can convert a RGB (Red, Green, Blue) color to a Hexadecimal RGB color."
extended_desc = "The first pin controls red amount, the second pin controls green amount, and the third controls blue amount. They all go from 0-255."
icon_state = "rgb-hex"
inputs = list(
"red" = IC_PINTYPE_NUMBER,
"green" = IC_PINTYPE_NUMBER,
"blue" = IC_PINTYPE_NUMBER
)
outputs = list("hexadecimal rgb" = IC_PINTYPE_COLOR)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/rgb2hex/do_work()
var/result = null
pull_data()
var/red = get_pin_data(IC_INPUT, 1)
var/green = get_pin_data(IC_INPUT, 2)
var/blue = get_pin_data(IC_INPUT, 3)
if(isnum(red) && isnum(green) && isnum(blue))
result = rgb(red, green, blue)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)

View File

@@ -76,6 +76,25 @@
push_data()
activate_pin(1)
/obj/item/integrated_circuit/input/colorpad
name = "color pad"
desc = "This small color pad allows someone to input a hexadecimal color into the system."
icon_state = "colorpad"
complexity = 2
can_be_asked_input = 1
inputs = list()
outputs = list("color entered" = IC_PINTYPE_COLOR)
activators = list("on entered" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/input/colorpad/ask_for_input(mob/user)
var/new_color = input(user, "Enter a color, please.", "Color pad", get_pin_data(IC_OUTPUT, 1)) as color|null
if(new_color && CanInteract(user, physical_state))
set_pin_data(IC_OUTPUT, 1, new_color)
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."
@@ -145,6 +164,59 @@
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("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,
"density" = IC_PINTYPE_BOOLEAN,
"opacity" = IC_PINTYPE_BOOLEAN,
"occupied turf" = IC_PINTYPE_REF
)
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)
set_pin_data(IC_OUTPUT, 8, H.density)
set_pin_data(IC_OUTPUT, 9, H.opacity)
set_pin_data(IC_OUTPUT, 10, get_turf(H))
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 \
@@ -201,6 +273,50 @@
set_pin_data(IC_OUTPUT, 1, pick(valid_things))
push_data()
/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 of up to 7 meters."
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 to given sample. If this pin is a string, the locator will search for 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" = IC_PINTYPE_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, 7)
radius = rad
/obj/item/integrated_circuit/input/advanced_locator/do_work()
set_pin_data(IC_OUTPUT, 1, null)
var/turf/T = get_turf(src)
var/list/nearby_things = view(radius, T)
var/list/valid_things = list()
var/I = get_pin_data(IC_INPUT, 1)
if(isweakref(I))
var/datum/weakref/WR = I
var/atom/A = WR.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))
var/DT = I
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)
set_pin_data(IC_OUTPUT, 1, pick(valid_things))
activate_pin(2)
else
activate_pin(3)
push_data()
/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."
@@ -381,7 +497,9 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A)
/obj/item/integrated_circuit/input/sensor/proc/sense(var/atom/A)
if(!src.Adjacent(A))
return FALSE
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
if(istype(A, /obj/item/weapon/storage))
@@ -413,6 +531,85 @@
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
power_draw_per_use = 60
/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 = ITEMSIZE_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, 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 watch the battery level of any device in range."
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 = ITEMSIZE_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/weapon/cell/cell = null
if(istype(AM, /obj/item/weapon/cell)) // Is this already a cell?
cell = AM
else // If not, maybe there's a cell inside it?
for(var/obj/item/weapon/cell/C in AM.contents)
if(C) // Find one cell to charge.
cell = C
break
if(cell)
var/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)
/obj/item/integrated_circuit/input/atmo_scanner/do_work()
var/turf/T = get_turf(src)
if(!istype(T)) //Invalid input
@@ -553,4 +750,246 @@
/obj/item/integrated_circuit/input/gas_sensor/phoron
gas_name = "phoron"
gas_display_name = "phoron"
gas_display_name = "phoron"
/obj/item/integrated_circuit/input/turfpoint
name = "tile pointer"
desc = "This circuit will get a tile ref with the provided absolute coordinates."
extended_desc = "If the machine cannot see the target, it will not be able to calculate the correct direction.\
This circuit only works while inside an assembly."
icon_state = "numberpad"
complexity = 5
inputs = list("X" = IC_PINTYPE_NUMBER,"Y" = IC_PINTYPE_NUMBER)
outputs = list("tile" = IC_PINTYPE_REF)
activators = list("calculate dir" = IC_PINTYPE_PULSE_IN, "on calculated" = IC_PINTYPE_PULSE_OUT,"not calculated" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 40
/obj/item/integrated_circuit/input/turfpoint/do_work()
if(!assembly)
activate_pin(3)
return
var/turf/T = get_turf(assembly)
var/target_x = Clamp(get_pin_data(IC_INPUT, 1), 0, world.maxx)
var/target_y = Clamp(get_pin_data(IC_INPUT, 2), 0, world.maxy)
var/turf/A = locate(target_x, target_y, T.z)
set_pin_data(IC_OUTPUT, 1, null)
if(!A || !(A in view(T)))
activate_pin(3)
return
else
set_pin_data(IC_OUTPUT, 1, A)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/turfscan
name = "tile analyzer"
desc = "This circuit can analyze the contents of the scanned turf, and can read letters on the turf."
icon_state = "video_camera"
complexity = 5
inputs = list(
"target" = IC_PINTYPE_REF
)
outputs = list(
"located ref" = IC_PINTYPE_LIST,
"Written letters" = IC_PINTYPE_STRING,
"area" = IC_PINTYPE_STRING
)
activators = list(
"scan" = IC_PINTYPE_PULSE_IN,
"on scanned" = IC_PINTYPE_PULSE_OUT,
"not scanned" = IC_PINTYPE_PULSE_OUT
)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 40
cooldown_per_use = 10
/obj/item/integrated_circuit/input/turfscan/do_work()
var/turf/scanned_turf = get_pin_data_as_type(IC_INPUT, 1, /turf)
var/turf/circuit_turf = get_turf(src)
var/area_name = get_area_name(scanned_turf)
if(!istype(scanned_turf)) //Invalid input
activate_pin(3)
return
if(scanned_turf in view(circuit_turf)) // This is a camera. It can't examine things that it can't see.
var/list/turf_contents = new()
for(var/obj/U in scanned_turf)
turf_contents += WEAKREF(U)
for(var/mob/U in scanned_turf)
turf_contents += WEAKREF(U)
set_pin_data(IC_OUTPUT, 1, turf_contents)
set_pin_data(IC_OUTPUT, 3, area_name)
var/list/St = new()
for(var/obj/effect/decal/cleanable/crayon/I in scanned_turf)
St.Add(I.icon_state)
if(St.len)
set_pin_data(IC_OUTPUT, 2, jointext(St, ",", 1, 0))
push_data()
activate_pin(2)
else
activate_pin(3)
/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 target to act upon. This type locates something \
that is standing in given radius of up to 8 meters. Output is non-associative. Input will only consider keys if associative."
extended_desc = "The first pin requires a list of the kinds of objects that you want the locator to acquire. It will locate nearby objects by name and description, \
and will then provide a list of all found objects which are similar. \
The second pin is a radius."
inputs = list("desired type ref list" = 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
cooldown_per_use = 10
/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()
set_pin_data(IC_OUTPUT, 1, null)
var/list/input_list = list()
input_list = get_pin_data(IC_INPUT, 1)
if(length(input_list)) //if there is no input don't do anything.
var/turf/T = get_turf(src)
var/list/nearby_things = view(radius,T)
var/list/valid_things = list()
for(var/item in input_list)
if(!isnull(item) && !isnum(item))
if(istext(item))
for(var/i in nearby_things)
var/atom/thing = i
if(ismob(thing) && !isliving(thing))
continue
if(findtext(addtext(thing.name," ",thing.desc), item, 1, 0) )
valid_things.Add(WEAKREF(thing))
else
var/atom/A = item
var/desired_type = A.type
for(var/i in nearby_things)
var/atom/thing = i
if(thing.type != desired_type)
continue
if(ismob(thing) && !isliving(thing))
continue
valid_things.Add(WEAKREF(thing))
if(valid_things.len)
set_pin_data(IC_OUTPUT, 1, valid_things)
activate_pin(2)
else
activate_pin(3)
else
activate_pin(3)
push_data()
/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 the target."
extended_desc = "If the '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/sensor/ranged/sense(atom/A, mob/user)
if(!user || (!istype(A) && !isliving(A)))
return FALSE
if(user.client)
if(!(A in view(user.client)))
return FALSE
else
if(!(A in view(user)))
return FALSE
if(!check_then_do_work())
return FALSE
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
if(istype(A, /obj/item/weapon/storage))
return FALSE
set_pin_data(IC_OUTPUT, 1, A)
push_data()
to_chat(user, "<span class='notice'>You scan [A] with [assembly].</span>")
activate_pin(1)
return TRUE
/obj/item/integrated_circuit/input/obj_scanner
name = "scanner"
desc = "Scans and obtains a reference for any objects you use on the assembly."
extended_desc = "If the 'put down' pin is set to true, the assembly will take the scanned object from your hands to its location. \
Useful for interaction with the grabber. The scanner only works using the help intent."
icon_state = "recorder"
complexity = 4
inputs = list("put down" = 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 = 20
/obj/item/integrated_circuit/input/obj_scanner/attackby_react(var/atom/A,var/mob/user,intent)
if(intent!=I_HELP)
return FALSE
if(!check_then_do_work())
return FALSE
var/pu = get_pin_data(IC_INPUT, 1)
if(pu)
user.drop_from_inventory(A)
set_pin_data(IC_OUTPUT, 1, A)
push_data()
to_chat(user, "<span class='notice'>You let [assembly] scan [A].</span>")
activate_pin(1)
return TRUE
/obj/item/integrated_circuit/input/card_reader
name = "ID card reader" //To differentiate it from the data card reader
desc = "A circuit that can read the registred name, assignment, and PassKey string from an ID card."
icon_state = "card_reader"
complexity = 4
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
inputs = list(
"enable credential cache" = IC_PINTYPE_BOOLEAN
)
outputs = list(
"registered name" = IC_PINTYPE_STRING,
"assignment" = IC_PINTYPE_STRING,
"passkey" = IC_PINTYPE_LIST
)
activators = list(
"on read" = IC_PINTYPE_PULSE_OUT
)
/obj/item/integrated_circuit/input/card_reader/attackby_react(obj/item/I, mob/living/user, intent)
var/obj/item/weapon/card/id/card = I.GetID()
var/list/access = I.GetAccess()
if(!access)
return
if(get_pin_data(IC_INPUT, 1))
assembly?.access_card.access |= access
if(card) // An ID card.
set_pin_data(IC_OUTPUT, 1, card.registered_name)
set_pin_data(IC_OUTPUT, 2, card.assignment)
else if(length(access)) // A non-card object that has access levels.
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
else
return FALSE
set_pin_data(IC_OUTPUT, 3, access)
push_data()
activate_pin(1)
return TRUE

View File

@@ -50,6 +50,116 @@
push_data()
activate_pin(2)
/obj/item/integrated_circuit/list/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/list/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/list/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/list/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/list/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/list/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)
var/j = 0
for(var/I in input_list)
j = j + 1
if(j != index)
red_list.Add(I)
set_pin_data(IC_OUTPUT, 1, red_list)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/list/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/list/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)
input_list[index] = item
set_pin_data(IC_OUTPUT, 1, input_list)
push_data()
activate_pin(2)
obj/item/integrated_circuit/list/len
name = "len circuit"
desc = "This circuit will give length 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/list/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/list/jointext
name = "join text circuit"
desc = "This circuit will add all elements of a list into one string, seperated by a character."

View File

@@ -77,6 +77,84 @@
/obj/item/integrated_circuit/logic/binary/equals/do_compare(A, B)
return A == B
/obj/item/integrated_circuit/logic/binary/jklatch
name = "JK latch"
desc = "This gate is a synchronized JK latch."
icon_state = "jklatch"
inputs = list("J" = IC_PINTYPE_ANY,"K" = IC_PINTYPE_ANY)
outputs = list("Q" = IC_PINTYPE_BOOLEAN,"!Q" = IC_PINTYPE_BOOLEAN)
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()
if(get_pin_data(IC_INPUT, 1))
if(get_pin_data(IC_INPUT, 2))
lstate=!lstate
else
lstate = TRUE
else
if(get_pin_data(IC_INPUT, 2))
lstate=FALSE
set_pin_data(IC_OUTPUT, 1, lstate ? TRUE : FALSE)
set_pin_data(IC_OUTPUT, 2, !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 a synchronized RS latch. If both R and S are true, its state will not change."
icon_state = "sr_nor"
inputs = list("S" = IC_PINTYPE_ANY,"R" = IC_PINTYPE_ANY)
outputs = list("Q" = IC_PINTYPE_BOOLEAN,"!Q" = IC_PINTYPE_BOOLEAN)
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()
if(get_pin_data(IC_INPUT, 1))
if(!get_pin_data(IC_INPUT, 2))
lstate=TRUE
else
if(get_pin_data(IC_INPUT, 2))
lstate=FALSE
set_pin_data(IC_OUTPUT, 1, lstate ? TRUE : FALSE)
set_pin_data(IC_OUTPUT, 2, !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 a synchronized gated D latch."
icon_state = "gated_d"
inputs = list("D" = IC_PINTYPE_ANY,"E" = IC_PINTYPE_ANY)
outputs = list("Q" = IC_PINTYPE_BOOLEAN,"!Q" = IC_PINTYPE_BOOLEAN)
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()
if(get_pin_data(IC_INPUT, 2))
if(get_pin_data(IC_INPUT, 1))
lstate=TRUE
else
lstate=FALSE
set_pin_data(IC_OUTPUT, 1, lstate ? TRUE : FALSE)
set_pin_data(IC_OUTPUT, 2, !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."

View File

@@ -111,10 +111,10 @@
/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."
desc = "This circuit comes with the ability to attach most types of grenades and 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!"
Beware: Once primed, there is no aborting the process!"
icon_state = "grenade"
complexity = 30
size = 2
@@ -185,3 +185,154 @@
pre_attached_grenade_type = /obj/item/weapon/grenade/frag
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 10)
spawn_flags = null // Used for world initializing, see the #defines above.
/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 to shock. It can shock a target on adjacent tiles. \
Severity determines hardness of shock and its power consumption. It accepts values between 0 and 60."
w_class = ITEMSIZE_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)*4
/obj/item/integrated_circuit/manipulation/shocker/do_work()
..()
var/turf/T = get_turf(src)
var/mob/living/M = get_pin_data_as_type(IC_INPUT, 1, /mob/living)
if(!istype(M)) //Invalid input
return
if(!M.Adjacent(T))
return //Can't reach
to_chat(M, "<span class='danger'>You feel a sharp shock!</span>")
spark(get_turf(M), 3, 1)
M.stun_effect_act(0, Clamp(get_pin_data(IC_INPUT, 2),0,60), null)
/obj/item/integrated_circuit/manipulation/grabber
name = "grabber"
desc = "A circuit with its 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 = ITEMSIZE_TINY
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)
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/grabber/do_work()
var/turf/T = get_turf(src)
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
var/mode = get_pin_data(IC_INPUT, 2)
if(mode == 1)
if(AM.Adjacent(T))
if(contents.len < 10)
if(istype(AM,/obj/item))
var/obj/item/A = AM
if(A.w_class < ITEMSIZE_NORMAL)
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)
set_pin_data(IC_OUTPUT, 1, contents[1])
set_pin_data(IC_OUTPUT, 2, contents[contents.len])
set_pin_data(IC_OUTPUT, 3, src.contents.len)
push_data()
activate_pin(2)
/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 = ITEMSIZE_TINY
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)
return
if(A.w_class>ITEMSIZE_NORMAL)
return
var/turf/T = get_turf(src.assembly)
var/turf/TP = get_turf(A)
if(!(TP.Adjacent(T)))
return
if(src.assembly)
if(isnum(target_x.data))
target_x.data = round(target_x.data)
if(isnum(target_y.data))
target_y.data = round(target_y.data)
if(target_x.data == 0 && target_y.data == 0)
return
// We need to do this in order to enable relative coordinates, as locate() only works for absolute coordinates.
var/i
if(target_x.data > 0)
i = abs(target_x.data)
while(i > 0)
T = get_step(T, EAST)
i--
else
i = abs(target_x.data)
while(i > 0)
T = get_step(T, WEST)
i--
i = 0
if(target_y.data > 0)
i = abs(target_y.data)
while(i > 0)
T = get_step(T, NORTH)
i--
else if(target_y.data < 0)
i = abs(target_y.data)
while(i > 0)
T = get_step(T, SOUTH)
i--
if(!T)
return
A.forceMove(get_turf(src))
A.throw_at(T, round(Clamp(sqrt(target_x.data*target_x.data+target_y.data*target_y.data),0,8),1), 3, assembly)

View File

@@ -18,13 +18,22 @@
complexity = 20
cooldown_per_use = 30 SECONDS
inputs = list()
outputs = list()
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF)
activators = list("create smoke" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3)
volume = 100
power_draw_per_use = 20
/obj/item/integrated_circuit/reagent/smoke/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, src)
push_data()
..()
/obj/item/integrated_circuit/reagent/smoke/do_work()
playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
var/datum/effect/effect/system/smoke_spread/chem/smoke_system = new()
@@ -45,40 +54,125 @@
cooldown_per_use = 6 SECONDS
inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER)
inputs_default = list("2" = 5)
outputs = list()
activators = list("inject" = IC_PINTYPE_PULSE_IN)
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/direc = 1
var/transfer_amount = 10
/obj/item/integrated_circuit/reagent/injector/proc/inject_amount()
var/amount = get_pin_data(IC_INPUT, 2)
if(isnum(amount))
return Clamp(amount, 0, 30)
/obj/item/integrated_circuit/reagent/injector/interact(mob/user)
set_pin_data(IC_OUTPUT, 2, 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
direc = 0
else
direc = 1
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, volume)
transfer_amount = new_amount
/obj/item/integrated_circuit/reagent/injector/do_work()
set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(!istype(AM)) //Invalid input
activate_pin(3)
return
if(!reagents.total_volume) // Empty
return
if(AM.can_be_injected_by(src))
if(isliving(AM))
var/mob/living/L = AM
var/turf/T = get_turf(AM)
T.visible_message("<span class='warning'>[src] is trying to inject [L]!</span>")
sleep(3 SECONDS)
if(!L.can_be_injected_by(src))
if(direc == 1)
if(!istype(AM)) //Invalid input
activate_pin(3)
return
if(!reagents.total_volume) // Empty
activate_pin(3)
return
if(AM.can_be_injected_by(src))
if(isliving(AM))
var/mob/living/L = AM
var/turf/T = get_turf(AM)
T.visible_message("<span class='warning'>[src] is trying to inject [L]!</span>")
sleep(3 SECONDS)
if(!L.can_be_injected_by(src))
activate_pin(3)
return
var/contained = reagents.get_reagents()
var/trans = reagents.trans_to_mob(L, transfer_amount, CHEM_BLOOD)
message_admins("[src] injected \the [L] with [trans]u of [contained].")
to_chat(AM, "<span class='notice'>You feel a tiny prick!</span>")
visible_message("<span class='warning'>[src] injects [L]!</span>")
else
reagents.trans_to(AM, transfer_amount)
else
if(reagents.total_volume >= volume) // Full
activate_pin(3)
return
var/obj/target = AM
if(!target.reagents)
activate_pin(3)
return
var/turf/TS = get_turf(src)
var/turf/TT = get_turf(AM)
if(!TS.Adjacent(TT))
activate_pin(3)
return
var/tramount = Clamp(min(transfer_amount, reagents.maximum_volume - reagents.total_volume), 0, reagents.maximum_volume)
if(ismob(target))//Blood!
if(istype(target, /mob/living/carbon))
var/mob/living/carbon/T = target
if(!T.dna)
if(T.reagents.trans_to_obj(src, tramount))
activate_pin(2)
else
activate_pin(3)
return
if(NOCLONE in T.mutations) //target done been et, no more blood in him
if(T.reagents.trans_to_obj(src, tramount))
activate_pin(2)
else
activate_pin(3)
return
return
var/datum/reagent/B
if(istype(T, /mob/living/carbon/human))
var/mob/living/carbon/human/H = T
if(H.species && !H.has_organ("heart"))
H.reagents.trans_to_obj(src, tramount)
else
B = T.take_blood(src, tramount)
else
B = T.take_blood(src,tramount)
if (B)
reagents.reagent_list |= B
reagents.update_total()
on_reagent_change()
reagents.handle_reactions()
B = null
visible_message( "<span class='notice'>Machine takes a blood sample from [target].</span>")
else
activate_pin(3)
return
var/contained = reagents.get_reagents()
var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD)
message_admins("[src] injected \the [L] with [trans]u of [contained].")
to_chat(AM, "<span class='notice'>You feel a tiny prick!</span>")
visible_message("<span class='warning'>[src] injects [L]!</span>")
else
reagents.trans_to(AM, inject_amount())
else //if not mob
if(!target.reagents.total_volume)
visible_message( "<span class='notice'>[target] is empty.</span>")
activate_pin(3)
return
target.reagents.trans_to_obj(src, tramount)
activate_pin(2)
/obj/item/integrated_circuit/reagent/pump
name = "reagent pump"
@@ -103,11 +197,17 @@
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/direc = 1
power_draw_per_use = 10
/obj/item/integrated_circuit/reagent/pump/on_data_written()
var/new_amount = get_pin_data(IC_INPUT, 3)
if(!isnull(new_amount))
if(new_amount < 0)
new_amount = -new_amount
direc = 0
else
direc = 1
if(isnum(new_amount))
new_amount = Clamp(new_amount, 0, 50)
transfer_amount = new_amount
@@ -130,9 +230,14 @@
return
if(!source.is_open_container() || !target.is_open_container())
return
if(!target.reagents.get_free_space())
return
source.reagents.trans_to(target, transfer_amount)
if(direc)
if(!target.reagents.get_free_space())
return
source.reagents.trans_to(target, transfer_amount)
else
if(!source.reagents.get_free_space())
return
target.reagents.trans_to(source, transfer_amount)
activate_pin(2)
/obj/item/integrated_circuit/reagent/storage
@@ -143,7 +248,7 @@
flags = OPENCONTAINER
complexity = 4
inputs = list()
outputs = list("volume used" = IC_PINTYPE_NUMBER)
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)
@@ -153,6 +258,11 @@
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
push_data()
/obj/item/integrated_circuit/reagent/storage/interact(mob/user)
set_pin_data(IC_OUTPUT, 2, src)
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."
@@ -162,3 +272,92 @@
complexity = 8
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/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."
flags = OPENCONTAINER
complexity = 16
volume = 180
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_MATERIAL = 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, as well as analyse their taste."
icon_state = "reagent_scan"
extended_desc = "Mostly useful for reagent filters."
flags = OPENCONTAINER
complexity = 8
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF,"list of reagents" = IC_PINTYPE_LIST,"taste" = IC_PINTYPE_STRING)
activators = list("scan" = IC_PINTYPE_PULSE_IN)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
/obj/item/integrated_circuit/reagent/storage/scan/do_work()
var/list/cont = list()
for(var/datum/reagent/RE in reagents.reagent_list)
cont += RE.id
set_pin_data(IC_OUTPUT, 3, cont)
set_pin_data(IC_OUTPUT, 4, reagents.generate_taste_message(src))
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."
flags = OPENCONTAINER
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/direc = 1
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
direc = 0
else
direc = 1
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.get_free_space())
return
for(var/datum/reagent/G in source.reagents.reagent_list)
if (!direc)
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

@@ -4,33 +4,70 @@
/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 \
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)
complexity = 5
inputs = list("target" = IC_PINTYPE_REF,"ignore obstacles" = IC_PINTYPE_BOOLEAN)
outputs = list("dir" = IC_PINTYPE_DIR)
activators = list("calculate dir" = IC_PINTYPE_PULSE_IN, "on calculated" = IC_PINTYPE_PULSE_OUT)
activators = list("calculate dir" = IC_PINTYPE_PULSE_IN, "on calculated" = IC_PINTYPE_PULSE_OUT,"not 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))
push_data()
return
activate_pin(3)
var/atom/A = I.data.resolve()
if(!A)
push_data()
activate_pin(3)
return
if(!(A in view(get_turf(src))))
push_data()
activate_pin(3)
return // Can't see the target.
var/desired_dir = get_dir(get_turf(src), A)
set_pin_data(IC_OUTPUT, 1, desired_dir)
if(get_pin_data(IC_INPUT, 2))
set_pin_data(IC_OUTPUT, 1, get_dir(get_turf(src), get_turf(A)))
else
set_pin_data(IC_OUTPUT, 1, get_dir(get_turf(src), get_step_towards2(get_turf(src),A)))
push_data()
activate_pin(2)
/obj/item/integrated_circuit/smart/coord_basic_pathfinder
name = "coordinate pathfinder"
desc = "This complex circuit is able to determine what direction a given target is."
extended_desc = "This circuit uses absolute coordinates to determine where the target is. If the machine \
cannot see the target, it will not be able to calculate the correct direction. \
This circuit will only work while inside an assembly."
icon_state = "numberpad"
complexity = 5
inputs = list("X" = IC_PINTYPE_NUMBER,"Y" = IC_PINTYPE_NUMBER,"ignore obstacles" = IC_PINTYPE_BOOLEAN)
outputs = list( "dir" = IC_PINTYPE_DIR,
"distance" = IC_PINTYPE_NUMBER
)
activators = list("calculate dir" = IC_PINTYPE_PULSE_IN, "on calculated" = IC_PINTYPE_PULSE_OUT,"not calculated" = IC_PINTYPE_PULSE_OUT)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 40
/obj/item/integrated_circuit/smart/coord_basic_pathfinder/do_work()
if(!assembly)
activate_pin(3)
return
var/turf/T = get_turf(assembly)
var/target_x = Clamp(get_pin_data(IC_INPUT, 1), 0, world.maxx)
var/target_y = Clamp(get_pin_data(IC_INPUT, 2), 0, world.maxy)
var/turf/A = locate(target_x, target_y, T.z)
set_pin_data(IC_OUTPUT, 1, null)
if(!A||A==T)
activate_pin(3)
return
if(get_pin_data(IC_INPUT, 2))
set_pin_data(IC_OUTPUT, 1, get_dir(get_turf(src), get_turf(A)))
else
set_pin_data(IC_OUTPUT, 1, get_dir(get_turf(src), get_step_towards2(get_turf(src),A)))
set_pin_data(IC_OUTPUT, 2, sqrt((A.x-T.x)*(A.x-T.x)+ (A.y-T.y)*(A.y-T.y)))
push_data()
activate_pin(2)