wew
This commit is contained in:
@@ -490,6 +490,17 @@
|
||||
#define COMPONENT_PROGRAM_INSTALLED 1 //Installation successful
|
||||
#define COMPONENT_PROGRAM_NOT_INSTALLED 2 //Installation failed, but there are still nanites
|
||||
#define COMSIG_NANITE_SYNC "nanite_sync" //(datum/component/nanites, full_overwrite, copy_activation) Called to sync the target's nanites to a given nanite component
|
||||
/// Checks if a nanite component is able to be controlled by console
|
||||
#define COMSIG_NANITE_CHECK_CONSOLE_LOCK "is_console_locked"
|
||||
/// Checks if a nanite component is able to be interfaced with by a host with innate nanite control
|
||||
#define COMSIG_NANITE_CHECK_HOST_LOCK "is_host_locked"
|
||||
/// Checks if a nanite component is able to be overwritten by viral replica
|
||||
#define COMSIG_NANITE_CHECK_VIRAL_PREVENTION "is_virus_locked"
|
||||
#define NANITE_CHANGES_LOCKED 1
|
||||
// Internal signals that programs register to and respond with to not require for loops
|
||||
#define COMSIG_NANITE_INTERNAL_CONSOLE_LOCK_CHECK "naniteiconsolelocked"
|
||||
#define COMSIG_NANITE_INTERNAL_HOST_LOCK_CHECK "naniteihostlocked"
|
||||
#define COMSIG_NANITE_INTERNAL_VIRAL_PREVENTION_CHECK "naniteiviruslocked"
|
||||
|
||||
// /datum/component/storage signals
|
||||
#define COMSIG_CONTAINS_STORAGE "is_storage" //() - returns bool.
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
#define MOB_EPIC (1 << 7) // Megafauna
|
||||
#define MOB_REPTILE (1 << 8)
|
||||
#define MOB_SPIRIT (1 << 9)
|
||||
/// Mobs that otherwise support nanites
|
||||
#define MOB_NANITES (1 << 10)
|
||||
|
||||
// Organ defines for carbon mobs
|
||||
#define ORGAN_ORGANIC 1
|
||||
|
||||
@@ -17,6 +17,44 @@
|
||||
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
|
||||
|
||||
/// Delete ourselves when we're depleted.
|
||||
var/qdel_self_on_depletion = TRUE
|
||||
/// Allow deletion
|
||||
var/can_be_deleted = TRUE
|
||||
/// Whether or not we can survive no cloud syncing without errors
|
||||
var/requires_cloud_sync = TRUE
|
||||
/// Permanent programs - can never be deleted. does not count towards max_programs.
|
||||
var/list/datum/nanite_program/permanent_programs = list()
|
||||
|
||||
// Vulnerabilities
|
||||
/// EMP flat deletion upper
|
||||
var/emp_flat_deletion_upper = 35
|
||||
/// EMP flat deletion lower
|
||||
var/emp_Flat_deletion_lower = 20
|
||||
/// EMP percent deletion upper
|
||||
var/emp_percent_deletion_upper = 0.35
|
||||
/// EMP percent deletion lower
|
||||
var/emp_percent_deletion_lower = 0.25
|
||||
/// EMP severity multiplier, capping to 0 to 100
|
||||
var/emp_severity_mod = 1
|
||||
/// EMP severity div for cloudsync reset chance
|
||||
var/emp_desync_mod = 0.25
|
||||
|
||||
/// Shock flat deletion upper
|
||||
var/shock_flat_deletion_upper = 45
|
||||
/// Shock flat deletion lower
|
||||
var/shock_flat_deletion_lower = 25
|
||||
/// Shock percent deletion upper
|
||||
var/shock_percent_deletion_upper = 0.25
|
||||
/// Shock percent deletion lower
|
||||
var/shock_percent_deletion_lower = 0.15
|
||||
|
||||
|
||||
/// minor shock deletion lower
|
||||
var/minor_shock_deletion_lower = 5
|
||||
/// minor shock deletion upper
|
||||
var/minor_shock_deletion_upper = 15
|
||||
|
||||
/datum/component/nanites/Initialize(amount = 100, cloud = 0)
|
||||
if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
@@ -55,6 +93,9 @@
|
||||
RegisterSignal(parent, COMSIG_NANITE_ADD_PROGRAM, .proc/add_program)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SCAN, .proc/nanite_scan)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SYNC, .proc/sync)
|
||||
RegisterSignal(parent, COMSIG_NANITE_CHECK_CONSOLE_LOCK, .proc/check_console_locking)
|
||||
RegisterSignal(parent, COMSIG_NANITE_CHECK_HOST_LOCK, .proc/check_host_lockout)
|
||||
RegisterSignal(parent, COMSIG_NANITE_CHECK_VIRAL_PREVENTION, .proc/check_viral_prevention)
|
||||
|
||||
if(isliving(parent))
|
||||
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp)
|
||||
@@ -118,13 +159,60 @@
|
||||
next_sync = world.time + NANITE_SYNC_DELAY
|
||||
set_nanite_bar()
|
||||
|
||||
/**
|
||||
* Called when nanites are depleted.
|
||||
* Deletes ourselves by default.
|
||||
*/
|
||||
/datum/component/nanites/proc/nanites_depleted()
|
||||
if(qdel_self_on_depletion)
|
||||
delete_nantes()
|
||||
|
||||
/**
|
||||
* Used to rid ourselves
|
||||
*/
|
||||
/datum/component/nanites/proc/delete_nanites()
|
||||
qdel(src)
|
||||
if(can_be_deleted)
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
* Adds permanent programs
|
||||
*/
|
||||
/datum/component/nanites/proc/add_permanent_program(list/program, immutable = FALSE)
|
||||
if(!islist(program))
|
||||
program = list(program)
|
||||
for(var/i in program)
|
||||
if(i in permanent_programs)
|
||||
continue
|
||||
var/datum/nanite_program/P = i
|
||||
permanent_programs += P
|
||||
if(immutable)
|
||||
P.immutable = TRUE
|
||||
for(var/i in programs)
|
||||
if(P.collision_check(i))
|
||||
qdel(i)
|
||||
programs += P
|
||||
|
||||
/**
|
||||
* Checks if we can block out console modification
|
||||
*/
|
||||
/datum/component/nanites/proc/check_console_locking()
|
||||
return SEND_SIGNAL(src, COMSIG_NANITE_INTERNAL_CONSOLE_LOCK_CHECK)
|
||||
|
||||
/**
|
||||
* Checks if we can lock out host internal conscious modification
|
||||
*/
|
||||
/datum/component/nanites/proc/check_host_lockout()
|
||||
return SEND_SIGNAL(src, COMSIG_NANITE_INTERNAL_HOST_LOCK_CHECK)
|
||||
|
||||
/**
|
||||
* Checks if we can block out viral replica
|
||||
*/
|
||||
/datum/component/nanites/proc/check_viral_prevention()
|
||||
return SEND_SIGNAL(src, COMSIG_NANITE_INTERNAL_VIRAL_LOCK_CHECK)
|
||||
|
||||
//Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status)
|
||||
/datum/component/nanites/proc/sync(datum/signal_source, datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE)
|
||||
var/list/programs_to_remove = programs.Copy()
|
||||
var/list/programs_to_remove = programs.Copy() - permanent_programs
|
||||
var/list/programs_to_add = source.programs.Copy()
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
@@ -151,7 +239,7 @@
|
||||
sync(null, cloud_copy)
|
||||
return
|
||||
//Without cloud syncing nanites can accumulate errors and/or defects
|
||||
if(prob(8) && programs.len)
|
||||
if(prob(8) && programs.len && requires_cloud_sync)
|
||||
var/datum/nanite_program/NP = pick(programs)
|
||||
NP.software_error()
|
||||
|
||||
@@ -159,8 +247,11 @@
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
if(NP.unique && NP.type == new_program.type)
|
||||
qdel(NP)
|
||||
if(programs.len >= max_programs)
|
||||
if(NP in permanent_programs)
|
||||
return COMPONENT_PROGRAM_NOT_INSTALLED
|
||||
else
|
||||
qdel(NP)
|
||||
if((programs.len - length(permanent_programs)) >= max_programs)
|
||||
return COMPONENT_PROGRAM_NOT_INSTALLED
|
||||
if(source_program)
|
||||
source_program.copy_programming(new_program)
|
||||
@@ -177,7 +268,7 @@
|
||||
/datum/component/nanites/proc/adjust_nanites(datum/source, amount)
|
||||
nanite_volume = clamp(nanite_volume + amount, 0, max_nanites)
|
||||
if(nanite_volume <= 0) //oops we ran out
|
||||
qdel(src)
|
||||
nanites_depleted()
|
||||
|
||||
/datum/component/nanites/proc/set_nanite_bar(remove = FALSE)
|
||||
var/image/holder = host_mob.hud_list[DIAG_NANITE_FULL_HUD]
|
||||
@@ -191,28 +282,28 @@
|
||||
holder.icon_state = "nanites[nanite_percent]"
|
||||
|
||||
/datum/component/nanites/proc/on_emp(datum/source, severity)
|
||||
nanite_volume *= (rand(60, 90) * 0.01) //Lose 10-40% of nanites
|
||||
adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume
|
||||
if(prob(40/severity))
|
||||
severity *= emp_severity_mod
|
||||
var/loss = (severity / 100) * (rand(emp_percent_deletion_lower, emp_percent_deletion_upper) * nanite_volume) + rand(emp_flat_deletion_lower, emp_flat_deletion_upper)
|
||||
adjust_nanites(null, -loss)
|
||||
if(prob(severity / emp_desync_mod))
|
||||
cloud_id = 0
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_emp(severity)
|
||||
|
||||
|
||||
/datum/component/nanites/proc/on_shock(datum/source, shock_damage, siemens_coeff = 1, flags = NONE)
|
||||
if(shock_damage < 1)
|
||||
return
|
||||
|
||||
if(!HAS_TRAIT_NOT_FROM(host_mob, TRAIT_SHOCKIMMUNE, "nanites"))//Another shock protection must protect nanites too, but nanites protect only host
|
||||
nanite_volume *= (rand(45, 80) * 0.01) //Lose 20-55% of nanites
|
||||
adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume
|
||||
var/loss = (rand(shock_percent_deletion_lower, shock_percent_deletion_upper) * nanite_volume) + rand(shock_flat_deletion_lower, shock_flat_deletion_upper)
|
||||
adjust_nanites(null, -loss)
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_shock(shock_damage)
|
||||
|
||||
/datum/component/nanites/proc/on_minor_shock(datum/source)
|
||||
adjust_nanites(null, -(rand(5, 15))) //Lose 5-15 flat nanite volume
|
||||
adjust_nanites(null, -(rand(miner_shock_deletion_lower, miner_shock_deletion_uppper))) //Lose 5-15 flat nanite volume
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_minor_shock()
|
||||
@@ -237,7 +328,7 @@
|
||||
NP.receive_comm_signal(comm_code, comm_message, comm_source)
|
||||
|
||||
/datum/component/nanites/proc/check_viable_biotype()
|
||||
if(!(host_mob.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD)))
|
||||
if(!(host_mob.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD|MOB_NANITES)))
|
||||
qdel(src) //bodytype no longer sustains nanites
|
||||
|
||||
/datum/component/nanites/proc/check_access(datum/source, obj/O)
|
||||
@@ -378,3 +469,10 @@
|
||||
id++
|
||||
mob_programs += list(mob_program)
|
||||
data["mob_programs"] = mob_programs
|
||||
|
||||
/**
|
||||
* Subtype that doesn't erase itself from running out
|
||||
*/
|
||||
/datum/component/nanites/permanent
|
||||
qdel_self_on_depletion = FALSE
|
||||
can_be_deleted = FALSE
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user