Merge pull request #13699 from silicons/nanite_updates

nanite updates: permanent nanites, hostile lockdown, anti-virus, resistance tweaking
This commit is contained in:
DeltaFire
2020-12-14 05:56:48 +01:00
committed by GitHub
12 changed files with 268 additions and 45 deletions
@@ -113,7 +113,7 @@
/datum/design/nanites/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."
resulting in an extremely infective strain of nanites. Bypasses antiviral defense"
id = "spreading_nanites"
program_type = /datum/nanite_program/spreading
category = list("Utility Nanites")
@@ -133,6 +133,21 @@
program_type = /datum/nanite_program/mitosis
category = list("Utility Nanites")
/datum/design/nanites/antiviral
name = "Enhanced Error Correction"
desc = "The nanites self-propagate and replicate their program storage memory, preventing viral takeovers."
id = "antiviral_nanites"
program_type = /datum/nanite_program/lockout/antiviral
category = list("Utility Nanites")
/datum/design/nanites/hostile_lockdown
name = "Hostile Lockdown"
desc = "The nanites constantly encrypt and scramble their own control sectors, preventing consoles from controlling them. Furthermore, \
if the host happens to be a synthetic organism with innate control over nanite strains, this will prevent them from acting on the nanites as well."
id = "hostile_lockdown"
program_type = /datum/nanite_program/lockout/hostile_lockdown
category = list("Utility Nanites")
////////////////////MEDICAL NANITES//////////////////////////////////////
/datum/design/nanites/regenerative
name = "Accelerated Regeneration"
@@ -41,12 +41,12 @@
update_icon()
/obj/machinery/nanite_chamber/proc/set_safety(threshold)
if(!occupant)
if(!occupant || SEND_SIGNAL(occupant, COMSIG_NANITE_CHECK_CONSOLE_LOCK))
return
SEND_SIGNAL(occupant, COMSIG_NANITE_SET_SAFETY, threshold)
/obj/machinery/nanite_chamber/proc/set_cloud(cloud_id)
if(!occupant)
if(!occupant || SEND_SIGNAL(occupant, COMSIG_NANITE_CHECK_CONSOLE_LOCK))
return
SEND_SIGNAL(occupant, COMSIG_NANITE_SET_CLOUD, cloud_id)
@@ -82,7 +82,7 @@
return
if((stat & MAINT) || panel_open)
return
if(!occupant || busy)
if(!occupant || busy || SEND_SIGNAL(occupant, COMSIG_NANITE_CHECK_CONSOLE_LOCK))
return
var/locked_state = locked
@@ -173,7 +173,6 @@
return FALSE
..()
return TRUE
/obj/machinery/nanite_chamber/relaymove(mob/user as mob)
@@ -50,6 +50,10 @@
data["status_msg"] = chamber.busy_message
return data
if(SEND_SIGNAL(L, COMSIG_NANITE_CHECK_CONSOLE_LOCK))
data["status_msg"] = "Error: Nanite keycodes scrambled. Unable to operate."
return data
data["status_msg"] = null
data["scan_level"] = chamber.scan_level
data["locked"] = chamber.locked
@@ -54,6 +54,13 @@
//Rules that automatically manage if the program's active without requiring separate sensor programs
var/list/datum/nanite_rule/rules = list()
/// Corruptable - able to have code/configuration changed
var/corruptable = TRUE
/// error flicking - able to be randomly toggled by errors
var/error_flicking = TRUE
/// immutable - cannot be overwritten by other programs
var/immutable = FALSE
/datum/nanite_program/New()
. = ..()
register_extra_settings()
@@ -68,8 +75,15 @@
on_mob_remove()
if(nanites)
nanites.programs -= src
nanites.permanent_programs -= src
return ..()
/**
* Checks if we're a permanent program
*/
/datum/nanite_program/proc/is_permanent()
return nanites && (src in nanites.permanent_programs)
/datum/nanite_program/proc/copy()
var/datum/nanite_program/new_program = new type()
copy_programming(new_program, TRUE)
@@ -77,6 +91,8 @@
return new_program
/datum/nanite_program/proc/copy_programming(datum/nanite_program/target, copy_activated = TRUE)
if(target.immutable)
return
if(copy_activated)
target.activated = activated
target.timer_restart = timer_restart
@@ -234,7 +250,7 @@
/datum/nanite_program/proc/on_emp(severity)
if(program_flags & NANITE_EMP_IMMUNE)
return
if(prob(80 / severity))
if(prob(severity / 2))
software_error()
/datum/nanite_program/proc/on_shock(shock_damage)
@@ -242,7 +258,7 @@
if(prob(10))
software_error()
else if(prob(33))
qdel(src)
self_destruct()
/datum/nanite_program/proc/on_minor_shock()
if(!program_flags & NANITE_SHOCK_IMMUNE)
@@ -254,26 +270,29 @@
/datum/nanite_program/proc/software_error(type)
if(!type)
type = rand(1,5)
type = rand(1,is_permanent()? 4 : 5)
switch(type)
if(1)
qdel(src) //kill switch
self_destruct() //kill switch
return
if(2) //deprogram codes
activation_code = 0
deactivation_code = 0
kill_code = 0
trigger_code = 0
if(corruptable)
activation_code = 0
deactivation_code = 0
kill_code = 0
trigger_code = 0
if(3)
toggle() //enable/disable
if(error_flicking)
toggle() //enable/disable
if(4)
if(can_trigger)
if(error_flicking && can_trigger)
trigger()
if(5) //Program is scrambled and does something different
var/rogue_type = pick(rogue_types)
var/datum/nanite_program/rogue = new rogue_type
nanites.add_program(null, rogue, src)
qdel(src)
if(corruptable)
var/rogue_type = pick(rogue_types)
var/datum/nanite_program/rogue = new rogue_type
nanites.add_program(null, rogue, src)
self_destruct()
/datum/nanite_program/proc/receive_signal(code, source)
if(activation_code && code == activation_code && !activated)
@@ -285,10 +304,18 @@
if(can_trigger && trigger_code && code == trigger_code)
trigger()
host_mob.investigate_log("'s [name] nanite program was triggered by [source] with code [code].", INVESTIGATE_NANITES)
if(kill_code && code == kill_code)
if((kill_code && code == kill_code) && !is_permanent())
host_mob.investigate_log("'s [name] nanite program was deleted by [source] with code [code].", INVESTIGATE_NANITES)
qdel(src)
/**
* Attempts to destroy ourselves
*/
/datum/nanite_program/proc/self_destruct()
if(is_permanent())
return
qdel(src)
///A nanite program containing a behaviour protocol. Only one protocol of each class can be active at once.
//Moved to being 'normally' researched due to lack of B.E.P.I.S.
/datum/nanite_program/protocol
@@ -11,7 +11,7 @@
return FALSE
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
var/list/parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC))
var/list/parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC, BODYPART_NANITES))
if(!parts.len)
return FALSE
return ..()
@@ -19,7 +19,7 @@
/datum/nanite_program/regenerative/active_effect()
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
var/list/parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC))
var/list/parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC, BODYPART_NANITES))
if(!parts.len)
return
for(var/obj/item/bodypart/L in parts)
@@ -121,7 +121,7 @@
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
var/list/parts = C.get_damaged_bodyparts(TRUE, TRUE, status = list(BODYPART_ROBOTIC, BODYPART_HYBRID))
var/list/parts = C.get_damaged_bodyparts(TRUE, TRUE, status = list(BODYPART_ROBOTIC, BODYPART_HYBRID, BODYPART_NANITES))
if(!parts.len)
return FALSE
else
@@ -132,7 +132,7 @@
/datum/nanite_program/repairing/active_effect(mob/living/M)
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
var/list/parts = C.get_damaged_bodyparts(TRUE, TRUE, status = list(BODYPART_ROBOTIC, BODYPART_HYBRID))
var/list/parts = C.get_damaged_bodyparts(TRUE, TRUE, status = list(BODYPART_ROBOTIC, BODYPART_HYBRID, BODYPART_NANITES))
if(!parts.len)
return
var/update = FALSE
@@ -176,12 +176,12 @@
/datum/nanite_program/regenerative_advanced/active_effect()
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
var/list/parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC))
var/list/parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC, BODYPART_NANITES))
if(!parts.len)
return
var/update = FALSE
for(var/obj/item/bodypart/L in parts)
if(L.heal_damage(3/parts.len, 3/parts.len, FALSE))
if(L.heal_damage(3/parts.len, 3/parts.len, 0))
update = TRUE
if(update)
host_mob.update_damage_overlays()
@@ -16,7 +16,7 @@
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_IS_STEALTHY))
if(SEND_SIGNAL(M, COMSIG_NANITE_CHECK_VIRAL_PREVENTION))
continue
switch(program.get_value())
if("Overwrite")
@@ -350,3 +350,66 @@
/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
@@ -91,7 +91,7 @@
var/heavy_range = FLOOR(nanite_amount/100, 1) - 1
var/light_range = FLOOR(nanite_amount/50, 1) - 1
explosion(host_mob, 0, heavy_range, light_range)
qdel(nanites)
nanites.delete_nanites()
//TODO make it defuse if triggered again
@@ -23,7 +23,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", "dermal_button_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", "antiviral_nanites", "hostile_lockdown")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/nanite_bio