diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index d82444a1d0f30..ec6030c87d9b9 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -334,6 +334,7 @@ //Nanites #define COMSIG_HAS_NANITES "has_nanites" //() returns TRUE if nanites are found +#define COMSIG_NANITE_IS_STEALTHY "nanite_is_stealthy" //() returns TRUE if nanites have stealth #define COMSIG_NANITE_GET_PROGRAMS "nanite_get_programs" //(list/nanite_programs) - makes the input list a copy the nanites' program list #define COMSIG_NANITE_GET_VOLUME "nanite_get_volume" //(amount) Returns nanite amount #define COMSIG_NANITE_SET_VOLUME "nanite_set_volume" //(amount) Sets current nanite volume to the given amount diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm index 7085092326ae8..b98adba3d6d82 100644 --- a/code/datums/components/nanites.dm +++ b/code/datums/components/nanites.dm @@ -36,6 +36,7 @@ /datum/component/nanites/RegisterWithParent() RegisterSignal(parent, COMSIG_HAS_NANITES, .proc/confirm_nanites) + RegisterSignal(parent, COMSIG_NANITE_IS_STEALTHY, .proc/check_stealth) RegisterSignal(parent, COMSIG_NANITE_UI_DATA, .proc/nanite_ui_data) RegisterSignal(parent, COMSIG_NANITE_GET_PROGRAMS, .proc/get_programs) RegisterSignal(parent, COMSIG_NANITE_SET_VOLUME, .proc/set_volume) @@ -60,6 +61,7 @@ /datum/component/nanites/UnregisterFromParent() UnregisterSignal(parent, list(COMSIG_HAS_NANITES, + COMSIG_NANITE_IS_STEALTHY, COMSIG_NANITE_UI_DATA, COMSIG_NANITE_GET_PROGRAMS, COMSIG_NANITE_SET_VOLUME, @@ -192,6 +194,9 @@ var/datum/nanite_program/NP = X NP.on_minor_shock() +/datum/component/nanites/proc/check_stealth(datum/source) + return stealth + /datum/component/nanites/proc/on_death(datum/source, gibbed) for(var/X in programs) var/datum/nanite_program/NP = X diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index ecda528cbd8c9..4ad096f9bb70a 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -201,3 +201,10 @@ description = "HE'S CUTTING ME OPEN!!\n" mood_change = -8 +/datum/mood_event/nanite_sadness + description = "+++++++HAPPINESS SUPPRESSION+++++++\n" + mood_change = -7 + +/datum/mood_event/nanite_sadness/add_effects(message) + description = "+++++++[message]+++++++\n" + diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm index 17bad400d17a3..bcf6c6db5c921 100644 --- a/code/datums/mood_events/generic_positive_events.dm +++ b/code/datums/mood_events/generic_positive_events.dm @@ -158,6 +158,13 @@ mood_change = 2 timeout = 3 MINUTES +/datum/mood_event/nanite_happiness + description = "+++++++HAPPINESS ENHANCEMENT+++++++\n" + mood_change = 7 + +/datum/mood_event/nanite_happiness/add_effects(message) + description = "+++++++[message]+++++++\n" + /datum/mood_event/area description = "" //Fill this out in the area mood_change = 0 diff --git a/code/modules/research/designs/nanite_designs.dm b/code/modules/research/designs/nanite_designs.dm index 7b9a0805fc97d..d020238dccaeb 100644 --- a/code/modules/research/designs/nanite_designs.dm +++ b/code/modules/research/designs/nanite_designs.dm @@ -372,7 +372,7 @@ name = "Mind Control" desc = "The nanites imprint an absolute directive onto the host's brain while they're active." id = "mindcontrol_nanites" - program_type = /datum/nanite_program/mind_control + program_type = /datum/nanite_program/triggered/comm/mind_control category = list("Weaponized Nanites") ////////////////////SUPPRESSION NANITES////////////////////////////////////// @@ -454,6 +454,20 @@ program_type = /datum/nanite_program/triggered/comm/hallucination category = list("Suppression Nanites") +/datum/design/nanites/good_mood + name = "Happiness Enhancer" + desc = "The nanites synthesize serotonin inside the host's brain, creating an artificial sense of happiness." + id = "good_mood_nanites" + program_type = /datum/nanite_program/good_mood + category = list("Suppression Nanites") + +/datum/design/nanites/bad_mood + name = "Happiness Suppressor" + desc = "The nanites suppress the production of serotonin inside the host's brain, creating an artificial state of depression." + id = "bad_mood_nanites" + program_type = /datum/nanite_program/bad_mood + category = list("Suppression Nanites") + ////////////////////SENSOR NANITES////////////////////////////////////// /datum/design/nanites/sensor_health diff --git a/code/modules/research/nanites/nanite_programs/healing.dm b/code/modules/research/nanites/nanite_programs/healing.dm index 538646c267395..812048cf2e6fc 100644 --- a/code/modules/research/nanites/nanite_programs/healing.dm +++ b/code/modules/research/nanites/nanite_programs/healing.dm @@ -3,7 +3,7 @@ /datum/nanite_program/regenerative name = "Accelerated Regeneration" desc = "The nanites boost the host's natural regeneration, increasing their healing speed. Does not consume nanites if the host is unharmed." - use_rate = 2.5 + use_rate = 0.5 rogue_types = list(/datum/nanite_program/necrotic) /datum/nanite_program/regenerative/check_conditions() @@ -23,11 +23,11 @@ if(!parts.len) return for(var/obj/item/bodypart/L in parts) - if(L.heal_damage(1/parts.len, 1/parts.len, null, BODYPART_ORGANIC)) + if(L.heal_damage(0.5/parts.len, 0.5/parts.len, null, BODYPART_ORGANIC)) host_mob.update_damage_overlays() else - host_mob.adjustBruteLoss(-1, TRUE) - host_mob.adjustFireLoss(-1, TRUE) + host_mob.adjustBruteLoss(-0.5, TRUE) + host_mob.adjustFireLoss(-0.5, TRUE) /datum/nanite_program/temperature name = "Temperature Adjustment" @@ -108,7 +108,7 @@ /datum/nanite_program/repairing name = "Mechanical Repair" desc = "The nanites fix damage in the host's mechanical limbs." - use_rate = 0.5 //much more efficient than organic healing + use_rate = 0.5 rogue_types = list(/datum/nanite_program/necrotic) /datum/nanite_program/repairing/check_conditions() @@ -133,13 +133,13 @@ return var/update = FALSE for(var/obj/item/bodypart/L in parts) - if(L.heal_damage(1/parts.len, 1/parts.len, null, BODYPART_ROBOTIC)) + if(L.heal_damage(1.5/parts.len, 1.5/parts.len, null, BODYPART_ROBOTIC)) //much faster than organic healing update = TRUE if(update) host_mob.update_damage_overlays() else - host_mob.adjustBruteLoss(-1, TRUE) - host_mob.adjustFireLoss(-1, TRUE) + host_mob.adjustBruteLoss(-1.5, TRUE) + host_mob.adjustFireLoss(-1.5, TRUE) /datum/nanite_program/purging_advanced name = "Selective Blood Purification" diff --git a/code/modules/research/nanites/nanite_programs/suppression.dm b/code/modules/research/nanites/nanite_programs/suppression.dm index 8a1bcfb38aaa0..385f23672dfc1 100644 --- a/code/modules/research/nanites/nanite_programs/suppression.dm +++ b/code/modules/research/nanites/nanite_programs/suppression.dm @@ -359,3 +359,63 @@ target.hal_type = hal_type target.hal_details = hal_details target.comm_code = comm_code + +/datum/nanite_program/good_mood + name = "Happiness Enhancer" + desc = "The nanites synthesize serotonin inside the host's brain, creating an artificial sense of happiness." + use_rate = 0.1 + rogue_types = list(/datum/nanite_program/brain_decay) + extra_settings = list("Mood Message") + var/message = "HAPPINESS ENHANCEMENT" + +/datum/nanite_program/good_mood/set_extra_setting(user, setting) + if(setting == "Mood Message") + var/new_message = stripped_input(user, "Choose the message visible on the mood effect.", "Message", message, MAX_NAME_LEN) + if(!new_message) + return + message = new_message + +/datum/nanite_program/good_mood/get_extra_setting(setting) + if(setting == "Mood Message") + return message + +/datum/nanite_program/good_mood/copy_extra_settings_to(datum/nanite_program/good_mood/target) + target.message = message + +/datum/nanite_program/good_mood/enable_passive_effect() + . = ..() + SEND_SIGNAL(host_mob, COMSIG_ADD_MOOD_EVENT, "nanite_happy", /datum/mood_event/nanite_happiness, message) + +/datum/nanite_program/good_mood/disable_passive_effect() + . = ..() + SEND_SIGNAL(host_mob, COMSIG_CLEAR_MOOD_EVENT, "nanite_happy") + +/datum/nanite_program/bad_mood + name = "Happiness Suppressor" + desc = "The nanites suppress the production of serotonin inside the host's brain, creating an artificial state of depression." + use_rate = 0.1 + rogue_types = list(/datum/nanite_program/brain_decay) + extra_settings = list("Mood Message") + var/message = "HAPPINESS SUPPRESSION" + +/datum/nanite_program/bad_mood/set_extra_setting(user, setting) + if(setting == "Mood Message") + var/new_message = stripped_input(user, "Choose the message visible on the mood effect.", "Message", message, MAX_NAME_LEN) + if(!new_message) + return + message = new_message + +/datum/nanite_program/bad_mood/get_extra_setting(setting) + if(setting == "Mood Message") + return message + +/datum/nanite_program/bad_mood/copy_extra_settings_to(datum/nanite_program/bad_mood/target) + target.message = message + +/datum/nanite_program/bad_mood/enable_passive_effect() + . = ..() + SEND_SIGNAL(host_mob, COMSIG_ADD_MOOD_EVENT, "nanite_sadness", /datum/mood_event/nanite_sadness, message) + +/datum/nanite_program/bad_mood/disable_passive_effect() + . = ..() + SEND_SIGNAL(host_mob, COMSIG_CLEAR_MOOD_EVENT, "nanite_sadness") diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm index 8434a17f820d8..d4af485d475aa 100644 --- a/code/modules/research/nanites/nanite_programs/utility.dm +++ b/code/modules/research/nanites/nanite_programs/utility.dm @@ -6,6 +6,7 @@ rogue_types = list(/datum/nanite_program/toxic) extra_settings = list("Program Overwrite","Cloud Overwrite") + var/pulse_cooldown = 0 var/sync_programs = TRUE var/sync_overwrite = FALSE var/overwrite_cloud = FALSE @@ -67,12 +68,16 @@ target.sync_overwrite = sync_overwrite /datum/nanite_program/viral/active_effect() + if(world.time < pulse_cooldown) + return for(var/mob/M in orange(host_mob, 5)) - if(prob(5)) - if(sync_programs) - SEND_SIGNAL(M, COMSIG_NANITE_SYNC, nanites, sync_overwrite) - if(overwrite_cloud) - SEND_SIGNAL(M, COMSIG_NANITE_SET_CLOUD, set_cloud) + if(SEND_SIGNAL(M, COMSIG_NANITE_IS_STEALTHY)) + continue + if(sync_programs) + SEND_SIGNAL(M, COMSIG_NANITE_SYNC, nanites, sync_overwrite) + if(overwrite_cloud) + SEND_SIGNAL(M, COMSIG_NANITE_SET_CLOUD, set_cloud) + pulse_cooldown = world.time + 75 /datum/nanite_program/monitoring name = "Monitoring" @@ -256,22 +261,27 @@ 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(prob(10)) - var/list/mob/living/target_hosts = list() - for(var/mob/living/L in oview(5, host_mob)) - 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) + if(spread_cooldown < world.time) + 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/triggered/nanite_sting name = "Nanite Sting" diff --git a/code/modules/research/nanites/nanite_programs/weapon.dm b/code/modules/research/nanites/nanite_programs/weapon.dm index ef7c6464478e2..a5284b0ce6532 100644 --- a/code/modules/research/nanites/nanite_programs/weapon.dm +++ b/code/modules/research/nanites/nanite_programs/weapon.dm @@ -161,40 +161,55 @@ /datum/nanite_program/cryo/active_effect() host_mob.adjust_bodytemperature(-rand(15,25), 50) -/datum/nanite_program/mind_control +/datum/nanite_program/triggered/comm/mind_control name = "Mind Control" - desc = "The nanites imprint an absolute directive onto the host's brain while they're active." - use_rate = 3 + desc = "The nanites imprint an absolute directive onto the host's brain for one minute when triggered." + trigger_cost = 30 + trigger_cooldown = 1800 rogue_types = list(/datum/nanite_program/brain_decay, /datum/nanite_program/brain_misfire) - extra_settings = list("Directive") - var/cooldown = 0 //avoids spam when nanites are running low + extra_settings = list("Directive","Comm Code") var/directive = "..." -/datum/nanite_program/mind_control/set_extra_setting(user, setting) +/datum/nanite_program/triggered/comm/mind_control/set_extra_setting(user, setting) if(setting == "Directive") var/new_directive = stripped_input(user, "Choose the directive to imprint with mind control.", "Directive", directive, MAX_MESSAGE_LEN) if(!new_directive) return directive = new_directive + if(setting == "Comm Code") + var/new_code = input(user, "Set the communication code (1-9999) or set to 0 to disable external signals.", name, null) as null|num + if(isnull(new_code)) + return + comm_code = CLAMP(round(new_code, 1), 0, 9999) -/datum/nanite_program/mind_control/get_extra_setting(setting) +/datum/nanite_program/triggered/comm/mind_control/get_extra_setting(setting) if(setting == "Directive") return directive + if(setting == "Comm Code") + return comm_code -/datum/nanite_program/mind_control/copy_extra_settings_to(datum/nanite_program/mind_control/target) +/datum/nanite_program/triggered/comm/mind_control/copy_extra_settings_to(datum/nanite_program/triggered/comm/mind_control/target) target.directive = directive + target.comm_code = comm_code -/datum/nanite_program/mind_control/enable_passive_effect() - if(world.time < cooldown) +/datum/nanite_program/triggered/comm/mind_control/trigger(comm_message) + if(!..()) return - . = ..() - brainwash(host_mob, directive) + if(host_mob.stat == DEAD) + return + var/sent_directive = comm_message + if(!comm_message) + sent_directive = directive + brainwash(host_mob, sent_directive) log_game("A mind control nanite program brainwashed [key_name(host_mob)] with the objective '[directive]'.") + addtimer(CALLBACK(src, .proc/end_brainwashing), 600) -/datum/nanite_program/mind_control/disable_passive_effect() - . = ..() +/datum/nanite_program/triggered/comm/mind_control/proc/end_brainwashing() if(host_mob.mind && host_mob.mind.has_antag_datum(/datum/antagonist/brainwashed)) host_mob.mind.remove_antag_datum(/datum/antagonist/brainwashed) log_game("[key_name(host_mob)] is no longer brainwashed by nanites.") - cooldown = world.time + 450 + +/datum/nanite_program/triggered/comm/mind_control/disable_passive_effect() + . = ..() + end_brainwashing() diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index a98c562fa6f2b..486f778f85a6b 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -952,7 +952,7 @@ display_name = "Neural Nanite Programming" description = "Nanite programs affecting nerves and brain matter." prereq_ids = list("nanite_bio") - design_ids = list("nervous_nanites", "brainheal_nanites", "paralyzing_nanites", "stun_nanites", "selfscan_nanites") + design_ids = list("nervous_nanites", "brainheal_nanites", "paralyzing_nanites", "stun_nanites", "selfscan_nanites","good_mood_nanites","bad_mood_nanites") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000