Merge pull request #13699 from silicons/nanite_updates
nanite updates: permanent nanites, hostile lockdown, anti-virus, resistance tweaking
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user