416 lines
15 KiB
Plaintext
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
|