mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-23 13:05:44 +01:00
Port Integrated Electronics from Polaris (#3371)
Ports Polaris' integrated electronics system, whichallows for Roboticists & Electricians/Engineers to build custom devices and machines for a variety of purposes.
This commit is contained in:
@@ -190,6 +190,7 @@
|
||||
#include "code\controllers\subsystems\processing\calamity.dm"
|
||||
#include "code\controllers\subsystems\processing\disease.dm"
|
||||
#include "code\controllers\subsystems\processing\disposals.dm"
|
||||
#include "code\controllers\subsystems\processing\electronics.dm"
|
||||
#include "code\controllers\subsystems\processing\fast_process.dm"
|
||||
#include "code\controllers\subsystems\processing\modifiers.dm"
|
||||
#include "code\controllers\subsystems\processing\nanoui.dm"
|
||||
@@ -830,6 +831,7 @@
|
||||
#include "code\game\objects\items\weapons\implants\implant.dm"
|
||||
#include "code\game\objects\items\weapons\implants\implantcase.dm"
|
||||
#include "code\game\objects\items\weapons\implants\implantchair.dm"
|
||||
#include "code\game\objects\items\weapons\implants\implantcircuits.dm"
|
||||
#include "code\game\objects\items\weapons\implants\implanter.dm"
|
||||
#include "code\game\objects\items\weapons\implants\implantfreedom.dm"
|
||||
#include "code\game\objects\items\weapons\implants\implantpad.dm"
|
||||
@@ -1344,6 +1346,40 @@
|
||||
#include "code\modules\hydroponics\trays\tray_soil.dm"
|
||||
#include "code\modules\hydroponics\trays\tray_tools.dm"
|
||||
#include "code\modules\hydroponics\trays\tray_update_icons.dm"
|
||||
#include "code\modules\integrated_electronics\_defines.dm"
|
||||
#include "code\modules\integrated_electronics\core\assemblies.dm"
|
||||
#include "code\modules\integrated_electronics\core\device.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\printer.dm"
|
||||
#include "code\modules\integrated_electronics\core\tools.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\built_in.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\integrated_electronics\~defines\~defines.dm"
|
||||
#include "code\modules\intern\intern.dm"
|
||||
#include "code\modules\item_worth\_helpers.dm"
|
||||
#include "code\modules\item_worth\item_worth.dm"
|
||||
@@ -1931,6 +1967,7 @@
|
||||
#include "code\modules\reagents\Chemistry-Machinery.dm"
|
||||
#include "code\modules\reagents\Chemistry-Metabolism.dm"
|
||||
#include "code\modules\reagents\Chemistry-Readme.dm"
|
||||
#include "code\modules\reagents\Chemistry-Reagents-Helpers.dm"
|
||||
#include "code\modules\reagents\Chemistry-Reagents.dm"
|
||||
#include "code\modules\reagents\Chemistry-Recipes.dm"
|
||||
#include "code\modules\reagents\reagent_containers.dm"
|
||||
|
||||
@@ -78,3 +78,5 @@
|
||||
#define CanInteract(user, state) (CanUseTopic(user, state) == STATUS_INTERACTIVE)
|
||||
|
||||
#define isopenturf(target) istype(target, /turf/simulated/open)
|
||||
#define isweakref(target) istype(target, /datum/weakref)
|
||||
#define isdatum(target) istype(target, /datum)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Math constants.
|
||||
#define M_PI 3.14159265
|
||||
#define M_PI 3.14159
|
||||
|
||||
#define R_IDEAL_GAS_EQUATION 8.31 // kPa*L/(K*mol).
|
||||
#define ONE_ATMOSPHERE 101.325 // kPa.
|
||||
@@ -43,3 +43,6 @@
|
||||
//for when you need a reliable time number that doesn't depend on byond time.
|
||||
#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
|
||||
#define MIDNIGHT_ROLLOVER_CHECK ( rollovercheck_last_timeofday != world.timeofday ? update_midnight_rollover() : midnight_rollovers )
|
||||
|
||||
#define round_duration_in_ticks (round_start_time ? world.time - round_start_time : 0)
|
||||
#define station_time_in_ticks (roundstart_hour HOURS + round_duration_in_ticks)
|
||||
|
||||
@@ -382,3 +382,10 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
|
||||
//If set to 0, then armor will always prevent the same amount of damage, always, with no randomness whatsoever.
|
||||
//Of course, this will affect code that checks for blocked < 100, as blocked will be less likely to actually be 100.
|
||||
#define ARMOR_BLOCK_CHANCE_MULT 1.0
|
||||
|
||||
// We should start using these.
|
||||
#define ITEMSIZE_TINY 1
|
||||
#define ITEMSIZE_SMALL 2
|
||||
#define ITEMSIZE_NORMAL 3
|
||||
#define ITEMSIZE_LARGE 4
|
||||
#define ITEMSIZE_HUGE 5
|
||||
|
||||
@@ -83,3 +83,6 @@
|
||||
|
||||
// -- SSlistener --
|
||||
#define GET_LISTENERS(id) (id ? SSlistener.listeners["[id]"] : null)
|
||||
|
||||
// Connection prefixes for player-editable fields
|
||||
#define WP_ELECTRONICS "elec_"
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#define SS_PRIORITY_MOB 150 // Mob Life().
|
||||
#define SS_PRIORITY_NANOUI 120 // UI updates.
|
||||
#define SS_PRIORITY_VOTE 110
|
||||
#define SS_PRIORITY_ELECTRONICS 100 // Integrated Electronics processing.
|
||||
#define SS_PRIORITY_MACHINERY 95 // Machinery + powernet ticks.
|
||||
#define SS_PRIORITY_CHEMISTRY 90 // Multi-tick chemical reactions.
|
||||
#define SS_PRIORITY_SHUTTLE 85 // Shuttle movement.
|
||||
|
||||
+32
-6
@@ -44,12 +44,16 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/instances_of_type_in_list(var/atom/A, var/list/L)
|
||||
var/instances = 0
|
||||
for(var/type in L)
|
||||
if(istype(A, type))
|
||||
instances++
|
||||
return instances
|
||||
/proc/instances_of_type_in_list(atom/A, list/L, strict = FALSE)
|
||||
. = 0
|
||||
if (strict)
|
||||
for (var/type in L)
|
||||
if (type == A.type)
|
||||
.++
|
||||
else
|
||||
for(var/type in L)
|
||||
if(istype(A, type))
|
||||
.++
|
||||
|
||||
//Removes any null entries from the list
|
||||
//Returns TRUE if the list had nulls, FALSE otherwise
|
||||
@@ -292,6 +296,28 @@
|
||||
L += new path()
|
||||
return L
|
||||
|
||||
//returns a new list with only atoms that are in typecache L
|
||||
/proc/typecache_filter_list(list/atoms, list/typecache)
|
||||
. = list()
|
||||
for(var/thing in atoms)
|
||||
var/atom/A = thing
|
||||
if (typecache[A.type])
|
||||
. += A
|
||||
|
||||
/proc/typecache_filter_list_reverse(list/atoms, list/typecache)
|
||||
. = list()
|
||||
for(var/thing in atoms)
|
||||
var/atom/A = thing
|
||||
if(!typecache[A.type])
|
||||
. += A
|
||||
|
||||
/proc/typecache_filter_multi_list_exclusion(list/atoms, list/typecache_include, list/typecache_exclude)
|
||||
. = list()
|
||||
for(var/thing in atoms)
|
||||
var/atom/A = thing
|
||||
if(typecache_include[A.type] && !typecache_exclude[A.type])
|
||||
. += A
|
||||
|
||||
//Like typesof() or subtypesof(), but returns a typecache instead of a list
|
||||
/proc/typecacheof(path, ignore_root_path, only_root_path = FALSE)
|
||||
if(ispath(path))
|
||||
|
||||
+16
-3
@@ -4,16 +4,24 @@
|
||||
#define MINUTE *600
|
||||
#define MINUTES *600
|
||||
|
||||
#define HOUR *36000
|
||||
#define HOURS *36000
|
||||
|
||||
#define DAY *864000
|
||||
#define DAYS *864000
|
||||
|
||||
var/roundstart_hour = 0
|
||||
var/round_start_time
|
||||
|
||||
//Returns the world time in english
|
||||
/proc/worldtime2text(time = world.time, timeshift = 1)
|
||||
if(!roundstart_hour) roundstart_hour = rand(0, 23)
|
||||
return timeshift ? time2text(time+(36000*roundstart_hour), "hh:mm") : time2text(time, "hh:mm")
|
||||
return timeshift ? time2text(time+(roundstart_hour HOURS), "hh:mm") : time2text(time, "hh:mm")
|
||||
|
||||
/proc/worldtime2hours()
|
||||
if (!roundstart_hour)
|
||||
worldtime2text()
|
||||
. = text2num(time2text(world.time + (36000 * roundstart_hour), "hh"))
|
||||
. = text2num(time2text(world.time + (roundstart_hour HOURS), "hh"))
|
||||
|
||||
/proc/worlddate2text()
|
||||
return num2text(game_year) + "-" + time2text(world.timeofday, "MM-DD")
|
||||
@@ -39,8 +47,13 @@ var/last_round_duration = 0
|
||||
if(last_round_duration && world.time < next_duration_update)
|
||||
return last_round_duration
|
||||
|
||||
var/mills = world.time // 1/10 of a second, not real milliseconds but whatever
|
||||
var/mills = round_duration_in_ticks // 1/10 of a second, not real milliseconds but whatever
|
||||
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
|
||||
if (!mills)
|
||||
last_round_duration = "00:00"
|
||||
next_duration_update = world.time + 1 MINUTE
|
||||
return last_round_duration
|
||||
|
||||
var/mins = round((mills % 36000) / 600)
|
||||
var/hours = round(mills / 36000)
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
/datum/controller/subsystem
|
||||
// Metadata; you should define these.
|
||||
name = "fire coderbus" //name of the subsystem
|
||||
var/init_order = SS_INIT_MISC //order of initialization. Higher numbers are initialized first, lower numbers later. Can be decimal and negative values.
|
||||
var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
|
||||
var/priority = 50 //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep
|
||||
name = "fire coderbus" //name of the subsystem
|
||||
var/init_order = SS_INIT_MISC //order of initialization. Higher numbers are initialized first, lower numbers later. Can be decimal and negative values.
|
||||
var/wait = 20 //time to wait between each call to fire(). Must be a positive integer. In ticks if SS_TICKER, deciseconds otherwise.
|
||||
var/priority = 50 //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep.
|
||||
|
||||
var/flags = 0 //see MC.dm in __DEFINES Most flags must be set on world start to take full effect. (You can also restart the mc to force them to process again)
|
||||
var/flags = 0 //see master_controller.dm in __defines. Most flags must be set on world start to take full effect. (You can also restart the mc to force them to process again)
|
||||
|
||||
//set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later
|
||||
//set to 0 to prevent fire() calls, mostly for admin use.
|
||||
// use the SS_NO_FIRE flag instead for systems that never fire to keep it from even being added to the list
|
||||
var/can_fire = TRUE
|
||||
// Similar to can_fire, but intended explicitly for subsystems that are asleep. Using this var instead of can_fire
|
||||
@@ -17,30 +17,30 @@
|
||||
var/suspended = FALSE
|
||||
|
||||
// Bookkeeping variables; probably shouldn't mess with these.
|
||||
var/last_fire = 0 //last world.time we called fire()
|
||||
var/next_fire = 0 //scheduled world.time for next fire()
|
||||
var/cost = 0 //average time to execute
|
||||
var/tick_usage = 0 //average tick usage
|
||||
var/tick_overrun = 0 //average tick overrun
|
||||
var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc.
|
||||
var/paused_ticks = 0 //ticks this ss is taking to run right now.
|
||||
var/paused_tick_usage //total tick_usage of all of our runs while pausing this run
|
||||
var/ticks = 1 //how many ticks does this ss take to run on avg.
|
||||
var/times_fired = 0 //number of times we have called fire()
|
||||
var/queued_time = 0 //time we entered the queue, (for timing and priority reasons)
|
||||
var/queued_priority //we keep a running total to make the math easier, if priority changes mid-fire that would break our running total, so we store it here
|
||||
|
||||
// Subsystem startup accounting.
|
||||
var/init_state = FALSE
|
||||
var/init_time = 0
|
||||
var/init_start = 0
|
||||
var/init_finish
|
||||
|
||||
var/last_fire = 0 //last world.time we called fire()
|
||||
var/next_fire = 0 //scheduled world.time for next fire()
|
||||
var/cost = 0 //average time to execute
|
||||
var/tick_usage = 0 //average tick usage
|
||||
var/tick_overrun = 0 //average tick overrun
|
||||
var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc.
|
||||
var/paused_ticks = 0 //ticks this ss is taking to run right now.
|
||||
var/paused_tick_usage //total tick_usage of all of our runs while pausing this run
|
||||
var/ticks = 1 //how many ticks does this ss take to run on avg.
|
||||
var/times_fired = 0 //number of times we have called fire()
|
||||
var/queued_time = 0 //time we entered the queue, (for timing and priority reasons)
|
||||
var/queued_priority //we keep a running total to make the math easier, if priority changes mid-fire that would break our running total, so we store it here
|
||||
|
||||
// Subsystem startup accounting - these variables cannot be trusted if the subsystem has crashed and been Recover()'d.
|
||||
var/init_state = SS_INITSTATE_NONE // The current initialization state of this SS - this might be invalid if the subsystem has been Recover()'d.
|
||||
var/init_time = 0 // How long the subsystem took to initialize, in seconds.
|
||||
var/init_start = 0 // What timeofday did we start initializing?
|
||||
var/init_finish // What timeofday did we finish initializing?
|
||||
|
||||
//linked list stuff for the queue
|
||||
var/datum/controller/subsystem/queue_next
|
||||
var/datum/controller/subsystem/queue_prev
|
||||
|
||||
var/static/list/failure_strikes //How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out!
|
||||
var/static/list/failure_strikes //How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out! This is an assoc list indexed by type.
|
||||
|
||||
// Used to initialize the subsystem BEFORE the map has loaded
|
||||
/datum/controller/subsystem/New()
|
||||
@@ -167,12 +167,11 @@
|
||||
init_state = SS_INITSTATE_DONE
|
||||
|
||||
//used to initialize the subsystem AFTER the map has loaded
|
||||
/datum/controller/subsystem/Initialize(start_timeofday, silent = FALSE)
|
||||
/datum/controller/subsystem/Initialize(start_timeofday)
|
||||
var/time = (REALTIMEOFDAY - start_timeofday) / 10
|
||||
init_time = time
|
||||
var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!"
|
||||
if (!silent)
|
||||
admin_notice(span("danger", msg), R_DEBUG)
|
||||
admin_notice(span("danger", msg), R_DEBUG)
|
||||
world.log << "SS Init: [msg]"
|
||||
log_ss_init(msg)
|
||||
return time
|
||||
|
||||
@@ -21,7 +21,7 @@ var/datum/controller/subsystem/nightlight/SSnightlight
|
||||
|
||||
fire(FALSE, FALSE)
|
||||
|
||||
..(timeofday, silent = TRUE)
|
||||
..()
|
||||
|
||||
/datum/controller/subsystem/nightlight/stat_entry()
|
||||
..("A:[isactive] T:[worldtime2hours()] DT:[config.nl_start] NT:[config.nl_finish] D:[disable_type]")
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#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.
|
||||
|
||||
/var/datum/controller/subsystem/processing/electronics/SSelectronics
|
||||
|
||||
/datum/controller/subsystem/processing/electronics
|
||||
name = "Electronics"
|
||||
wait = 2 SECONDS
|
||||
priority = SS_PRIORITY_ELECTRONICS
|
||||
flags = SS_KEEP_TIMING
|
||||
init_order = SS_INIT_MISC_FIRST
|
||||
|
||||
var/list/all_integrated_circuits = list()
|
||||
var/list/printer_recipe_list = list()
|
||||
|
||||
/datum/controller/subsystem/processing/electronics/New()
|
||||
NEW_SS_GLOBAL(SSelectronics)
|
||||
|
||||
/datum/controller/subsystem/processing/electronics/Initialize(timeofday)
|
||||
init_subtypes(/obj/item/integrated_circuit, all_integrated_circuits)
|
||||
|
||||
// First loop is to seperate the actual circuits from base circuits.
|
||||
var/list/circuits_to_use = list()
|
||||
for(var/obj/item/integrated_circuit/IC in all_integrated_circuits)
|
||||
if((IC.spawn_flags & (IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH)))
|
||||
circuits_to_use += IC
|
||||
|
||||
// Second loop is to find all categories.
|
||||
var/list/found_categories = list()
|
||||
for(var/obj/item/integrated_circuit/IC in circuits_to_use)
|
||||
if(!(IC.category_text in found_categories))
|
||||
found_categories += IC.category_text
|
||||
|
||||
// Third loop is to initialize lists by category names, then put circuits matching the category inside.
|
||||
for(var/category in found_categories)
|
||||
printer_recipe_list[category] = list()
|
||||
var/list/current_list = printer_recipe_list[category]
|
||||
for(var/obj/item/integrated_circuit/IC in circuits_to_use)
|
||||
if(IC.category_text == category)
|
||||
current_list += IC
|
||||
|
||||
// Now for non-circuit things.
|
||||
printer_recipe_list["Assemblies"] = list(
|
||||
new /obj/item/device/electronic_assembly,
|
||||
new /obj/item/device/electronic_assembly/medium,
|
||||
new /obj/item/device/electronic_assembly/large,
|
||||
new /obj/item/device/electronic_assembly/drone,
|
||||
new /obj/item/weapon/implant/integrated_circuit,
|
||||
new /obj/item/device/assembly/electronic_assembly
|
||||
)
|
||||
|
||||
printer_recipe_list["Tools"] = list(
|
||||
new /obj/item/device/integrated_electronics/wirer,
|
||||
new /obj/item/device/integrated_electronics/debugger
|
||||
)
|
||||
|
||||
..()
|
||||
|
||||
#undef IC_SPAWN_DEFAULT
|
||||
#undef IC_SPAWN_RESEARCH
|
||||
@@ -25,7 +25,7 @@ var/datum/controller/subsystem/processing/SSprocessing
|
||||
while(current_run.len)
|
||||
var/datum/thing = current_run[current_run.len]
|
||||
current_run.len--
|
||||
if(thing)
|
||||
if(!QDELETED(thing))
|
||||
if (thing.process() == PROCESS_KILL)
|
||||
stop_processing(thing)
|
||||
else
|
||||
|
||||
@@ -398,6 +398,7 @@ var/datum/controller/subsystem/ticker/SSticker
|
||||
data_core.manifest()
|
||||
|
||||
Master.RoundStart()
|
||||
round_start_time = world.time
|
||||
|
||||
callHook("roundstart")
|
||||
|
||||
|
||||
@@ -426,3 +426,17 @@
|
||||
|
||||
/atom/proc/change_area_name(var/oldname, var/newname)
|
||||
name = replacetext(name,oldname,newname)
|
||||
|
||||
/atom/movable/proc/dropInto(var/atom/destination)
|
||||
while(istype(destination))
|
||||
var/atom/drop_destination = destination.onDropInto(src)
|
||||
if(!istype(drop_destination) || drop_destination == destination)
|
||||
return forceMove(destination)
|
||||
destination = drop_destination
|
||||
return forceMove(null)
|
||||
|
||||
/atom/proc/onDropInto(var/atom/movable/AM)
|
||||
return // If onDropInto returns null, then dropInto will forceMove AM into us.
|
||||
|
||||
/atom/movable/onDropInto(var/atom/movable/AM)
|
||||
return loc // If onDropInto returns something, then dropInto will attempt to drop AM there.
|
||||
|
||||
@@ -58,6 +58,18 @@
|
||||
implants -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/implant/attackby(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/weapon/implanter))
|
||||
var/obj/item/weapon/implanter/implanter = I
|
||||
if(implanter.imp)
|
||||
return // It's full.
|
||||
user.drop_from_inventory(src)
|
||||
forceMove(implanter)
|
||||
implanter.imp = src
|
||||
implanter.update()
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/implant/tracking
|
||||
name = "tracking implant"
|
||||
desc = "Track with this."
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/obj/item/weapon/implant/integrated_circuit
|
||||
name = "electronic implant"
|
||||
desc = "It's a case, for building very tiny electronics with."
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "setup_implant"
|
||||
var/obj/item/device/electronic_assembly/implant/IC = null
|
||||
|
||||
/obj/item/weapon/implant/integrated_circuit/islegal()
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/implant/integrated_circuit/Initialize()
|
||||
..()
|
||||
IC = new(src)
|
||||
IC.implant = src
|
||||
|
||||
/obj/item/weapon/implant/integrated_circuit/Destroy()
|
||||
IC.implant = null
|
||||
qdel(IC)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/implant/integrated_circuit/get_data()
|
||||
var/dat = {"
|
||||
<b>Implant Specifications:</b><BR>
|
||||
<b>Name:</b> Modular Implant<BR>
|
||||
<b>Life:</b> 3 years.<BR>
|
||||
<b>Important Notes: EMP can cause malfunctions in the internal electronics of this implant.</B><BR>
|
||||
<HR>
|
||||
<b>Implant Details:</b><BR>
|
||||
<b>Function:</b> Contains no innate functions until other components are added.<BR>
|
||||
<b>Special Features:</b>
|
||||
<i>Modular Circuitry</i>- Can be loaded with specific modular circuitry in order to fulfill a wide possibility of functions.<BR>
|
||||
<b>Integrity:</b> Implant is not shielded from electromagnetic interference, otherwise it is independant of subject's status."}
|
||||
return dat
|
||||
|
||||
/obj/item/weapon/implant/integrated_circuit/emp_act(severity)
|
||||
IC.emp_act(severity)
|
||||
|
||||
/obj/item/weapon/implant/integrated_circuit/examine(mob/user)
|
||||
IC.examine(user)
|
||||
|
||||
/obj/item/weapon/implant/integrated_circuit/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) || istype(O, /obj/item/weapon/cell/device) )
|
||||
IC.attackby(O, user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/implant/integrated_circuit/attack_self(mob/user)
|
||||
IC.attack_self(user)
|
||||
@@ -322,7 +322,7 @@
|
||||
usr << "<span class='notice'>[src] cannot hold \the [W].</span>"
|
||||
return 0
|
||||
var/max_instances = can_hold[W.type]
|
||||
if(max_instances && instances_of_type_in_list(W, contents) >= max_instances)
|
||||
if(max_instances && instances_of_type_in_list(W, contents, TRUE) >= max_instances)
|
||||
if(!stop_messages && !istype(W, /obj/item/weapon/hand_labeler))
|
||||
usr << "<span class='notice'>[src] has no more space specifically for \the [W].</span>"
|
||||
return 0
|
||||
|
||||
@@ -450,3 +450,5 @@
|
||||
BD.unwrap()
|
||||
open()
|
||||
|
||||
/obj/structure/closet/onDropInto(var/atom/movable/AM)
|
||||
return
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
#define IC_INPUT "input"
|
||||
#define IC_OUTPUT "output"
|
||||
#define IC_ACTIVATOR "activator"
|
||||
|
||||
// Pin functionality.
|
||||
#define DATA_CHANNEL "data channel"
|
||||
#define PULSE_CHANNEL "pulse channel"
|
||||
|
||||
// Methods of obtaining a circuit. These are also defined in SSelectronics.
|
||||
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
|
||||
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
|
||||
|
||||
// Displayed along with the pin name to show what type of pin it is.
|
||||
#define IC_FORMAT_ANY "\<ANY\>"
|
||||
#define IC_FORMAT_STRING "\<TEXT\>"
|
||||
#define IC_FORMAT_CHAR "\<CHAR\>"
|
||||
#define IC_FORMAT_COLOR "\<COLOR\>"
|
||||
#define IC_FORMAT_NUMBER "\<NUM\>"
|
||||
#define IC_FORMAT_DIR "\<DIR\>"
|
||||
#define IC_FORMAT_BOOLEAN "\<BOOL\>"
|
||||
#define IC_FORMAT_REF "\<REF\>"
|
||||
#define IC_FORMAT_LIST "\<LIST\>"
|
||||
|
||||
#define IC_FORMAT_PULSE "\<PULSE\>"
|
||||
|
||||
// Used inside input/output list to tell the constructor what pin to make.
|
||||
#define IC_PINTYPE_ANY /datum/integrated_io
|
||||
#define IC_PINTYPE_STRING /datum/integrated_io/string
|
||||
#define IC_PINTYPE_CHAR /datum/integrated_io/char
|
||||
#define IC_PINTYPE_COLOR /datum/integrated_io/color
|
||||
#define IC_PINTYPE_NUMBER /datum/integrated_io/number
|
||||
#define IC_PINTYPE_DIR /datum/integrated_io/dir
|
||||
#define IC_PINTYPE_BOOLEAN /datum/integrated_io/boolean
|
||||
#define IC_PINTYPE_REF /datum/integrated_io/ref
|
||||
#define IC_PINTYPE_LIST /datum/integrated_io/list
|
||||
|
||||
#define IC_PINTYPE_PULSE_IN /datum/integrated_io/activate
|
||||
#define IC_PINTYPE_PULSE_OUT /datum/integrated_io/activate/out
|
||||
|
||||
// Data limits.
|
||||
#define IC_MAX_LIST_LENGTH 200
|
||||
|
||||
/obj/item/integrated_circuit
|
||||
name = "integrated circuit"
|
||||
desc = "It's a tiny chip! This one doesn't seem to do much, however."
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "template"
|
||||
w_class = ITEMSIZE_TINY
|
||||
var/obj/item/device/electronic_assembly/assembly // Reference to the assembly holding this circuit, if any.
|
||||
var/extended_desc
|
||||
var/list/inputs = list()
|
||||
var/list/inputs_default = list() // Assoc list which will fill a pin with data upon creation. e.g. "2" = 0 will set input pin 2 to equal 0 instead of null.
|
||||
var/list/outputs = list()
|
||||
var/list/outputs_default = list() // Ditto, for output.
|
||||
var/list/activators = list()
|
||||
var/next_use = 0 //Uses world.time
|
||||
var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
|
||||
var/size //This acts as a limitation on building machines, bigger components cost more 'space'. -1 for size 0
|
||||
var/cooldown_per_use = 1 SECOND // Circuits are limited in how many times they can be work()'d by this variable.
|
||||
var/power_draw_per_use = 0 // How much power is drawn when work()'d.
|
||||
var/power_draw_idle = 0 // How much power is drawn when doing nothing.
|
||||
var/spawn_flags // Used for world initializing, see the #defines above.
|
||||
var/category_text = "NO CATEGORY THIS IS A BUG" // To show up on circuit printer, and perhaps other places.
|
||||
var/removable = TRUE // Determines if a circuit is removable from the assembly.
|
||||
var/displayed_name = ""
|
||||
var/allow_multitool = TRUE // Allows additional multitool functionality
|
||||
// Used as a global var, (Do not set manually in children).
|
||||
@@ -0,0 +1,336 @@
|
||||
#define IC_COMPONENTS_BASE 20
|
||||
#define IC_COMPLEXITY_BASE 60
|
||||
|
||||
/obj/item/device/electronic_assembly
|
||||
name = "electronic assembly"
|
||||
desc = "It's a case, for building small electronics with."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "setup_small"
|
||||
var/max_components = IC_COMPONENTS_BASE
|
||||
var/max_complexity = IC_COMPLEXITY_BASE
|
||||
var/opened = 0
|
||||
var/obj/item/weapon/cell/device/battery // Internal cell which most circuits need to work.
|
||||
|
||||
/obj/item/device/electronic_assembly/medium
|
||||
name = "electronic mechanism"
|
||||
icon_state = "setup_medium"
|
||||
desc = "It's a case, for building medium-sized electronics with."
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
max_components = IC_COMPONENTS_BASE * 2
|
||||
max_complexity = IC_COMPLEXITY_BASE * 2
|
||||
|
||||
/obj/item/device/electronic_assembly/large
|
||||
name = "electronic machine"
|
||||
icon_state = "setup_large"
|
||||
desc = "It's a case, for building large electronics with."
|
||||
w_class = ITEMSIZE_LARGE
|
||||
max_components = IC_COMPONENTS_BASE * 4
|
||||
max_complexity = IC_COMPLEXITY_BASE * 4
|
||||
|
||||
/obj/item/device/electronic_assembly/drone
|
||||
name = "electronic drone"
|
||||
icon_state = "setup_drone"
|
||||
desc = "It's a case, for building mobile electronics with."
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
max_components = IC_COMPONENTS_BASE * 1.5
|
||||
max_complexity = IC_COMPLEXITY_BASE * 1.5
|
||||
|
||||
/obj/item/device/electronic_assembly/implant
|
||||
name = "electronic implant"
|
||||
icon_state = "setup_implant"
|
||||
desc = "It's a case, for building very tiny electronics with."
|
||||
w_class = ITEMSIZE_TINY
|
||||
max_components = IC_COMPONENTS_BASE / 2
|
||||
max_complexity = IC_COMPLEXITY_BASE / 2
|
||||
var/obj/item/weapon/implant/integrated_circuit/implant = null
|
||||
|
||||
/obj/item/device/electronic_assembly/Initialize(mapload, printed = FALSE)
|
||||
..()
|
||||
if (!printed)
|
||||
battery = new(src)
|
||||
START_PROCESSING(SSelectronics, src)
|
||||
|
||||
/obj/item/device/electronic_assembly/Destroy()
|
||||
QDEL_NULL(battery)
|
||||
STOP_PROCESSING(SSelectronics, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/device/electronic_assembly/process()
|
||||
handle_idle_power()
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/handle_idle_power()
|
||||
// First we generate power.
|
||||
for(var/obj/item/integrated_circuit/passive/power/P in contents)
|
||||
P.make_energy()
|
||||
|
||||
// Now spend it.
|
||||
for(var/obj/item/integrated_circuit/IC in contents)
|
||||
if(IC.power_draw_idle && !draw_power(IC.power_draw_idle))
|
||||
IC.power_fail()
|
||||
|
||||
/obj/item/device/electronic_assembly/implant/update_icon()
|
||||
..()
|
||||
implant.icon_state = icon_state
|
||||
|
||||
/obj/item/device/electronic_assembly/implant/nano_host()
|
||||
return implant
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/resolve_nano_host()
|
||||
return src
|
||||
|
||||
/obj/item/device/electronic_assembly/implant/resolve_nano_host()
|
||||
return implant
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user)
|
||||
if(!CanInteract(user, physical_state))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/device/electronic_assembly/interact(mob/user)
|
||||
if(!check_interactivity(user))
|
||||
return
|
||||
|
||||
var/total_parts = 0
|
||||
var/total_complexity = 0
|
||||
for(var/obj/item/integrated_circuit/part in contents)
|
||||
total_parts += part.size
|
||||
total_complexity = total_complexity + part.complexity
|
||||
var/list/HTML = list()
|
||||
|
||||
HTML += "<br><a href='?src=\ref[src]'>Refresh</a> | "
|
||||
HTML += "<a href='?src=\ref[src];rename=1'>Rename</a><br>"
|
||||
HTML += "[total_parts]/[max_components] ([round((total_parts / max_components) * 100, 0.1)]%) space taken up in the assembly.<br>"
|
||||
HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.<br>"
|
||||
if(battery)
|
||||
HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. <a href='?src=\ref[src];remove_cell=1'>Remove</a>"
|
||||
else
|
||||
HTML += "<span class='danger'>No powercell detected!</span>"
|
||||
HTML += "<br><br>"
|
||||
HTML += "Components:<hr>"
|
||||
HTML += "Built in:<br>"
|
||||
|
||||
|
||||
//Put removable circuits in separate categories from non-removable
|
||||
for(var/obj/item/integrated_circuit/circuit in contents)
|
||||
if(!circuit.removable)
|
||||
HTML += "<a href=?src=\ref[circuit];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
|
||||
HTML += "<a href=?src=\ref[circuit];rename=1;from_assembly=1>Rename</a> | "
|
||||
HTML += "<a href=?src=\ref[circuit];scan=1;from_assembly=1>Scan with Debugger</a> | "
|
||||
HTML += "<a href=?src=\ref[circuit];bottom=\ref[circuit];from_assembly=1>Move to Bottom</a>"
|
||||
HTML += "<br>"
|
||||
|
||||
HTML += "<hr>"
|
||||
HTML += "Removable:<br>"
|
||||
|
||||
for(var/obj/item/integrated_circuit/circuit in contents)
|
||||
if(circuit.removable)
|
||||
HTML += "<a href=?src=\ref[circuit];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
|
||||
HTML += "<a href=?src=\ref[circuit];rename=1;from_assembly=1>Rename</a> | "
|
||||
HTML += "<a href=?src=\ref[circuit];scan=1;from_assembly=1>Scan with Debugger</a> | "
|
||||
HTML += "<a href=?src=\ref[circuit];remove=1;from_assembly=1>Remove</a> | "
|
||||
HTML += "<a href=?src=\ref[circuit];bottom=\ref[circuit];from_assembly=1>Move to Bottom</a>"
|
||||
HTML += "<br>"
|
||||
|
||||
var/datum/browser/B = new(user, "assembly-\ref[src]", name, 600, 400)
|
||||
B.set_content(HTML.Join())
|
||||
B.open(FALSE)
|
||||
|
||||
/obj/item/device/electronic_assembly/Topic(href, href_list[])
|
||||
if(..())
|
||||
return 1
|
||||
if(!opened)
|
||||
to_chat(usr, "<span class='warning'>\The [src] is not open!</span>")
|
||||
return
|
||||
|
||||
if(href_list["rename"])
|
||||
rename(usr)
|
||||
|
||||
if(href_list["remove_cell"])
|
||||
if(!battery)
|
||||
to_chat(usr, "<span class='warning'>There's no power cell to remove from \the [src].</span>")
|
||||
else
|
||||
var/turf/T = get_turf(src)
|
||||
battery.forceMove(T)
|
||||
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
to_chat(usr, "<span class='notice'>You pull \the [battery] out of \the [src]'s power supply.</span>")
|
||||
battery = null
|
||||
|
||||
interact(usr) // To refresh the UI.
|
||||
|
||||
/obj/item/device/electronic_assembly/verb/rename()
|
||||
set name = "Rename Circuit"
|
||||
set category = "Object"
|
||||
set desc = "Rename your circuit, useful to stay organized."
|
||||
|
||||
var/mob/M = usr
|
||||
if(!check_interactivity(M))
|
||||
return
|
||||
|
||||
var/input = sanitizeSafe(input("What do you want to name this?", "Rename", src.name) as null|text, MAX_NAME_LEN)
|
||||
if(src && input)
|
||||
to_chat(M, "<span class='notice'>The machine now has a label reading '[input]'.</span>")
|
||||
name = input
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/can_move()
|
||||
return FALSE
|
||||
|
||||
/obj/item/device/electronic_assembly/drone/can_move()
|
||||
return TRUE
|
||||
|
||||
/obj/item/device/electronic_assembly/update_icon()
|
||||
if(opened)
|
||||
icon_state = "[initial(icon_state)]-open"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/device/electronic_assembly/GetAccess()
|
||||
. = list()
|
||||
for(var/obj/item/integrated_circuit/part in contents)
|
||||
. |= part.GetAccess()
|
||||
|
||||
/obj/item/device/electronic_assembly/examine(mob/user)
|
||||
. = ..(user, 1)
|
||||
if(.)
|
||||
for(var/obj/item/integrated_circuit/IC in contents)
|
||||
IC.external_examine(user)
|
||||
if(opened)
|
||||
interact(user)
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/get_part_complexity()
|
||||
. = 0
|
||||
for(var/obj/item/integrated_circuit/part in contents)
|
||||
. += part.complexity
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/get_part_size()
|
||||
. = 0
|
||||
for(var/obj/item/integrated_circuit/part in contents)
|
||||
. += part.size
|
||||
|
||||
// Returns true if the circuit made it inside.
|
||||
/obj/item/device/electronic_assembly/proc/add_circuit(obj/item/integrated_circuit/IC, mob/user)
|
||||
if(!opened)
|
||||
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
|
||||
return FALSE
|
||||
|
||||
if(IC.w_class > w_class)
|
||||
to_chat(user, "<span class='warning'>\The [IC] is way too big to fit into \the [src].</span>")
|
||||
return FALSE
|
||||
|
||||
var/total_part_size = get_part_size()
|
||||
var/total_complexity = get_part_complexity()
|
||||
|
||||
if((total_part_size + IC.size) > max_components)
|
||||
to_chat(user, "<span class='warning'>You can't seem to add the '[IC.name]', as there's insufficient space.</span>")
|
||||
return FALSE
|
||||
if((total_complexity + IC.complexity) > max_complexity)
|
||||
to_chat(user, "<span class='warning'>You can't seem to add the '[IC.name]', since this setup's too complicated for the case.</span>")
|
||||
return FALSE
|
||||
|
||||
if(!IC.forceMove(src))
|
||||
return FALSE
|
||||
|
||||
IC.assembly = src
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/device/electronic_assembly/afterattack(atom/target, mob/user, proximity)
|
||||
if(proximity)
|
||||
var/scanned = FALSE
|
||||
for(var/obj/item/integrated_circuit/input/sensor/S in contents)
|
||||
if(S.scan(target))
|
||||
scanned = TRUE
|
||||
if(scanned)
|
||||
visible_message("<span class='notice'>\The [user] waves \the [src] around [target].</span>")
|
||||
|
||||
/obj/item/device/electronic_assembly/attackby(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/integrated_circuit))
|
||||
if(!user.unEquip(I))
|
||||
return FALSE
|
||||
|
||||
if(add_circuit(I, user))
|
||||
to_chat(user, "<span class='notice'>You slide \the [I] inside \the [src].</span>")
|
||||
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
else if(istype(I, /obj/item/weapon/crowbar))
|
||||
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
|
||||
opened = !opened
|
||||
to_chat(user, "<span class='notice'>You [opened ? "open" : "close"] \the [src].</span>")
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
else if(istype(I, /obj/item/device/integrated_electronics/wirer) || istype(I, /obj/item/device/integrated_electronics/debugger) || istype(I, /obj/item/weapon/screwdriver))
|
||||
if(opened)
|
||||
interact(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] isn't open, so you can't fiddle with the internal components. \
|
||||
Try using a crowbar.</span>")
|
||||
|
||||
else if(istype(I, /obj/item/weapon/cell/device))
|
||||
if(!opened)
|
||||
to_chat(user, "<span class='warning'>\The [src] isn't open, so you can't put anything inside. Try using a crowbar.</span>")
|
||||
return FALSE
|
||||
|
||||
if(battery)
|
||||
to_chat(user, "<span class='warning'>\The [src] already has \a [battery] inside. Remove it first if you want to replace it.</span>")
|
||||
return FALSE
|
||||
|
||||
var/obj/item/weapon/cell/device/cell = I
|
||||
user.drop_item(cell)
|
||||
cell.forceMove(src)
|
||||
battery = cell
|
||||
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You slot \the [cell] inside \the [src]'s power supply.</span>")
|
||||
interact(user)
|
||||
return TRUE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/electronic_assembly/attack_self(mob/user)
|
||||
if(!check_interactivity(user))
|
||||
return
|
||||
if(opened)
|
||||
interact(user)
|
||||
|
||||
var/list/input_selection = list()
|
||||
var/list/available_inputs = list()
|
||||
for(var/obj/item/integrated_circuit/input/input in contents)
|
||||
if(input.can_be_asked_input)
|
||||
available_inputs.Add(input)
|
||||
var/i = 0
|
||||
for(var/obj/item/integrated_circuit/s in available_inputs)
|
||||
if(s.name == input.name && s.displayed_name == input.displayed_name && s != input)
|
||||
i++
|
||||
var/disp_name= "[input.displayed_name] \[[input.name]\]"
|
||||
if(i)
|
||||
disp_name += " ([i+1])"
|
||||
input_selection.Add(disp_name)
|
||||
|
||||
var/obj/item/integrated_circuit/input/choice
|
||||
if(available_inputs)
|
||||
var/selection = input(user, "What do you want to interact with?", "Interaction") as null|anything in input_selection
|
||||
if(selection)
|
||||
var/index = input_selection.Find(selection)
|
||||
choice = available_inputs[index]
|
||||
|
||||
if(choice)
|
||||
choice.ask_for_input(user)
|
||||
|
||||
/obj/item/device/electronic_assembly/emp_act(severity)
|
||||
..()
|
||||
for(var/atom/movable/AM in contents)
|
||||
AM.emp_act(severity)
|
||||
|
||||
// Returns true if power was successfully drawn.
|
||||
/obj/item/device/electronic_assembly/proc/draw_power(amount)
|
||||
if(battery && battery.checked_use(amount * CELLRATE))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// Ditto for giving.
|
||||
/obj/item/device/electronic_assembly/proc/give_power(amount)
|
||||
if(battery && battery.give(amount * CELLRATE))
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -0,0 +1,81 @@
|
||||
/obj/item/device/assembly/electronic_assembly
|
||||
name = "electronic device"
|
||||
desc = "It's a case for building electronics with. It can be attached to other small devices."
|
||||
icon_state = "setup_device"
|
||||
var/opened = 0
|
||||
|
||||
var/obj/item/device/electronic_assembly/device/EA
|
||||
|
||||
/obj/item/device/assembly/electronic_assembly/Initialize()
|
||||
EA = new(src)
|
||||
EA.holder = src
|
||||
. = ..()
|
||||
|
||||
/obj/item/device/assembly/electronic_assembly/attackby(obj/item/I, mob/user)
|
||||
if (iscrowbar(I))
|
||||
toggle_open(user)
|
||||
else if (opened)
|
||||
EA.attackby(I, user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/assembly/electronic_assembly/proc/toggle_open(mob/user)
|
||||
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
|
||||
opened = !opened
|
||||
EA.opened = opened
|
||||
to_chat(user, "<span class='notice'>You [opened ? "open" : "close"] \the [src].</span>")
|
||||
secured = 1
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/assembly/electronic_assembly/update_icon()
|
||||
if(EA)
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
icon_state = "[initial(icon_state)]0"
|
||||
if(opened)
|
||||
icon_state = "[icon_state]-open"
|
||||
|
||||
/obj/item/device/assembly/electronic_assembly/attack_self(mob/user as mob)
|
||||
if(EA)
|
||||
EA.attack_self(user)
|
||||
|
||||
//Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
|
||||
/obj/item/device/assembly/electronic_assembly/pulsed(radio = 0)
|
||||
if(EA)
|
||||
for(var/obj/item/integrated_circuit/built_in/device_input/I in EA.contents)
|
||||
I.do_work()
|
||||
|
||||
/obj/item/device/assembly/electronic_assembly/examine(mob/user)
|
||||
. = ..(user, 1)
|
||||
if(EA)
|
||||
for(var/obj/item/integrated_circuit/IC in EA.contents)
|
||||
IC.external_examine(user)
|
||||
|
||||
/obj/item/device/assembly/electronic_assembly/verb/toggle()
|
||||
set src in usr
|
||||
set category = "Object"
|
||||
set name = "Open/Close Device Assembly"
|
||||
set desc = "Open or close device assembly!"
|
||||
|
||||
toggle_open(usr)
|
||||
|
||||
/obj/item/device/electronic_assembly/device
|
||||
name = "electronic device"
|
||||
icon_state = "setup_device"
|
||||
desc = "It's a tiny electronic device with specific use for attaching to other devices."
|
||||
var/obj/item/device/assembly/electronic_assembly/holder
|
||||
w_class = ITEMSIZE_TINY
|
||||
max_components = IC_COMPONENTS_BASE * 3/4
|
||||
max_complexity = IC_COMPLEXITY_BASE * 3/4
|
||||
|
||||
/obj/item/device/electronic_assembly/device/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/integrated_circuit/built_in/device_input/input = new(src)
|
||||
var/obj/item/integrated_circuit/built_in/device_output/output = new(src)
|
||||
input.assembly = src
|
||||
output.assembly = src
|
||||
|
||||
/obj/item/device/electronic_assembly/device/check_interactivity(mob/user)
|
||||
if(!CanInteract(user, state = deep_inventory_state))
|
||||
return 0
|
||||
return 1
|
||||
@@ -0,0 +1,78 @@
|
||||
/obj/item/integrated_circuit/proc/setup_io(list/io_list, io_type, list/io_default_list)
|
||||
var/list/io_list_copy = io_list.Copy()
|
||||
io_list.Cut()
|
||||
var/i = 0
|
||||
for(var/io_entry in io_list_copy)
|
||||
var/default_data = null
|
||||
var/io_type_override = null
|
||||
// Override the default data.
|
||||
if(LAZYLEN(io_default_list)) // List containing special pin types that need to be added.
|
||||
default_data = io_default_list["[i]"] // This is deliberately text because the index is a number in text form.
|
||||
|
||||
// Override the pin type.
|
||||
if(io_list_copy[io_entry])
|
||||
io_type_override = io_list_copy[io_entry]
|
||||
|
||||
if(io_type_override)
|
||||
io_list += new io_type_override(src, io_entry, default_data)
|
||||
else
|
||||
io_list += new io_type(src, io_entry, default_data)
|
||||
|
||||
/obj/item/integrated_circuit/proc/set_pin_data(pin_type, pin_number, datum/new_data)
|
||||
if (istype(new_data) && !isweakref(new_data))
|
||||
PROCLOG_WEIRD("converting hardref to [DEBUG_REF(new_data)] into weakref.")
|
||||
new_data = WEAKREF(new_data)
|
||||
|
||||
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
|
||||
if (!pin)
|
||||
CRASH("Invalid pin ref.")
|
||||
return pin.write_data_to_pin(new_data)
|
||||
|
||||
/obj/item/integrated_circuit/proc/get_pin_data(pin_type, pin_number)
|
||||
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
|
||||
return pin.get_data()
|
||||
|
||||
/obj/item/integrated_circuit/proc/get_pin_data_as_type(pin_type, pin_number, as_type)
|
||||
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
|
||||
return pin.data_as_type(as_type)
|
||||
|
||||
/obj/item/integrated_circuit/proc/activate_pin(pin_number)
|
||||
var/datum/integrated_io/activate/A = activators[pin_number]
|
||||
A.push_data()
|
||||
|
||||
/datum/integrated_io/proc/get_data()
|
||||
if(isnull(data))
|
||||
return
|
||||
if(isweakref(data))
|
||||
return data.resolve()
|
||||
return data
|
||||
|
||||
/obj/item/integrated_circuit/proc/get_pin_ref(pin_type, pin_number)
|
||||
switch(pin_type)
|
||||
if(IC_INPUT)
|
||||
if(pin_number > inputs.len)
|
||||
return null
|
||||
return inputs[pin_number]
|
||||
if(IC_OUTPUT)
|
||||
if(pin_number > outputs.len)
|
||||
return null
|
||||
return outputs[pin_number]
|
||||
if(IC_ACTIVATOR)
|
||||
if(pin_number > activators.len)
|
||||
return null
|
||||
return activators[pin_number]
|
||||
return null
|
||||
|
||||
/obj/item/integrated_circuit/proc/handle_wire(datum/integrated_io/pin, obj/item/device/integrated_electronics/tool)
|
||||
if(istype(tool, /obj/item/device/integrated_electronics/wirer))
|
||||
var/obj/item/device/integrated_electronics/wirer/wirer = tool
|
||||
if(pin)
|
||||
wirer.wire(pin, usr)
|
||||
return 1
|
||||
|
||||
else if(istype(tool, /obj/item/device/integrated_electronics/debugger))
|
||||
var/obj/item/device/integrated_electronics/debugger/debugger = tool
|
||||
if(pin)
|
||||
debugger.write_data(pin, usr)
|
||||
return 1
|
||||
return 0
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
Integrated circuits are essentially modular machines. Each circuit has a specific function, and combining them inside Electronic Assemblies allows
|
||||
a creative player the means to solve many problems. Circuits are held inside an electronic assembly, and are wired using special tools.
|
||||
*/
|
||||
|
||||
/obj/item/integrated_circuit/examine(mob/user)
|
||||
interact(user)
|
||||
external_examine(user)
|
||||
. = ..()
|
||||
|
||||
// This should be used when someone is examining while the case is opened.
|
||||
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
|
||||
to_chat(user, "This board has [inputs.len] input pin\s, [outputs.len] output pin\s and [activators.len] activation pin\s.")
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
if(I.linked.len)
|
||||
to_chat(user, "The '[I]' is connected to [I.get_linked_to_desc()].")
|
||||
for(var/datum/integrated_io/O in outputs)
|
||||
if(O.linked.len)
|
||||
to_chat(user, "The '[O]' is connected to [O.get_linked_to_desc()].")
|
||||
for(var/datum/integrated_io/activate/A in activators)
|
||||
if(A.linked.len)
|
||||
to_chat(user, "The '[A]' is connected to [A.get_linked_to_desc()].")
|
||||
any_examine(user)
|
||||
interact(user)
|
||||
|
||||
// This should be used when someone is examining from an 'outside' perspective, e.g. reading a screen or LED.
|
||||
/obj/item/integrated_circuit/proc/external_examine(mob/user)
|
||||
any_examine(user)
|
||||
|
||||
/obj/item/integrated_circuit/proc/any_examine(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/integrated_circuit/Initialize()
|
||||
displayed_name = name
|
||||
if(!size)
|
||||
size = w_class
|
||||
if(size == -1)
|
||||
size = 0
|
||||
setup_io(inputs, /datum/integrated_io, inputs_default)
|
||||
setup_io(outputs, /datum/integrated_io, outputs_default)
|
||||
setup_io(activators, /datum/integrated_io/activate)
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit.
|
||||
return
|
||||
|
||||
/obj/item/integrated_circuit/Destroy()
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
qdel(I)
|
||||
for(var/datum/integrated_io/O in outputs)
|
||||
qdel(O)
|
||||
for(var/datum/integrated_io/A in activators)
|
||||
qdel(A)
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/nano_host()
|
||||
if(istype(src.loc, /obj/item/device/electronic_assembly))
|
||||
var/obj/item/device/electronic_assembly/assembly = loc
|
||||
return assembly.resolve_nano_host()
|
||||
return ..()
|
||||
|
||||
/obj/item/integrated_circuit/emp_act(severity)
|
||||
for(var/datum/integrated_io/io in inputs + outputs + activators)
|
||||
io.scramble()
|
||||
|
||||
/obj/item/integrated_circuit/proc/check_interactivity(mob/user)
|
||||
if(assembly)
|
||||
return assembly.check_interactivity(user)
|
||||
else if(!CanInteract(user, physical_state))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/integrated_circuit/verb/rename_component()
|
||||
set name = "Rename Circuit"
|
||||
set category = "Object"
|
||||
set desc = "Rename your circuit, useful to stay organized."
|
||||
|
||||
var/mob/M = usr
|
||||
if(!check_interactivity(M))
|
||||
return
|
||||
|
||||
var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name) as null|text, MAX_NAME_LEN)
|
||||
if(src && input && assembly.check_interactivity(M))
|
||||
to_chat(M, "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>")
|
||||
displayed_name = input
|
||||
|
||||
/obj/item/integrated_circuit/interact(mob/user)
|
||||
if(!check_interactivity(user))
|
||||
return
|
||||
|
||||
var/window_height = 350
|
||||
var/window_width = 600
|
||||
var/table_edge_width = "30%"
|
||||
var/table_middle_width = "40%"
|
||||
|
||||
var/list/HTML = list(
|
||||
"<div align='center'>",
|
||||
"<table border='1' style='undefined;table-layout: fixed; width: 80%'>",
|
||||
"<br><a href='?src=\ref[src];return=1'>Return to Assembly</a>",
|
||||
"<br><a href='?src=\ref[src];'>Refresh</a> | ",
|
||||
"<a href='?src=\ref[src];rename=1'>Rename</a> | ",
|
||||
"<a href='?src=\ref[src];scan=1'>Scan with Device</a> | "
|
||||
)
|
||||
if(src.removable)
|
||||
HTML += "<a href='?src=\ref[src];remove=1'>Remove</a><br>"
|
||||
|
||||
HTML += "<colgroup>"
|
||||
HTML += "<col style='width: [table_edge_width]'>"
|
||||
HTML += "<col style='width: [table_middle_width]'>"
|
||||
HTML += "<col style='width: [table_edge_width]'>"
|
||||
HTML += "</colgroup>"
|
||||
|
||||
var/column_width = 3
|
||||
var/row_height = max(inputs.len, outputs.len, 1)
|
||||
|
||||
for(var/i = 1 to row_height)
|
||||
HTML += "<tr>"
|
||||
for(var/j = 1 to column_width)
|
||||
var/datum/integrated_io/io = null
|
||||
var/words = list()
|
||||
var/height = 1
|
||||
switch(j)
|
||||
if(1)
|
||||
io = get_pin_ref(IC_INPUT, i)
|
||||
if(io)
|
||||
words += "<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]>[io.display_pin_type()] [io.name]</a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]>[io.display_data(io.data)]</a></b><br>"
|
||||
if(io.linked.len)
|
||||
for(var/datum/integrated_io/linked in io.linked)
|
||||
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]>[linked.name]</a> \
|
||||
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder.displayed_name]</a><br>"
|
||||
|
||||
if(outputs.len > inputs.len)
|
||||
height = 1
|
||||
if(2)
|
||||
if(i == 1)
|
||||
words += "[src.displayed_name]<br>[src.name != src.displayed_name ? "([src.name])":""]<hr>[src.desc]"
|
||||
height = row_height
|
||||
else
|
||||
continue
|
||||
if(3)
|
||||
io = get_pin_ref(IC_OUTPUT, i)
|
||||
if(io)
|
||||
words += "<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]>[io.display_pin_type()] [io.name]</a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]>[io.display_data(io.data)]</a></b><br>"
|
||||
if(io.linked.len)
|
||||
for(var/datum/integrated_io/linked in io.linked)
|
||||
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]>[linked.name]</a> \
|
||||
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder.displayed_name]</a><br>"
|
||||
|
||||
if(inputs.len > outputs.len)
|
||||
height = 1
|
||||
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
|
||||
HTML += "</tr>"
|
||||
|
||||
for(var/activator in activators)
|
||||
var/datum/integrated_io/io = activator
|
||||
var/words = list(
|
||||
"<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]><span class='bad'>[io.name]</span></a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]><span class='bad'>[io.data?"\<PULSE OUT\>":"\<PULSE IN\>"]</span></a></b><br>"
|
||||
)
|
||||
|
||||
if(io.linked.len)
|
||||
for(var/datum/integrated_io/linked in io.linked)
|
||||
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]><span class='bad'>[linked.name]</span></a> \
|
||||
@ <a href=?src=\ref[linked.holder];examine=1;><span class='bad'>[linked.holder.displayed_name]</span></a><br>"
|
||||
|
||||
HTML += "<tr>"
|
||||
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
|
||||
HTML += "</tr>"
|
||||
|
||||
HTML += "</table>"
|
||||
HTML += "</div>"
|
||||
|
||||
// HTML += "<br><font color='33CC33'>Meta Variables;</font>" // If more meta vars get introduced, uncomment this.
|
||||
// HTML += "<br>"
|
||||
|
||||
HTML += "<br><span class='highlight'>Complexity: [complexity]</span>"
|
||||
if(power_draw_idle)
|
||||
HTML += "<br><span class='highlight'>Power Draw: [power_draw_idle] W (Idle)</span>"
|
||||
if(power_draw_per_use)
|
||||
HTML += "<br><span class='highlight'>Power Draw: [power_draw_per_use] W (Active)</span>" // Borgcode says that powercells' checked_use() takes joules as input.
|
||||
HTML += "<br><span class='highlight'>[extended_desc]</span>"
|
||||
|
||||
var/datum/browser/B = new(user, assembly ? "assembly-\ref[assembly]" : "circuit-\ref[src]", (displayed_name && displayed_name != name) ? "[displayed_name] ([name])" : name, window_width, window_height)
|
||||
B.set_content(HTML.Join())
|
||||
B.open()
|
||||
|
||||
/obj/item/integrated_circuit/Topic(href, href_list, state = interactive_state)
|
||||
if(!check_interactivity(usr))
|
||||
return
|
||||
if (assembly && !assembly.opened)
|
||||
to_chat(usr, "<span class='warning'>\The [assembly] is not open!</span>")
|
||||
return
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
var/update = 1
|
||||
var/obj/item/device/electronic_assembly/A = src.assembly
|
||||
var/update_to_assembly = 0
|
||||
var/datum/integrated_io/pin = locate(href_list["pin"]) in inputs + outputs + activators
|
||||
var/datum/integrated_io/linked = null
|
||||
if(href_list["link"])
|
||||
linked = locate(href_list["link"]) in pin.linked
|
||||
|
||||
var/obj/held_item = usr.get_active_hand()
|
||||
|
||||
if(href_list["rename"])
|
||||
rename_component(usr)
|
||||
if(href_list["from_assembly"])
|
||||
update = 0
|
||||
var/obj/item/device/electronic_assembly/ea = loc
|
||||
if(istype(ea))
|
||||
ea.interact(usr)
|
||||
|
||||
if(href_list["pin_name"])
|
||||
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
|
||||
href_list["wire"] = 1
|
||||
else
|
||||
var/obj/item/device/multitool/M = held_item
|
||||
M.wire(pin,usr)
|
||||
|
||||
if(href_list["pin_data"])
|
||||
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
|
||||
href_list["wire"] = 1
|
||||
|
||||
else
|
||||
var/datum/integrated_io/io = pin
|
||||
io.ask_for_pin_data(usr) // The pins themselves will determine how to ask for data, and will validate the data.
|
||||
|
||||
if(href_list["pin_unwire"])
|
||||
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
|
||||
href_list["wire"] = 1
|
||||
else
|
||||
var/obj/item/device/multitool/M = held_item
|
||||
M.unwire(pin, linked, usr)
|
||||
|
||||
if(href_list["wire"])
|
||||
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
|
||||
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
|
||||
if(linked)
|
||||
wirer.wire(linked, usr)
|
||||
else if(pin)
|
||||
wirer.wire(pin, usr)
|
||||
|
||||
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
|
||||
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
|
||||
if(pin)
|
||||
debugger.write_data(pin, usr)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
|
||||
|
||||
if(href_list["examine"])
|
||||
var/obj/item/integrated_circuit/examined
|
||||
if(href_list["examined"])
|
||||
examined = href_list["examined"]
|
||||
else
|
||||
examined = src
|
||||
examined.interact(usr)
|
||||
update = 0
|
||||
|
||||
if(href_list["bottom"])
|
||||
var/obj/item/integrated_circuit/circuit = locate(href_list["bottom"]) in src.assembly.contents
|
||||
var/assy = circuit.assembly
|
||||
if(!circuit)
|
||||
return
|
||||
circuit.loc = null
|
||||
circuit.loc = assy
|
||||
. = 1
|
||||
update_to_assembly = 1
|
||||
|
||||
if(href_list["scan"])
|
||||
if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
|
||||
var/obj/item/device/integrated_electronics/debugger/D = held_item
|
||||
if(D.accepting_refs)
|
||||
D.afterattack(src, usr, TRUE)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>The Debugger's 'ref scanner' needs to be on.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You need a multitool/debugger set to 'ref' mode to do that.</span>")
|
||||
|
||||
if(href_list["return"])
|
||||
if(A)
|
||||
update_to_assembly = 1
|
||||
usr << browse(null, "window=circuit-\ref[src]")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
|
||||
|
||||
if(href_list["remove"])
|
||||
if(!A)
|
||||
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
|
||||
return
|
||||
if(!removable)
|
||||
to_chat(usr, "<span class='warning'>\The [src] seems to be permanently attached to the case.</span>")
|
||||
return
|
||||
var/obj/item/device/electronic_assembly/ea = loc
|
||||
disconnect_all()
|
||||
var/turf/T = get_turf(src)
|
||||
forceMove(T)
|
||||
assembly = null
|
||||
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
to_chat(usr, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
|
||||
|
||||
if(istype(ea))
|
||||
ea.interact(usr)
|
||||
update = 0
|
||||
return
|
||||
|
||||
if(update)
|
||||
if(istype(A) && update_to_assembly)
|
||||
A.interact(usr)
|
||||
else
|
||||
interact(usr) // To refresh the UI.
|
||||
|
||||
/obj/item/integrated_circuit/proc/push_data()
|
||||
for(var/datum/integrated_io/O in outputs)
|
||||
O.push_data()
|
||||
|
||||
/obj/item/integrated_circuit/proc/pull_data()
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
I.push_data()
|
||||
|
||||
/obj/item/integrated_circuit/proc/draw_idle_power()
|
||||
if(assembly)
|
||||
return assembly.draw_power(power_draw_idle)
|
||||
|
||||
// Override this for special behaviour when there's no power left.
|
||||
/obj/item/integrated_circuit/proc/power_fail()
|
||||
return
|
||||
|
||||
// Returns true if there's enough power to work().
|
||||
/obj/item/integrated_circuit/proc/check_power()
|
||||
if(!assembly)
|
||||
return FALSE // Not in an assembly, therefore no power.
|
||||
if(assembly.draw_power(power_draw_per_use))
|
||||
return TRUE // Battery has enough.
|
||||
return FALSE // Not enough power.
|
||||
|
||||
/obj/item/integrated_circuit/proc/check_then_do_work(ignore_power = FALSE)
|
||||
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
|
||||
return
|
||||
if(power_draw_per_use && !ignore_power)
|
||||
if(!check_power())
|
||||
power_fail()
|
||||
return
|
||||
next_use = world.time + cooldown_per_use
|
||||
do_work()
|
||||
|
||||
/obj/item/integrated_circuit/proc/do_work()
|
||||
return
|
||||
|
||||
/obj/item/integrated_circuit/proc/disconnect_all()
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
I.disconnect()
|
||||
for(var/datum/integrated_io/O in outputs)
|
||||
O.disconnect()
|
||||
for(var/datum/integrated_io/activate/A in activators)
|
||||
A.disconnect()
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
Pins both hold data for circuits, as well move data between them. Some also cause circuits to do their function. DATA_CHANNEL pins are the data holding/moving kind,
|
||||
where as PULSE_CHANNEL causes circuits to work() when their pulse hits them.
|
||||
|
||||
|
||||
A visualization of how pins work is below. Imagine the below image involves an addition circuit.
|
||||
When the bottom pin, the activator, receives a pulse, all the numbers on the left (input) get added, and the answer goes on the right side (output).
|
||||
|
||||
Inputs Outputs
|
||||
|
||||
A [2]\ /[8] result
|
||||
B [1]-\|++|/
|
||||
C [4]-/|++|
|
||||
D [1]/ ||
|
||||
||
|
||||
Activator
|
||||
|
||||
|
||||
|
||||
*/
|
||||
/datum/integrated_io
|
||||
var/name = "input/output"
|
||||
var/obj/item/integrated_circuit/holder = null
|
||||
var/datum/weakref/data = null // This is a weakref, to reduce typecasts. Note that oftentimes numbers and text may also occupy this.
|
||||
var/list/linked = list()
|
||||
var/io_type = DATA_CHANNEL
|
||||
|
||||
/datum/integrated_io/New(var/newloc, var/name, var/new_data)
|
||||
..()
|
||||
src.name = name
|
||||
if(new_data)
|
||||
src.data = new_data
|
||||
holder = newloc
|
||||
if(!istype(holder))
|
||||
message_admins("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.")
|
||||
log_debug("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.")
|
||||
|
||||
/datum/integrated_io/Destroy()
|
||||
disconnect()
|
||||
data = null
|
||||
holder = null
|
||||
. = ..()
|
||||
|
||||
/datum/integrated_io/nano_host()
|
||||
return holder.nano_host()
|
||||
|
||||
/datum/integrated_io/proc/data_as_type(var/as_type)
|
||||
if(!isweakref(data))
|
||||
return
|
||||
var/datum/weakref/w = data
|
||||
var/output = w.resolve()
|
||||
return istype(output, as_type) ? output : null
|
||||
|
||||
/datum/integrated_io/proc/display_data(var/input)
|
||||
if(isnull(input))
|
||||
return "(null)" // Empty data means nothing to show.
|
||||
|
||||
if(istext(input))
|
||||
return "(\"[input]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'.
|
||||
|
||||
/*
|
||||
list[](
|
||||
"A",
|
||||
"B",
|
||||
"C"
|
||||
)
|
||||
*/
|
||||
|
||||
if(islist(input))
|
||||
var/list/my_list = input
|
||||
var/result = "list\[[my_list.len]\]("
|
||||
if(my_list.len)
|
||||
result += "<br>"
|
||||
var/pos = 0
|
||||
for(var/line in my_list)
|
||||
result += "[display_data(line)]"
|
||||
pos++
|
||||
if(pos != my_list.len)
|
||||
result += ",<br>"
|
||||
result += "<br>"
|
||||
result += ")"
|
||||
return result
|
||||
|
||||
if(isweakref(input))
|
||||
var/datum/weakref/w = input
|
||||
var/atom/A = w.resolve()
|
||||
//return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed.
|
||||
return A ? "(\ref[A] \[Ref\])" : "(null)"
|
||||
|
||||
return "([input])" // Nothing special needed for numbers or other stuff.
|
||||
|
||||
/datum/integrated_io/activate/display_data()
|
||||
return "(\[pulse\])"
|
||||
|
||||
/datum/integrated_io/proc/display_pin_type()
|
||||
return IC_FORMAT_ANY
|
||||
|
||||
/datum/integrated_io/activate/display_pin_type()
|
||||
return IC_FORMAT_PULSE
|
||||
|
||||
/datum/integrated_io/proc/scramble()
|
||||
if(isnull(data))
|
||||
return
|
||||
if(isnum(data))
|
||||
write_data_to_pin(rand(-10000, 10000))
|
||||
if(istext(data))
|
||||
write_data_to_pin("ERROR")
|
||||
push_data()
|
||||
|
||||
/datum/integrated_io/activate/scramble()
|
||||
push_data()
|
||||
|
||||
/datum/integrated_io/proc/write_data_to_pin(var/new_data)
|
||||
if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data)) // Anything else is a type we don't want.
|
||||
data = new_data
|
||||
holder.on_data_written()
|
||||
|
||||
/datum/integrated_io/proc/push_data()
|
||||
for(var/datum/integrated_io/io in linked)
|
||||
io.write_data_to_pin(data)
|
||||
|
||||
/datum/integrated_io/activate/push_data()
|
||||
for(var/datum/integrated_io/io in linked)
|
||||
io.holder.check_then_do_work()
|
||||
|
||||
/datum/integrated_io/proc/pull_data()
|
||||
for(var/datum/integrated_io/io in linked)
|
||||
write_data_to_pin(io.data)
|
||||
|
||||
/datum/integrated_io/proc/get_linked_to_desc()
|
||||
if(linked.len)
|
||||
return "the [english_list(linked)]"
|
||||
return "nothing"
|
||||
|
||||
/datum/integrated_io/proc/disconnect()
|
||||
//First we iterate over everything we are linked to.
|
||||
for(var/datum/integrated_io/their_io in linked)
|
||||
//While doing that, we iterate them as well, and disconnect ourselves from them.
|
||||
for(var/datum/integrated_io/their_linked_io in their_io.linked)
|
||||
if(their_linked_io == src)
|
||||
their_io.linked -= src
|
||||
|
||||
//Now that we're removed from them, we gotta remove them from us.
|
||||
linked -= their_io
|
||||
|
||||
/datum/integrated_io/proc/ask_for_data_type(mob/user, var/default, var/list/allowed_data_types = list("string","number","null"))
|
||||
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in allowed_data_types
|
||||
if(!holder.check_interactivity(user))
|
||||
return
|
||||
|
||||
var/new_data = null
|
||||
switch(type_to_use)
|
||||
if("string")
|
||||
new_data = sanitize(input("Now type in a string.","[src] string writing", istext(default) ? default : null) as null|text)
|
||||
if(istext(new_data) && holder.check_interactivity(user) )
|
||||
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
|
||||
return new_data
|
||||
|
||||
if("number")
|
||||
new_data = input("Now type in a number.","[src] number writing", isnum(default) ? default : null) as null|num
|
||||
if(isnum(new_data) && holder.check_interactivity(user) )
|
||||
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
|
||||
return new_data
|
||||
|
||||
if("null")
|
||||
if(holder.check_interactivity(user))
|
||||
to_chat(user, "<span class='notice'>You clear the pin's memory.</span>")
|
||||
return new_data
|
||||
|
||||
// Basically a null check
|
||||
/datum/integrated_io/proc/is_valid()
|
||||
return !isnull(data)
|
||||
|
||||
// This proc asks for the data to write, then writes it.
|
||||
/datum/integrated_io/proc/ask_for_pin_data(mob/user)
|
||||
var/new_data = ask_for_data_type(user)
|
||||
write_data_to_pin(new_data)
|
||||
|
||||
/datum/integrated_io/activate/ask_for_pin_data(mob/user) // This just pulses the pin.
|
||||
holder.check_then_do_work(ignore_power = TRUE)
|
||||
to_chat(user, "<span class='notice'>You pulse \the [holder]'s [src] pin.</span>")
|
||||
|
||||
/datum/integrated_io/activate
|
||||
name = "activation pin"
|
||||
io_type = PULSE_CHANNEL
|
||||
|
||||
/datum/integrated_io/activate/out // All this does is just make the UI say 'out' instead of 'in'
|
||||
data = 1
|
||||
@@ -0,0 +1,159 @@
|
||||
/obj/item/device/integrated_circuit_printer
|
||||
name = "integrated circuit printer"
|
||||
desc = "A portable(ish) machine made to print tiny modular circuitry out of metal."
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "circuit_printer"
|
||||
w_class = ITEMSIZE_LARGE
|
||||
var/metal = 0
|
||||
var/max_metal = 100
|
||||
var/metal_per_sheet = 10 // One sheet equals this much metal.
|
||||
|
||||
var/upgraded = FALSE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits.
|
||||
var/can_clone = FALSE // Same for above, but will allow the printer to duplicate a specific assembly.
|
||||
var/current_category
|
||||
var/obj/item/device/electronic_assembly/assembly_to_clone
|
||||
|
||||
/obj/item/device/integrated_circuit_printer/upgraded
|
||||
upgraded = TRUE
|
||||
can_clone = TRUE
|
||||
|
||||
/obj/item/device/integrated_circuit_printer/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/stack/material))
|
||||
var/obj/item/stack/material/stack = O
|
||||
if(stack.material.name == DEFAULT_WALL_MATERIAL)
|
||||
var/num = min((max_metal - metal) / metal_per_sheet, stack.amount)
|
||||
if(num < 1)
|
||||
to_chat(user, "<span class='warning'>\The [src] is too full to add more metal.</span>")
|
||||
return
|
||||
if(stack.use(num))
|
||||
to_chat(user, "<span class='notice'>You add [num] sheet\s to \the [src].</span>")
|
||||
metal += num * metal_per_sheet
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
if(istype(O,/obj/item/integrated_circuit))
|
||||
to_chat(user, "<span class='notice'>You insert the circuit into \the [src]. </span>")
|
||||
user.unEquip(O)
|
||||
metal = min(metal + O.w_class, max_metal)
|
||||
qdel(O)
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
if(istype(O,/obj/item/weapon/disk/integrated_circuit/upgrade/advanced))
|
||||
if(upgraded)
|
||||
to_chat(user, "<span class='warning'>\The [src] already has this upgrade. </span>")
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You install \the [O] into \the [src]. </span>")
|
||||
upgraded = TRUE
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
if(istype(O,/obj/item/weapon/disk/integrated_circuit/upgrade/clone))
|
||||
if(can_clone)
|
||||
to_chat(user, "<span class='warning'>\The [src] already has this upgrade. </span>")
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You install \the [O] into \the [src]. </span>")
|
||||
can_clone = TRUE
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/device/integrated_circuit_printer/attack_self(var/mob/user)
|
||||
interact(user)
|
||||
|
||||
/obj/item/device/integrated_circuit_printer/interact(mob/user)
|
||||
var/window_height = 600
|
||||
var/window_width = 500
|
||||
|
||||
if(isnull(current_category))
|
||||
current_category = SSelectronics.printer_recipe_list[1]
|
||||
|
||||
var/HTML = "<center><h2>Integrated Circuit Printer</h2></center><br>"
|
||||
HTML += "Metal: [metal/metal_per_sheet]/[max_metal/metal_per_sheet] sheets.<br>"
|
||||
HTML += "Circuits available: [upgraded ? "Regular":"Advanced"]."
|
||||
HTML += "Assembly Cloning: [can_clone ? "Available": "Unavailable"]."
|
||||
if(assembly_to_clone)
|
||||
HTML += "Assembly '[assembly_to_clone.name]' loaded."
|
||||
HTML += "Crossed out circuits mean that the printer is not sufficentally upgraded to create that circuit.<br>"
|
||||
HTML += "<hr>"
|
||||
HTML += "Categories:"
|
||||
for(var/category in SSelectronics.printer_recipe_list)
|
||||
if(category != current_category)
|
||||
HTML += " <a href='?src=\ref[src];category=[category]'>[category]</a> "
|
||||
else // Bold the button if it's already selected.
|
||||
HTML += " <b>[category]</b> "
|
||||
HTML += "<hr>"
|
||||
HTML += "<center><h4>[current_category]</h4></center>"
|
||||
|
||||
var/list/current_list = SSelectronics.printer_recipe_list[current_category]
|
||||
for(var/obj/O in current_list)
|
||||
var/can_build = TRUE
|
||||
if(istype(O, /obj/item/integrated_circuit))
|
||||
var/obj/item/integrated_circuit/IC = O
|
||||
if((IC.spawn_flags & IC_SPAWN_RESEARCH) && (!(IC.spawn_flags & IC_SPAWN_DEFAULT)) && !upgraded)
|
||||
can_build = FALSE
|
||||
if(can_build)
|
||||
HTML += "<A href='?src=\ref[src];build=[O.type]'>[O.name]</A>: [O.desc]<br>"
|
||||
else
|
||||
HTML += "<s>[O.name]: [O.desc]</s><br>"
|
||||
|
||||
var/datum/browser/B = new(user, "integrated_printer", null, window_width, window_height)
|
||||
B.set_content(HTML)
|
||||
B.open(FALSE)
|
||||
|
||||
/obj/item/device/integrated_circuit_printer/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["category"])
|
||||
current_category = href_list["category"]
|
||||
|
||||
if(href_list["build"])
|
||||
var/build_type = text2path(href_list["build"])
|
||||
if(!build_type || !ispath(build_type))
|
||||
return 1
|
||||
|
||||
var/cost = 1
|
||||
var/is_asm = FALSE
|
||||
if(ispath(build_type, /obj/item/device/electronic_assembly))
|
||||
var/obj/item/device/electronic_assembly/E = build_type
|
||||
cost = round( (initial(E.max_complexity) + initial(E.max_components) ) / 4)
|
||||
is_asm = TRUE
|
||||
else if(ispath(build_type, /obj/item/integrated_circuit))
|
||||
var/obj/item/integrated_circuit/IC = build_type
|
||||
cost = initial(IC.w_class)
|
||||
|
||||
if(metal - cost < 0)
|
||||
to_chat(usr, "<span class='warning'>You need [cost] metal to build that!.</span>")
|
||||
return 1
|
||||
metal -= cost
|
||||
if (is_asm)
|
||||
new build_type(get_turf(loc), TRUE)
|
||||
else
|
||||
new build_type(get_turf(loc))
|
||||
|
||||
interact(usr)
|
||||
|
||||
// FUKKEN UPGRADE DISKS
|
||||
/obj/item/weapon/disk/integrated_circuit/upgrade
|
||||
name = "integrated circuit printer upgrade disk"
|
||||
desc = "Install this into your integrated circuit printer to enhance it."
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "upgrade_disk"
|
||||
item_state = "card-id"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4)
|
||||
|
||||
/obj/item/weapon/disk/integrated_circuit/upgrade/advanced
|
||||
name = "integrated circuit printer upgrade disk - advanced designs"
|
||||
desc = "Install this into your integrated circuit printer to enhance it. This one adds new, advanced designs to the printer."
|
||||
|
||||
// To be implemented later.
|
||||
/obj/item/weapon/disk/integrated_circuit/upgrade/clone
|
||||
name = "integrated circuit printer upgrade disk - circuit cloner"
|
||||
desc = "Install this into your integrated circuit printer to enhance it. This one allows the printer to duplicate assemblies."
|
||||
icon_state = "upgrade_disk_clone"
|
||||
origin_tech = list(TECH_ENGINEERING = 5, TECH_DATA = 6)
|
||||
@@ -0,0 +1,25 @@
|
||||
// These pins only contain 0 or 1. Null is not allowed.
|
||||
/datum/integrated_io/boolean
|
||||
name = "boolean pin"
|
||||
data = FALSE
|
||||
|
||||
/datum/integrated_io/boolean/ask_for_pin_data(mob/user) // 'Ask' is a bit misleading, acts more like a toggle.
|
||||
var/new_data = !data
|
||||
write_data_to_pin(new_data)
|
||||
|
||||
/datum/integrated_io/boolean/write_data_to_pin(var/new_data)
|
||||
if(new_data == FALSE || new_data == TRUE)
|
||||
data = new_data
|
||||
holder.on_data_written()
|
||||
|
||||
/datum/integrated_io/boolean/scramble()
|
||||
write_data_to_pin(rand(FALSE,TRUE))
|
||||
push_data()
|
||||
|
||||
/datum/integrated_io/boolean/display_pin_type()
|
||||
return IC_FORMAT_BOOLEAN
|
||||
|
||||
/datum/integrated_io/boolean/display_data(var/input)
|
||||
if(data == TRUE)
|
||||
return "(True)"
|
||||
return "(False)"
|
||||
@@ -0,0 +1,27 @@
|
||||
// These pins can only contain a 1 character string or null.
|
||||
/datum/integrated_io/char
|
||||
name = "char pin"
|
||||
|
||||
/datum/integrated_io/char/ask_for_pin_data(mob/user)
|
||||
var/new_data = sanitize(input("Please type in one character.","[src] char writing") as null|text)
|
||||
if(holder.check_interactivity(user) )
|
||||
to_chat(user, "<span class='notice'>You input [new_data ? "'[new_data]'" : "NULL"] into the pin.</span>")
|
||||
write_data_to_pin(new_data)
|
||||
|
||||
/datum/integrated_io/char/write_data_to_pin(var/new_data)
|
||||
if(isnull(new_data) || istext(new_data))
|
||||
if(length(new_data) > 1)
|
||||
return
|
||||
data = new_data
|
||||
holder.on_data_written()
|
||||
|
||||
// This makes the text go from "A" to "%".
|
||||
/datum/integrated_io/char/scramble()
|
||||
if(!is_valid())
|
||||
return
|
||||
var/list/options = list("!","@","#","$","%","^","&","*") + alphabet_uppercase
|
||||
data = pick(options)
|
||||
push_data()
|
||||
|
||||
/datum/integrated_io/char/display_pin_type()
|
||||
return IC_FORMAT_CHAR
|
||||
@@ -0,0 +1,44 @@
|
||||
// These pins can only contain a color (in the form of #FFFFFF) or null.
|
||||
/datum/integrated_io/color
|
||||
name = "color pin"
|
||||
|
||||
/datum/integrated_io/color/ask_for_pin_data(mob/user)
|
||||
var/new_data = input("Please select a color.","[src] color writing") as null|color
|
||||
if(holder.check_interactivity(user) )
|
||||
to_chat(user, "<span class='notice'>You input a <font color='[new_data]'>new color</font> into the pin.</span>")
|
||||
write_data_to_pin(new_data)
|
||||
|
||||
/datum/integrated_io/color/write_data_to_pin(new_data)
|
||||
// Since this is storing the color as a string hex color code, we need to make sure it's actually one.
|
||||
if(isnull(new_data) || istext(new_data))
|
||||
if(istext(new_data))
|
||||
new_data = uppertext(new_data)
|
||||
if(length(new_data) != 7) // We can hex if we want to, we can leave your strings behind
|
||||
return // Cause your strings don't hex and if they don't hex
|
||||
var/friends = copytext(new_data, 2, 8) // Well they're are no strings of mine
|
||||
// I say, we can go where we want to, a place where they will never find
|
||||
var/safety_dance = 1
|
||||
while(safety_dance >= 7) // And we can act like we come from out of this world.log
|
||||
var/hex = copytext(friends, safety_dance, safety_dance+1)
|
||||
if(!(hex in list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")))
|
||||
return // Leave the fake one far behind,
|
||||
safety_dance++
|
||||
|
||||
data = new_data // And we can hex
|
||||
holder.on_data_written()
|
||||
|
||||
// This randomizes the color.
|
||||
/datum/integrated_io/color/scramble()
|
||||
if(!is_valid())
|
||||
return
|
||||
var/new_data = get_random_colour(simple = FALSE, lower = 0, upper = 255)
|
||||
data = new_data
|
||||
push_data()
|
||||
|
||||
/datum/integrated_io/color/display_pin_type()
|
||||
return IC_FORMAT_COLOR
|
||||
|
||||
/datum/integrated_io/color/display_data(input)
|
||||
if(!isnull(data))
|
||||
return "(<font color='[data]'>[data]</font>)"
|
||||
return ..()
|
||||
@@ -0,0 +1,33 @@
|
||||
// These pins can only contain directions (1,2,4,8...) or null.
|
||||
/datum/integrated_io/dir
|
||||
name = "dir pin"
|
||||
|
||||
/datum/integrated_io/dir/ask_for_pin_data(mob/user)
|
||||
var/new_data = input("Please type in a valid dir number. \
|
||||
Valid dirs are;\n\
|
||||
North/Fore = [NORTH],\n\
|
||||
South/Aft = [SOUTH],\n\
|
||||
East/Starboard = [EAST],\n\
|
||||
West/Port = [WEST],\n\
|
||||
Northeast = [NORTHEAST],\n\
|
||||
Northwest = [NORTHWEST],\n\
|
||||
Southeast = [SOUTHEAST],\n\
|
||||
Southwest = [SOUTHWEST],\n\
|
||||
Up = [UP],\n\
|
||||
Down = [DOWN]","[src] dir writing") as null|num
|
||||
if(isnum(new_data) && holder.check_interactivity(user) )
|
||||
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
|
||||
write_data_to_pin(new_data)
|
||||
|
||||
/datum/integrated_io/dir/write_data_to_pin(var/new_data)
|
||||
if(isnull(new_data) || new_data in alldirs + list(UP, DOWN))
|
||||
data = new_data
|
||||
holder.on_data_written()
|
||||
|
||||
/datum/integrated_io/dir/display_pin_type()
|
||||
return IC_FORMAT_DIR
|
||||
|
||||
/datum/integrated_io/dir/display_data(var/input)
|
||||
if(!isnull(data))
|
||||
return "([dir2text(data)])"
|
||||
return ..()
|
||||
@@ -0,0 +1,149 @@
|
||||
// These pins contain a list. Null is not allowed.
|
||||
/datum/integrated_io/list
|
||||
name = "list pin"
|
||||
data = list()
|
||||
|
||||
/datum/integrated_io/list/ask_for_pin_data(mob/user)
|
||||
interact(user)
|
||||
|
||||
/datum/integrated_io/list/proc/interact(mob/user)
|
||||
var/list/my_list = data
|
||||
var/t = "<h2>[src]</h2><br>"
|
||||
t += "List length: [my_list.len]<br>"
|
||||
t += "<a href='?src=\ref[src]'>Refresh</a> | "
|
||||
t += "<a href='?src=\ref[src];add=1'>Add</a> | "
|
||||
t += "<a href='?src=\ref[src];swap=1'>Swap</a> | "
|
||||
t += "<a href='?src=\ref[src];clear=1'>Clear</a><br>"
|
||||
t += "<hr>"
|
||||
var/i = 0
|
||||
for(var/line in my_list)
|
||||
i++
|
||||
t += "#[i] | [display_data(line)] | "
|
||||
t += "<a href='?src=\ref[src];edit=1;pos=[i]'>Edit</a> | "
|
||||
t += "<a href='?src=\ref[src];remove=1;pos=[i]'>Remove</a><br>"
|
||||
var/datum/browser/B = new(user, "list_pin_\ref[src]", null, 500, 400)
|
||||
B.set_content(t)
|
||||
B.open(FALSE)
|
||||
|
||||
/datum/integrated_io/list/proc/add_to_list(mob/user, new_entry)
|
||||
if(!new_entry && user)
|
||||
new_entry = ask_for_data_type(user)
|
||||
if(is_valid(new_entry))
|
||||
Add(new_entry)
|
||||
|
||||
/datum/integrated_io/list/proc/Add(new_entry)
|
||||
var/list/my_list = data
|
||||
if(my_list.len > IC_MAX_LIST_LENGTH)
|
||||
my_list.Cut(1, 2)
|
||||
my_list.Add(new_entry)
|
||||
|
||||
/datum/integrated_io/list/proc/remove_from_list_by_position(mob/user, position)
|
||||
var/list/my_list = data
|
||||
if(!my_list.len)
|
||||
to_chat(user, "<span class='warning'>The list is empty, there's nothing to remove.</span>")
|
||||
return
|
||||
if(!position)
|
||||
return
|
||||
var/target_entry = my_list.Find(position)
|
||||
if(target_entry)
|
||||
my_list -= target_entry
|
||||
|
||||
/datum/integrated_io/list/proc/remove_from_list(mob/user, target_entry)
|
||||
var/list/my_list = data
|
||||
if(!my_list.len)
|
||||
to_chat(user, "<span class='warning'>The list is empty, there's nothing to remove.</span>")
|
||||
return
|
||||
if(!target_entry)
|
||||
target_entry = input("Which piece of data do you want to remove?", "Remove") as null|anything in my_list
|
||||
if(target_entry)
|
||||
my_list -= target_entry
|
||||
|
||||
/datum/integrated_io/list/proc/edit_in_list(mob/user, target_entry)
|
||||
var/list/my_list = data
|
||||
if(!my_list.len)
|
||||
to_chat(user, "<span class='warning'>The list is empty, there's nothing to modify.</span>")
|
||||
return
|
||||
if(!target_entry)
|
||||
target_entry = input("Which piece of data do you want to edit?", "Edit") as null|anything in my_list
|
||||
if(target_entry)
|
||||
var/edited_entry = ask_for_data_type(user, target_entry)
|
||||
if(edited_entry)
|
||||
target_entry = edited_entry
|
||||
|
||||
/datum/integrated_io/list/proc/edit_in_list_by_position(mob/user, var/position)
|
||||
var/list/my_list = data
|
||||
if(!my_list.len)
|
||||
to_chat(user, "<span class='warning'>The list is empty, there's nothing to modify.</span>")
|
||||
return
|
||||
if(!position)
|
||||
return
|
||||
var/target_entry = my_list.Find(position)
|
||||
if(target_entry)
|
||||
var/edited_entry = ask_for_data_type(user, target_entry)
|
||||
if(edited_entry)
|
||||
target_entry = edited_entry
|
||||
|
||||
/datum/integrated_io/list/proc/swap_inside_list(mob/user, var/first_target, var/second_target)
|
||||
var/list/my_list = data
|
||||
if(my_list.len <= 1)
|
||||
to_chat(user, "<span class='warning'>The list is empty, or too small to do any meaningful swapping.</span>")
|
||||
return
|
||||
if(!first_target)
|
||||
first_target = input("Which piece of data do you want to swap? (1)", "Swap") as null|anything in my_list
|
||||
|
||||
if(first_target)
|
||||
if(!second_target)
|
||||
second_target = input("Which piece of data do you want to swap? (2)", "Swap") as null|anything in my_list - first_target
|
||||
|
||||
if(second_target)
|
||||
var/first_pos = my_list.Find(first_target)
|
||||
var/second_pos = my_list.Find(second_target)
|
||||
my_list.Swap(first_pos, second_pos)
|
||||
|
||||
/datum/integrated_io/list/proc/clear_list(mob/user)
|
||||
var/list/my_list = data
|
||||
my_list.Cut()
|
||||
|
||||
/datum/integrated_io/list/scramble()
|
||||
var/list/my_list = data
|
||||
my_list = shuffle(my_list)
|
||||
push_data()
|
||||
|
||||
/datum/integrated_io/list/write_data_to_pin(var/new_data)
|
||||
if(islist(new_data))
|
||||
var/list/new_list = new_data
|
||||
data = new_list.Copy()
|
||||
holder.on_data_written()
|
||||
|
||||
/datum/integrated_io/list/display_pin_type()
|
||||
return IC_FORMAT_LIST
|
||||
|
||||
/datum/integrated_io/list/Topic(href, href_list, state = interactive_state)
|
||||
if(!holder.check_interactivity(usr))
|
||||
return
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["add"])
|
||||
add_to_list(usr)
|
||||
|
||||
if(href_list["swap"])
|
||||
swap_inside_list(usr)
|
||||
|
||||
if(href_list["clear"])
|
||||
clear_list(usr)
|
||||
|
||||
if(href_list["remove"])
|
||||
if(href_list["pos"])
|
||||
remove_from_list_by_position(usr, text2num(href_list["pos"]))
|
||||
else
|
||||
remove_from_list(usr)
|
||||
|
||||
if(href_list["edit"])
|
||||
if(href_list["pos"])
|
||||
edit_in_list_by_position(usr, text2num(href_list["pos"]))
|
||||
else
|
||||
edit_in_list(usr)
|
||||
|
||||
holder.interact(usr) // Refresh the main UI,
|
||||
interact(usr) // and the list UI.
|
||||
@@ -0,0 +1,17 @@
|
||||
// These pins can only contain numbers (int and floating point) or null.
|
||||
/datum/integrated_io/number
|
||||
name = "number pin"
|
||||
|
||||
/datum/integrated_io/number/ask_for_pin_data(mob/user)
|
||||
var/new_data = input("Please type in a number.","[src] number writing") as null|num
|
||||
if(isnum(new_data) && holder.check_interactivity(user) )
|
||||
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
|
||||
write_data_to_pin(new_data)
|
||||
|
||||
/datum/integrated_io/number/write_data_to_pin(var/new_data)
|
||||
if(isnull(new_data) || isnum(new_data))
|
||||
data = new_data
|
||||
holder.on_data_written()
|
||||
|
||||
/datum/integrated_io/number/display_pin_type()
|
||||
return IC_FORMAT_NUMBER
|
||||
@@ -0,0 +1,14 @@
|
||||
// These pins only contain weakrefs or null.
|
||||
/datum/integrated_io/ref
|
||||
name = "ref pin"
|
||||
|
||||
/datum/integrated_io/ref/ask_for_pin_data(mob/user) // This clears the pin.
|
||||
write_data_to_pin(null)
|
||||
|
||||
/datum/integrated_io/ref/write_data_to_pin(var/new_data)
|
||||
if(isnull(new_data) || isweakref(new_data))
|
||||
data = new_data
|
||||
holder.on_data_written()
|
||||
|
||||
/datum/integrated_io/ref/display_pin_type()
|
||||
return IC_FORMAT_REF
|
||||
@@ -0,0 +1,29 @@
|
||||
// These pins can only contain text and null.
|
||||
/datum/integrated_io/string
|
||||
name = "string pin"
|
||||
|
||||
/datum/integrated_io/string/ask_for_pin_data(mob/user)
|
||||
var/new_data = sanitize(input("Please type in a string.","[src] string writing") as null|text)
|
||||
if(holder.check_interactivity(user) )
|
||||
to_chat(user, "<span class='notice'>You input [new_data ? "new_data" : "NULL"] into the pin.</span>")
|
||||
write_data_to_pin(new_data)
|
||||
|
||||
/datum/integrated_io/string/write_data_to_pin(var/new_data)
|
||||
if(isnull(new_data) || istext(new_data))
|
||||
data = new_data
|
||||
holder.on_data_written()
|
||||
|
||||
// This makes the text go "from this" to "#G&*!HD$%L"
|
||||
/datum/integrated_io/string/scramble()
|
||||
if(!is_valid())
|
||||
return
|
||||
var/string_length = length(data)
|
||||
var/list/options = list("!","@","#","$","%","^","&","*") + alphabet_uppercase
|
||||
var/new_data = ""
|
||||
while(string_length)
|
||||
new_data += pick(options)
|
||||
string_length--
|
||||
push_data()
|
||||
|
||||
/datum/integrated_io/string/display_pin_type()
|
||||
return IC_FORMAT_STRING
|
||||
@@ -0,0 +1,461 @@
|
||||
#define WIRE "wire"
|
||||
#define WIRING "wiring"
|
||||
#define UNWIRE "unwire"
|
||||
#define UNWIRING "unwiring"
|
||||
|
||||
/obj/item/device/integrated_electronics/wirer
|
||||
name = "circuit wirer"
|
||||
desc = "It's a small wiring tool, with a wire roll, electric soldering iron, wire cutter, and more in one package. \
|
||||
The wires used are generally useful for small electronics, such as circuitboards and breadboards, as opposed to larger wires \
|
||||
used for power or data transmission."
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "wirer-wire"
|
||||
item_state = "wirer"
|
||||
flags = CONDUCT
|
||||
w_class = 2
|
||||
var/datum/integrated_io/selected_io
|
||||
var/mode = WIRE
|
||||
|
||||
/obj/item/device/integrated_electronics/wirer/update_icon()
|
||||
icon_state = "wirer-[mode]"
|
||||
|
||||
/obj/item/device/integrated_electronics/wirer/proc/wire(var/datum/integrated_io/io, mob/user)
|
||||
if(!io.holder.assembly)
|
||||
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
|
||||
return
|
||||
|
||||
switch (mode)
|
||||
if (WIRE)
|
||||
selected_io = io
|
||||
to_chat(user, "<span class='notice'>You attach a data wire to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
|
||||
mode = WIRING
|
||||
update_icon()
|
||||
|
||||
if (WIRING)
|
||||
if(io == selected_io)
|
||||
to_chat(user, "<span class='warning'>Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless.</span>")
|
||||
return
|
||||
if(io.io_type != selected_io.io_type)
|
||||
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
|
||||
while the second is a [io.io_type].</span>")
|
||||
return
|
||||
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
|
||||
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
|
||||
return
|
||||
selected_io.linked |= io
|
||||
io.linked |= selected_io
|
||||
|
||||
to_chat(user, "<span class='notice'>You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name].</span>")
|
||||
mode = WIRE
|
||||
update_icon()
|
||||
selected_io.holder.interact(user) // This is to update the UI.
|
||||
selected_io = null
|
||||
|
||||
if (UNWIRE)
|
||||
selected_io = io
|
||||
if(!io.linked.len)
|
||||
to_chat(user, "<span class='warning'>There is nothing connected to \the [selected_io] data channel.</span>")
|
||||
selected_io = null
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You prepare to detach a data wire from \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
|
||||
mode = UNWIRING
|
||||
update_icon()
|
||||
|
||||
if (UNWIRING)
|
||||
if(io == selected_io)
|
||||
to_chat(user, "<span class='warning'>You can't wire a pin into each other, so unwiring \the [selected_io.holder] from \
|
||||
the same pin is rather moot.</span>")
|
||||
return
|
||||
if(selected_io in io.linked)
|
||||
io.linked.Remove(selected_io)
|
||||
selected_io.linked.Remove(io)
|
||||
to_chat(user, "<span class='notice'>You disconnect \the [selected_io.holder]'s [selected_io.name] from \
|
||||
\the [io.holder]'s [io.name].</span>")
|
||||
selected_io.holder.interact(user) // This is to update the UI.
|
||||
selected_io = null
|
||||
mode = UNWIRE
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [selected_io.holder]'s [selected_io.name] and \the [io.holder]'s \
|
||||
[io.name] are not connected.</span>")
|
||||
|
||||
/obj/item/device/integrated_electronics/wirer/attack_self(mob/user)
|
||||
switch(mode)
|
||||
if(WIRE)
|
||||
mode = UNWIRE
|
||||
if(WIRING)
|
||||
if(selected_io)
|
||||
to_chat(user, "<span class='notice'>You decide not to wire the data channel.</span>")
|
||||
selected_io = null
|
||||
mode = WIRE
|
||||
if(UNWIRE)
|
||||
mode = WIRE
|
||||
if(UNWIRING)
|
||||
if(selected_io)
|
||||
to_chat(user, "<span class='notice'>You decide not to disconnect the data channel.</span>")
|
||||
selected_io = null
|
||||
mode = UNWIRE
|
||||
update_icon()
|
||||
to_chat(user, "<span class='notice'>You set \the [src] to [mode].</span>")
|
||||
|
||||
#undef WIRE
|
||||
#undef WIRING
|
||||
#undef UNWIRE
|
||||
#undef UNWIRING
|
||||
|
||||
/obj/item/device/integrated_electronics/debugger
|
||||
name = "circuit debugger"
|
||||
desc = "This small tool allows one working with custom machinery to directly set data to a specific pin, useful for writing \
|
||||
settings to specific circuits, or for debugging purposes. It can also pulse activation pins."
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "debugger"
|
||||
flags = CONDUCT
|
||||
w_class = 2
|
||||
var/data_to_write = null
|
||||
var/accepting_refs = 0
|
||||
|
||||
/obj/item/device/integrated_electronics/debugger/attack_self(mob/user)
|
||||
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null")
|
||||
if(!CanInteract(user, physical_state))
|
||||
return
|
||||
|
||||
var/new_data = null
|
||||
switch(type_to_use)
|
||||
if("string")
|
||||
accepting_refs = 0
|
||||
new_data = sanitize(input("Now type in a string.","[src] string writing") as null|text)
|
||||
if(istext(new_data) && CanInteract(user, physical_state))
|
||||
data_to_write = new_data
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to \"[new_data]\".</span>")
|
||||
if("number")
|
||||
accepting_refs = 0
|
||||
new_data = input("Now type in a number.","[src] number writing") as null|num
|
||||
if(isnum(new_data) && CanInteract(user, physical_state))
|
||||
data_to_write = new_data
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [new_data].</span>")
|
||||
if("ref")
|
||||
accepting_refs = 1
|
||||
to_chat(user, "<span class='notice'>You turn \the [src]'s ref scanner on. Slide it across \
|
||||
an object for a ref of that object to save it in memory.</span>")
|
||||
if("null")
|
||||
data_to_write = null
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
|
||||
|
||||
/obj/item/device/integrated_electronics/debugger/afterattack(atom/target, mob/living/user, proximity)
|
||||
if(accepting_refs && proximity)
|
||||
data_to_write = WEAKREF(target)
|
||||
visible_message("<span class='notice'>[user] slides [src]'s ref scanner over \the [target].</span>")
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to a reference to [target.name] \[Ref\]. The ref scanner is \
|
||||
now off.</span>")
|
||||
accepting_refs = 0
|
||||
|
||||
/obj/item/device/integrated_electronics/debugger/proc/write_data(var/datum/integrated_io/io, mob/user)
|
||||
switch (io.io_type)
|
||||
if (DATA_CHANNEL)
|
||||
io.write_data_to_pin(data_to_write)
|
||||
var/data_to_show = data_to_write
|
||||
if(isweakref(data_to_write))
|
||||
var/datum/weakref/w = data_to_write
|
||||
var/atom/A = w.resolve()
|
||||
data_to_show = A.name
|
||||
to_chat(user, "<span class='notice'>You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].</span>")
|
||||
if (PULSE_CHANNEL)
|
||||
io.holder.check_then_do_work(ignore_power = TRUE)
|
||||
to_chat(user, "<span class='notice'>You pulse \the [io.holder]'s '[io]' pin.</span>")
|
||||
|
||||
io.holder.interact(user) // This is to update the UI.
|
||||
|
||||
/obj/item/device/multitool
|
||||
var/datum/integrated_io/selected_io = null
|
||||
var/mode = 0
|
||||
|
||||
/obj/item/device/multitool/attack_self(mob/user)
|
||||
if(selected_io)
|
||||
selected_io = null
|
||||
to_chat(user, "<span class='notice'>You clear the wired connection from the multitool.</span>")
|
||||
else
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/multitool/update_icon()
|
||||
if(selected_io)
|
||||
if(buffer || connecting || buffer_object)
|
||||
icon_state = "multitool_tracking"
|
||||
else
|
||||
icon_state = "multitool_red"
|
||||
else
|
||||
if(buffer || connecting || buffer_object)
|
||||
icon_state = "multitool_tracking_fail"
|
||||
else
|
||||
icon_state = "multitool"
|
||||
|
||||
/obj/item/device/multitool/proc/wire(datum/integrated_io/io, mob/user)
|
||||
if(!io.holder.assembly)
|
||||
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
|
||||
return
|
||||
|
||||
if(selected_io)
|
||||
if(io == selected_io)
|
||||
to_chat(user, "<span class='warning'>Wiring \the [selected_io.holder]'s '[selected_io.name]' pin into itself is rather pointless.</span>")
|
||||
return
|
||||
if(io.io_type != selected_io.io_type)
|
||||
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
|
||||
while the second is a [io.io_type].</span>")
|
||||
return
|
||||
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
|
||||
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
|
||||
return
|
||||
selected_io.linked |= io
|
||||
io.linked |= selected_io
|
||||
|
||||
to_chat(user, "<span class='notice'>You connect \the [selected_io.holder]'s '[selected_io.name]' pin to \the [io.holder]'s '[io.name]' pin.</span>")
|
||||
selected_io.holder.interact(user) // This is to update the UI.
|
||||
selected_io = null
|
||||
|
||||
else
|
||||
selected_io = io
|
||||
to_chat(user, "<span class='notice'>You link \the multitool to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/multitool/proc/unwire(datum/integrated_io/io1, datum/integrated_io/io2, mob/user)
|
||||
if(!io1.linked.len || !io2.linked.len)
|
||||
to_chat(user, "<span class='warning'>There is nothing connected to the data channel.</span>")
|
||||
return
|
||||
|
||||
if(!(io1 in io2.linked) || !(io2 in io1.linked) )
|
||||
to_chat(user, "<span class='warning'>These data pins aren't connected!</span>")
|
||||
return
|
||||
else
|
||||
io1.linked.Remove(io2)
|
||||
io2.linked.Remove(io1)
|
||||
to_chat(user, "<span class='notice'>You clip the data connection between the [io1.holder.displayed_name]'s \
|
||||
'[io1.name]' pin and the [io2.holder.displayed_name]'s '[io2.name]' pin.</span>")
|
||||
io1.holder.interact(user) // This is to update the UI.
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits
|
||||
name = "circuit kit"
|
||||
desc = "This kit's essential for any circuitry projects."
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "circuit_kit"
|
||||
w_class = 3
|
||||
display_contents_with_number = 0
|
||||
can_hold = list(
|
||||
/obj/item/integrated_circuit,
|
||||
/obj/item/weapon/storage/bag/circuits/mini,
|
||||
/obj/item/device/electronic_assembly,
|
||||
/obj/item/device/integrated_electronics,
|
||||
/obj/item/weapon/crowbar,
|
||||
/obj/item/weapon/screwdriver,
|
||||
/obj/item/device/multitool
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/basic/fill()
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/arithmetic(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/trig(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/input(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/output(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/memory(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/logic(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/time(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/reagents(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/transfer(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/converter(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/power(src)
|
||||
|
||||
new /obj/item/device/electronic_assembly(src)
|
||||
new /obj/item/device/assembly/electronic_assembly(src)
|
||||
new /obj/item/device/assembly/electronic_assembly(src)
|
||||
new /obj/item/device/multitool(src)
|
||||
new /obj/item/weapon/screwdriver(src)
|
||||
new /obj/item/weapon/crowbar(src)
|
||||
make_exact_fit()
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/all/fill()
|
||||
..()
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/arithmetic/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/trig/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/input/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/output/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/memory/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/logic/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/smart/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/manipulation/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/time/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/reagents/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/transfer/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/converter/all(src)
|
||||
new /obj/item/weapon/storage/bag/circuits/mini/power/all(src)
|
||||
|
||||
new /obj/item/device/electronic_assembly(src)
|
||||
new /obj/item/device/electronic_assembly/medium(src)
|
||||
new /obj/item/device/electronic_assembly/large(src)
|
||||
new /obj/item/device/electronic_assembly/drone(src)
|
||||
new /obj/item/device/integrated_electronics/wirer(src)
|
||||
new /obj/item/device/integrated_electronics/debugger(src)
|
||||
new /obj/item/weapon/crowbar(src)
|
||||
make_exact_fit()
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini
|
||||
name = "circuit box"
|
||||
desc = "Used to partition categories of circuits, for a neater workspace."
|
||||
w_class = 2
|
||||
display_contents_with_number = 1
|
||||
can_hold = list(/obj/item/integrated_circuit)
|
||||
var/spawn_flags_to_use = IC_SPAWN_DEFAULT
|
||||
var/list/spawn_types = list()
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/fill()
|
||||
spawn_types = typecacheof(spawn_types)
|
||||
for (var/thing in typecache_filter_list(SSelectronics.all_integrated_circuits, spawn_types))
|
||||
var/obj/item/integrated_circuit/IC = thing
|
||||
if (IC.spawn_flags & spawn_flags_to_use)
|
||||
for (var/i in 1 to 4)
|
||||
new IC.type(src)
|
||||
|
||||
make_exact_fit()
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/arithmetic
|
||||
name = "arithmetic circuit box"
|
||||
desc = "Warning: Contains math."
|
||||
icon_state = "box_arithmetic"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/arithmetic
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/arithmetic/all // Don't believe this will ever be needed.
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/trig
|
||||
name = "trig circuit box"
|
||||
desc = "Danger: Contains more math."
|
||||
icon_state = "box_trig"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/trig
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/trig/all // Ditto
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/input
|
||||
name = "input circuit box"
|
||||
desc = "Tell these circuits everything you know."
|
||||
icon_state = "box_input"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/input
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/input/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/output
|
||||
name = "output circuit box"
|
||||
desc = "Circuits to interface with the world beyond itself."
|
||||
icon_state = "box_output"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/output
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/output/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/memory
|
||||
name = "memory circuit box"
|
||||
desc = "Machines can be quite forgetful without these."
|
||||
icon_state = "box_memory"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/memory
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/memory/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/logic
|
||||
name = "logic circuit box"
|
||||
desc = "May or may not be Turing complete."
|
||||
icon_state = "box_logic"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/logic
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/logic/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/time
|
||||
name = "time circuit box"
|
||||
desc = "No time machine parts, sadly."
|
||||
icon_state = "box_time"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/time
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/time/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/reagents
|
||||
name = "reagent circuit box"
|
||||
desc = "Unlike most electronics, these circuits are supposed to come in contact with liquids."
|
||||
icon_state = "box_reagents"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/reagent
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/reagents/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/transfer
|
||||
name = "transfer circuit box"
|
||||
desc = "Useful for moving data representing something arbitrary to another arbitrary virtual place."
|
||||
icon_state = "box_transfer"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/transfer
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/transfer/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/converter
|
||||
name = "converter circuit box"
|
||||
desc = "Transform one piece of data to another type of data with these."
|
||||
icon_state = "box_converter"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/converter
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/converter/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/smart
|
||||
name = "smart box"
|
||||
desc = "Sentience not included."
|
||||
icon_state = "box_ai"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/smart
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/smart/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/manipulation
|
||||
name = "manipulation box"
|
||||
desc = "Make your machines actually useful with these."
|
||||
icon_state = "box_manipulation"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/manipulation
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/manipulation/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/power
|
||||
name = "power circuit box"
|
||||
desc = "Electronics generally require electricity."
|
||||
icon_state = "box_power"
|
||||
spawn_types = list(
|
||||
/obj/item/integrated_circuit/passive/power,
|
||||
/obj/item/integrated_circuit/power
|
||||
)
|
||||
|
||||
/obj/item/weapon/storage/bag/circuits/mini/power/all
|
||||
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
@@ -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
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
/obj/item/integrated_circuit/passive/power
|
||||
name = "power thingy"
|
||||
desc = "Does power stuff."
|
||||
complexity = 5
|
||||
origin_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 2, TECH_DATA = 2)
|
||||
category_text = "Power - Passive"
|
||||
|
||||
/obj/item/integrated_circuit/passive/power/proc/make_energy()
|
||||
return
|
||||
|
||||
// For calculators.
|
||||
/obj/item/integrated_circuit/passive/power/solar_cell
|
||||
name = "tiny photovoltaic cell"
|
||||
desc = "It's a very tiny solar cell, generally used in calculators."
|
||||
extended_desc = "The cell generates 1W of energy per second in optimal lighting conditions. Less light will result in less power being generated."
|
||||
icon_state = "solar_cell"
|
||||
complexity = 8
|
||||
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
var/max_power = 1
|
||||
|
||||
/obj/item/integrated_circuit/passive/power/solar_cell/make_energy()
|
||||
var/turf/T = get_turf(src)
|
||||
var/light_amount = T ? T.get_lumcount() : 0
|
||||
var/adjusted_power = max(max_power * light_amount, 0)
|
||||
adjusted_power = round(adjusted_power, 0.1)
|
||||
if(adjusted_power && assembly)
|
||||
assembly.give_power(adjusted_power)
|
||||
|
||||
// For fat machines that need fat power, like drones.
|
||||
/obj/item/integrated_circuit/passive/power/relay
|
||||
name = "tesla power relay"
|
||||
desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them."
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
extended_desc = "The siphon generates 250W of energy, so long as an APC is in the same room, with a cell that has energy. It will always drain \
|
||||
from the 'equipment' power channel."
|
||||
icon_state = "power_relay"
|
||||
complexity = 7
|
||||
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
var/power_amount = 250
|
||||
|
||||
// For really fat machines.
|
||||
/obj/item/integrated_circuit/passive/power/relay/large
|
||||
name = "large tesla power relay"
|
||||
desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them, now in industiral size!"
|
||||
w_class = ITEMSIZE_LARGE
|
||||
extended_desc = "The siphon generates 2 kW of energy, so long as an APC is in the same room, with a cell that has energy. It will always drain \
|
||||
from the 'equipment' power channel."
|
||||
icon_state = "power_relay"
|
||||
complexity = 15
|
||||
origin_tech = list(TECH_POWER = 6, TECH_ENGINEERING = 5, TECH_DATA = 4)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
power_amount = 2000
|
||||
|
||||
/obj/item/integrated_circuit/passive/power/relay/make_energy()
|
||||
if(!assembly)
|
||||
return
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
if(A.powered(EQUIP) && assembly.give_power(power_amount))
|
||||
A.use_power(power_amount, EQUIP)
|
||||
// give_power() handles CELLRATE on its own.
|
||||
|
||||
// For implants.
|
||||
/obj/item/integrated_circuit/passive/power/metabolic_siphon
|
||||
name = "metabolic siphon"
|
||||
desc = "A complicated piece of technology which converts bodily nutriments of a host into electricity."
|
||||
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a biological entity. The entity will feel an increased \
|
||||
appetite and will need to eat more often due to this. This device will fail if used inside synthetic entities."
|
||||
icon_state = "setup_implant"
|
||||
complexity = 10
|
||||
origin_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_BIO = 5)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/passive/power/metabolic_siphon/proc/test_validity(var/mob/living/carbon/human/host)
|
||||
if(!host || host.isSynthetic() || host.stat == DEAD || host.nutrition <= 10)
|
||||
return FALSE // Robots and dead people don't have a metabolism.
|
||||
return TRUE
|
||||
|
||||
/obj/item/integrated_circuit/passive/power/metabolic_siphon/make_energy()
|
||||
var/mob/living/carbon/human/host
|
||||
if(assembly && istype(assembly, /obj/item/device/electronic_assembly/implant))
|
||||
var/obj/item/device/electronic_assembly/implant/implant_assembly = assembly
|
||||
if(implant_assembly.implant.imp_in)
|
||||
host = implant_assembly.implant.imp_in
|
||||
|
||||
if(test_validity(host))
|
||||
assembly.give_power(10)
|
||||
host.nutrition = max(host.nutrition - HUNGER_FACTOR, 0)
|
||||
|
||||
/obj/item/integrated_circuit/passive/power/metabolic_siphon/synthetic
|
||||
name = "internal energy siphon"
|
||||
desc = "A small circuit designed to be connected to an internal power wire inside a synthetic entity."
|
||||
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a synthetic entity. The entity need to recharge \
|
||||
more often due to this. This device will fail if used inside organic entities."
|
||||
icon_state = "setup_implant"
|
||||
complexity = 10
|
||||
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 4, TECH_DATA = 3)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/passive/power/metabolic_siphon/synthetic/test_validity(var/mob/living/carbon/human/host)
|
||||
if(!host || !host.isSynthetic() || host.stat == DEAD || host.nutrition <= 10)
|
||||
return FALSE // This time we don't want a metabolism.
|
||||
return TRUE
|
||||
@@ -0,0 +1,314 @@
|
||||
//These circuits do simple math.
|
||||
/obj/item/integrated_circuit/arithmetic
|
||||
complexity = 1
|
||||
inputs = list(
|
||||
"A" = IC_PINTYPE_NUMBER,
|
||||
"B" = IC_PINTYPE_NUMBER,
|
||||
"C" = IC_PINTYPE_NUMBER,
|
||||
"D" = IC_PINTYPE_NUMBER,
|
||||
"E" = IC_PINTYPE_NUMBER,
|
||||
"F" = IC_PINTYPE_NUMBER,
|
||||
"G" = IC_PINTYPE_NUMBER,
|
||||
"H" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list("result" = IC_PINTYPE_NUMBER)
|
||||
activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT)
|
||||
category_text = "Arithmetic"
|
||||
power_draw_per_use = 5 // Math is pretty cheap.
|
||||
|
||||
// +Adding+ //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/addition
|
||||
name = "addition circuit"
|
||||
desc = "This circuit can add numbers together."
|
||||
extended_desc = "The order that the calculation goes is;<br>\
|
||||
result = ((((A + B) + C) + D) ... ) and so on, until all pins have been added. \
|
||||
Null pins are ignored."
|
||||
icon_state = "addition"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/addition/do_work()
|
||||
var/result = 0
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
I.pull_data()
|
||||
if(isnum(I.data))
|
||||
result = result + I.data
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// -Subtracting- //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/subtraction
|
||||
name = "subtraction circuit"
|
||||
desc = "This circuit can subtract numbers."
|
||||
extended_desc = "The order that the calculation goes is;<br>\
|
||||
result = ((((A - B) - C) - D) ... ) and so on, until all pins have been subtracted. \
|
||||
Null pins are ignored. Pin A <b>must</b> be a number or the circuit will not function."
|
||||
icon_state = "subtraction"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/subtraction/do_work()
|
||||
var/datum/integrated_io/A = inputs[1]
|
||||
if(!isnum(A.data))
|
||||
return
|
||||
var/result = A.data
|
||||
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
if(I == A)
|
||||
continue
|
||||
I.pull_data()
|
||||
if(isnum(I.data))
|
||||
result = result - I.data
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// *Multiply* //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/multiplication
|
||||
name = "multiplication circuit"
|
||||
desc = "This circuit can multiply numbers."
|
||||
extended_desc = "The order that the calculation goes is;<br>\
|
||||
result = ((((A * B) * C) * D) ... ) and so on, until all pins have been multiplied. \
|
||||
Null pins are ignored. Pin A <b>must</b> be a number or the circuit will not function."
|
||||
icon_state = "multiplication"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/multiplication/do_work()
|
||||
var/datum/integrated_io/A = inputs[1]
|
||||
if(!isnum(A.data))
|
||||
return
|
||||
var/result = A.data
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
if(I == A)
|
||||
continue
|
||||
I.pull_data()
|
||||
if(isnum(I.data))
|
||||
result = result * I.data
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// /Division/ //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/division
|
||||
name = "division circuit"
|
||||
desc = "This circuit can divide numbers, just don't think about trying to divide by zero!"
|
||||
extended_desc = "The order that the calculation goes is;<br>\
|
||||
result = ((((A / B) / C) / D) ... ) and so on, until all pins have been divided. \
|
||||
Null pins, and pins containing 0, are ignored. Pin A <b>must</b> be a number or the circuit will not function."
|
||||
icon_state = "division"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/division/do_work()
|
||||
var/datum/integrated_io/A = inputs[1]
|
||||
if(!isnum(A.data))
|
||||
return
|
||||
var/result = A.data
|
||||
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
if(I == A)
|
||||
continue
|
||||
I.pull_data()
|
||||
if(isnum(I.data) && I.data != 0) //No runtimes here.
|
||||
result = result / I.data
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
//^ Exponent ^//
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/exponent
|
||||
name = "exponent circuit"
|
||||
desc = "Outputs A to the power of B."
|
||||
icon_state = "exponent"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/exponent/do_work()
|
||||
var/result = 0
|
||||
var/datum/integrated_io/A = inputs[1]
|
||||
var/datum/integrated_io/B = inputs[2]
|
||||
if(isnum(A.data) && isnum(B.data))
|
||||
result = A.data ** B.data
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// +-Sign-+ //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/sign
|
||||
name = "sign circuit"
|
||||
desc = "This will say if a number is positive, negative, or zero."
|
||||
extended_desc = "Will output 1, -1, or 0, depending on if A is a postive number, a negative number, or zero, respectively."
|
||||
icon_state = "sign"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/sign/do_work()
|
||||
var/result = 0
|
||||
var/datum/integrated_io/A = inputs[1]
|
||||
if(isnum(A.data))
|
||||
if(A.data > 0)
|
||||
result = 1
|
||||
else if (A.data < 0)
|
||||
result = -1
|
||||
else
|
||||
result = 0
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// Round //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/round
|
||||
name = "round circuit"
|
||||
desc = "Rounds A to the nearest B multiple of A."
|
||||
extended_desc = "If B is not given a number, it will output the floor of A instead."
|
||||
icon_state = "round"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/round/do_work()
|
||||
var/result = 0
|
||||
var/datum/integrated_io/A = inputs[1]
|
||||
var/datum/integrated_io/B = inputs[2]
|
||||
if(isnum(A.data))
|
||||
if(isnum(B.data) && B.data != 0)
|
||||
result = round(A.data, B.data)
|
||||
else
|
||||
result = round(A.data)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
|
||||
// Absolute //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/absolute
|
||||
name = "absolute circuit"
|
||||
desc = "This outputs a non-negative version of the number you put in. This may also be thought of as its distance from zero."
|
||||
icon_state = "absolute"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/absolute/do_work()
|
||||
var/result = 0
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
I.pull_data()
|
||||
if(isnum(I.data))
|
||||
result = abs(I.data)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// Averaging //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/average
|
||||
name = "average circuit"
|
||||
desc = "This circuit is of average quality, however it will compute the average for numbers you give it."
|
||||
extended_desc = "Note that null pins are ignored, where as a pin containing 0 is included in the averaging calculation."
|
||||
icon_state = "average"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/average/do_work()
|
||||
var/result = 0
|
||||
var/inputs_used = 0
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
I.pull_data()
|
||||
if(isnum(I.data))
|
||||
inputs_used++
|
||||
result = result + I.data
|
||||
|
||||
if(inputs_used)
|
||||
result = result / inputs_used
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// Pi, because why the hell not? //
|
||||
/obj/item/integrated_circuit/arithmetic/pi
|
||||
name = "pi constant circuit"
|
||||
desc = "Not recommended for cooking. Outputs '3.14159' when it receives a pulse."
|
||||
icon_state = "pi"
|
||||
inputs = list()
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/pi/do_work()
|
||||
set_pin_data(IC_OUTPUT, 1, M_PI)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// Random //
|
||||
/obj/item/integrated_circuit/arithmetic/random
|
||||
name = "random number generator circuit"
|
||||
desc = "This gives a random (integer) number between values A and B inclusive."
|
||||
extended_desc = "'Inclusive' means that the upper bound is included in the range of numbers, e.g. L = 1 and H = 3 will allow \
|
||||
for outputs of 1, 2, or 3. H being the higher number is not <i>strictly</i> required."
|
||||
icon_state = "random"
|
||||
inputs = list("L" = IC_PINTYPE_NUMBER,"H" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/random/do_work()
|
||||
var/result = 0
|
||||
var/L = get_pin_data(IC_INPUT, 1)
|
||||
var/H = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
if(isnum(L) && isnum(H))
|
||||
result = rand(L, H)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// Square Root //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/square_root
|
||||
name = "square root circuit"
|
||||
desc = "This outputs the square root of a number you put in."
|
||||
icon_state = "square_root"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/square_root/do_work()
|
||||
var/result = 0
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
I.pull_data()
|
||||
if(isnum(I.data))
|
||||
result = sqrt(I.data)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// % Modulo % //
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/modulo
|
||||
name = "modulo circuit"
|
||||
desc = "Gets the remainder of A / B."
|
||||
icon_state = "modulo"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/modulo/do_work()
|
||||
var/result = 0
|
||||
var/A = get_pin_data(IC_INPUT, 1)
|
||||
var/B = get_pin_data(IC_INPUT, 2)
|
||||
if(isnum(A) && isnum(B) && B != 0)
|
||||
result = A % B
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/obj/item/integrated_circuit/built_in
|
||||
name = "integrated circuit"
|
||||
desc = "It's a tiny chip! This one doesn't seem to do much, however."
|
||||
icon = 'icons/obj/electronic_assemblies.dmi'
|
||||
icon_state = "template"
|
||||
size = -1
|
||||
w_class = ITEMSIZE_TINY
|
||||
removable = FALSE // Determines if a circuit is removable from the assembly.
|
||||
|
||||
/obj/item/integrated_circuit/built_in/device_input
|
||||
name = "assembly input"
|
||||
desc = "A built in chip for handling pulses from attached assembly items."
|
||||
complexity = 0 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
|
||||
activators = list("on pulsed" = IC_PINTYPE_PULSE_OUT)
|
||||
|
||||
/obj/item/integrated_circuit/built_in/device_input/do_work()
|
||||
activate_pin(1)
|
||||
|
||||
/obj/item/integrated_circuit/built_in/device_output
|
||||
name = "assembly out"
|
||||
desc = "A built in chip for pulsing attached assembly items."
|
||||
complexity = 0 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
|
||||
activators = list("pulse attached" = IC_PINTYPE_PULSE_IN)
|
||||
|
||||
/obj/item/integrated_circuit/built_in/device_output/do_work()
|
||||
if(istype(assembly, /obj/item/device/electronic_assembly/device))
|
||||
var/obj/item/device/electronic_assembly/device/device = assembly
|
||||
device.holder.pulse()
|
||||
@@ -0,0 +1,238 @@
|
||||
//These circuits convert one variable to another.
|
||||
/obj/item/integrated_circuit/converter
|
||||
complexity = 2
|
||||
inputs = list("input")
|
||||
outputs = list("output")
|
||||
activators = list("convert" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT)
|
||||
category_text = "Converter"
|
||||
power_draw_per_use = 10
|
||||
|
||||
/obj/item/integrated_circuit/converter/num2text
|
||||
name = "number to string"
|
||||
desc = "This circuit can convert a number variable into a string."
|
||||
extended_desc = "Because of game limitations null/false variables will output a '0' string."
|
||||
icon_state = "num-string"
|
||||
inputs = list("input" = IC_PINTYPE_NUMBER)
|
||||
outputs = list("output" = IC_PINTYPE_STRING)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/num2text/do_work()
|
||||
var/result = null
|
||||
pull_data()
|
||||
var/incoming = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(incoming))
|
||||
result = num2text(incoming)
|
||||
else if(!incoming)
|
||||
result = "0"
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/text2num
|
||||
name = "string to number"
|
||||
desc = "This circuit can convert a string variable into a number."
|
||||
icon_state = "string-num"
|
||||
inputs = list("input" = IC_PINTYPE_STRING)
|
||||
outputs = list("output" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/text2num/do_work()
|
||||
var/result = null
|
||||
pull_data()
|
||||
var/incoming = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(incoming))
|
||||
result = text2num(incoming)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/ref2text
|
||||
name = "reference to string"
|
||||
desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference."
|
||||
icon_state = "ref-string"
|
||||
inputs = list("input" = IC_PINTYPE_REF)
|
||||
outputs = list("output" = IC_PINTYPE_STRING)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/ref2text/do_work()
|
||||
var/result = null
|
||||
pull_data()
|
||||
var/atom/A = get_pin_data_as_type(IC_INPUT, 1, /atom)
|
||||
if(A)
|
||||
result = A.name
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/lowercase
|
||||
name = "lowercase string converter"
|
||||
desc = "this will cause a string to come out in all lowercase."
|
||||
icon_state = "lowercase"
|
||||
inputs = list("input" = IC_PINTYPE_STRING)
|
||||
outputs = list("output" = IC_PINTYPE_STRING)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/lowercase/do_work()
|
||||
var/result = null
|
||||
pull_data()
|
||||
var/incoming = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(incoming))
|
||||
result = lowertext(incoming)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/uppercase
|
||||
name = "uppercase string converter"
|
||||
desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE."
|
||||
icon_state = "uppercase"
|
||||
inputs = list("input" = IC_PINTYPE_STRING)
|
||||
outputs = list("output" = IC_PINTYPE_STRING)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/uppercase/do_work()
|
||||
var/result = null
|
||||
pull_data()
|
||||
var/incoming = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(incoming))
|
||||
result = uppertext(incoming)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/concatenator
|
||||
name = "concatenator"
|
||||
desc = "This joins many strings together to get one big string."
|
||||
complexity = 4
|
||||
inputs = list(
|
||||
"A" = IC_PINTYPE_STRING,
|
||||
"B" = IC_PINTYPE_STRING,
|
||||
"C" = IC_PINTYPE_STRING,
|
||||
"D" = IC_PINTYPE_STRING,
|
||||
"E" = IC_PINTYPE_STRING,
|
||||
"F" = IC_PINTYPE_STRING,
|
||||
"G" = IC_PINTYPE_STRING,
|
||||
"H" = IC_PINTYPE_STRING
|
||||
)
|
||||
outputs = list("result" = IC_PINTYPE_STRING)
|
||||
activators = list("concatenate" = IC_PINTYPE_PULSE_IN, "on concatenated" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/concatenator/do_work()
|
||||
var/result = null
|
||||
for(var/datum/integrated_io/I in inputs)
|
||||
I.pull_data()
|
||||
if(!isnull(I.data))
|
||||
result = result + I.data
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/separator
|
||||
name = "separator"
|
||||
desc = "This splits as single string into two at the relative split point."
|
||||
extended_desc = "This circuits splits a given string into two, based on the string, and the index value. \
|
||||
The index splits the string <b>after</b> the given index, including spaces. So 'a person' with an index of '3' \
|
||||
will split into 'a p' and 'erson'."
|
||||
complexity = 4
|
||||
inputs = list(
|
||||
"string to split" = IC_PINTYPE_STRING,
|
||||
"index" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list(
|
||||
"before split" = IC_PINTYPE_STRING,
|
||||
"after split" = IC_PINTYPE_STRING
|
||||
)
|
||||
activators = list("separate" = IC_PINTYPE_PULSE_IN, "on separated" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/converter/separator/do_work()
|
||||
var/text = get_pin_data(IC_INPUT, 1)
|
||||
var/index = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
var/split = min(index+1, length(text))
|
||||
|
||||
var/before_text = copytext(text, 1, split)
|
||||
var/after_text = copytext(text, split, 0)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, before_text)
|
||||
set_pin_data(IC_OUTPUT, 2, after_text)
|
||||
push_data()
|
||||
|
||||
activate_pin(2)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/converter/radians2degrees
|
||||
name = "radians to degrees converter"
|
||||
desc = "Converts radians to degrees."
|
||||
inputs = list("radian" = IC_PINTYPE_NUMBER)
|
||||
outputs = list("degrees" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/radians2degrees/do_work()
|
||||
var/result = null
|
||||
pull_data()
|
||||
var/incoming = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(incoming))
|
||||
result = ToDegrees(incoming)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/degrees2radians
|
||||
name = "degrees to radians converter"
|
||||
desc = "Converts degrees to radians."
|
||||
inputs = list("degrees" = IC_PINTYPE_NUMBER)
|
||||
outputs = list("radians" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/degrees2radians/do_work()
|
||||
var/result = null
|
||||
pull_data()
|
||||
var/incoming = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(incoming))
|
||||
result = ToRadians(incoming)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/converter/abs_to_rel_coords
|
||||
name = "abs to rel coordinate converter"
|
||||
desc = "Easily convert absolute coordinates to relative coordinates with this."
|
||||
complexity = 4
|
||||
inputs = list(
|
||||
"X1" = IC_PINTYPE_NUMBER,
|
||||
"Y1" = IC_PINTYPE_NUMBER,
|
||||
"X2" = IC_PINTYPE_NUMBER,
|
||||
"Y2" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list(
|
||||
"X" = IC_PINTYPE_NUMBER,
|
||||
"Y" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("compute rel coordinates" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work()
|
||||
var/x1 = get_pin_data(IC_INPUT, 1)
|
||||
var/y1 = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
var/x2 = get_pin_data(IC_INPUT, 3)
|
||||
var/y2 = get_pin_data(IC_INPUT, 4)
|
||||
|
||||
if(!isnull(x1) && !isnull(y1) && !isnull(x2) && !isnull(y2))
|
||||
set_pin_data(IC_OUTPUT, 1, x1 - x2)
|
||||
set_pin_data(IC_OUTPUT, 2, y1 - y2)
|
||||
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
@@ -0,0 +1,165 @@
|
||||
/obj/item/integrated_circuit/transfer
|
||||
category_text = "Data Transfer"
|
||||
power_draw_per_use = 2
|
||||
|
||||
/obj/item/integrated_circuit/transfer/multiplexer
|
||||
name = "two multiplexer"
|
||||
desc = "This is what those in the business tend to refer to as a 'mux' or data selector. It moves data from one of the selected inputs to the output."
|
||||
extended_desc = "The first input pin is used to select which of the other input pins which has its data moved to the output. \
|
||||
If the input selection is outside the valid range then no output is given."
|
||||
complexity = 2
|
||||
icon_state = "mux2"
|
||||
inputs = list("input selection" = IC_PINTYPE_NUMBER)
|
||||
outputs = list("output" = IC_PINTYPE_ANY)
|
||||
activators = list(
|
||||
"select" = IC_PINTYPE_PULSE_IN,
|
||||
"on select" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 4
|
||||
var/number_of_inputs = 2
|
||||
|
||||
/obj/item/integrated_circuit/transfer/multiplexer/Initialize()
|
||||
for(var/i = 1 to number_of_inputs)
|
||||
inputs["input [i]"] = IC_PINTYPE_ANY // This is just a string since pins don't get built until ..() is called.
|
||||
|
||||
complexity = number_of_inputs
|
||||
. = ..()
|
||||
desc += " It has [number_of_inputs] input pins."
|
||||
extended_desc += " This multiplexer has a range from 1 to [inputs.len - 1]."
|
||||
|
||||
/obj/item/integrated_circuit/transfer/multiplexer/do_work()
|
||||
var/input_index = get_pin_data(IC_INPUT, 1)
|
||||
var/output = null
|
||||
|
||||
if(!isnull(input_index) && (input_index >= 1 && input_index < inputs.len))
|
||||
output = get_pin_data(IC_INPUT, input_index + 1)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, output)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/transfer/multiplexer/medium
|
||||
name = "four multiplexer"
|
||||
number_of_inputs = 4
|
||||
icon_state = "mux4"
|
||||
|
||||
/obj/item/integrated_circuit/transfer/multiplexer/large
|
||||
name = "eight multiplexer"
|
||||
number_of_inputs = 8
|
||||
w_class = ITEMSIZE_SMALL
|
||||
icon_state = "mux8"
|
||||
|
||||
/obj/item/integrated_circuit/transfer/multiplexer/huge
|
||||
name = "sixteen multiplexer"
|
||||
icon_state = "mux16"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
number_of_inputs = 16
|
||||
|
||||
/obj/item/integrated_circuit/transfer/demultiplexer
|
||||
name = "two demultiplexer"
|
||||
desc = "This is what those in the business tend to refer to as a 'demux'. It moves data from the input to one of the selected outputs."
|
||||
extended_desc = "The first input pin is used to select which of the output pins is given the data from the second input pin. \
|
||||
If the output selection is outside the valid range then no output is given."
|
||||
complexity = 2
|
||||
icon_state = "dmux2"
|
||||
inputs = list(
|
||||
"output selection" = IC_PINTYPE_NUMBER,
|
||||
"input" = IC_PINTYPE_ANY
|
||||
)
|
||||
outputs = list()
|
||||
activators = list(
|
||||
"select" = IC_PINTYPE_PULSE_IN,
|
||||
"on select" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 4
|
||||
var/number_of_outputs = 2
|
||||
|
||||
/obj/item/integrated_circuit/transfer/demultiplexer/Initialize()
|
||||
for(var/i = 1 to number_of_outputs)
|
||||
outputs["output [i]"] = IC_PINTYPE_ANY
|
||||
complexity = number_of_outputs
|
||||
|
||||
. = ..()
|
||||
desc += " It has [number_of_outputs] output pins."
|
||||
extended_desc += " This demultiplexer has a range from 1 to [outputs.len]."
|
||||
|
||||
/obj/item/integrated_circuit/transfer/demultiplexer/do_work()
|
||||
var/output_index = get_pin_data(IC_INPUT, 1)
|
||||
var/output = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
for(var/i = 1 to outputs.len)
|
||||
set_pin_data(IC_OUTPUT, i, i == output_index ? output : null)
|
||||
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/transfer/demultiplexer/medium
|
||||
name = "four demultiplexer"
|
||||
icon_state = "dmux4"
|
||||
number_of_outputs = 4
|
||||
|
||||
/obj/item/integrated_circuit/transfer/demultiplexer/large
|
||||
name = "eight demultiplexer"
|
||||
icon_state = "dmux8"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
number_of_outputs = 8
|
||||
|
||||
/obj/item/integrated_circuit/transfer/demultiplexer/huge
|
||||
name = "sixteen demultiplexer"
|
||||
icon_state = "dmux16"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
number_of_outputs = 16
|
||||
|
||||
/obj/item/integrated_circuit/transfer/wireless
|
||||
name = "subspace transceiver"
|
||||
desc = "A wireless transmitter-receiver pair that can transmit data between devices."
|
||||
extended_desc = "The first input is the data to send to the other device, and the second input is the channel to send it on."
|
||||
complexity = 12
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
icon_state = "bluespace"
|
||||
power_draw_per_use = 100 // fancy subspace comms aren't cheap power-wise
|
||||
w_class = ITEMSIZE_SMALL
|
||||
inputs = list(
|
||||
"data" = IC_PINTYPE_ANY,
|
||||
"channel" = IC_PINTYPE_STRING
|
||||
)
|
||||
outputs = list(
|
||||
"data" = IC_PINTYPE_ANY
|
||||
)
|
||||
activators = list(
|
||||
"send" = IC_PINTYPE_PULSE_IN,
|
||||
"receive" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
|
||||
var/last_channel
|
||||
|
||||
var/listener/listener
|
||||
|
||||
/obj/item/integrated_circuit/transfer/wireless/do_work()
|
||||
pull_data()
|
||||
|
||||
var/data = get_pin_data(IC_INPUT, 1)
|
||||
if (data != null)
|
||||
var/chan = "[WP_ELECTRONICS][get_pin_data(IC_INPUT, 2) || "default"]"
|
||||
for (var/thing in GET_LISTENERS(chan))
|
||||
var/listener/L = thing
|
||||
var/obj/item/integrated_circuit/transfer/wireless/W = L.target
|
||||
if (W != src)
|
||||
W.receive(data)
|
||||
|
||||
/obj/item/integrated_circuit/transfer/wireless/proc/receive(datum/data)
|
||||
set_pin_data(IC_OUTPUT, 1, data)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/transfer/wireless/Destroy()
|
||||
QDEL_NULL(listener)
|
||||
return ..()
|
||||
|
||||
/obj/item/integrated_circuit/transfer/wireless/on_data_written()
|
||||
var/chan = "[WP_ELECTRONICS][get_pin_data(IC_INPUT, 2) || "default"]"
|
||||
if (chan != last_channel)
|
||||
QDEL_NULL(listener)
|
||||
listener = new(chan, src)
|
||||
last_channel = chan
|
||||
@@ -0,0 +1,381 @@
|
||||
/obj/item/integrated_circuit/input
|
||||
var/can_be_asked_input = 0
|
||||
category_text = "Input"
|
||||
power_draw_per_use = 5
|
||||
|
||||
/obj/item/integrated_circuit/input/proc/ask_for_input(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/integrated_circuit/input/button
|
||||
name = "button"
|
||||
desc = "This tiny button must do something, right?"
|
||||
icon_state = "button"
|
||||
complexity = 1
|
||||
can_be_asked_input = 1
|
||||
inputs = list()
|
||||
outputs = list()
|
||||
activators = list("on pressed" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use.
|
||||
to_chat(user, "<span class='notice'>You press the button labeled '[src.name]'.</span>")
|
||||
activate_pin(1)
|
||||
|
||||
/obj/item/integrated_circuit/input/toggle_button
|
||||
name = "toggle button"
|
||||
desc = "It toggles on, off, on, off..."
|
||||
icon_state = "toggle_button"
|
||||
complexity = 1
|
||||
can_be_asked_input = 1
|
||||
inputs = list()
|
||||
outputs = list("on" = IC_PINTYPE_BOOLEAN)
|
||||
activators = list("on toggle" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto.
|
||||
set_pin_data(IC_OUTPUT, 1, !get_pin_data(IC_OUTPUT, 1))
|
||||
push_data()
|
||||
activate_pin(1)
|
||||
to_chat(user, "<span class='notice'>You toggle the button labeled '[src.name]' [get_pin_data(IC_OUTPUT, 1) ? "on" : "off"].</span>")
|
||||
|
||||
/obj/item/integrated_circuit/input/numberpad
|
||||
name = "number pad"
|
||||
desc = "This small number pad allows someone to input a number into the system."
|
||||
icon_state = "numberpad"
|
||||
complexity = 2
|
||||
can_be_asked_input = 1
|
||||
inputs = list()
|
||||
outputs = list("number entered" = IC_PINTYPE_NUMBER)
|
||||
activators = list("on entered" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 4
|
||||
|
||||
/obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user)
|
||||
var/new_input = input(user, "Enter a number, please.","Number pad") as null|num
|
||||
if(isnum(new_input) && CanInteract(user, physical_state))
|
||||
set_pin_data(IC_OUTPUT, 1, new_input)
|
||||
push_data()
|
||||
activate_pin(1)
|
||||
|
||||
/obj/item/integrated_circuit/input/textpad
|
||||
name = "text pad"
|
||||
desc = "This small text pad allows someone to input a string into the system."
|
||||
icon_state = "textpad"
|
||||
complexity = 2
|
||||
can_be_asked_input = 1
|
||||
inputs = list()
|
||||
outputs = list("string entered" = IC_PINTYPE_STRING)
|
||||
activators = list("on entered" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 4
|
||||
|
||||
/obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user)
|
||||
var/new_input = sanitize(input(user, "Enter some words, please.","Number pad") as null|text)
|
||||
if(istext(new_input) && CanInteract(user, physical_state))
|
||||
set_pin_data(IC_OUTPUT, 1, new_input)
|
||||
push_data()
|
||||
activate_pin(1)
|
||||
|
||||
/obj/item/integrated_circuit/input/med_scanner
|
||||
name = "integrated medical analyser"
|
||||
desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is."
|
||||
icon_state = "medscan"
|
||||
complexity = 4
|
||||
inputs = list("target" = IC_PINTYPE_REF)
|
||||
outputs = list(
|
||||
"total health %" = IC_PINTYPE_NUMBER,
|
||||
"total missing health" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
|
||||
power_draw_per_use = 40
|
||||
|
||||
/obj/item/integrated_circuit/input/med_scanner/do_work()
|
||||
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
|
||||
if(!istype(H)) //Invalid input
|
||||
return
|
||||
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
|
||||
var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100
|
||||
var/missing_health = H.getMaxHealth() - H.health
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, total_health)
|
||||
set_pin_data(IC_OUTPUT, 2, missing_health)
|
||||
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/input/adv_med_scanner
|
||||
name = "integrated advanced medical analyser"
|
||||
desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is. \
|
||||
This type is much more precise, allowing the machine to know much more about the target than a normal analyzer."
|
||||
icon_state = "medscan_adv"
|
||||
complexity = 12
|
||||
inputs = list("target" = IC_PINTYPE_REF)
|
||||
outputs = list(
|
||||
"total health %" = IC_PINTYPE_NUMBER,
|
||||
"total missing health" = IC_PINTYPE_NUMBER,
|
||||
"brute damage" = IC_PINTYPE_NUMBER,
|
||||
"burn damage" = IC_PINTYPE_NUMBER,
|
||||
"tox damage" = IC_PINTYPE_NUMBER,
|
||||
"oxy damage" = IC_PINTYPE_NUMBER,
|
||||
"clone damage" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4)
|
||||
power_draw_per_use = 80
|
||||
|
||||
/obj/item/integrated_circuit/input/adv_med_scanner/do_work()
|
||||
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
|
||||
if(!istype(H)) //Invalid input
|
||||
return
|
||||
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
|
||||
var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100
|
||||
var/missing_health = H.getMaxHealth() - H.health
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, total_health)
|
||||
set_pin_data(IC_OUTPUT, 2, missing_health)
|
||||
set_pin_data(IC_OUTPUT, 3, H.getBruteLoss())
|
||||
set_pin_data(IC_OUTPUT, 4, H.getFireLoss())
|
||||
set_pin_data(IC_OUTPUT, 5, H.getToxLoss())
|
||||
set_pin_data(IC_OUTPUT, 6, H.getOxyLoss())
|
||||
set_pin_data(IC_OUTPUT, 7, H.getCloneLoss())
|
||||
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/input/local_locator
|
||||
name = "local locator"
|
||||
desc = "This is needed for certain devices that demand a reference for a target to act upon. This type only locates something \
|
||||
that is holding the machine containing it."
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"located ref" = IC_PINTYPE_REF
|
||||
)
|
||||
activators = list(
|
||||
"locate" = IC_PINTYPE_PULSE_IN,
|
||||
"on locate" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 20
|
||||
|
||||
/obj/item/integrated_circuit/input/local_locator/do_work()
|
||||
if(assembly && istype(assembly.loc, /mob/living))
|
||||
set_pin_data(IC_OUTPUT, 1, assembly.loc)
|
||||
else
|
||||
set_pin_data(IC_OUTPUT, 1, null)
|
||||
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/input/adjacent_locator
|
||||
name = "adjacent locator"
|
||||
desc = "This is needed for certain devices that demand a reference for a target to act upon. This type only locates something \
|
||||
that is standing a meter away from the machine."
|
||||
extended_desc = "The first pin requires a ref to a kind of object that you want the locator to acquire. This means that it will \
|
||||
give refs to nearby objects that are similar. If more than one valid object is found nearby, it will choose one of them at \
|
||||
random."
|
||||
inputs = list("desired type ref" = IC_PINTYPE_REF)
|
||||
outputs = list("located ref" = IC_PINTYPE_REF)
|
||||
activators = list("locate" = IC_PINTYPE_PULSE_IN)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 30
|
||||
|
||||
/obj/item/integrated_circuit/input/adjacent_locator/do_work()
|
||||
var/atom/A = get_pin_data_as_type(IC_INPUT, 1, /atom)
|
||||
if(!A)
|
||||
set_pin_data(IC_OUTPUT, 1, null)
|
||||
return
|
||||
var/desired_type = A.type
|
||||
|
||||
var/list/nearby_things = range(1, get_turf(src))
|
||||
var/list/valid_things = list()
|
||||
for(var/atom/thing in nearby_things)
|
||||
if(thing.type != desired_type)
|
||||
continue
|
||||
valid_things += thing
|
||||
|
||||
if(valid_things.len)
|
||||
set_pin_data(IC_OUTPUT, 1, pick(valid_things))
|
||||
|
||||
/obj/item/integrated_circuit/input/signaler
|
||||
name = "integrated signaler"
|
||||
desc = "Signals from a signaler can be received with this, allowing for remote control. Additionally, it can send signals as well."
|
||||
extended_desc = "When a signal is received from another signaler, the 'on signal received' activator pin will be pulsed. \
|
||||
The two input pins are to configure the integrated signaler's settings. Note that the frequency should not have a decimal in it. \
|
||||
Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin."
|
||||
icon_state = "signal"
|
||||
complexity = 4
|
||||
inputs = list(
|
||||
"frequency" = IC_PINTYPE_NUMBER,
|
||||
"code" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list()
|
||||
activators = list(
|
||||
"send signal" = IC_PINTYPE_PULSE_IN,
|
||||
"on signal sent" = IC_PINTYPE_PULSE_OUT,
|
||||
"on signal received" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2)
|
||||
power_draw_idle = 5
|
||||
power_draw_per_use = 40
|
||||
|
||||
var/frequency = 1457
|
||||
var/code = 30
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/item/integrated_circuit/input/signaler/Initialize()
|
||||
..()
|
||||
set_frequency(frequency)
|
||||
// Set the pins so when someone sees them, they won't show as null
|
||||
set_pin_data(IC_INPUT, 1, frequency)
|
||||
set_pin_data(IC_INPUT, 2, code)
|
||||
|
||||
/obj/item/integrated_circuit/input/signaler/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
frequency = 0
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/input/signaler/on_data_written()
|
||||
var/new_freq = get_pin_data(IC_INPUT, 1)
|
||||
var/new_code = get_pin_data(IC_INPUT, 2)
|
||||
if(isnum(new_freq) && new_freq > 0)
|
||||
set_frequency(new_freq)
|
||||
if(isnum(new_code))
|
||||
code = new_code
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/input/signaler/do_work() // Sends a signal.
|
||||
if(!radio_connection)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = new()
|
||||
signal.source = src
|
||||
signal.encryption = code
|
||||
signal.data["message"] = "ACTIVATE"
|
||||
radio_connection.post_signal(src, signal)
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency)
|
||||
if(!frequency)
|
||||
return
|
||||
SSradio.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_CHAT)
|
||||
|
||||
/obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal)
|
||||
var/new_code = get_pin_data(IC_INPUT, 2)
|
||||
var/code = 0
|
||||
|
||||
if(isnum(new_code))
|
||||
code = new_code
|
||||
if(!signal)
|
||||
return 0
|
||||
if(signal.encryption != code)
|
||||
return 0
|
||||
if(signal.source == src) // Don't trigger ourselves.
|
||||
return 0
|
||||
|
||||
activate_pin(3)
|
||||
|
||||
for(var/mob/O in hearers(1, get_turf(src)))
|
||||
O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2)
|
||||
|
||||
//This circuit gives information on where the machine is.
|
||||
/obj/item/integrated_circuit/input/gps
|
||||
name = "global positioning system"
|
||||
desc = "This allows you to easily know the position of a machine containing this device."
|
||||
extended_desc = "The GPS's coordinates it gives is absolute, not relative."
|
||||
icon_state = "gps"
|
||||
complexity = 4
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"X"= IC_PINTYPE_NUMBER,
|
||||
"Y" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list(
|
||||
"get coordinates" = IC_PINTYPE_PULSE_IN,
|
||||
"on get coordinates" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 30
|
||||
|
||||
/obj/item/integrated_circuit/input/gps/do_work()
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, null)
|
||||
set_pin_data(IC_OUTPUT, 2, null)
|
||||
if(!T)
|
||||
return
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, T.x)
|
||||
set_pin_data(IC_OUTPUT, 2, T.y)
|
||||
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/input/microphone
|
||||
name = "microphone"
|
||||
desc = "Useful for spying on people or for voice activated machines."
|
||||
extended_desc = "This will automatically translate most languages it hears to Tau Ceti Basic. \
|
||||
The first activation pin is always pulsed when the circuit hears someone talk, while the second one \
|
||||
is only triggered if it hears someone speaking a language other than Tau Ceti Basic."
|
||||
icon_state = "recorder"
|
||||
complexity = 8
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"speaker" = IC_PINTYPE_STRING,
|
||||
"message" = IC_PINTYPE_STRING
|
||||
)
|
||||
activators = list(
|
||||
"on message received" = IC_PINTYPE_PULSE_OUT,
|
||||
"on translation" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 15
|
||||
|
||||
/obj/item/integrated_circuit/input/microphone/Initialize()
|
||||
. = ..()
|
||||
listening_objects |= src
|
||||
|
||||
/obj/item/integrated_circuit/input/microphone/Destroy()
|
||||
listening_objects -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
|
||||
var/translated = FALSE
|
||||
if(M && msg)
|
||||
if(speaking)
|
||||
if(!istype(speaking, /datum/language/common))
|
||||
translated = TRUE
|
||||
set_pin_data(IC_OUTPUT, 1, M.GetVoice())
|
||||
set_pin_data(IC_OUTPUT, 2, msg)
|
||||
|
||||
push_data()
|
||||
activate_pin(1)
|
||||
if(translated)
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/input/sensor
|
||||
name = "sensor"
|
||||
desc = "Scans and obtains a reference for any objects or persons near you. All you need to do is shove the machine in their face."
|
||||
extended_desc = "If 'ignore storage' pin is set to true, the sensor will disregard scanning various storage containers such as backpacks."
|
||||
icon_state = "recorder"
|
||||
complexity = 12
|
||||
inputs = list("ignore storage" = IC_PINTYPE_BOOLEAN)
|
||||
outputs = list("scanned" = IC_PINTYPE_REF)
|
||||
activators = list("on scanned" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 120
|
||||
|
||||
/obj/item/integrated_circuit/input/sensor/proc/scan(var/atom/A)
|
||||
var/ignore_bags = get_pin_data(IC_INPUT, 1)
|
||||
if(ignore_bags)
|
||||
if(istype(A, /obj/item/weapon/storage))
|
||||
return FALSE
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, A)
|
||||
push_data()
|
||||
activate_pin(1)
|
||||
return TRUE
|
||||
@@ -0,0 +1,87 @@
|
||||
//These circuits do things with lists, and use special list pins for stability.
|
||||
/obj/item/integrated_circuit/list
|
||||
complexity = 1
|
||||
inputs = list(
|
||||
"input" = IC_PINTYPE_LIST
|
||||
)
|
||||
outputs = list("result" = IC_PINTYPE_STRING)
|
||||
activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT)
|
||||
category_text = "Lists"
|
||||
power_draw_per_use = 20
|
||||
|
||||
/obj/item/integrated_circuit/list/pick
|
||||
name = "pick circuit"
|
||||
desc = "This circuit will randomly 'pick' an element from a list that is inputted."
|
||||
extended_desc = "Will output null if the list is empty. Input list is unmodified."
|
||||
icon_state = "addition"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/list/pick/do_work()
|
||||
var/result = null
|
||||
var/list/input_list = get_pin_data(IC_INPUT, 1) // List pins guarantee that there is a list inside, even if just an empty one.
|
||||
if(input_list.len)
|
||||
result = pick(input_list)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/list/append
|
||||
name = "append circuit"
|
||||
desc = "This circuit will add an element to a list."
|
||||
extended_desc = "The new element will always be at the bottom of the list."
|
||||
inputs = list(
|
||||
"list to append" = IC_PINTYPE_LIST,
|
||||
"input" = IC_PINTYPE_ANY
|
||||
)
|
||||
outputs = list(
|
||||
"appended list" = IC_PINTYPE_LIST
|
||||
)
|
||||
icon_state = "addition"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/list/append/do_work()
|
||||
var/list/input_list = get_pin_data(IC_INPUT, 1)
|
||||
var/list/output_list = list()
|
||||
var/new_entry = get_pin_data(IC_INPUT, 2)
|
||||
output_list = input_list + new_entry
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, output_list)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/list/jointext
|
||||
name = "join text circuit"
|
||||
desc = "This circuit will add all elements of a list into one string, seperated by a character."
|
||||
extended_desc = "Default settings will encode the entire list into a string."
|
||||
inputs = list(
|
||||
"list to join" = IC_PINTYPE_LIST,
|
||||
"delimiter" = IC_PINTYPE_CHAR,
|
||||
"start" = IC_PINTYPE_NUMBER,
|
||||
"end" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
inputs_default = list(
|
||||
"2" = ",",
|
||||
"3" = 1,
|
||||
"4" = 0
|
||||
)
|
||||
outputs = list(
|
||||
"joined text" = IC_PINTYPE_STRING
|
||||
)
|
||||
icon_state = "addition"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/list/jointext/do_work()
|
||||
var/list/input_list = get_pin_data(IC_INPUT, 1)
|
||||
var/delimiter = get_pin_data(IC_INPUT, 2)
|
||||
var/start = get_pin_data(IC_INPUT, 3)
|
||||
var/end = get_pin_data(IC_INPUT, 4)
|
||||
|
||||
var/result = null
|
||||
|
||||
if(input_list.len && delimiter && !isnull(start) && !isnull(end))
|
||||
result = jointext(input_list, delimiter, start, end)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
@@ -0,0 +1,135 @@
|
||||
/obj/item/integrated_circuit/logic
|
||||
name = "logic gate"
|
||||
desc = "This tiny chip will decide for you!"
|
||||
extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE."
|
||||
complexity = 3
|
||||
outputs = list("result" = IC_PINTYPE_BOOLEAN)
|
||||
activators = list("compare" = IC_PINTYPE_PULSE_IN)
|
||||
category_text = "Logic"
|
||||
power_draw_per_use = 1
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary
|
||||
inputs = list(
|
||||
"A" = IC_PINTYPE_ANY,
|
||||
"B" = IC_PINTYPE_ANY
|
||||
)
|
||||
activators = list(
|
||||
"compare" = IC_PINTYPE_PULSE_IN,
|
||||
"on true result" = IC_PINTYPE_PULSE_OUT,
|
||||
"on false result" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/do_work()
|
||||
var/data1 = get_pin_data(IC_INPUT, 1)
|
||||
var/data2 = get_pin_data(IC_INPUT, 2)
|
||||
var/result = !!do_compare(data1, data2)
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
|
||||
if (result)
|
||||
activate_pin(2)
|
||||
else
|
||||
activate_pin(3)
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/proc/do_compare(A, B)
|
||||
return FALSE
|
||||
|
||||
/obj/item/integrated_circuit/logic/unary
|
||||
inputs = list(
|
||||
"A" = IC_PINTYPE_ANY
|
||||
)
|
||||
activators = list(
|
||||
"compare" = IC_PINTYPE_PULSE_IN,
|
||||
"on compare" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
|
||||
/obj/item/integrated_circuit/logic/unary/do_work()
|
||||
var/mydata = get_pin_data(IC_INPUT, 1)
|
||||
set_pin_data(IC_OUTPUT, 1, !!do_check(mydata))
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/logic/unary/proc/do_check(A)
|
||||
return FALSE
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/equals
|
||||
name = "equal gate"
|
||||
desc = "This gate compares two values, and outputs the number one if both are the same."
|
||||
icon_state = "equal"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/equals/do_compare(A, B)
|
||||
return A == B
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/not_equals
|
||||
name = "not equal gate"
|
||||
desc = "This gate compares two values, and outputs the number one if both are different."
|
||||
icon_state = "not_equal"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/not_equals/do_compare(A, B)
|
||||
return A != B
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/and
|
||||
name = "and gate"
|
||||
desc = "This gate will output 'one' if both inputs evaluate to true."
|
||||
icon_state = "and"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/and/do_compare(A, B)
|
||||
return A && B
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/or
|
||||
name = "or gate"
|
||||
desc = "This gate will output 'one' if one of the inputs evaluate to true."
|
||||
icon_state = "or"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/or/do_compare(A, B)
|
||||
return A || B
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/less_than
|
||||
name = "less than gate"
|
||||
desc = "This will output 'one' if the first input is less than the second input."
|
||||
icon_state = "less_than"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/less_than/do_compare(A, B)
|
||||
return A < B
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/less_than_or_equal
|
||||
name = "less than or equal gate"
|
||||
desc = "This will output 'one' if the first input is less than, or equal to the second input."
|
||||
icon_state = "less_than_or_equal"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/less_than_or_equal/do_compare(A, B)
|
||||
return A <= B
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/greater_than
|
||||
name = "greater than gate"
|
||||
desc = "This will output 'one' if the first input is greater than the second input."
|
||||
icon_state = "greater_than"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/greater_than/do_compare(A, B)
|
||||
return A > B
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/greater_than_or_equal
|
||||
name = "greater_than or equal gate"
|
||||
desc = "This will output 'one' if the first input is greater than, or equal to the second input."
|
||||
icon_state = "greater_than_or_equal"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/greater_than_or_equal/do_compare(A, B)
|
||||
return A >= B
|
||||
|
||||
/obj/item/integrated_circuit/logic/unary/not
|
||||
name = "not gate"
|
||||
desc = "This gate inverts what's fed into it."
|
||||
icon_state = "not"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
activators = list("invert" = IC_PINTYPE_PULSE_IN, "on inverted" = IC_PINTYPE_PULSE_OUT)
|
||||
|
||||
/obj/item/integrated_circuit/logic/unary/not/do_check(A)
|
||||
return !A
|
||||
@@ -0,0 +1,188 @@
|
||||
/obj/item/integrated_circuit/manipulation
|
||||
category_text = "Manipulation"
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/weapon_firing
|
||||
name = "weapon firing mechanism"
|
||||
desc = "This somewhat complicated system allows one to slot in a gun, direct it towards a position, and remotely fire it."
|
||||
extended_desc = "The firing mechanism can slot in most ranged weapons, ballistic and energy. \
|
||||
The first and second inputs need to be numbers. They are coordinates for the gun to fire at, relative to the machine itself. \
|
||||
The 'fire' activator will cause the mechanism to attempt to fire the weapon at the coordinates, if possible. Note that the \
|
||||
normal limitations to firearms, such as ammunition requirements and firing delays, still hold true if fired by the mechanism."
|
||||
complexity = 20
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
size = 3
|
||||
inputs = list(
|
||||
"target X rel" = IC_PINTYPE_NUMBER,
|
||||
"target Y rel" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list()
|
||||
activators = list(
|
||||
"fire" = IC_PINTYPE_PULSE_IN
|
||||
)
|
||||
var/obj/item/weapon/gun/installed_gun
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
|
||||
power_draw_per_use = 50 // The targeting mechanism uses this. The actual gun uses its own cell for firing if it's an energy weapon.
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/weapon_firing/Destroy()
|
||||
QDEL_NULL(installed_gun)
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/weapon_firing/attackby(var/obj/O, var/mob/user)
|
||||
if(istype(O, /obj/item/weapon/gun))
|
||||
var/obj/item/weapon/gun/gun = O
|
||||
if(installed_gun)
|
||||
user << "<span class='warning'>There's already a weapon installed.</span>"
|
||||
return
|
||||
user.drop_from_inventory(gun)
|
||||
installed_gun = gun
|
||||
size += gun.w_class
|
||||
gun.forceMove(src)
|
||||
user << "<span class='notice'>You slide \the [gun] into the firing mechanism.</span>"
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/weapon_firing/attack_self(var/mob/user)
|
||||
if(installed_gun)
|
||||
installed_gun.forceMove(get_turf(src))
|
||||
user << "<span class='notice'>You slide \the [installed_gun] out of the firing mechanism.</span>"
|
||||
size = initial(size)
|
||||
playsound(loc, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
installed_gun = null
|
||||
else
|
||||
user << "<span class='notice'>There's no weapon to remove from the mechanism.</span>"
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/weapon_firing/do_work()
|
||||
if(!installed_gun)
|
||||
return
|
||||
|
||||
var/target_x = get_pin_data(IC_INPUT, 1)
|
||||
var/target_y = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
if (!isnum(target_x) || !isnum(target_y) || !assembly)
|
||||
return
|
||||
|
||||
target_x = round(target_x)
|
||||
target_y = round(target_y)
|
||||
|
||||
if(target_x == 0 && target_y == 0) // Don't shoot ourselves.
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(assembly)
|
||||
var/Tx = T.x + target_x
|
||||
var/Ty = T.y + target_y
|
||||
if (Tx > world.maxx || Tx < 1 || Ty > world.maxy || Ty < 1)
|
||||
return // Off the edge of the map.
|
||||
|
||||
T = locate(Tx, Ty, T.z)
|
||||
|
||||
if(!T)
|
||||
return
|
||||
|
||||
installed_gun.Fire_userless(T)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/locomotion
|
||||
name = "locomotion circuit"
|
||||
desc = "This allows a machine to move in a given direction."
|
||||
icon_state = "locomotion"
|
||||
extended_desc = "The circuit accepts a 'dir' number as a direction to move towards.<br>\
|
||||
Pulsing the 'step towards dir' activator pin will cause the machine to move a meter in that direction, assuming it is not \
|
||||
being held, or anchored in some way. It should be noted that the ability to move is dependant on the type of assembly that this circuit inhabits."
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
complexity = 20
|
||||
// size = 5
|
||||
inputs = list("direction" = IC_PINTYPE_DIR)
|
||||
outputs = list()
|
||||
activators = list("step towards dir" = IC_PINTYPE_PULSE_IN)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 100
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/locomotion/do_work()
|
||||
..()
|
||||
var/turf/T = get_turf(src)
|
||||
if(T && assembly)
|
||||
if(assembly.anchored || !assembly.can_move())
|
||||
return
|
||||
if(assembly.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held.
|
||||
var/datum/integrated_io/wanted_dir = inputs[1]
|
||||
if(isnum(wanted_dir.data))
|
||||
step(assembly, wanted_dir.data)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade
|
||||
name = "grenade primer"
|
||||
desc = "This circuit comes with the ability to attach most types of grenades at prime them at will."
|
||||
extended_desc = "Time between priming and detonation is limited to between 1 to 12 seconds but is optional. \
|
||||
If unset, not a number, or a number less than 1 then the grenade's built-in timing will be used. \
|
||||
Beware: Once primed there is no aborting the process!"
|
||||
icon_state = "grenade"
|
||||
complexity = 30
|
||||
size = 2
|
||||
inputs = list("detonation time" = IC_PINTYPE_NUMBER)
|
||||
outputs = list()
|
||||
activators = list("prime grenade" = IC_PINTYPE_PULSE_IN)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
|
||||
var/obj/item/weapon/grenade/attached_grenade
|
||||
var/pre_attached_grenade_type
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/Initialize()
|
||||
. = ..()
|
||||
if(pre_attached_grenade_type)
|
||||
var/grenade = new pre_attached_grenade_type(src)
|
||||
attach_grenade(grenade)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/Destroy()
|
||||
if(attached_grenade && !attached_grenade.active)
|
||||
attached_grenade.dropInto(loc)
|
||||
detach_grenade()
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/attackby(var/obj/item/weapon/grenade/G, var/mob/user)
|
||||
if(istype(G))
|
||||
if(attached_grenade)
|
||||
to_chat(user, "<span class='warning'>There is already a grenade attached!</span>")
|
||||
else if(user.unEquip(G, force=1))
|
||||
user.visible_message("<span class='warning'>\The [user] attaches \a [G] to \the [src]!</span>", "<span class='notice'>You attach \the [G] to \the [src].</span>")
|
||||
attach_grenade(G)
|
||||
G.forceMove(src)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/attack_self(var/mob/user)
|
||||
if(attached_grenade)
|
||||
user.visible_message("<span class='warning'>\The [user] removes \an [attached_grenade] from \the [src]!</span>", "<span class='notice'>You remove \the [attached_grenade] from \the [src].</span>")
|
||||
user.put_in_any_hand_if_possible(attached_grenade) || attached_grenade.dropInto(loc)
|
||||
detach_grenade()
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/do_work()
|
||||
if(attached_grenade && !attached_grenade.active)
|
||||
var/datum/integrated_io/detonation_time = inputs[1]
|
||||
if(isnum(detonation_time.data) && detonation_time.data > 0)
|
||||
attached_grenade.det_time = between(1, detonation_time.data, 12) SECONDS
|
||||
attached_grenade.activate()
|
||||
var/atom/holder = loc
|
||||
log_and_message_admins("activated a grenade assembly. Last touches: Assembly: [holder.fingerprintslast] Circuit: [fingerprintslast] Grenade: [attached_grenade.fingerprintslast]")
|
||||
|
||||
// These procs do not relocate the grenade, that's the callers responsibility
|
||||
/obj/item/integrated_circuit/manipulation/grenade/proc/attach_grenade(var/obj/item/weapon/grenade/G)
|
||||
attached_grenade = G
|
||||
attached_grenade.OnDestroy(CALLBACK(src, .proc/detach_grenade))
|
||||
size += G.w_class
|
||||
desc += " \An [attached_grenade] is attached to it!"
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade()
|
||||
if(!attached_grenade)
|
||||
return
|
||||
attached_grenade.UnregisterOnDestroy(src)
|
||||
attached_grenade = null
|
||||
size = initial(size)
|
||||
desc = initial(desc)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/frag
|
||||
pre_attached_grenade_type = /obj/item/weapon/grenade/frag
|
||||
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 10)
|
||||
spawn_flags = null // Used for world initializing, see the #defines above.
|
||||
@@ -0,0 +1,125 @@
|
||||
/obj/item/integrated_circuit/memory
|
||||
complexity = 1
|
||||
category_text = "Memory"
|
||||
power_draw_per_use = 1
|
||||
|
||||
/obj/item/integrated_circuit/memory/storage
|
||||
name = "memory chip"
|
||||
icon_state = "memory"
|
||||
desc = "This tiny chip can store one piece of data."
|
||||
inputs = list()
|
||||
outputs = list()
|
||||
activators = list(
|
||||
"set" = IC_PINTYPE_PULSE_IN,
|
||||
"on set" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
var/number_of_pins = 1
|
||||
|
||||
/obj/item/integrated_circuit/memory/storage/Initialize()
|
||||
for(var/i = 1 to number_of_pins)
|
||||
inputs["input [i]"] = IC_PINTYPE_ANY // This is just a string since pins don't get built until ..() is called.
|
||||
outputs["output [i]"] = IC_PINTYPE_ANY
|
||||
complexity = number_of_pins
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/memory/storage/examine(mob/user)
|
||||
..()
|
||||
var/i
|
||||
for (i in 1 to outputs.len)
|
||||
var/datum/integrated_io/O = outputs[i]
|
||||
var/data = "nothing"
|
||||
if(isweakref(O.data))
|
||||
var/datum/d = O.data_as_type(/datum)
|
||||
if(d)
|
||||
data = "[d]"
|
||||
else if(!isnull(O.data))
|
||||
data = O.data
|
||||
to_chat(user, "\The [src] has [data] saved to address [i].")
|
||||
|
||||
/obj/item/integrated_circuit/memory/storage/do_work()
|
||||
for(var/i = 1 to inputs.len)
|
||||
var/data = get_pin_data(IC_INPUT, i)
|
||||
set_pin_data(IC_OUTPUT, i, data)
|
||||
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/memory/storage/medium
|
||||
name = "memory circuit"
|
||||
desc = "This circuit can store four pieces of data."
|
||||
icon_state = "memory4"
|
||||
power_draw_per_use = 2
|
||||
number_of_pins = 4
|
||||
|
||||
/obj/item/integrated_circuit/memory/storage/large
|
||||
name = "large memory circuit"
|
||||
desc = "This big circuit can hold eight pieces of data."
|
||||
icon_state = "memory8"
|
||||
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
|
||||
power_draw_per_use = 4
|
||||
number_of_pins = 8
|
||||
|
||||
/obj/item/integrated_circuit/memory/storage/huge
|
||||
name = "large memory stick"
|
||||
desc = "This stick of memory can hold up up to sixteen pieces of data."
|
||||
icon_state = "memory16"
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4)
|
||||
power_draw_per_use = 8
|
||||
number_of_pins = 16
|
||||
|
||||
/obj/item/integrated_circuit/memory/constant
|
||||
name = "constant chip"
|
||||
desc = "This tiny chip can store one piece of data, which cannot be overwritten without disassembly."
|
||||
icon_state = "memory"
|
||||
inputs = list()
|
||||
outputs = list("output pin" = IC_PINTYPE_ANY)
|
||||
activators = list(
|
||||
"push data" = IC_PINTYPE_PULSE_IN,
|
||||
"on push" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
var/accepting_refs = 0
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
var/data
|
||||
|
||||
/obj/item/integrated_circuit/memory/constant/do_work()
|
||||
set_pin_data(IC_OUTPUT, 1, data)
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/memory/constant/attack_self(mob/user)
|
||||
var/datum/integrated_io/O = outputs[1]
|
||||
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null")
|
||||
if(!CanInteract(user, physical_state))
|
||||
return
|
||||
|
||||
var/new_data = null
|
||||
switch(type_to_use)
|
||||
if("string")
|
||||
accepting_refs = 0
|
||||
new_data = sanitize(input("Now type in a string.","[src] string writing") as null|text)
|
||||
if(istext(new_data) && CanInteract(user, physical_state))
|
||||
data = new_data
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [O.display_data(data)].</span>")
|
||||
if("number")
|
||||
accepting_refs = 0
|
||||
new_data = input("Now type in a number.","[src] number writing") as null|num
|
||||
if(isnum(new_data) && CanInteract(user, physical_state))
|
||||
data = new_data
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [O.display_data(data)].</span>")
|
||||
if("ref")
|
||||
accepting_refs = 1
|
||||
to_chat(user, "<span class='notice'>You turn \the [src]'s ref scanner on. Slide it across \
|
||||
an object for a ref of that object to save it in memory.</span>")
|
||||
if("null")
|
||||
data = null
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
|
||||
|
||||
/obj/item/integrated_circuit/memory/constant/afterattack(atom/target, mob/living/user, proximity)
|
||||
if(accepting_refs && proximity)
|
||||
var/datum/integrated_io/O = outputs[1]
|
||||
data = WEAKREF(target)
|
||||
visible_message("<span class='notice'>[user] slides [src]'s ref scanner over \the [target].</span>")
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to a reference to [O.display_data(data)]. The ref scanner is \
|
||||
now off.</span>")
|
||||
accepting_refs = 0
|
||||
@@ -0,0 +1,352 @@
|
||||
/obj/item/integrated_circuit/output
|
||||
category_text = "Output"
|
||||
|
||||
/obj/item/integrated_circuit/output/screen
|
||||
name = "small screen"
|
||||
desc = "This small screen can display a single piece of data, when the machine is examined closely."
|
||||
icon_state = "screen"
|
||||
inputs = list("displayed data" = IC_PINTYPE_ANY)
|
||||
outputs = list()
|
||||
activators = list("load data" = IC_PINTYPE_PULSE_IN)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 10
|
||||
var/stuff_to_display = null
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/disconnect_all()
|
||||
..()
|
||||
stuff_to_display = null
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/any_examine(mob/user)
|
||||
if (displayed_name)
|
||||
to_chat(user, "There is a little screen labeled '[displayed_name]', which displays [!isnull(stuff_to_display) ? "'[stuff_to_display]'" : "nothing"].")
|
||||
else
|
||||
to_chat(user, "There is an unlabelled little screen, which displays [!isnull(stuff_to_display) ? "'[stuff_to_display]'" : "nothing"].")
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/do_work()
|
||||
var/datum/integrated_io/I = inputs[1]
|
||||
if(isweakref(I.data))
|
||||
var/datum/d = I.data_as_type(/datum)
|
||||
if(d)
|
||||
stuff_to_display = "[d]"
|
||||
else
|
||||
stuff_to_display = I.data
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/medium
|
||||
name = "screen"
|
||||
desc = "This screen allows for people holding the device to see a piece of data."
|
||||
icon_state = "screen_medium"
|
||||
power_draw_per_use = 20
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/medium/do_work()
|
||||
..()
|
||||
var/list/nearby_things = range(0, get_turf(src))
|
||||
for(var/mob/M in nearby_things)
|
||||
var/obj/O = assembly ? assembly : src
|
||||
to_chat(M, "<span class='notice'>\icon[O] [stuff_to_display]</span>")
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/large
|
||||
name = "large screen"
|
||||
desc = "This screen allows for people able to see the device to see a piece of data."
|
||||
icon_state = "screen_large"
|
||||
power_draw_per_use = 40
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/large/do_work()
|
||||
..()
|
||||
var/obj/O = assembly ? loc : assembly
|
||||
O.visible_message("<span class='notice'>\icon[O] [stuff_to_display]</span>")
|
||||
|
||||
/obj/item/integrated_circuit/output/light
|
||||
name = "light"
|
||||
desc = "This light can turn on and off on command."
|
||||
icon_state = "light"
|
||||
complexity = 4
|
||||
inputs = list()
|
||||
outputs = list()
|
||||
activators = list("toggle light" = IC_PINTYPE_PULSE_IN)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
var/light_toggled = 0
|
||||
var/light_brightness = 3
|
||||
var/light_rgb = "#FFFFFF"
|
||||
power_draw_idle = 0 // Adjusted based on brightness.
|
||||
|
||||
/obj/item/integrated_circuit/output/light/do_work()
|
||||
light_toggled = !light_toggled
|
||||
update_lighting()
|
||||
|
||||
/obj/item/integrated_circuit/output/light/proc/update_lighting()
|
||||
if(light_toggled)
|
||||
if(assembly)
|
||||
assembly.set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb)
|
||||
else
|
||||
if(assembly)
|
||||
assembly.set_light(0)
|
||||
power_draw_idle = light_toggled ? light_brightness * 2 : 0
|
||||
|
||||
/obj/item/integrated_circuit/output/light/advanced/update_lighting()
|
||||
var/new_color = get_pin_data(IC_INPUT, 1)
|
||||
var/brightness = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
if(new_color && isnum(brightness))
|
||||
brightness = Clamp(brightness, 0, 6)
|
||||
light_rgb = new_color
|
||||
light_brightness = brightness
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/integrated_circuit/output/light/power_fail() // Turns off the flashlight if there's no power left.
|
||||
light_toggled = FALSE
|
||||
update_lighting()
|
||||
|
||||
/obj/item/integrated_circuit/output/light/advanced
|
||||
name = "advanced light"
|
||||
desc = "This light can turn on and off on command, in any color, and in various brightness levels."
|
||||
icon_state = "light_adv"
|
||||
complexity = 8
|
||||
inputs = list(
|
||||
"color" = IC_PINTYPE_COLOR,
|
||||
"brightness" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list()
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
|
||||
|
||||
/obj/item/integrated_circuit/output/light/advanced/on_data_written()
|
||||
update_lighting()
|
||||
|
||||
/obj/item/integrated_circuit/output/sound
|
||||
name = "speaker circuit"
|
||||
desc = "A miniature speaker is attached to this component."
|
||||
icon_state = "speaker"
|
||||
complexity = 8
|
||||
cooldown_per_use = 4 SECONDS
|
||||
inputs = list(
|
||||
"sound ID" = IC_PINTYPE_STRING,
|
||||
"volume" = IC_PINTYPE_NUMBER,
|
||||
"frequency" = IC_PINTYPE_BOOLEAN
|
||||
)
|
||||
outputs = list()
|
||||
activators = list("play sound" = IC_PINTYPE_PULSE_IN)
|
||||
power_draw_per_use = 20
|
||||
var/list/sounds = list()
|
||||
|
||||
/obj/item/integrated_circuit/output/text_to_speech
|
||||
name = "text-to-speech circuit"
|
||||
desc = "A miniature speaker is attached to this component."
|
||||
extended_desc = "This unit is more advanced than the plain speaker circuit, able to transpose any valid text to speech."
|
||||
icon_state = "speaker"
|
||||
complexity = 12
|
||||
cooldown_per_use = 4 SECONDS
|
||||
inputs = list("text" = IC_PINTYPE_STRING)
|
||||
outputs = list()
|
||||
activators = list("to speech" = IC_PINTYPE_PULSE_IN)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 60
|
||||
|
||||
/obj/item/integrated_circuit/output/text_to_speech/do_work()
|
||||
text = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(text))
|
||||
var/obj/O = assembly ? loc : assembly
|
||||
audible_message("\icon[O] \The [O.name] states, \"[text]\"")
|
||||
|
||||
/obj/item/integrated_circuit/output/sound/Initialize()
|
||||
. = ..()
|
||||
extended_desc = list()
|
||||
extended_desc += "The first input pin determines which sound is used. The choices are; "
|
||||
extended_desc += jointext(sounds, ", ")
|
||||
extended_desc += ". The second pin determines the volume of sound that is played"
|
||||
extended_desc += ", and the third determines if the frequency of the sound will vary with each activation."
|
||||
extended_desc = jointext(extended_desc, null)
|
||||
|
||||
/obj/item/integrated_circuit/output/sound/do_work()
|
||||
var/ID = get_pin_data(IC_INPUT, 1)
|
||||
var/vol = get_pin_data(IC_INPUT, 2)
|
||||
var/freq = get_pin_data(IC_INPUT, 3)
|
||||
if(!isnull(ID) && !isnull(vol))
|
||||
var/selected_sound = sounds[ID]
|
||||
if(!selected_sound)
|
||||
return
|
||||
vol = between(0, vol, 100)
|
||||
playsound(get_turf(src), selected_sound, vol, freq, -1)
|
||||
|
||||
/obj/item/integrated_circuit/output/sound/beeper
|
||||
name = "beeper circuit"
|
||||
desc = "A miniature speaker is attached to this component. This is often used in the construction of motherboards, which use \
|
||||
the speaker to tell the user if something goes very wrong when booting up. It can also do other similar synthetic sounds such \
|
||||
as buzzing, pinging, chiming, and more."
|
||||
sounds = list(
|
||||
"beep" = 'sound/machines/twobeep.ogg',
|
||||
"chime" = 'sound/machines/chime.ogg',
|
||||
"buzz sigh" = 'sound/machines/buzz-sigh.ogg',
|
||||
"buzz twice" = 'sound/machines/buzz-two.ogg',
|
||||
"ping" = 'sound/machines/ping.ogg',
|
||||
"synth yes" = 'sound/machines/synth_yes.ogg',
|
||||
"synth no" = 'sound/machines/synth_no.ogg',
|
||||
"warning buzz" = 'sound/machines/warning-buzzer.ogg'
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/output/sound/beepsky
|
||||
name = "securitron sound circuit"
|
||||
desc = "A miniature speaker is attached to this component. Considered by some to be the essential component for a securitron."
|
||||
sounds = list(
|
||||
"creep" = 'sound/voice/bcreep.ogg',
|
||||
"criminal" = 'sound/voice/bcriminal.ogg',
|
||||
"freeze" = 'sound/voice/bfreeze.ogg',
|
||||
"god" = 'sound/voice/bgod.ogg',
|
||||
"i am the law" = 'sound/voice/biamthelaw.ogg',
|
||||
"insult" = 'sound/voice/binsult.ogg',
|
||||
"radio" = 'sound/voice/bradio.ogg',
|
||||
"secure day" = 'sound/voice/bsecureday.ogg'
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 1)
|
||||
|
||||
/obj/item/integrated_circuit/output/sound/medbot
|
||||
name = "medbot sound circuit"
|
||||
desc = "A miniature speaker is attached to this component, used to annoy patients while they get pricked by a medbot."
|
||||
sounds = list(
|
||||
"surgeon" = 'sound/voice/medbot/msurgeon.ogg',
|
||||
"radar" = 'sound/voice/medbot/mradar.ogg',
|
||||
"feel better" = 'sound/voice/medbot/mfeelbetter.ogg',
|
||||
"patched up" = 'sound/voice/medbot/mpatchedup.ogg',
|
||||
"injured" = 'sound/voice/medbot/minjured.ogg',
|
||||
"insult" = 'sound/voice/medbot/minsult.ogg',
|
||||
"coming" = 'sound/voice/medbot/mcoming.ogg',
|
||||
"help" = 'sound/voice/medbot/mhelp.ogg',
|
||||
"live" = 'sound/voice/medbot/mlive.ogg',
|
||||
"lost" = 'sound/voice/medbot/mlost.ogg',
|
||||
"flies" = 'sound/voice/medbot/mflies.ogg',
|
||||
"catch" = 'sound/voice/medbot/mcatch.ogg',
|
||||
"delicious" = 'sound/voice/medbot/mdelicious.ogg',
|
||||
"apple" = 'sound/voice/medbot/mapple.ogg',
|
||||
"no" = 'sound/voice/medbot/mno.ogg'
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 1)
|
||||
|
||||
/obj/item/integrated_circuit/output/video_camera
|
||||
name = "video camera circuit"
|
||||
desc = "This small camera allows a remote viewer to see what it sees."
|
||||
extended_desc = "The camera is linked to the Research camera network."
|
||||
icon_state = "video_camera"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
complexity = 10
|
||||
inputs = list(
|
||||
"camera name" = IC_PINTYPE_STRING,
|
||||
"camera active" = IC_PINTYPE_BOOLEAN
|
||||
)
|
||||
inputs_default = list("1" = "video camera circuit")
|
||||
outputs = list()
|
||||
activators = list()
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_idle = 5 // Raises to 80 when on.
|
||||
var/obj/machinery/camera/network/research/camera
|
||||
|
||||
/obj/item/integrated_circuit/output/video_camera/Initialize()
|
||||
. = ..()
|
||||
camera = new(src)
|
||||
on_data_written()
|
||||
|
||||
/obj/item/integrated_circuit/output/video_camera/Destroy()
|
||||
QDEL_NULL(camera)
|
||||
return ..()
|
||||
|
||||
/obj/item/integrated_circuit/output/video_camera/proc/set_camera_status(var/status)
|
||||
if(camera)
|
||||
camera.set_status(status)
|
||||
power_draw_idle = camera.status ? 80 : 5
|
||||
if(camera.status) // Ensure that there's actually power.
|
||||
if(!draw_idle_power())
|
||||
power_fail()
|
||||
|
||||
/obj/item/integrated_circuit/output/video_camera/on_data_written()
|
||||
if(camera)
|
||||
var/cam_name = get_pin_data(IC_INPUT, 1)
|
||||
var/cam_active = get_pin_data(IC_INPUT, 2)
|
||||
if(!isnull(cam_name))
|
||||
camera.c_tag = cam_name
|
||||
set_camera_status(cam_active)
|
||||
|
||||
/obj/item/integrated_circuit/output/video_camera/power_fail()
|
||||
if(camera)
|
||||
set_camera_status(0)
|
||||
set_pin_data(IC_INPUT, 2, FALSE)
|
||||
|
||||
/obj/item/integrated_circuit/output/led
|
||||
name = "light-emitting diode"
|
||||
desc = "This a LED that is lit whenever there is TRUE-equivalent data on its input."
|
||||
extended_desc = "TRUE-equivalent values are: Non-empty strings, non-zero numbers, and valid refs."
|
||||
complexity = 0.1
|
||||
icon_state = "led"
|
||||
inputs = list("lit" = IC_PINTYPE_BOOLEAN)
|
||||
outputs = list()
|
||||
activators = list()
|
||||
power_draw_idle = 0 // Raises to 1 when lit.
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
var/led_color
|
||||
var/color_name
|
||||
|
||||
/obj/item/integrated_circuit/output/led/on_data_written()
|
||||
power_draw_idle = get_pin_data(IC_INPUT, 1) ? 1 : 0
|
||||
|
||||
/obj/item/integrated_circuit/output/led/power_fail()
|
||||
set_pin_data(IC_INPUT, 1, FALSE)
|
||||
|
||||
/obj/item/integrated_circuit/output/led/any_examine(mob/user)
|
||||
var/text_output = list()
|
||||
var/initial_name = initial(name)
|
||||
|
||||
// Doing all this work just to have a color-blind friendly output.
|
||||
text_output += "There is "
|
||||
if(name == initial_name)
|
||||
text_output += "\an [name]"
|
||||
else
|
||||
text_output += "\an ["\improper[initial_name]"] labeled '[name]'"
|
||||
text_output += " which is currently [get_pin_data(IC_INPUT, 1) ? "lit <font color=[led_color]>[color_name]</font>" : "unlit."]"
|
||||
to_chat(user,jointext(text_output,null))
|
||||
|
||||
/obj/item/integrated_circuit/output/led/red
|
||||
name = "red LED"
|
||||
led_color = COLOR_RED
|
||||
color_name = "red"
|
||||
|
||||
/obj/item/integrated_circuit/output/led/orange
|
||||
name = "orange LED"
|
||||
led_color = COLOR_ORANGE
|
||||
color_name = "orange"
|
||||
|
||||
/obj/item/integrated_circuit/output/led/yellow
|
||||
name = "yellow LED"
|
||||
led_color = COLOR_YELLOW
|
||||
color_name = "yellow"
|
||||
|
||||
/obj/item/integrated_circuit/output/led/green
|
||||
name = "green LED"
|
||||
led_color = COLOR_GREEN
|
||||
color_name = "green"
|
||||
|
||||
/obj/item/integrated_circuit/output/led/blue
|
||||
name = "blue LED"
|
||||
led_color = COLOR_BLUE
|
||||
color_name = "blue"
|
||||
|
||||
/obj/item/integrated_circuit/output/led/purple
|
||||
name = "purple LED"
|
||||
led_color = COLOR_PURPLE
|
||||
color_name = "purple"
|
||||
|
||||
/obj/item/integrated_circuit/output/led/cyan
|
||||
name = "cyan LED"
|
||||
led_color = COLOR_CYAN
|
||||
color_name = "cyan"
|
||||
|
||||
/obj/item/integrated_circuit/output/led/white
|
||||
name = "white LED"
|
||||
led_color = COLOR_WHITE
|
||||
color_name = "white"
|
||||
|
||||
/obj/item/integrated_circuit/output/led/pink
|
||||
name = "pink LED"
|
||||
led_color = COLOR_PINK
|
||||
color_name = "pink"
|
||||
@@ -0,0 +1,88 @@
|
||||
/obj/item/integrated_circuit/power/
|
||||
category_text = "Power - Active"
|
||||
|
||||
/obj/item/integrated_circuit/power/transmitter
|
||||
name = "power transmission circuit"
|
||||
desc = "This can wirelessly transmit electricity from an assembly's battery towards a nearby machine."
|
||||
icon_state = "power_transmitter"
|
||||
extended_desc = "This circuit transmits 5 kJ of electricity every time the activator pin is pulsed. The input pin must be \
|
||||
a reference to a machine to send electricity to. This can be a battery, or anything containing a battery. The machine can exist \
|
||||
inside the assembly, or adjacent to it. The power is sourced from the assembly's power cell. If the target is outside of the assembly, \
|
||||
some power is lost due to ineffiency."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
complexity = 16
|
||||
inputs = list("target" = IC_PINTYPE_REF)
|
||||
outputs = list(
|
||||
"target cell charge" = IC_PINTYPE_NUMBER,
|
||||
"target cell max charge" = IC_PINTYPE_NUMBER,
|
||||
"target cell percentage" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("transmit" = IC_PINTYPE_PULSE_IN, "on transmit" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3)
|
||||
power_draw_per_use = 500 // Inefficency has to come from somewhere.
|
||||
var/amount_to_move = 5000
|
||||
|
||||
/obj/item/integrated_circuit/power/transmitter/large
|
||||
name = "large power transmission circuit"
|
||||
desc = "This can wirelessly transmit a lot of electricity from an assembly's battery towards a nearby machine. Warning: Do not operate in flammable enviroments."
|
||||
extended_desc = "This circuit transmits 20 kJ of electricity every time the activator pin is pulsed. The input pin must be \
|
||||
a reference to a machine to send electricity to. This can be a battery, or anything containing a battery. The machine can exist \
|
||||
inside the assembly, or adjacent to it. The power is sourced from the assembly's power cell. If the target is outside of the assembly, \
|
||||
some power is lost due to ineffiency."
|
||||
w_class = ITEMSIZE_LARGE
|
||||
complexity = 32
|
||||
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 6, TECH_MAGNET = 5)
|
||||
power_draw_per_use = 2000
|
||||
amount_to_move = 20000
|
||||
|
||||
/obj/item/integrated_circuit/power/transmitter/do_work()
|
||||
|
||||
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
|
||||
if(AM && assembly)
|
||||
var/obj/item/weapon/cell/cell = null
|
||||
if(istype(AM, /obj/item/weapon/cell)) // Is this already a cell?
|
||||
cell = AM
|
||||
else // If not, maybe there's a cell inside it?
|
||||
for(var/obj/item/weapon/cell/C in AM.contents)
|
||||
if(C) // Find one cell to charge.
|
||||
cell = C
|
||||
break
|
||||
if(cell)
|
||||
var/transfer_amount = amount_to_move
|
||||
var/turf/A = get_turf(src)
|
||||
var/turf/B = get_turf(AM)
|
||||
if(A.Adjacent(B))
|
||||
if(AM.loc != assembly)
|
||||
transfer_amount *= 0.8 // Losses due to distance.
|
||||
|
||||
if(cell.fully_charged())
|
||||
set_pin_data(IC_OUTPUT, 1, cell.charge)
|
||||
set_pin_data(IC_OUTPUT, 2, cell.maxcharge)
|
||||
set_pin_data(IC_OUTPUT, 3, cell.percent())
|
||||
push_data()
|
||||
return FALSE
|
||||
|
||||
if(transfer_amount && assembly.draw_power(amount_to_move)) // CELLRATE is already handled in draw_power()
|
||||
cell.give(transfer_amount * CELLRATE)
|
||||
AM.update_icon()
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, cell.charge)
|
||||
set_pin_data(IC_OUTPUT, 2, cell.maxcharge)
|
||||
set_pin_data(IC_OUTPUT, 3, cell.percent())
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
return TRUE
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, null)
|
||||
set_pin_data(IC_OUTPUT, 2, null)
|
||||
set_pin_data(IC_OUTPUT, 3, null)
|
||||
push_data()
|
||||
|
||||
return FALSE
|
||||
|
||||
/obj/item/integrated_circuit/power/transmitter/large/do_work()
|
||||
if(..()) // If the above code succeeds, do this below.
|
||||
if(prob(2))
|
||||
spark(src, 3)
|
||||
visible_message("<span class='warning'>\The [assembly] makes some sparks!</span>")
|
||||
@@ -0,0 +1,160 @@
|
||||
/obj/item/integrated_circuit/reagent
|
||||
category_text = "Reagent"
|
||||
var/volume = 0
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
|
||||
|
||||
/obj/item/integrated_circuit/reagent/Initialize()
|
||||
. = ..()
|
||||
if(volume)
|
||||
create_reagents(volume)
|
||||
|
||||
/obj/item/integrated_circuit/reagent/smoke
|
||||
name = "smoke generator"
|
||||
desc = "Unlike most electronics, creating smoke is completely intentional."
|
||||
icon_state = "smoke"
|
||||
extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \
|
||||
into the smoke clouds when activated. The reagents are consumed when smoke is made."
|
||||
flags = OPENCONTAINER
|
||||
complexity = 20
|
||||
cooldown_per_use = 30 SECONDS
|
||||
inputs = list()
|
||||
outputs = list()
|
||||
activators = list("create smoke" = IC_PINTYPE_PULSE_IN)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3)
|
||||
volume = 100
|
||||
power_draw_per_use = 20
|
||||
|
||||
/obj/item/integrated_circuit/reagent/smoke/do_work()
|
||||
playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
var/datum/effect/effect/system/smoke_spread/chem/smoke_system = new()
|
||||
smoke_system.set_up(reagents, 10, 0, get_turf(src))
|
||||
spawn(0)
|
||||
for(var/i = 1 to 8)
|
||||
smoke_system.start()
|
||||
reagents.clear_reagents()
|
||||
|
||||
/obj/item/integrated_circuit/reagent/injector
|
||||
name = "integrated hypo-injector"
|
||||
desc = "This scary looking thing is able to pump liquids into whatever it's pointed at."
|
||||
icon_state = "injector"
|
||||
extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine. The target \
|
||||
must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing."
|
||||
flags = OPENCONTAINER
|
||||
complexity = 20
|
||||
cooldown_per_use = 6 SECONDS
|
||||
inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER)
|
||||
inputs_default = list("2" = 5)
|
||||
outputs = list()
|
||||
activators = list("inject" = IC_PINTYPE_PULSE_IN)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
volume = 30
|
||||
power_draw_per_use = 15
|
||||
|
||||
/obj/item/integrated_circuit/reagent/injector/proc/inject_amount()
|
||||
var/amount = get_pin_data(IC_INPUT, 2)
|
||||
if(isnum(amount))
|
||||
return Clamp(amount, 0, 30)
|
||||
|
||||
/obj/item/integrated_circuit/reagent/injector/do_work()
|
||||
set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
|
||||
|
||||
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
|
||||
if(!istype(AM)) //Invalid input
|
||||
return
|
||||
if(!reagents.total_volume) // Empty
|
||||
return
|
||||
if(AM.can_be_injected_by(src))
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
var/turf/T = get_turf(AM)
|
||||
T.visible_message("<span class='warning'>[src] is trying to inject [L]!</span>")
|
||||
sleep(3 SECONDS)
|
||||
if(!L.can_be_injected_by(src))
|
||||
return
|
||||
var/contained = reagents.get_reagents()
|
||||
var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD)
|
||||
message_admins("[src] injected \the [L] with [trans]u of [contained].")
|
||||
to_chat(AM, "<span class='notice'>You feel a tiny prick!</span>")
|
||||
visible_message("<span class='warning'>[src] injects [L]!</span>")
|
||||
else
|
||||
reagents.trans_to(AM, inject_amount())
|
||||
|
||||
/obj/item/integrated_circuit/reagent/pump
|
||||
name = "reagent pump"
|
||||
desc = "Moves liquids safely inside a machine, or even nearby it."
|
||||
icon_state = "reagent_pump"
|
||||
extended_desc = "This is a pump, which will move liquids from the source ref to the target ref. The third pin determines \
|
||||
how much liquid is moved per pulse, between 0 and 50. The pump can move reagents to any open container inside the machine, or \
|
||||
outside the machine if it is next to the machine. Note that this cannot be used on entities."
|
||||
flags = OPENCONTAINER
|
||||
complexity = 8
|
||||
inputs = list(
|
||||
"source" = IC_PINTYPE_REF,
|
||||
"target" = IC_PINTYPE_REF,
|
||||
"injection amount" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
inputs_default = list("3" = 5)
|
||||
outputs = list()
|
||||
activators = list(
|
||||
"transfer reagents" = IC_PINTYPE_PULSE_IN,
|
||||
"on transfer" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
|
||||
var/transfer_amount = 10
|
||||
power_draw_per_use = 10
|
||||
|
||||
/obj/item/integrated_circuit/reagent/pump/on_data_written()
|
||||
var/new_amount = get_pin_data(IC_INPUT, 3)
|
||||
if(!isnull(new_amount))
|
||||
new_amount = Clamp(new_amount, 0, 50)
|
||||
transfer_amount = new_amount
|
||||
|
||||
/obj/item/integrated_circuit/reagent/pump/do_work()
|
||||
var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
|
||||
var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable)
|
||||
|
||||
if(!istype(source) || !istype(target)) //Invalid input
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
if(source.Adjacent(T) && target.Adjacent(T))
|
||||
if(!source.reagents || !target.reagents)
|
||||
return
|
||||
if(ismob(source) || ismob(target))
|
||||
return
|
||||
if(!source.is_open_container() || !target.is_open_container())
|
||||
return
|
||||
if(!target.reagents.get_free_space())
|
||||
return
|
||||
|
||||
source.reagents.trans_to(target, transfer_amount)
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/reagent/storage
|
||||
name = "reagent storage"
|
||||
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u."
|
||||
icon_state = "reagent_storage"
|
||||
extended_desc = "This is effectively an internal beaker."
|
||||
flags = OPENCONTAINER
|
||||
complexity = 4
|
||||
inputs = list()
|
||||
outputs = list("volume used" = IC_PINTYPE_NUMBER)
|
||||
activators = list()
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
|
||||
volume = 60
|
||||
|
||||
/obj/item/integrated_circuit/reagent/storage/on_reagent_change()
|
||||
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
|
||||
push_data()
|
||||
|
||||
/obj/item/integrated_circuit/reagent/storage/cryo
|
||||
name = "cryo reagent storage"
|
||||
desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. This will also suppress reactions."
|
||||
icon_state = "reagent_storage_cryo"
|
||||
extended_desc = "This is effectively an internal cryo beaker."
|
||||
flags = OPENCONTAINER | NOREACT
|
||||
complexity = 8
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_MATERIALS = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
|
||||
@@ -0,0 +1,33 @@
|
||||
/obj/item/integrated_circuit/smart
|
||||
category_text = "Smart"
|
||||
|
||||
/obj/item/integrated_circuit/smart/basic_pathfinder
|
||||
name = "basic pathfinder"
|
||||
desc = "This complex circuit is able to determine what direction a given target is."
|
||||
extended_desc = "This circuit uses a miniturized, integrated camera to determine where the target is. If the machine \
|
||||
cannot see the target, it will not be able to calculate the correct direction."
|
||||
icon_state = "numberpad"
|
||||
complexity = 25
|
||||
inputs = list("target" = IC_PINTYPE_REF)
|
||||
outputs = list("dir" = IC_PINTYPE_DIR)
|
||||
activators = list("calculate dir" = IC_PINTYPE_PULSE_IN, "on calculated" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5)
|
||||
power_draw_per_use = 40
|
||||
|
||||
/obj/item/integrated_circuit/smart/basic_pathfinder/do_work()
|
||||
var/datum/integrated_io/I = inputs[1]
|
||||
set_pin_data(IC_OUTPUT, 1, null)
|
||||
|
||||
if(!isweakref(I.data))
|
||||
return
|
||||
var/atom/A = I.data.resolve()
|
||||
if(!A)
|
||||
return
|
||||
if(!(A in view(get_turf(src))))
|
||||
return // Can't see the target.
|
||||
var/desired_dir = get_dir(get_turf(src), A)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, desired_dir)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
@@ -0,0 +1,147 @@
|
||||
/obj/item/integrated_circuit/time
|
||||
name = "time circuit"
|
||||
desc = "Now you can build your own clock!"
|
||||
complexity = 2
|
||||
inputs = list()
|
||||
outputs = list()
|
||||
category_text = "Time"
|
||||
|
||||
/obj/item/integrated_circuit/time/delay
|
||||
name = "two-sec delay circuit"
|
||||
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
|
||||
This circuit is set to send a pulse after a delay of two seconds."
|
||||
icon_state = "delay-20"
|
||||
var/delay = 2 SECONDS
|
||||
activators = list("incoming"= IC_PINTYPE_PULSE_IN,"outgoing" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 2
|
||||
|
||||
/obj/item/integrated_circuit/time/delay/do_work()
|
||||
addtimer(CALLBACK(src, /obj/item/integrated_circuit/.proc/activate_pin, 2), delay)
|
||||
|
||||
/obj/item/integrated_circuit/time/delay/five_sec
|
||||
name = "five-sec delay circuit"
|
||||
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
|
||||
This circuit is set to send a pulse after a delay of five seconds."
|
||||
icon_state = "delay-50"
|
||||
delay = 5 SECONDS
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/time/delay/one_sec
|
||||
name = "one-sec delay circuit"
|
||||
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
|
||||
This circuit is set to send a pulse after a delay of one second."
|
||||
icon_state = "delay-10"
|
||||
delay = 1 SECOND
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/time/delay/half_sec
|
||||
name = "half-sec delay circuit"
|
||||
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
|
||||
This circuit is set to send a pulse after a delay of half a second."
|
||||
icon_state = "delay-5"
|
||||
delay = 5
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/time/delay/tenth_sec
|
||||
name = "tenth-sec delay circuit"
|
||||
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
|
||||
This circuit is set to send a pulse after a delay of 1/10th of a second."
|
||||
icon_state = "delay-1"
|
||||
delay = 1
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/time/delay/custom
|
||||
name = "custom delay circuit"
|
||||
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
|
||||
This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse."
|
||||
icon_state = "delay"
|
||||
inputs = list("delay time" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/time/delay/custom/do_work()
|
||||
var/delay_input = get_pin_data(IC_INPUT, 1)
|
||||
if(delay_input && isnum(delay_input) )
|
||||
var/new_delay = between(1, delay_input, 1 HOUR)
|
||||
delay = new_delay
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/integrated_circuit/time/ticker
|
||||
name = "ticker circuit"
|
||||
desc = "This circuit sends an automatic pulse every four seconds."
|
||||
icon_state = "tick-m"
|
||||
complexity = 8
|
||||
var/ticks_to_pulse = 4
|
||||
var/ticks_completed = 0
|
||||
var/is_running = FALSE
|
||||
inputs = list("enable ticking" = IC_PINTYPE_BOOLEAN)
|
||||
activators = list("outgoing pulse" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 4
|
||||
|
||||
/obj/item/integrated_circuit/time/ticker/Destroy()
|
||||
STOP_PROCESSING(SSelectronics, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/time/ticker/on_data_written()
|
||||
var/do_tick = get_pin_data(IC_INPUT, 1)
|
||||
if(do_tick && !is_running)
|
||||
is_running = TRUE
|
||||
START_PROCESSING(SSelectronics, src)
|
||||
else if(is_running)
|
||||
is_running = FALSE
|
||||
STOP_PROCESSING(SSelectronics, src)
|
||||
ticks_completed = 0
|
||||
|
||||
/obj/item/integrated_circuit/time/ticker/process()
|
||||
var/process_ticks = SSelectronics.wait
|
||||
ticks_completed += process_ticks
|
||||
if(ticks_completed >= ticks_to_pulse)
|
||||
if(ticks_to_pulse >= process_ticks)
|
||||
ticks_completed -= ticks_to_pulse
|
||||
else
|
||||
ticks_completed = 0
|
||||
activate_pin(1)
|
||||
|
||||
/obj/item/integrated_circuit/time/ticker/fast
|
||||
name = "fast ticker"
|
||||
desc = "This advanced circuit sends an automatic pulse every two seconds."
|
||||
icon_state = "tick-f"
|
||||
complexity = 12
|
||||
ticks_to_pulse = 2
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 8
|
||||
|
||||
/obj/item/integrated_circuit/time/ticker/slow
|
||||
name = "slow ticker"
|
||||
desc = "This simple circuit sends an automatic pulse every six seconds."
|
||||
icon_state = "tick-s"
|
||||
complexity = 4
|
||||
ticks_to_pulse = 6
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 2
|
||||
|
||||
/obj/item/integrated_circuit/time/clock
|
||||
name = "integrated clock"
|
||||
desc = "Tells you what the local time is, specific to your station, planet, or facility."
|
||||
icon_state = "clock"
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"time" = IC_PINTYPE_STRING,
|
||||
"hours" = IC_PINTYPE_NUMBER,
|
||||
"minutes" = IC_PINTYPE_NUMBER,
|
||||
"seconds" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("get time" = IC_PINTYPE_PULSE_IN, "on time got" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 4
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/do_work()
|
||||
set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") )
|
||||
set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) )
|
||||
set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) )
|
||||
set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) )
|
||||
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
@@ -0,0 +1,143 @@
|
||||
//These circuits do not-so-simple math.
|
||||
/obj/item/integrated_circuit/trig
|
||||
complexity = 1
|
||||
inputs = list(
|
||||
"A" = IC_PINTYPE_NUMBER,
|
||||
"B" = IC_PINTYPE_NUMBER,
|
||||
"C" = IC_PINTYPE_NUMBER,
|
||||
"D" = IC_PINTYPE_NUMBER,
|
||||
"E" = IC_PINTYPE_NUMBER,
|
||||
"F" = IC_PINTYPE_NUMBER,
|
||||
"G" = IC_PINTYPE_NUMBER,
|
||||
"H" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list("result" = IC_PINTYPE_NUMBER)
|
||||
activators = list(
|
||||
"compute" = IC_PINTYPE_PULSE_IN,
|
||||
"on computed" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
category_text = "Trig"
|
||||
extended_desc = "Input and output are in degrees."
|
||||
power_draw_per_use = 1 // Still cheap math.
|
||||
|
||||
// Sine //
|
||||
|
||||
/obj/item/integrated_circuit/trig/sine
|
||||
name = "sin circuit"
|
||||
desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A."
|
||||
icon_state = "sine"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/trig/sine/do_work()
|
||||
pull_data()
|
||||
var/result = null
|
||||
var/A = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(A))
|
||||
result = sin(A)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// Cosine //
|
||||
|
||||
/obj/item/integrated_circuit/trig/cosine
|
||||
name = "cos circuit"
|
||||
desc = "Outputs the cosine of A."
|
||||
icon_state = "cosine"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/trig/cosine/do_work()
|
||||
pull_data()
|
||||
var/result = null
|
||||
var/A = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(A))
|
||||
result = cos(A)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// Tangent //
|
||||
|
||||
/obj/item/integrated_circuit/trig/tangent
|
||||
name = "tan circuit"
|
||||
desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance."
|
||||
icon_state = "tangent"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/trig/tangent/do_work()
|
||||
pull_data()
|
||||
var/result = null
|
||||
var/A = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(A))
|
||||
result = Tan(A)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// Cosecant //
|
||||
|
||||
/obj/item/integrated_circuit/trig/cosecant
|
||||
name = "csc circuit"
|
||||
desc = "Outputs the cosecant of A."
|
||||
icon_state = "cosecant"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/trig/cosecant/do_work()
|
||||
pull_data()
|
||||
var/result = null
|
||||
var/A = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(A))
|
||||
result = Csc(A)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
|
||||
// Secant //
|
||||
|
||||
/obj/item/integrated_circuit/trig/secant
|
||||
name = "sec circuit"
|
||||
desc = "Outputs the secant of A. Has nothing to do with the security department."
|
||||
icon_state = "secant"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/trig/secant/do_work()
|
||||
pull_data()
|
||||
var/result = null
|
||||
var/A = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(A))
|
||||
result = Sec(A)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
|
||||
// Cotangent //
|
||||
|
||||
/obj/item/integrated_circuit/trig/cotangent
|
||||
name = "cot circuit"
|
||||
desc = "Outputs the cotangent of A."
|
||||
icon_state = "cotangent"
|
||||
inputs = list("A" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/trig/cotangent/do_work()
|
||||
pull_data()
|
||||
var/result = null
|
||||
var/A = get_pin_data(IC_INPUT, 1)
|
||||
if(!isnull(A))
|
||||
result = Cot(A)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
@@ -0,0 +1,36 @@
|
||||
#undef IC_INPUT
|
||||
#undef IC_OUTPUT
|
||||
#undef IC_ACTIVATOR
|
||||
|
||||
#undef DATA_CHANNEL
|
||||
#undef PULSE_CHANNEL
|
||||
|
||||
#undef IC_SPAWN_DEFAULT
|
||||
//#undef IC_SPAWN_RESEARCH // Research designs depend on this unfortunately.
|
||||
|
||||
#undef IC_FORMAT_ANY
|
||||
#undef IC_FORMAT_STRING
|
||||
#undef IC_FORMAT_CHAR
|
||||
#undef IC_FORMAT_COLOR
|
||||
#undef IC_FORMAT_NUMBER
|
||||
#undef IC_FORMAT_DIR
|
||||
#undef IC_FORMAT_BOOLEAN
|
||||
#undef IC_FORMAT_REF
|
||||
#undef IC_FORMAT_LIST
|
||||
|
||||
#undef IC_FORMAT_PULSE
|
||||
|
||||
#undef IC_PINTYPE_ANY
|
||||
#undef IC_PINTYPE_STRING
|
||||
#undef IC_PINTYPE_CHAR
|
||||
#undef IC_PINTYPE_COLOR
|
||||
#undef IC_PINTYPE_NUMBER
|
||||
#undef IC_PINTYPE_DIR
|
||||
#undef IC_PINTYPE_BOOLEAN
|
||||
#undef IC_PINTYPE_REF
|
||||
#undef IC_PINTYPE_LIST
|
||||
|
||||
#undef IC_PINTYPE_PULSE_IN
|
||||
#undef IC_PINTYPE_PULSE_OUT
|
||||
|
||||
#undef IC_MAX_LIST_LENGTH
|
||||
@@ -201,6 +201,59 @@
|
||||
user.setMoveCooldown(move_delay)
|
||||
next_fire_time = world.time + fire_delay
|
||||
|
||||
// Similar to the above proc, but does not require a user, which is ideal for things like turrets.
|
||||
/obj/item/weapon/gun/proc/Fire_userless(atom/target)
|
||||
if(!target)
|
||||
return
|
||||
|
||||
if(world.time < next_fire_time)
|
||||
return
|
||||
|
||||
var/shoot_time = (burst - 1)* burst_delay
|
||||
next_fire_time = world.time + shoot_time
|
||||
|
||||
var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed.
|
||||
for(var/i in 1 to burst)
|
||||
var/obj/projectile = consume_next_projectile()
|
||||
if(!projectile)
|
||||
handle_click_empty()
|
||||
break
|
||||
|
||||
if(istype(projectile, /obj/item/projectile))
|
||||
var/obj/item/projectile/P = projectile
|
||||
|
||||
var/acc = burst_accuracy[min(i, burst_accuracy.len)]
|
||||
var/disp = dispersion[min(i, dispersion.len)]
|
||||
|
||||
P.accuracy = accuracy + acc
|
||||
P.dispersion = disp
|
||||
|
||||
P.shot_from = src.name
|
||||
P.silenced = silenced
|
||||
|
||||
P.launch(target)
|
||||
|
||||
if(silenced)
|
||||
playsound(src, fire_sound, 10, 1)
|
||||
else
|
||||
playsound(src, fire_sound, 50, 1)
|
||||
|
||||
if (muzzle_flash)
|
||||
set_light(muzzle_flash)
|
||||
addtimer(CALLBACK(src, /atom/.proc/set_light, 0), 2, TIMER_UNIQUE | TIMER_OVERRIDE)
|
||||
update_icon()
|
||||
|
||||
if(i < burst)
|
||||
sleep(burst_delay)
|
||||
|
||||
if(!(target && target.loc))
|
||||
target = targloc
|
||||
|
||||
//update timing
|
||||
next_fire_time = world.time + fire_delay
|
||||
|
||||
accuracy = initial(accuracy) //Reset the gun's accuracy
|
||||
|
||||
//obtains the next projectile to fire
|
||||
/obj/item/weapon/gun/proc/consume_next_projectile()
|
||||
return null
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/atom/movable/proc/can_be_injected_by(var/atom/injector)
|
||||
if(!Adjacent(get_turf(injector)))
|
||||
return FALSE
|
||||
if(!reagents)
|
||||
return FALSE
|
||||
if(!reagents.get_free_space())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/can_be_injected_by(var/atom/injector)
|
||||
return is_open_container() && ..()
|
||||
|
||||
/mob/living/can_be_injected_by(var/atom/injector)
|
||||
return ..() && (can_inject(null, 0, "chest") || can_inject(null, 0, "groin"))
|
||||
@@ -345,3 +345,92 @@ other types of metals and chemistry for reagents).
|
||||
id = "cart_captain"
|
||||
build_path = /obj/item/weapon/cartridge/captain
|
||||
sort_string = "VBAAO"
|
||||
|
||||
// Integrated Electronics stuff.
|
||||
/datum/design/item/wirer
|
||||
name = "Custom wirer tool"
|
||||
id = "wirer"
|
||||
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500)
|
||||
build_path = /obj/item/device/integrated_electronics/wirer
|
||||
sort_string = "VBVAA"
|
||||
|
||||
/datum/design/item/debugger
|
||||
name = "Custom circuit debugger tool"
|
||||
id = "debugger"
|
||||
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500)
|
||||
build_path = /obj/item/device/integrated_electronics/debugger
|
||||
sort_string = "VBVAB"
|
||||
|
||||
/datum/design/item/custom_circuit_assembly
|
||||
name = "Small custom assembly"
|
||||
desc = "A customizable assembly for simple, small devices."
|
||||
id = "assembly-small"
|
||||
req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_POWER = 2)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 10000)
|
||||
build_path = /obj/item/device/electronic_assembly
|
||||
sort_string = "VCAAA"
|
||||
|
||||
/datum/design/item/custom_circuit_assembly/medium
|
||||
name = "Medium custom assembly"
|
||||
desc = "A customizable assembly suited for more ambitious mechanisms."
|
||||
id = "assembly-medium"
|
||||
req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 20000)
|
||||
build_path = /obj/item/device/electronic_assembly/medium
|
||||
sort_string = "VCAAB"
|
||||
|
||||
/datum/design/item/custom_circuit_assembly/drone
|
||||
name = "Drone custom assembly"
|
||||
desc = "A customizable assembly optimized for autonomous devices."
|
||||
id = "assembly-drone"
|
||||
req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 30000)
|
||||
build_path = /obj/item/device/electronic_assembly/drone
|
||||
sort_string = "VCAAC"
|
||||
|
||||
/datum/design/item/custom_circuit_assembly/large
|
||||
name = "Large custom assembly"
|
||||
desc = "A customizable assembly for large machines."
|
||||
id = "assembly-large"
|
||||
req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 40000)
|
||||
build_path = /obj/item/device/electronic_assembly/large
|
||||
sort_string = "VCAAD"
|
||||
|
||||
/datum/design/item/custom_circuit_assembly/implant
|
||||
name = "Implant custom assembly"
|
||||
desc = "An customizable assembly for very small devices, implanted into living entities."
|
||||
id = "assembly-implant"
|
||||
req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 2000)
|
||||
build_path = /obj/item/weapon/implant/integrated_circuit
|
||||
sort_string = "VCAAE"
|
||||
|
||||
/datum/design/item/custom_circuit_assembly/device
|
||||
name = "Device custom assembly"
|
||||
desc = "An customizable assembly designed to interface with other devices."
|
||||
id = "assembly-device"
|
||||
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 5000)
|
||||
build_path = /obj/item/device/assembly/electronic_assembly
|
||||
sort_string = "VCAAF"
|
||||
|
||||
/datum/design/item/custom_circuit_printer
|
||||
name = "Portable integrated circuit printer"
|
||||
desc = "A portable(ish) printer for modular machines."
|
||||
id = "ic_printer"
|
||||
req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4, TECH_DATA = 5)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 10000)
|
||||
build_path = /obj/item/device/integrated_circuit_printer
|
||||
sort_string = "VCAAG"
|
||||
|
||||
/datum/design/item/custom_circuit_printer_upgrade
|
||||
name = "Integrated circuit printer upgrade - advanced designs"
|
||||
desc = "Allows the integrated circuit printer to create advanced circuits"
|
||||
id = "ic_printer_upgrade_adv"
|
||||
req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 2000)
|
||||
build_path = /obj/item/weapon/disk/integrated_circuit/upgrade/advanced
|
||||
sort_string = "VCAAH"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
author: Lohikar
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "NT is proud to announce general availability of modular electronics kits for Research and Engineering departments galaxy-wide, batteries not not included. (Ported from Polaris)"
|
||||
- tweak: "Implants now actually bit back in the implanter that they were removed from."
|
||||
- tweak: "Round duration is now actually the duration of the round, instead of time passed since last server reboot."
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
@@ -9518,6 +9518,8 @@
|
||||
/obj/machinery/atmospherics/unary/vent_pump/on{
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/weapon/storage/bag/circuits/basic,
|
||||
/obj/structure/table/reinforced,
|
||||
/turf/simulated/floor/plating,
|
||||
/area/engineering/storage)
|
||||
"asP" = (
|
||||
@@ -25432,6 +25434,8 @@
|
||||
/obj/structure/closet/secure_closet/engineering_chief,
|
||||
/obj/item/weapon/tank/emergency_oxygen/engi,
|
||||
/obj/item/device/gps/engineering,
|
||||
/obj/item/device/integrated_electronics/debugger,
|
||||
/obj/item/device/integrated_electronics/wirer,
|
||||
/turf/simulated/floor/carpet,
|
||||
/area/crew_quarters/heads/chief)
|
||||
"aSX" = (
|
||||
@@ -62897,6 +62901,13 @@
|
||||
/obj/machinery/light/small,
|
||||
/turf/simulated/floor/tiled/dark,
|
||||
/area/turbolift/cargo_station)
|
||||
"cgm" = (
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/item/weapon/storage/bag/circuits/basic,
|
||||
/obj/item/device/integrated_electronics/debugger,
|
||||
/obj/item/device/integrated_electronics/wirer,
|
||||
/turf/simulated/floor/tiled,
|
||||
/area/assembly/robotics)
|
||||
|
||||
(1,1,1) = {"
|
||||
aaa
|
||||
@@ -88477,7 +88488,7 @@ bjw
|
||||
bkJ
|
||||
bin
|
||||
bnx
|
||||
boI
|
||||
cgm
|
||||
aZK
|
||||
brj
|
||||
bsC
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user