diff --git a/code/controllers/subsystem/processing/nanites.dm b/code/controllers/subsystem/processing/nanites.dm
index 69bd5781..5b53f9f8 100644
--- a/code/controllers/subsystem/processing/nanites.dm
+++ b/code/controllers/subsystem/processing/nanites.dm
@@ -6,6 +6,7 @@ PROCESSING_SUBSYSTEM_DEF(nanites)
var/list/datum/nanite_cloud_backup/cloud_backups = list()
var/list/mob/living/nanite_monitored_mobs = list()
var/list/datum/nanite_program/relay/nanite_relays = list()
+ var/neural_network_count = 0
/datum/controller/subsystem/processing/nanites/proc/check_hardware(datum/nanite_cloud_backup/backup)
if(QDELETED(backup.storage) || (backup.storage.stat & (NOPOWER|BROKEN)))
diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm
index 85e67698..a2566aef 100644
--- a/code/datums/components/nanites.dm
+++ b/code/datums/components/nanites.dm
@@ -11,8 +11,9 @@
var/list/datum/nanite_program/programs = list()
var/max_programs = NANITE_PROGRAM_LIMIT
- var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans, and does not display the program list on nanite scans
-
+ var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans
+ var/diagnostics = TRUE //if TRUE, displays program list when scanned by nanite scanners
+
/datum/component/nanites/Initialize(amount = 100, cloud = 0)
if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup))
return COMPONENT_INCOMPATIBLE
@@ -250,8 +251,8 @@
to_chat(user, "Cloud ID: [cloud_id ? cloud_id : "Disabled"]")
to_chat(user, "================")
to_chat(user, "Program List:")
- if(stealth)
- to_chat(user, "%#$ENCRYPTED&^@")
+ if(!diagnostics)
+ to_chat(user, "Diagnostics Disabled")
else
for(var/X in programs)
var/datum/nanite_program/NP = X
diff --git a/code/modules/research/designs/nanite_designs.dm b/code/modules/research/designs/nanite_designs.dm
index 177d7073..09fe1d9c 100644
--- a/code/modules/research/designs/nanite_designs.dm
+++ b/code/modules/research/designs/nanite_designs.dm
@@ -25,6 +25,20 @@
program_type = /datum/nanite_program/viral
category = list("Utility Nanites")
+/datum/design/nanites/research
+ name = "Distributed Computing"
+ desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
+ id = "research_nanites"
+ program_type = /datum/nanite_program/research
+ category = list("Utility Nanites")
+
+/datum/design/nanites/researchplus
+ name = "Neural Network"
+ desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts. Can be overloaded to increase research output."
+ id = "researchplus_nanites"
+ program_type = /datum/nanite_program/researchplus
+ category = list("Utility Nanites")
+
/datum/design/nanites/monitoring
name = "Monitoring"
desc = "The nanites monitor the host's vitals and location, sending them to the suit sensor network."
@@ -39,6 +53,13 @@
program_type = /datum/nanite_program/triggered/self_scan
category = list("Utility Nanites")
+/datum/design/nanites/dermal_button
+ name = "Dermal Button"
+ desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
+ id = "dermal_button_nanites"
+ program_type = /datum/nanite_program/dermal_button
+ category = list("Utility Nanites")
+
/datum/design/nanites/stealth
name = "Stealth"
desc = "The nanites hide their activity and programming from superficial scans."
@@ -46,6 +67,15 @@
program_type = /datum/nanite_program/stealth
category = list("Utility Nanites")
+
+/datum/design/nanites/reduced_diagnostics
+ name = "Reduced Diagnostics"
+ desc = "Disables some high-cost diagnostics in the nanites, making them unable to communicate their program list to portable scanners. \
+ Doing so saves some power, slightly increasing their replication speed."
+ id = "red_diag_nanites"
+ program_type = /datum/nanite_program/reduced_diagnostics
+ category = list("Utility Nanites")
+
/datum/design/nanites/access
name = "Subdermal ID"
desc = "The nanites store the host's ID access rights in a subdermal magnetic strip. Updates when triggered, copying the host's current access."
diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm
index a269d01a..3db482d9 100644
--- a/code/modules/research/nanites/nanite_programs/utility.dm
+++ b/code/modules/research/nanites/nanite_programs/utility.dm
@@ -130,7 +130,7 @@
/datum/nanite_program/stealth
name = "Stealth"
- desc = "The nanites hide their activity and programming from superficial scans."
+ desc = "The nanites mask their activity from superficial scans, becoming undetectable by HUDs and non-specialized scanners."
rogue_types = list(/datum/nanite_program/toxic)
use_rate = 0.2
@@ -142,6 +142,22 @@
. = ..()
nanites.stealth = FALSE
+/datum/nanite_program/reduced_diagnostics
+ name = "Reduced Diagnostics"
+ desc = "Disables some high-cost diagnostics in the nanites, making them unable to communicate their program list to portable scanners. \
+ Doing so saves some power, slightly increasing their replication speed."
+ rogue_types = list(/datum/nanite_program/toxic)
+ use_rate = -0.1
+
+/datum/nanite_program/reduced_diagnostics/enable_passive_effect()
+ . = ..()
+ nanites.diagnostics = FALSE
+
+/datum/nanite_program/reduced_diagnostics/disable_passive_effect()
+ . = ..()
+ nanites.diagnostics = TRUE
+
+
/datum/nanite_program/relay
name = "Relay"
desc = "The nanites receive and relay long-range nanite signals."
@@ -271,3 +287,138 @@
if(fault == src)
return
fault.software_error()
+
+/datum/nanite_program/dermal_button
+ name = "Dermal Button"
+ desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
+ extra_settings = list("Sent Code","Button Name","Icon","Color")
+ unique = FALSE
+ var/datum/action/innate/nanite_button/button
+ var/button_name = "Button"
+ var/icon = "power"
+ var/color = "green"
+ var/sent_code = 0
+
+/datum/nanite_program/dermal_button/set_extra_setting(user, setting)
+ if(setting == "Sent Code")
+ var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
+ if(isnull(new_code))
+ return
+ sent_code = CLAMP(round(new_code, 1), 1, 9999)
+ if(setting == "Button Name")
+ var/new_button_name = stripped_input(user, "Choose the name for the button.", "Button Name", button_name, MAX_NAME_LEN)
+ if(!new_button_name)
+ return
+ button_name = new_button_name
+ if(setting == "Icon")
+ var/new_icon = input("Select the icon to display on the button:", name) as null|anything in list("one","two","three","four","five","plus","minus","power")
+ if(!new_icon)
+ return
+ icon = new_icon
+ if(setting == "Color")
+ var/new_color = input("Select the color of the button's icon:", name) as null|anything in list("green","red","yellow","blue")
+ if(!new_color)
+ return
+ color = new_color
+
+/datum/nanite_program/dermal_button/get_extra_setting(setting)
+ if(setting == "Sent Code")
+ return sent_code
+ if(setting == "Button Name")
+ return button_name
+ if(setting == "Icon")
+ return capitalize(icon)
+ if(setting == "Color")
+ return capitalize(color)
+
+/datum/nanite_program/dermal_button/copy_extra_settings_to(datum/nanite_program/dermal_button/target)
+ target.sent_code = sent_code
+ target.button_name = button_name
+ target.icon = icon
+ target.color = color
+
+/datum/nanite_program/dermal_button/enable_passive_effect()
+ . = ..()
+ if(!button)
+ button = new(src, button_name, icon, color)
+ button.target = host_mob
+ button.Grant(host_mob)
+
+/datum/nanite_program/dermal_button/disable_passive_effect()
+ . = ..()
+ if(button)
+ button.Remove(host_mob)
+
+/datum/nanite_program/dermal_button/on_mob_remove()
+ . = ..()
+ qdel(button)
+
+/datum/nanite_program/dermal_button/proc/press()
+ if(activated)
+ host_mob.visible_message("[host_mob] presses a button on [host_mob.p_their()] forearm.",
+ "You press the nanite button on your forearm.", null, 2)
+ SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, sent_code, "a [name] program")
+
+/datum/action/innate/nanite_button
+ name = "Button"
+ icon_icon = 'icons/mob/actions/actions_items.dmi'
+ check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
+ button_icon_state = "power_green"
+ var/datum/nanite_program/dermal_button/program
+
+/datum/action/innate/nanite_button/New(datum/nanite_program/dermal_button/_program, _name, _icon, _color)
+ ..()
+ program = _program
+ name = _name
+ button_icon_state = "[_icon]_[_color]"
+
+/datum/action/innate/nanite_button/Activate()
+ program.press()
+
+/datum/nanite_program/research
+ name = "Distributed Computing"
+ desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
+ use_rate = 0.2
+ rogue_types = list(/datum/nanite_program/toxic)
+
+/datum/nanite_program/research/active_effect()
+ if(!iscarbon(host_mob))
+ return
+ var/points = 1
+ if(!host_mob.client) //less brainpower
+ points *= 0.25
+ SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
+
+/datum/nanite_program/researchplus
+ name = "Neural Network"
+ desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts."
+ use_rate = 0.3
+ rogue_types = list(/datum/nanite_program/brain_decay)
+
+/datum/nanite_program/researchplus/enable_passive_effect()
+ . = ..()
+ if(!iscarbon(host_mob))
+ return
+ if(host_mob.client)
+ SSnanites.neural_network_count++
+ else
+ SSnanites.neural_network_count += 0.25
+
+/datum/nanite_program/researchplus/disable_passive_effect()
+ . = ..()
+ if(!iscarbon(host_mob))
+ return
+ if(host_mob.client)
+ SSnanites.neural_network_count--
+ else
+ SSnanites.neural_network_count -= 0.25
+
+/datum/nanite_program/researchplus/active_effect()
+ if(!iscarbon(host_mob))
+ return
+ var/mob/living/carbon/C = host_mob
+ var/points = round(SSnanites.neural_network_count / 12, 0.1)
+ if(!C.client) //less brainpower
+ points *= 0.25
+ SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
+
diff --git a/code/modules/research/nanites/program_disks.dm b/code/modules/research/nanites/program_disks.dm
index 86b7803f..f780f409 100644
--- a/code/modules/research/nanites/program_disks.dm
+++ b/code/modules/research/nanites/program_disks.dm
@@ -130,4 +130,16 @@
program_type = /datum/nanite_program/pacifying
/obj/item/disk/nanite_program/stun
- program_type = /datum/nanite_program/triggered/stun
\ No newline at end of file
+ program_type = /datum/nanite_program/triggered/stun
+
+/obj/item/disk/nanite_program/dermal_button
+ program_type = /datum/nanite_program/dermal_button
+
+/obj/item/disk/nanite_program/research
+ program_type = /datum/nanite_program/research
+
+/obj/item/disk/nanite_program/researchplus
+ program_type = /datum/nanite_program/researchplus
+
+/obj/item/disk/nanite_program/reduced_diagnostics
+ program_type = /datum/nanite_program/reduced_diagnostics
\ No newline at end of file
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 2d364d9f..c8685849 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -961,7 +961,7 @@
prereq_ids = list("datatheory","robotics")
design_ids = list("nanite_disk","nanite_remote","nanite_scanner",\
"nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\
- "relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites")
+ "relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites","red_diag_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -970,7 +970,7 @@
display_name = "Smart Nanite Programming"
description = "Nanite programs that require nanites to perform complex actions, act independently, roam or seek targets."
prereq_ids = list("nanite_base","adv_robotics")
- design_ids = list("purging_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites")
+ design_ids = list("purging_nanites", "research_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000)
export_price = 4000
@@ -979,7 +979,7 @@
display_name = "Mesh Nanite Programming"
description = "Nanite programs that require static structures and membranes."
prereq_ids = list("nanite_base","engineering")
- design_ids = list("hardening_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites")
+ design_ids = list("hardening_nanites", "dermal_button_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -1016,7 +1016,7 @@
display_name = "Harmonic Nanite Programming"
description = "Nanite programs that require seamless integration between nanites and biology."
prereq_ids = list("nanite_bio","nanite_smart","nanite_mesh")
- design_ids = list("fakedeath_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites")
+ design_ids = list("fakedeath_nanites","researchplus_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000)
export_price = 8000