Files
GS13NG/code/modules/research/nanites/nanite_programs/utility.dm
2020-11-22 14:56:02 -07:00

416 lines
15 KiB
Plaintext

//Programs that interact with other programs or nanites directly, or have other special purposes.
/datum/nanite_program/viral
name = "Viral Replica"
desc = "The nanites constantly send encrypted signals attempting to forcefully copy their own programming into other nanite clusters, also overriding or disabling their cloud sync."
use_rate = 0.5
rogue_types = list(/datum/nanite_program/toxic)
var/pulse_cooldown = 0
/datum/nanite_program/viral/register_extra_settings()
extra_settings[NES_PROGRAM_OVERWRITE] = new /datum/nanite_extra_setting/type("Add To", list("Overwrite", "Add To", "Ignore"))
extra_settings[NES_CLOUD_OVERWRITE] = new /datum/nanite_extra_setting/number(0, 0, 100)
/datum/nanite_program/viral/active_effect()
if(world.time < pulse_cooldown)
return
var/datum/nanite_extra_setting/program = extra_settings[NES_PROGRAM_OVERWRITE]
var/datum/nanite_extra_setting/cloud = extra_settings[NES_CLOUD_OVERWRITE]
for(var/mob/M in orange(host_mob, 5))
if(SEND_SIGNAL(M, COMSIG_NANITE_CHECK_VIRAL_PREVENTION))
continue
switch(program.get_value())
if("Overwrite")
SEND_SIGNAL(M, COMSIG_NANITE_SYNC, nanites, TRUE)
if("Add To")
SEND_SIGNAL(M, COMSIG_NANITE_SYNC, nanites, FALSE)
SEND_SIGNAL(M, COMSIG_NANITE_SET_CLOUD, cloud.get_value())
pulse_cooldown = world.time + 75
/datum/nanite_program/monitoring
name = "Monitoring"
desc = "The nanites monitor the host's vitals and location, sending them to the suit sensor network."
rogue_types = list(/datum/nanite_program/toxic)
/datum/nanite_program/monitoring/enable_passive_effect()
. = ..()
SSnanites.nanite_monitored_mobs |= host_mob
host_mob.hud_set_nanite_indicator()
/datum/nanite_program/monitoring/disable_passive_effect()
. = ..()
SSnanites.nanite_monitored_mobs -= host_mob
host_mob.hud_set_nanite_indicator()
/datum/nanite_program/self_scan
name = "Host Scan"
desc = "The nanites display a detailed readout of a body scan to the host."
unique = FALSE
can_trigger = TRUE
trigger_cost = 3
trigger_cooldown = 50
rogue_types = list(/datum/nanite_program/toxic)
/datum/nanite_program/self_scan/register_extra_settings()
extra_settings[NES_SCAN_TYPE] = new /datum/nanite_extra_setting/type("Medical", list("Medical", "Chemical", "Wound", "Nanite"))
/datum/nanite_program/self_scan/on_trigger(comm_message)
if(host_mob.stat == DEAD)
return
var/datum/nanite_extra_setting/NS = extra_settings[NES_SCAN_TYPE]
switch(NS.get_value())
if("Medical")
healthscan(host_mob, host_mob)
if("Chemical")
chemscan(host_mob, host_mob)
if("Wound")
woundscan(host_mob, host_mob)
if("Nanite")
SEND_SIGNAL(host_mob, COMSIG_NANITE_SCAN, host_mob, TRUE)
/datum/nanite_program/stealth
name = "Stealth"
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
/datum/nanite_program/stealth/enable_passive_effect()
. = ..()
nanites.stealth = TRUE
/datum/nanite_program/stealth/disable_passive_effect()
. = ..()
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."
rogue_types = list(/datum/nanite_program/toxic)
/datum/nanite_program/relay/register_extra_settings()
extra_settings[NES_RELAY_CHANNEL] = new /datum/nanite_extra_setting/number(1, 1, 9999)
/datum/nanite_program/relay/enable_passive_effect()
. = ..()
SSnanites.nanite_relays |= src
/datum/nanite_program/relay/disable_passive_effect()
. = ..()
SSnanites.nanite_relays -= src
/datum/nanite_program/relay/proc/relay_signal(code, relay_code, source)
if(!activated)
return
if(!host_mob)
return
var/datum/nanite_extra_setting/NS = extra_settings[NES_RELAY_CHANNEL]
if(relay_code != NS.get_value())
return
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, code, source)
/datum/nanite_program/relay/proc/relay_comm_signal(comm_code, relay_code, comm_message)
if(!activated)
return
if(!host_mob)
return
var/datum/nanite_extra_setting/NS = extra_settings[NES_RELAY_CHANNEL]
if(relay_code != NS.get_value())
return
SEND_SIGNAL(host_mob, COMSIG_NANITE_COMM_SIGNAL, comm_code, comm_message)
/datum/nanite_program/metabolic_synthesis
name = "Metabolic Synthesis"
desc = "The nanites use the metabolic cycle of the host to speed up their replication rate, using their extra nutrition as fuel."
rogue_types = list(/datum/nanite_program/toxic)
/datum/nanite_program/metabolic_synthesis/check_conditions()
if(!iscarbon(host_mob))
return FALSE
var/mob/living/carbon/C = host_mob
if(C.nutrition <= NUTRITION_LEVEL_FED)
return FALSE
return ..()
/datum/nanite_program/metabolic_synthesis/active_effect()
host_mob.adjust_nutrition(-0.5)
nanites.adjust_nanites(src, 0.5)
/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))
/datum/nanite_program/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."
can_trigger = TRUE
trigger_cost = 3
trigger_cooldown = 30
rogue_types = list(/datum/nanite_program/skin_decay)
var/access = list()
//Syncs the nanites with the cumulative current mob's access level. Can potentially wipe existing access.
/datum/nanite_program/access/on_trigger(comm_message)
var/list/new_access = list()
var/obj/item/current_item
current_item = host_mob.get_active_held_item()
if(current_item)
new_access += current_item.GetAccess()
current_item = host_mob.get_inactive_held_item()
if(current_item)
new_access += current_item.GetAccess()
if(ishuman(host_mob))
var/mob/living/carbon/human/H = host_mob
current_item = H.wear_id
if(current_item)
new_access += current_item.GetAccess()
else if(isanimal(host_mob))
var/mob/living/simple_animal/A = host_mob
current_item = A.access_card
if(current_item)
new_access += current_item.GetAccess()
access = new_access
/datum/nanite_program/spreading
name = "Infective Exo-Locomotion"
desc = "The nanites gain the ability to survive for brief periods outside of the human body, as well as the ability to start new colonies without an integration process; \
resulting in an extremely infective strain of nanites."
use_rate = 1.50
rogue_types = list(/datum/nanite_program/aggressive_replication, /datum/nanite_program/necrotic)
var/spread_cooldown = 0
/datum/nanite_program/spreading/active_effect()
if(world.time < spread_cooldown)
return
spread_cooldown = world.time + 50
var/list/mob/living/target_hosts = list()
for(var/mob/living/L in oview(5, host_mob))
if(!prob(25))
continue
if(!(L.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD)))
continue
target_hosts += L
if(!target_hosts.len)
return
var/mob/living/infectee = pick(target_hosts)
if(prob(100 - (infectee.get_permeability_protection() * 100)))
//this will potentially take over existing nanites!
infectee.AddComponent(/datum/component/nanites, 10)
SEND_SIGNAL(infectee, COMSIG_NANITE_SYNC, nanites)
infectee.investigate_log("was infected by spreading nanites by [key_name(host_mob)] at [AREACOORD(infectee)].", INVESTIGATE_NANITES)
/datum/nanite_program/nanite_sting
name = "Nanite Sting"
desc = "When triggered, projects a nearly invisible spike of nanites that attempts to infect a nearby non-host with a copy of the host's nanites cluster."
can_trigger = TRUE
trigger_cost = 5
trigger_cooldown = 100
rogue_types = list(/datum/nanite_program/glitch, /datum/nanite_program/toxic)
/datum/nanite_program/nanite_sting/on_trigger(comm_message)
var/list/mob/living/target_hosts = list()
for(var/mob/living/L in oview(1, host_mob))
if(!(L.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD)) || SEND_SIGNAL(L, COMSIG_HAS_NANITES) || !L.Adjacent(host_mob))
continue
target_hosts += L
if(!target_hosts.len)
consume_nanites(-5)
return
var/mob/living/infectee = pick(target_hosts)
if(prob(100 - (infectee.get_permeability_protection() * 100)))
//unlike with Infective Exo-Locomotion, this can't take over existing nanites, because Nanite Sting only targets non-hosts.
infectee.AddComponent(/datum/component/nanites, 5)
SEND_SIGNAL(infectee, COMSIG_NANITE_SYNC, nanites)
infectee.investigate_log("was infected by a nanite cluster by [key_name(host_mob)] at [AREACOORD(infectee)].", INVESTIGATE_NANITES)
to_chat(infectee, "<span class='warning'>You feel a tiny prick.</span>")
/datum/nanite_program/mitosis
name = "Mitosis"
desc = "The nanites gain the ability to self-replicate, using bluespace to power the process. Becomes more effective the more nanites are already in the host.\
The replication has also a chance to corrupt the nanite programming due to copy faults - cloud sync is highly recommended."
use_rate = 0
rogue_types = list(/datum/nanite_program/toxic)
/datum/nanite_program/mitosis/active_effect()
var/rep_rate = round(nanites.nanite_volume / 50, 1) //0.5 per 50 nanite volume
rep_rate *= 0.5
nanites.adjust_nanites(null, rep_rate)
if(prob(rep_rate))
var/datum/nanite_program/fault = pick(nanites.programs)
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."
unique = FALSE
var/datum/action/innate/nanite_button/button
/datum/nanite_program/dermal_button/register_extra_settings()
extra_settings[NES_SENT_CODE] = new /datum/nanite_extra_setting/number(1, 1, 9999)
extra_settings[NES_BUTTON_NAME] = new /datum/nanite_extra_setting/text("Button")
extra_settings[NES_ICON] = new /datum/nanite_extra_setting/type("power", list("one","two","three","four","five","plus","minus","power"))
extra_settings[NES_COLOR] = new /datum/nanite_extra_setting/type("green", list("green","red","yellow","blue"))
/datum/nanite_program/dermal_button/enable_passive_effect()
. = ..()
var/datum/nanite_extra_setting/bn_name = extra_settings[NES_BUTTON_NAME]
var/datum/nanite_extra_setting/bn_icon = extra_settings[NES_ICON]
var/datum/nanite_extra_setting/bn_color = extra_settings[NES_COLOR]
if(!button)
button = new(src, bn_name.get_value(), bn_icon.get_value(), bn_color.get_value())
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("<span class='notice'>[host_mob] presses a button on [host_mob.p_their()] forearm.</span>",
"<span class='notice'>You press the nanite button on your forearm.</span>", null, 2)
var/datum/nanite_extra_setting/sent_code = extra_settings[NES_SENT_CODE]
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, sent_code.get_value(), "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/lockout
unique = TRUE
var/emp_disable_time = 0
var/shock_disable_time = 0
var/minor_shock_disable_time = 0
var/disable_time = 0
var/lock_console = FALSE
var/lock_virus = FALSE
var/lock_host = FALSE
/datum/nanite_program/lockout/enable_passive_effect()
. = ..()
if(lock_console)
RegisterSignal(src, COMSIG_NANITE_INTERNAL_CONSOLE_LOCK_CHECK, .proc/check_antivirus)
if(lock_host)
RegisterSignal(src, COMSIG_NANITE_INTERNAL_HOST_LOCK_CHECK, .proc/check_antivirus)
if(lock_virus)
RegisterSignal(src, COMSIG_NANITE_INTERNAL_VIRAL_PREVENTION_CHECK, .proc/check_antivirus)
/datum/nanite_program/lockout/disable_passive_effect()
. = ..()
UnregisterSignal(src, list(
COMSIG_NANITE_INTERNAL_HOST_LOCK_CHECK,
COMSIG_NANITE_INTERNAL_CONSOLE_LOCK_CHECK,
COMSIG_NANITE_INTERNAL_VIRAL_PREVENTION_CHECK
))
/datum/nanite_program/lockout/on_emp(severity)
// no parent call on purpose
disable_time = max(disable_time, world.time + emp_disable_time)
/datum/nanite_program/lockout/on_shock(shock_damage)
// no parent call on purpose
disable_time = max(disable_time, world.time + shock_disable_time)
/datum/nanite_program/lockout/on_minor_shock()
// no parent call on purpose
disable_time = max(disable_time, world.time + minor_shock_disable_time)
/datum/nanite_program/lockout/proc/check_antivirus()
return (world.time <= disable_time)? NANITE_CHANGES_LOCKED : NONE
/datum/nanite_program/lockout/antiviral
name = "Enhanced Error Correction"
desc = "Through expensive CRC checking and replication, prevents viral takeover of the nanite strain's control sectors. \
Temporarily disabled by EMPs and shocks."
use_rate = 0.5
emp_disable_time = 3 MINUTES
shock_disable_time = 45 SECONDS
minor_shock_disable_time = 10 SECONDS
lock_virus = TRUE
/datum/nanite_program/lockout/hostile_lockdown
name = "Hostile Lockdown"
desc = "Constantly encrypts and scrambles the nanites' control memory, preventing consoles from modifying them and also locking out conscious host control of the nanite strain, if the host happens to be capable of that. \
Temporarily disabled by EMPs and shocks."
use_rate = 0.5
emp_disable_time = 3 MINUTES
shock_disable_time = 1 MINUTES
minor_shock_disable_time = 15 SECONDS
lock_host = TRUE
lock_console = TRUE