Nanites port from /tg/station, original coder XDTM
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
//Programs that buff the host in generally passive ways.
|
||||
|
||||
/datum/nanite_program/nervous
|
||||
name = "Nerve Support"
|
||||
desc = "The nanites act as a secondary nervous system, reducing the amount of time the host is stunned."
|
||||
use_rate = 1.5
|
||||
rogue_types = list(/datum/nanite_program/nerve_decay)
|
||||
|
||||
/datum/nanite_program/nervous/enable_passive_effect()
|
||||
. = ..()
|
||||
if(ishuman(host_mob))
|
||||
var/mob/living/carbon/human/H = host_mob
|
||||
H.physiology.stun_mod *= 0.5
|
||||
|
||||
/datum/nanite_program/nervous/disable_passive_effect()
|
||||
. = ..()
|
||||
if(ishuman(host_mob))
|
||||
var/mob/living/carbon/human/H = host_mob
|
||||
H.physiology.stun_mod *= 2
|
||||
|
||||
/datum/nanite_program/triggered/adrenaline
|
||||
name = "Adrenaline Burst"
|
||||
desc = "The nanites cause a burst of adrenaline when triggered, waking the host from stuns and temporarily increasing their speed."
|
||||
trigger_cost = 25
|
||||
trigger_cooldown = 1200
|
||||
rogue_types = list(/datum/nanite_program/toxic, /datum/nanite_program/nerve_decay)
|
||||
|
||||
/datum/nanite_program/triggered/adrenaline/trigger()
|
||||
if(!..())
|
||||
return
|
||||
to_chat(host_mob, "<span class='notice'>You feel a sudden surge of energy!</span>")
|
||||
host_mob.SetStun(0)
|
||||
host_mob.SetKnockdown(0)
|
||||
host_mob.SetUnconscious(0)
|
||||
host_mob.adjustStaminaLoss(-75)
|
||||
host_mob.lying = 0
|
||||
host_mob.update_canmove()
|
||||
host_mob.reagents.add_reagent("stimulants", 1.5)
|
||||
|
||||
/datum/nanite_program/hardening
|
||||
name = "Dermal Hardening"
|
||||
desc = "The nanites form a mesh under the host's skin, protecting them from melee and bullet impacts."
|
||||
use_rate = 0.5
|
||||
rogue_types = list(/datum/nanite_program/skin_decay)
|
||||
|
||||
//TODO on_hit effect that turns skin grey for a moment
|
||||
|
||||
/datum/nanite_program/hardening/enable_passive_effect()
|
||||
. = ..()
|
||||
if(ishuman(host_mob))
|
||||
var/mob/living/carbon/human/H = host_mob
|
||||
H.physiology.armor.melee += 50
|
||||
H.physiology.armor.bullet += 35
|
||||
|
||||
/datum/nanite_program/hardening/disable_passive_effect()
|
||||
. = ..()
|
||||
if(ishuman(host_mob))
|
||||
var/mob/living/carbon/human/H = host_mob
|
||||
H.physiology.armor.melee -= 50
|
||||
H.physiology.armor.bullet -= 35
|
||||
|
||||
/datum/nanite_program/refractive
|
||||
name = "Dermal Refractive Surface"
|
||||
desc = "The nanites form a membrane above the host's skin, reducing the effect of laser and energy impacts."
|
||||
use_rate = 0.50
|
||||
rogue_types = list(/datum/nanite_program/skin_decay)
|
||||
|
||||
/datum/nanite_program/refractive/enable_passive_effect()
|
||||
. = ..()
|
||||
if(ishuman(host_mob))
|
||||
var/mob/living/carbon/human/H = host_mob
|
||||
H.physiology.armor.laser += 50
|
||||
H.physiology.armor.energy += 35
|
||||
|
||||
/datum/nanite_program/refractive/disable_passive_effect()
|
||||
. = ..()
|
||||
if(ishuman(host_mob))
|
||||
var/mob/living/carbon/human/H = host_mob
|
||||
H.physiology.armor.laser -= 50
|
||||
H.physiology.armor.energy -= 35
|
||||
|
||||
/datum/nanite_program/coagulating
|
||||
name = "Rapid Coagulation"
|
||||
desc = "The nanites induce rapid coagulation when the host is wounded, dramatically reducing bleeding rate."
|
||||
use_rate = 0.10
|
||||
rogue_types = list(/datum/nanite_program/suffocating)
|
||||
|
||||
/datum/nanite_program/coagulating/enable_passive_effect()
|
||||
. = ..()
|
||||
if(ishuman(host_mob))
|
||||
var/mob/living/carbon/human/H = host_mob
|
||||
H.physiology.bleed_mod *= 0.1
|
||||
|
||||
/datum/nanite_program/coagulating/disable_passive_effect()
|
||||
. = ..()
|
||||
if(ishuman(host_mob))
|
||||
var/mob/living/carbon/human/H = host_mob
|
||||
H.physiology.bleed_mod *= 10
|
||||
|
||||
/datum/nanite_program/conductive
|
||||
name = "Electric Conduction"
|
||||
desc = "The nanites act as a grounding rod for electric shocks, protecting the host. Shocks can still damage the nanites themselves."
|
||||
use_rate = 0.20
|
||||
program_flags = NANITE_SHOCK_IMMUNE
|
||||
rogue_types = list(/datum/nanite_program/nerve_decay)
|
||||
|
||||
/datum/nanite_program/conductive/enable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.add_trait(TRAIT_SHOCKIMMUNE, "nanites")
|
||||
|
||||
/datum/nanite_program/conductive/disable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.remove_trait(TRAIT_SHOCKIMMUNE, "nanites")
|
||||
|
||||
/datum/nanite_program/mindshield
|
||||
name = "Mental Barrier"
|
||||
desc = "The nanites form a protective membrane around the host's brain, shielding them from abnormal influences while they're active."
|
||||
use_rate = 0.40
|
||||
rogue_types = list(/datum/nanite_program/brain_decay, /datum/nanite_program/brain_misfire)
|
||||
|
||||
/datum/nanite_program/mindshield/enable_passive_effect()
|
||||
. = ..()
|
||||
if(!host_mob.mind.has_antag_datum(/datum/antagonist/rev)) //won't work if on a rev, to avoid having implanted revs
|
||||
host_mob.add_trait(TRAIT_MINDSHIELD, "nanites")
|
||||
host_mob.sec_hud_set_implants()
|
||||
|
||||
/datum/nanite_program/mindshield/disable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.remove_trait(TRAIT_MINDSHIELD, "nanites")
|
||||
host_mob.sec_hud_set_implants()
|
||||
@@ -0,0 +1,250 @@
|
||||
//Programs that heal the host in some way.
|
||||
|
||||
/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
|
||||
rogue_types = list(/datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/regenerative/check_conditions()
|
||||
if(!host_mob.getBruteLoss() && !host_mob.getFireLoss())
|
||||
return FALSE
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
var/list/parts = C.get_damaged_bodyparts(TRUE,TRUE, status = BODYPART_ORGANIC)
|
||||
if(!parts.len)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/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 = BODYPART_ORGANIC)
|
||||
if(!parts.len)
|
||||
return
|
||||
for(var/obj/item/bodypart/L in parts)
|
||||
if(L.heal_damage(1/parts.len, 1/parts.len))
|
||||
host_mob.update_damage_overlays()
|
||||
else
|
||||
host_mob.adjustBruteLoss(-1, TRUE)
|
||||
host_mob.adjustFireLoss(-1, TRUE)
|
||||
|
||||
/datum/nanite_program/temperature
|
||||
name = "Temperature Adjustment"
|
||||
desc = "The nanites adjust the host's internal temperature to an ideal level."
|
||||
use_rate = 3.5
|
||||
rogue_types = list(/datum/nanite_program/skin_decay)
|
||||
|
||||
/datum/nanite_program/temperature/check_conditions()
|
||||
if(host_mob.bodytemperature > (BODYTEMP_NORMAL - 30) && host_mob.bodytemperature < (BODYTEMP_NORMAL + 30))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/temperature/active_effect()
|
||||
if(host_mob.bodytemperature > BODYTEMP_NORMAL)
|
||||
host_mob.adjust_bodytemperature(-40 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
|
||||
else if(host_mob.bodytemperature < (BODYTEMP_NORMAL + 1))
|
||||
host_mob.adjust_bodytemperature(40 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
|
||||
|
||||
/datum/nanite_program/purging
|
||||
name = "Blood Purification"
|
||||
desc = "The nanites purge toxins and chemicals from the host's bloodstream."
|
||||
use_rate = 1
|
||||
rogue_types = list(/datum/nanite_program/suffocating, /datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/purging/check_conditions()
|
||||
var/foreign_reagent = LAZYLEN(host_mob.reagents.reagent_list)
|
||||
if(!host_mob.getToxLoss() && !foreign_reagent)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/purging/active_effect()
|
||||
host_mob.adjustToxLoss(-1)
|
||||
for(var/datum/reagent/R in host_mob.reagents.reagent_list)
|
||||
host_mob.reagents.remove_reagent(R.id,1)
|
||||
|
||||
/datum/nanite_program/brain_heal
|
||||
name = "Neural Regeneration"
|
||||
desc = "The nanites fix neural connections in the host's brain, reversing brain damage and minor traumas."
|
||||
use_rate = 1.5
|
||||
rogue_types = list(/datum/nanite_program/brain_decay)
|
||||
|
||||
/datum/nanite_program/brain_heal/check_conditions()
|
||||
if(!host_mob.getBrainLoss())
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/brain_heal/active_effect()
|
||||
host_mob.adjustBrainLoss(-1, TRUE)
|
||||
if(iscarbon(host_mob) && prob(10))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC)
|
||||
|
||||
/datum/nanite_program/blood_restoring
|
||||
name = "Blood Regeneration"
|
||||
desc = "The nanites stimulate and boost blood cell production in the host."
|
||||
use_rate = 1
|
||||
rogue_types = list(/datum/nanite_program/suffocating)
|
||||
|
||||
/datum/nanite_program/blood_restoring/check_conditions()
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
if(C.blood_volume >= BLOOD_VOLUME_SAFE)
|
||||
return FALSE
|
||||
else
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/blood_restoring/active_effect()
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
C.blood_volume += 2
|
||||
|
||||
/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
|
||||
rogue_types = list(/datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/repairing/check_conditions()
|
||||
if(!host_mob.getBruteLoss() && !host_mob.getFireLoss())
|
||||
return FALSE
|
||||
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
var/list/parts = C.get_damaged_bodyparts(TRUE, TRUE, status = BODYPART_ROBOTIC)
|
||||
if(!parts.len)
|
||||
return FALSE
|
||||
else
|
||||
if(!(MOB_ROBOTIC in host_mob.mob_biotypes))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/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 = BODYPART_ROBOTIC)
|
||||
if(!parts.len)
|
||||
return
|
||||
var/update = FALSE
|
||||
for(var/obj/item/bodypart/L in parts)
|
||||
if(L.heal_damage(1/parts.len, 1/parts.len))
|
||||
update = TRUE
|
||||
if(update)
|
||||
host_mob.update_damage_overlays()
|
||||
else
|
||||
host_mob.adjustBruteLoss(-1, TRUE)
|
||||
host_mob.adjustFireLoss(-1, TRUE)
|
||||
|
||||
/datum/nanite_program/purging_advanced
|
||||
name = "Selective Blood Purification"
|
||||
desc = "The nanites purge toxins and dangerous chemicals from the host's bloodstream, while ignoring beneficial chemicals. \
|
||||
The added processing power required to analyze the chemicals severely increases the nanite consumption rate."
|
||||
use_rate = 2
|
||||
rogue_types = list(/datum/nanite_program/suffocating, /datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/purging_advanced/check_conditions()
|
||||
var/foreign_reagent = FALSE
|
||||
for(var/datum/reagent/toxin/R in host_mob.reagents.reagent_list)
|
||||
foreign_reagent = TRUE
|
||||
break
|
||||
if(!host_mob.getToxLoss() && !foreign_reagent)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/purging_advanced/active_effect()
|
||||
host_mob.adjustToxLoss(-1)
|
||||
for(var/datum/reagent/toxin/R in host_mob.reagents.reagent_list)
|
||||
host_mob.reagents.remove_reagent(R.id,1)
|
||||
|
||||
/datum/nanite_program/regenerative_advanced
|
||||
name = "Bio-Reconstruction"
|
||||
desc = "The nanites manually repair and replace organic cells, acting much faster than normal regeneration. \
|
||||
However, this program cannot detect the difference between harmed and unharmed, causing it to consume nanites even if it has no effect."
|
||||
use_rate = 5.5
|
||||
rogue_types = list(/datum/nanite_program/suffocating, /datum/nanite_program/necrotic)
|
||||
|
||||
/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 = BODYPART_ORGANIC)
|
||||
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))
|
||||
update = TRUE
|
||||
if(update)
|
||||
host_mob.update_damage_overlays()
|
||||
else
|
||||
host_mob.adjustBruteLoss(-3, TRUE)
|
||||
host_mob.adjustFireLoss(-3, TRUE)
|
||||
|
||||
/datum/nanite_program/brain_heal_advanced
|
||||
name = "Neural Reimaging"
|
||||
desc = "The nanites are able to backup and restore the host's neural connections, potentially replacing entire chunks of missing or damaged brain matter."
|
||||
use_rate = 3
|
||||
rogue_types = list(/datum/nanite_program/brain_decay, /datum/nanite_program/brain_misfire)
|
||||
|
||||
/datum/nanite_program/brain_heal_advanced/check_conditions()
|
||||
if(!host_mob.getBrainLoss())
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/brain_heal_advanced/active_effect()
|
||||
host_mob.adjustBrainLoss(-2, TRUE)
|
||||
if(iscarbon(host_mob) && prob(10))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_LOBOTOMY)
|
||||
|
||||
/datum/nanite_program/triggered/defib
|
||||
name = "Defibrillation"
|
||||
desc = "The nanites shock the host's heart when triggered, bringing them back to life if the body can sustain it."
|
||||
trigger_cost = 25
|
||||
trigger_cooldown = 120
|
||||
rogue_types = list(/datum/nanite_program/triggered/shocking)
|
||||
|
||||
/datum/nanite_program/triggered/defib/trigger()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
playsound(host_mob, 'sound/machines/defib_zap.ogg', 75, 1, -1)
|
||||
if(check_revivable())
|
||||
host_mob.notify_ghost_cloning("Your heart is being defibrillated. Re-enter your corpse if you want to be revived!", source = src)
|
||||
addtimer(CALLBACK(src, .proc/zap), 30)
|
||||
|
||||
/datum/nanite_program/triggered/defib/proc/check_revivable()
|
||||
if(!iscarbon(host_mob)) //nonstandard biology
|
||||
return FALSE
|
||||
var/mob/living/carbon/C = host_mob
|
||||
if(C.suiciding || C.has_trait(TRAIT_NOCLONE) || C.hellbound) //can't revive
|
||||
return FALSE
|
||||
if((world.time - C.timeofdeath) < 1800) //too late
|
||||
return FALSE
|
||||
if((C.getBruteLoss() > 180) || (C.getFireLoss() > 180)) //too damaged
|
||||
return FALSE
|
||||
if(!C.getorgan(/obj/item/organ/heart)) //what are we even shocking
|
||||
return FALSE
|
||||
var/obj/item/organ/brain/BR = C.getorgan(/obj/item/organ/brain)
|
||||
if(QDELETED(BR) || BR.damaged_brain)
|
||||
return FALSE
|
||||
if(!C.get_ghost())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/nanite_program/triggered/defib/proc/zap()
|
||||
if(check_revivable())
|
||||
var/mob/living/carbon/C = host_mob
|
||||
playsound(C, 'sound/machines/defib_success.ogg', 50, 0)
|
||||
C.set_heartattack(FALSE)
|
||||
C.revive()
|
||||
C.emote("gasp")
|
||||
C.Jitter(100)
|
||||
SEND_SIGNAL(C, COMSIG_LIVING_MINOR_SHOCK)
|
||||
var/tplus = world.time - C.timeofdeath
|
||||
if(tplus > 600)
|
||||
C.adjustBrainLoss( max(0, ((1800 - tplus) / 1800 * 150)), 150)
|
||||
log_game("[C] has been successfully defibrillated by nanites.")
|
||||
else
|
||||
playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
//Programs generated through degradation of other complex programs.
|
||||
//They generally cause minor damage or annoyance.
|
||||
|
||||
//Last stop of the error train
|
||||
/datum/nanite_program/glitch
|
||||
name = "Glitch"
|
||||
desc = "A heavy software corruption that causes nanites to gradually break down."
|
||||
use_rate = 1.5
|
||||
unique = FALSE
|
||||
rogue_types = list()
|
||||
|
||||
//Generic body-affecting programs will decay into this
|
||||
/datum/nanite_program/necrotic
|
||||
name = "Necrosis"
|
||||
desc = "The nanites attack internal tissues indiscriminately, causing widespread damage."
|
||||
use_rate = 0.75
|
||||
unique = FALSE
|
||||
rogue_types = list(/datum/nanite_program/glitch)
|
||||
|
||||
/datum/nanite_program/necrotic/active_effect()
|
||||
host_mob.adjustBruteLoss(0.75, TRUE)
|
||||
if(prob(1))
|
||||
to_chat(host_mob, "<span class='warning'>You feel a mild ache from somewhere inside you.</span>")
|
||||
|
||||
//Programs that don't directly interact with the body will decay into this
|
||||
/datum/nanite_program/toxic
|
||||
name = "Toxin Buildup"
|
||||
desc = "The nanites cause a slow but constant toxin buildup inside the host."
|
||||
use_rate = 0.25
|
||||
unique = FALSE
|
||||
rogue_types = list(/datum/nanite_program/glitch)
|
||||
|
||||
/datum/nanite_program/toxic/active_effect()
|
||||
host_mob.adjustToxLoss(0.5)
|
||||
if(prob(1))
|
||||
to_chat(host_mob, "<span class='warning'>You feel a bit sick.</span>")
|
||||
|
||||
//Generic blood-affecting programs will decay into this
|
||||
/datum/nanite_program/suffocating
|
||||
name = "Hypoxemia"
|
||||
desc = "The nanites prevent the host's blood from absorbing oxygen efficiently."
|
||||
use_rate = 0.75
|
||||
unique = FALSE
|
||||
rogue_types = list(/datum/nanite_program/glitch)
|
||||
|
||||
/datum/nanite_program/suffocating/active_effect()
|
||||
host_mob.adjustOxyLoss(3, 0)
|
||||
if(prob(1))
|
||||
to_chat(host_mob, "<span class='warning'>You feel short of breath.</span>")
|
||||
|
||||
//Generic brain-affecting programs will decay into this
|
||||
/datum/nanite_program/brain_decay
|
||||
name = "Neuro-Necrosis"
|
||||
desc = "The nanites seek and attack brain cells, causing extensive neural damage to the host."
|
||||
use_rate = 0.75
|
||||
unique = FALSE
|
||||
rogue_types = list(/datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/brain_decay/active_effect()
|
||||
if(prob(4))
|
||||
host_mob.hallucination = min(15, host_mob.hallucination)
|
||||
host_mob.adjustBrainLoss(1)
|
||||
|
||||
//Generic brain-affecting programs can also decay into this
|
||||
/datum/nanite_program/brain_misfire
|
||||
name = "Brain Misfire"
|
||||
desc = "The nanites interfere with neural pathways, causing minor psychological disturbances."
|
||||
use_rate = 0.50
|
||||
unique = FALSE
|
||||
rogue_types = list(/datum/nanite_program/brain_decay)
|
||||
|
||||
/datum/nanite_program/brain_misfire/active_effect()
|
||||
if(prob(10))
|
||||
switch(rand(1,4))
|
||||
if(1)
|
||||
host_mob.hallucination += 15
|
||||
if(2)
|
||||
host_mob.confused += 10
|
||||
if(3)
|
||||
host_mob.drowsyness += 10
|
||||
if(4)
|
||||
host_mob.slurring += 10
|
||||
|
||||
//Generic skin-affecting programs will decay into this
|
||||
/datum/nanite_program/skin_decay
|
||||
name = "Dermalysis"
|
||||
desc = "The nanites attack skin cells, causing irritation, rashes, and minor damage."
|
||||
use_rate = 0.25
|
||||
unique = FALSE
|
||||
rogue_types = list(/datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/skin_decay/active_effect()
|
||||
host_mob.adjustBruteLoss(0.25)
|
||||
if(prob(5)) //itching
|
||||
var/picked_bodypart = pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
|
||||
var/obj/item/bodypart/bodypart = host_mob.get_bodypart(picked_bodypart)
|
||||
var/can_scratch = !host_mob.incapacitated() && get_location_accessible(host_mob, picked_bodypart)
|
||||
|
||||
host_mob.visible_message("[can_scratch ? "<span class='warning'>[host_mob] scratches [host_mob.p_their()] [bodypart.name].</span>" : ""]",\
|
||||
"<span class='warning'>Your [bodypart.name] itches. [can_scratch ? " You scratch it." : ""]</span>")
|
||||
|
||||
//Generic nerve-affecting programs will decay into this
|
||||
/datum/nanite_program/nerve_decay
|
||||
name = "Nerve Decay"
|
||||
desc = "The nanites attack the host's nerves, causing lack of coordination and short bursts of paralysis."
|
||||
use_rate = 1
|
||||
unique = FALSE
|
||||
rogue_types = list(/datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/nerve_decay/active_effect()
|
||||
if(prob(5))
|
||||
to_chat(host_mob, "<span class='warning'>You feel unbalanced!</span>")
|
||||
host_mob.confused += 10
|
||||
else if(prob(4))
|
||||
to_chat(host_mob, "<span class='warning'>You can't feel your hands!</span>")
|
||||
host_mob.drop_all_held_items()
|
||||
else if(prob(4))
|
||||
to_chat(host_mob, "<span class='warning'>You can't feel your legs!</span>")
|
||||
host_mob.Knockdown(30)
|
||||
@@ -0,0 +1,392 @@
|
||||
/datum/nanite_program/sensor
|
||||
name = "Sensor Nanites"
|
||||
desc = "These nanites send a signal code when a certain condition is met."
|
||||
unique = FALSE
|
||||
extra_settings = list("Sent Code")
|
||||
|
||||
var/sent_code = 0
|
||||
|
||||
/datum/nanite_program/sensor/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
|
||||
/datum/nanite_program/sensor/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
|
||||
/datum/nanite_program/sensor/copy_extra_settings_to(datum/nanite_program/sensor/target)
|
||||
target.sent_code = sent_code
|
||||
|
||||
/datum/nanite_program/sensor/proc/check_event()
|
||||
return FALSE
|
||||
|
||||
/datum/nanite_program/sensor/proc/send_code()
|
||||
if(activated)
|
||||
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, sent_code, "a [name] program")
|
||||
|
||||
/datum/nanite_program/sensor/active_effect()
|
||||
if(sent_code && check_event())
|
||||
send_code()
|
||||
|
||||
/datum/nanite_program/sensor/repeat
|
||||
name = "Signal Repeater"
|
||||
desc = "When triggered, sends another signal to the nanites, optionally with a delay."
|
||||
can_trigger = TRUE
|
||||
trigger_cost = 0
|
||||
trigger_cooldown = 10
|
||||
extra_settings = list("Sent Code","Delay")
|
||||
var/spent = FALSE
|
||||
var/delay = 0
|
||||
|
||||
/datum/nanite_program/sensor/repeat/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
if(setting == "Delay")
|
||||
var/new_delay = input(user, "Set the delay in seconds:", name, null) as null|num
|
||||
if(isnull(new_delay))
|
||||
return
|
||||
delay = (CLAMP(round(new_delay, 1), 0, 3600)) * 10 //max 1 hour
|
||||
|
||||
/datum/nanite_program/sensor/repeat/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
if(setting == "Delay")
|
||||
return "[delay/10] seconds"
|
||||
|
||||
/datum/nanite_program/sensor/repeat/copy_extra_settings_to(datum/nanite_program/sensor/repeat/target)
|
||||
target.sent_code = sent_code
|
||||
target.delay = delay
|
||||
|
||||
/datum/nanite_program/sensor/repeat/trigger()
|
||||
if(!..())
|
||||
return
|
||||
addtimer(CALLBACK(src, .proc/send_code), delay)
|
||||
|
||||
/datum/nanite_program/sensor/relay_repeat
|
||||
name = "Relay Signal Repeater"
|
||||
desc = "When triggered, sends another signal to a relay channel, optionally with a delay."
|
||||
can_trigger = TRUE
|
||||
trigger_cost = 0
|
||||
trigger_cooldown = 10
|
||||
extra_settings = list("Sent Code","Relay Channel","Delay")
|
||||
var/spent = FALSE
|
||||
var/delay = 0
|
||||
var/relay_channel = 0
|
||||
|
||||
/datum/nanite_program/sensor/relay_repeat/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
if(setting == "Relay Channel")
|
||||
var/new_channel = input(user, "Set the relay channel (1-9999):", name, null) as null|num
|
||||
if(isnull(new_channel))
|
||||
return
|
||||
relay_channel = CLAMP(round(new_channel, 1), 1, 9999)
|
||||
if(setting == "Delay")
|
||||
var/new_delay = input(user, "Set the delay in seconds:", name, null) as null|num
|
||||
if(isnull(new_delay))
|
||||
return
|
||||
delay = (CLAMP(round(new_delay, 1), 0, 3600)) * 10 //max 1 hour
|
||||
|
||||
/datum/nanite_program/sensor/relay_repeat/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
if(setting == "Relay Channel")
|
||||
return relay_channel
|
||||
if(setting == "Delay")
|
||||
return "[delay/10] seconds"
|
||||
|
||||
/datum/nanite_program/sensor/relay_repeat/copy_extra_settings_to(datum/nanite_program/sensor/relay_repeat/target)
|
||||
target.sent_code = sent_code
|
||||
target.delay = delay
|
||||
target.relay_channel = relay_channel
|
||||
|
||||
/datum/nanite_program/sensor/relay_repeat/trigger()
|
||||
if(!..())
|
||||
return
|
||||
addtimer(CALLBACK(src, .proc/send_code), delay)
|
||||
|
||||
/datum/nanite_program/sensor/relay_repeat/send_code()
|
||||
if(activated && relay_channel)
|
||||
for(var/X in SSnanites.nanite_relays)
|
||||
var/datum/nanite_program/relay/N = X
|
||||
N.relay_signal(sent_code, relay_channel, "a [name] program")
|
||||
|
||||
/datum/nanite_program/sensor/health
|
||||
name = "Health Sensor"
|
||||
desc = "The nanites receive a signal when the host's health is above/below a target percentage."
|
||||
extra_settings = list("Sent Code","Health Percent","Direction")
|
||||
var/spent = FALSE
|
||||
var/percent = 50
|
||||
var/direction = "Above"
|
||||
|
||||
/datum/nanite_program/sensor/health/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
if(setting == "Health Percent")
|
||||
var/new_percent = input(user, "Set the health percentage:", name, null) as null|num
|
||||
if(isnull(new_percent))
|
||||
return
|
||||
percent = CLAMP(round(new_percent, 1), -99, 100)
|
||||
if(setting == "Direction")
|
||||
if(direction == "Above")
|
||||
direction = "Below"
|
||||
else
|
||||
direction = "Above"
|
||||
|
||||
/datum/nanite_program/sensor/health/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
if(setting == "Health Percent")
|
||||
return "[percent]%"
|
||||
if(setting == "Direction")
|
||||
return direction
|
||||
|
||||
/datum/nanite_program/sensor/health/copy_extra_settings_to(datum/nanite_program/sensor/health/target)
|
||||
target.sent_code = sent_code
|
||||
target.percent = percent
|
||||
target.direction = direction
|
||||
|
||||
/datum/nanite_program/sensor/health/check_event()
|
||||
var/health_percent = host_mob.health / host_mob.maxHealth * 100
|
||||
var/detected = FALSE
|
||||
if(direction == "Above")
|
||||
if(health_percent >= percent)
|
||||
detected = TRUE
|
||||
else
|
||||
if(health_percent < percent)
|
||||
detected = TRUE
|
||||
|
||||
if(detected)
|
||||
if(!spent)
|
||||
spent = TRUE
|
||||
return TRUE
|
||||
return FALSE
|
||||
else
|
||||
spent = FALSE
|
||||
return FALSE
|
||||
|
||||
/datum/nanite_program/sensor/crit
|
||||
name = "Critical Health Sensor"
|
||||
desc = "The nanites receive a signal when the host first reaches critical health."
|
||||
var/spent = FALSE
|
||||
|
||||
/datum/nanite_program/sensor/crit/check_event()
|
||||
if(host_mob.InCritical())
|
||||
if(!spent)
|
||||
spent = TRUE
|
||||
return TRUE
|
||||
return FALSE
|
||||
else
|
||||
spent = FALSE
|
||||
return FALSE
|
||||
|
||||
/datum/nanite_program/sensor/death
|
||||
name = "Death Sensor"
|
||||
desc = "The nanites receive a signal when they detect the host is dead."
|
||||
var/spent = FALSE
|
||||
|
||||
/datum/nanite_program/sensor/death/on_death()
|
||||
send_code()
|
||||
|
||||
/datum/nanite_program/sensor/nanite_volume
|
||||
name = "Nanite Volume Sensor"
|
||||
desc = "The nanites receive a signal when the nanite supply is above/below a certain percentage."
|
||||
extra_settings = list("Sent Code","Nanite Percent","Direction")
|
||||
var/spent = FALSE
|
||||
var/percent = 50
|
||||
var/direction = "Above"
|
||||
|
||||
/datum/nanite_program/sensor/nanite_volume/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
if(setting == "Nanite Percent")
|
||||
var/new_percent = input(user, "Set the nanite percentage:", name, null) as null|num
|
||||
if(isnull(new_percent))
|
||||
return
|
||||
percent = CLAMP(round(new_percent, 1), 1, 100)
|
||||
if(setting == "Direction")
|
||||
if(direction == "Above")
|
||||
direction = "Below"
|
||||
else
|
||||
direction = "Above"
|
||||
|
||||
/datum/nanite_program/sensor/nanite_volume/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
if(setting == "Nanite Percent")
|
||||
return "[percent]%"
|
||||
if(setting == "Direction")
|
||||
return direction
|
||||
|
||||
/datum/nanite_program/sensor/nanite_volume/copy_extra_settings_to(datum/nanite_program/sensor/nanite_volume/target)
|
||||
target.sent_code = sent_code
|
||||
target.percent = percent
|
||||
target.direction = direction
|
||||
|
||||
/datum/nanite_program/sensor/nanite_volume/check_event()
|
||||
var/nanite_percent = (nanites.nanite_volume - nanites.safety_threshold)/(nanites.max_nanites - nanites.safety_threshold)*100
|
||||
var/detected = FALSE
|
||||
|
||||
if(direction == "Above")
|
||||
if(nanite_percent >= percent)
|
||||
detected = TRUE
|
||||
else
|
||||
if(nanite_percent < percent)
|
||||
detected = TRUE
|
||||
|
||||
if(detected)
|
||||
if(!spent)
|
||||
spent = TRUE
|
||||
return TRUE
|
||||
return FALSE
|
||||
else
|
||||
spent = FALSE
|
||||
return FALSE
|
||||
|
||||
/datum/nanite_program/sensor/damage
|
||||
name = "Damage Sensor"
|
||||
desc = "The nanites receive a signal when a host's specific damage type is above/below a target value."
|
||||
extra_settings = list("Sent Code","Damage Type","Damage","Direction")
|
||||
var/spent = FALSE
|
||||
var/damage_type = "Brute"
|
||||
var/damage = 50
|
||||
var/direction = "Above"
|
||||
|
||||
/datum/nanite_program/sensor/damage/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
if(setting == "Damage")
|
||||
var/new_damage = input(user, "Set the damage threshold:", name, null) as null|num
|
||||
if(isnull(new_damage))
|
||||
return
|
||||
damage = CLAMP(round(new_damage, 1), 0, 500)
|
||||
if(setting == "Damage Type")
|
||||
var/list/damage_types = list("Brute","Burn","Toxin","Oxygen","Cellular")
|
||||
var/new_damage_type = input("Choose the damage type", name) as null|anything in damage_types
|
||||
if(!new_damage_type)
|
||||
return
|
||||
damage_type = new_damage_type
|
||||
if(setting == "Direction")
|
||||
if(direction == "Above")
|
||||
direction = "Below"
|
||||
else
|
||||
direction = "Above"
|
||||
|
||||
/datum/nanite_program/sensor/damage/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
if(setting == "Damage")
|
||||
return damage
|
||||
if(setting == "Damage Type")
|
||||
return damage_type
|
||||
if(setting == "Direction")
|
||||
return direction
|
||||
|
||||
/datum/nanite_program/sensor/damage/copy_extra_settings_to(datum/nanite_program/sensor/damage/target)
|
||||
target.sent_code = sent_code
|
||||
target.damage = damage
|
||||
target.damage_type = damage_type
|
||||
target.direction = direction
|
||||
|
||||
/datum/nanite_program/sensor/damage/check_event()
|
||||
var/reached_threshold = FALSE
|
||||
var/check_above = (direction == "Above")
|
||||
var/damage_amt = 0
|
||||
switch(damage_type)
|
||||
if("Brute")
|
||||
damage_amt = host_mob.getBruteLoss()
|
||||
if("Burn")
|
||||
damage_amt = host_mob.getFireLoss()
|
||||
if("Toxin")
|
||||
damage_amt = host_mob.getToxLoss()
|
||||
if("Oxygen")
|
||||
damage_amt = host_mob.getOxyLoss()
|
||||
if("Cellular")
|
||||
damage_amt = host_mob.getCloneLoss()
|
||||
|
||||
if(damage_amt >= damage)
|
||||
if(check_above)
|
||||
reached_threshold = TRUE
|
||||
else if(!check_above)
|
||||
reached_threshold = TRUE
|
||||
|
||||
if(reached_threshold)
|
||||
if(!spent)
|
||||
spent = TRUE
|
||||
return TRUE
|
||||
return FALSE
|
||||
else
|
||||
spent = FALSE
|
||||
return FALSE
|
||||
|
||||
/datum/nanite_program/sensor/voice
|
||||
name = "Voice Sensor"
|
||||
desc = "Sends a signal when the nanites hear a determined word or sentence."
|
||||
extra_settings = list("Sent Code","Sentence","Inclusive Mode")
|
||||
var/spent = FALSE
|
||||
var/sentence = ""
|
||||
var/inclusive = TRUE
|
||||
|
||||
/datum/nanite_program/sensor/voice/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
if(setting == "Sentence")
|
||||
var/new_sentence = stripped_input(user, "Choose the sentence that triggers the sensor.", "Sentence", sentence, MAX_MESSAGE_LEN)
|
||||
if(!new_sentence)
|
||||
return
|
||||
sentence = new_sentence
|
||||
if(setting == "Inclusive Mode")
|
||||
var/new_inclusive = input("Should the sensor detect the sentence if contained within another sentence?", name) as null|anything in list("Inclusive","Exclusive")
|
||||
if(!new_inclusive)
|
||||
return
|
||||
inclusive = (new_inclusive == "Inclusive")
|
||||
|
||||
/datum/nanite_program/sensor/voice/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
if(setting == "Sentence")
|
||||
return sentence
|
||||
if(setting == "Inclusive Mode")
|
||||
if(inclusive)
|
||||
return "Inclusive"
|
||||
else
|
||||
return "Exclusive"
|
||||
|
||||
/datum/nanite_program/sensor/voice/copy_extra_settings_to(datum/nanite_program/sensor/voice/target)
|
||||
target.sent_code = sent_code
|
||||
target.sentence = sentence
|
||||
target.inclusive = inclusive
|
||||
|
||||
/datum/nanite_program/sensor/voice/on_hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
if(!sentence)
|
||||
return
|
||||
//To make it not case sensitive
|
||||
var/low_message = lowertext(raw_message)
|
||||
var/low_sentence = lowertext(sentence)
|
||||
if(inclusive)
|
||||
if(findtext(low_message, low_sentence))
|
||||
send_code()
|
||||
else
|
||||
if(low_message == low_sentence)
|
||||
send_code()
|
||||
@@ -0,0 +1,311 @@
|
||||
//Programs that are generally useful for population control and non-harmful suppression.
|
||||
|
||||
/datum/nanite_program/triggered/sleepy
|
||||
name = "Sleep Induction"
|
||||
desc = "The nanites cause rapid narcolepsy when triggered."
|
||||
trigger_cost = 15
|
||||
trigger_cooldown = 1200
|
||||
rogue_types = list(/datum/nanite_program/brain_misfire, /datum/nanite_program/brain_decay)
|
||||
|
||||
/datum/nanite_program/triggered/sleepy/trigger()
|
||||
if(!..())
|
||||
return
|
||||
to_chat(host_mob, "<span class='warning'>You start to feel very sleepy...</span>")
|
||||
host_mob.drowsyness += 20
|
||||
addtimer(CALLBACK(host_mob, /mob/living.proc/Sleeping, 200), rand(60,200))
|
||||
|
||||
/datum/nanite_program/paralyzing
|
||||
name = "Paralysis"
|
||||
desc = "The nanites force muscle contraction, effectively paralyzing the host."
|
||||
use_rate = 3
|
||||
rogue_types = list(/datum/nanite_program/nerve_decay)
|
||||
|
||||
/datum/nanite_program/paralyzing/active_effect()
|
||||
host_mob.Stun(40)
|
||||
|
||||
/datum/nanite_program/paralyzing/enable_passive_effect()
|
||||
. = ..()
|
||||
to_chat(host_mob, "<span class='warning'>Your muscles seize! You can't move!</span>")
|
||||
|
||||
/datum/nanite_program/paralyzing/disable_passive_effect()
|
||||
. = ..()
|
||||
to_chat(host_mob, "<span class='notice'>Your muscles relax, and you can move again.</span>")
|
||||
|
||||
/datum/nanite_program/triggered/shocking
|
||||
name = "Electric Shock"
|
||||
desc = "The nanites shock the host when triggered. Destroys a large amount of nanites!"
|
||||
trigger_cost = 10
|
||||
trigger_cooldown = 300
|
||||
program_flags = NANITE_SHOCK_IMMUNE
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
/datum/nanite_program/triggered/shocking/trigger()
|
||||
if(!..())
|
||||
return
|
||||
host_mob.electrocute_act(rand(5,10), "shock nanites", TRUE, TRUE)
|
||||
|
||||
/datum/nanite_program/triggered/stun
|
||||
name = "Neural Shock"
|
||||
desc = "The nanites pulse the host's nerves when triggered, inapacitating them for a short period."
|
||||
trigger_cost = 4
|
||||
trigger_cooldown = 300
|
||||
rogue_types = list(/datum/nanite_program/triggered/shocking, /datum/nanite_program/nerve_decay)
|
||||
|
||||
/datum/nanite_program/triggered/stun/trigger()
|
||||
if(!..())
|
||||
return
|
||||
playsound(host_mob, "sparks", 75, 1, -1)
|
||||
host_mob.Knockdown(80)
|
||||
|
||||
/datum/nanite_program/pacifying
|
||||
name = "Pacification"
|
||||
desc = "The nanites suppress the aggression center of the brain, preventing the host from causing direct harm to others."
|
||||
use_rate = 1
|
||||
rogue_types = list(/datum/nanite_program/brain_misfire, /datum/nanite_program/brain_decay)
|
||||
|
||||
/datum/nanite_program/pacifying/enable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.add_trait(TRAIT_PACIFISM, "nanites")
|
||||
|
||||
/datum/nanite_program/pacifying/disable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.remove_trait(TRAIT_PACIFISM, "nanites")
|
||||
|
||||
/datum/nanite_program/blinding
|
||||
name = "Blindness"
|
||||
desc = "The nanites suppress the host's ocular nerves, blinding them while they're active."
|
||||
use_rate = 1.5
|
||||
rogue_types = list(/datum/nanite_program/nerve_decay)
|
||||
|
||||
/datum/nanite_program/blinding/enable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.become_blind("nanites")
|
||||
|
||||
/datum/nanite_program/blinding/disable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.cure_blind("nanites")
|
||||
|
||||
/datum/nanite_program/mute
|
||||
name = "Mute"
|
||||
desc = "The nanites suppress the host's speech, making them mute while they're active."
|
||||
use_rate = 0.75
|
||||
rogue_types = list(/datum/nanite_program/brain_decay, /datum/nanite_program/brain_misfire)
|
||||
|
||||
/datum/nanite_program/mute/enable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.add_trait(TRAIT_MUTE, "nanites")
|
||||
|
||||
/datum/nanite_program/mute/disable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.remove_trait(TRAIT_MUTE, "nanites")
|
||||
|
||||
/datum/nanite_program/fake_death
|
||||
name = "Death Simulation"
|
||||
desc = "The nanites induce a death-like coma into the host, able to fool most medical scans."
|
||||
use_rate = 3.5
|
||||
rogue_types = list(/datum/nanite_program/nerve_decay, /datum/nanite_program/necrotic, /datum/nanite_program/brain_decay)
|
||||
|
||||
/datum/nanite_program/fake_death/enable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.emote("deathgasp")
|
||||
host_mob.fakedeath("nanites")
|
||||
|
||||
/datum/nanite_program/fake_death/disable_passive_effect()
|
||||
. = ..()
|
||||
host_mob.cure_fakedeath("nanites")
|
||||
|
||||
/datum/nanite_program/triggered/speech
|
||||
name = "Forced Speech"
|
||||
desc = "The nanites force the host to say a pre-programmed sentence when triggered."
|
||||
unique = FALSE
|
||||
trigger_cost = 3
|
||||
trigger_cooldown = 20
|
||||
rogue_types = list(/datum/nanite_program/brain_misfire, /datum/nanite_program/brain_decay)
|
||||
|
||||
extra_settings = list("Sentence")
|
||||
var/sentence = ""
|
||||
|
||||
/datum/nanite_program/triggered/speech/set_extra_setting(user, setting)
|
||||
if(setting == "Sentence")
|
||||
var/new_sentence = stripped_input(user, "Choose the sentence that the host will be forced to say.", "Sentence", sentence, MAX_MESSAGE_LEN)
|
||||
if(!new_sentence)
|
||||
return
|
||||
if(copytext(new_sentence, 1, 2) == "*") //emotes are abusable, like surrender
|
||||
return
|
||||
sentence = new_sentence
|
||||
|
||||
/datum/nanite_program/triggered/speech/get_extra_setting(setting)
|
||||
if(setting == "Sentence")
|
||||
return sentence
|
||||
|
||||
/datum/nanite_program/triggered/speech/copy_extra_settings_to(datum/nanite_program/triggered/speech/target)
|
||||
target.sentence = sentence
|
||||
|
||||
/datum/nanite_program/triggered/speech/trigger()
|
||||
if(!..())
|
||||
return
|
||||
if(host_mob.stat == DEAD)
|
||||
return
|
||||
to_chat(host_mob, "<span class='warning'>You feel compelled to speak...</span>")
|
||||
host_mob.say(sentence)
|
||||
|
||||
/datum/nanite_program/triggered/voice
|
||||
name = "Skull Echo"
|
||||
desc = "The nanites echo a synthesized message inside the host's skull."
|
||||
unique = FALSE
|
||||
trigger_cost = 1
|
||||
trigger_cooldown = 20
|
||||
rogue_types = list(/datum/nanite_program/brain_misfire, /datum/nanite_program/brain_decay)
|
||||
|
||||
extra_settings = list("Message")
|
||||
var/message = ""
|
||||
|
||||
/datum/nanite_program/triggered/voice/set_extra_setting(user, setting)
|
||||
if(setting == "Message")
|
||||
var/new_message = stripped_input(user, "Choose the message sent to the host.", "Message", message, MAX_MESSAGE_LEN)
|
||||
if(!new_message)
|
||||
return
|
||||
message = new_message
|
||||
|
||||
/datum/nanite_program/triggered/voice/get_extra_setting(setting)
|
||||
if(setting == "Message")
|
||||
return message
|
||||
|
||||
/datum/nanite_program/triggered/voice/copy_extra_settings_to(datum/nanite_program/triggered/voice/target)
|
||||
target.message = message
|
||||
|
||||
/datum/nanite_program/triggered/voice/trigger()
|
||||
if(!..())
|
||||
return
|
||||
if(host_mob.stat == DEAD)
|
||||
return
|
||||
to_chat(host_mob, "<i>You hear a strange, robotic voice in your head...</i> \"<span class='robot'>[message]</span>\"")
|
||||
|
||||
/datum/nanite_program/triggered/hallucination
|
||||
name = "Hallucination"
|
||||
desc = "The nanites make the host hallucinate something when triggered."
|
||||
trigger_cost = 4
|
||||
trigger_cooldown = 80
|
||||
unique = FALSE
|
||||
rogue_types = list(/datum/nanite_program/brain_misfire)
|
||||
extra_settings = list("Hallucination Type")
|
||||
var/hal_type
|
||||
var/hal_details
|
||||
|
||||
/datum/nanite_program/triggered/hallucination/trigger()
|
||||
if(!..())
|
||||
return
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
var/mob/living/carbon/C = host_mob
|
||||
if(!hal_type)
|
||||
C.hallucination += 15
|
||||
else
|
||||
switch(hal_type)
|
||||
if("Message")
|
||||
new /datum/hallucination/chat(C, TRUE, null, hal_details)
|
||||
if("Battle")
|
||||
new /datum/hallucination/battle(C, TRUE, hal_details)
|
||||
if("Sound")
|
||||
new /datum/hallucination/sounds(C, TRUE, hal_details)
|
||||
if("Weird Sound")
|
||||
new /datum/hallucination/weird_sounds(C, TRUE, hal_details)
|
||||
if("Station Message")
|
||||
new /datum/hallucination/stationmessage(C, TRUE, hal_details)
|
||||
if("Health")
|
||||
new /datum/hallucination/hudscrew(C, TRUE, hal_details)
|
||||
if("Alert")
|
||||
new /datum/hallucination/fake_alert(C, TRUE, hal_details)
|
||||
if("Fire")
|
||||
new /datum/hallucination/fire(C, TRUE)
|
||||
if("Shock")
|
||||
new /datum/hallucination/shock(C, TRUE)
|
||||
if("Plasma Flood")
|
||||
new /datum/hallucination/fake_flood(C, TRUE)
|
||||
|
||||
/datum/nanite_program/triggered/hallucination/set_extra_setting(user, setting)
|
||||
if(setting == "Hallucination Type")
|
||||
var/list/possible_hallucinations = list("Random","Message","Battle","Sound","Weird Sound","Station Message","Health","Alert","Fire","Shock","Plasma Flood")
|
||||
var/hal_type_choice = input("Choose the hallucination type", name) as null|anything in possible_hallucinations
|
||||
if(!hal_type_choice)
|
||||
return
|
||||
switch(hal_type_choice)
|
||||
if("Random")
|
||||
hal_type = null
|
||||
hal_details = null
|
||||
if("Message")
|
||||
hal_type = "Message"
|
||||
var/hal_chat = stripped_input(user, "Choose the message the host will hear, or leave empty for random messages.", "Message", hal_details, MAX_MESSAGE_LEN)
|
||||
if(hal_chat)
|
||||
hal_details = hal_chat
|
||||
if("Battle")
|
||||
hal_type = "Battle"
|
||||
var/sound_list = list("random","laser","disabler","esword","gun","stunprod","harmbaton","bomb")
|
||||
var/hal_choice = input("Choose the hallucination battle type", name) as null|anything in sound_list
|
||||
if(!hal_choice || hal_choice == "random")
|
||||
hal_details = null
|
||||
else
|
||||
hal_details = hal_choice
|
||||
if("Sound")
|
||||
hal_type = "Sound"
|
||||
var/sound_list = list("random","airlock","airlock pry","console","explosion","far explosion","mech","glass","alarm","beepsky","mech","wall decon","door hack")
|
||||
var/hal_choice = input("Choose the hallucination sound", name) as null|anything in sound_list
|
||||
if(!hal_choice || hal_choice == "random")
|
||||
hal_details = null
|
||||
else
|
||||
hal_details = hal_choice
|
||||
if("Weird Sound")
|
||||
hal_type = "Weird Sound"
|
||||
var/sound_list = list("random","phone","hallelujah","highlander","laughter","hyperspace","game over","creepy","tesla")
|
||||
var/hal_choice = input("Choose the hallucination sound", name) as null|anything in sound_list
|
||||
if(!hal_choice || hal_choice == "random")
|
||||
hal_details = null
|
||||
else
|
||||
hal_details = hal_choice
|
||||
if("Station Message")
|
||||
hal_type = "Station Message"
|
||||
var/msg_list = list("random","ratvar","shuttle dock","blob alert","malf ai","meteors","supermatter")
|
||||
var/hal_choice = input("Choose the hallucination station message", name) as null|anything in msg_list
|
||||
if(!hal_choice || hal_choice == "random")
|
||||
hal_details = null
|
||||
else
|
||||
hal_details = hal_choice
|
||||
if("Health")
|
||||
hal_type = "Health"
|
||||
var/health_list = list("random","critical","dead","healthy")
|
||||
var/hal_choice = input("Choose the health status", name) as null|anything in health_list
|
||||
if(!hal_choice || hal_choice == "random")
|
||||
hal_details = null
|
||||
else
|
||||
switch(hal_choice)
|
||||
if("critical")
|
||||
hal_details = SCREWYHUD_CRIT
|
||||
if("dead")
|
||||
hal_details = SCREWYHUD_DEAD
|
||||
if("healthy")
|
||||
hal_details = SCREWYHUD_HEALTHY
|
||||
if("Alert")
|
||||
hal_type = "Alert"
|
||||
var/alert_list = list("random","not_enough_oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","too_much_tox","newlaw","nutrition","charge","gravity","fire","locked","hacked","temphot","tempcold","pressure")
|
||||
var/hal_choice = input("Choose the alert", name) as null|anything in alert_list
|
||||
if(!hal_choice || hal_choice == "random")
|
||||
hal_details = null
|
||||
else
|
||||
hal_details = hal_choice
|
||||
if("Fire")
|
||||
hal_type = "Fire"
|
||||
if("Shock")
|
||||
hal_type = "Shock"
|
||||
if("Plasma Flood")
|
||||
hal_type = "Plasma Flood"
|
||||
|
||||
/datum/nanite_program/triggered/hallucination/get_extra_setting(setting)
|
||||
if(setting == "Hallucination Type")
|
||||
if(!hal_type)
|
||||
return "Random"
|
||||
else
|
||||
return hal_type
|
||||
|
||||
/datum/nanite_program/triggered/hallucination/copy_extra_settings_to(datum/nanite_program/triggered/hallucination/target)
|
||||
target.hal_type = hal_type
|
||||
target.hal_details = hal_details
|
||||
@@ -0,0 +1,265 @@
|
||||
//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."
|
||||
use_rate = 0.5
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
extra_settings = list("Program Overwrite","Cloud Overwrite")
|
||||
|
||||
var/sync_programs = TRUE
|
||||
var/sync_overwrite = FALSE
|
||||
var/overwrite_cloud = FALSE
|
||||
var/set_cloud = 0
|
||||
|
||||
/datum/nanite_program/viral/set_extra_setting(user, setting)
|
||||
if(setting == "Program Overwrite")
|
||||
var/overwrite_type = input("Choose what to do with the target's programs", name) as null|anything in list("Overwrite","Add To","Ignore")
|
||||
if(!overwrite_type)
|
||||
return
|
||||
switch(overwrite_type)
|
||||
if("Ignore") //Do not affect programs (if you only want to set the cloud ID)
|
||||
sync_programs = FALSE
|
||||
sync_overwrite = FALSE
|
||||
if("Add To") //Add to existing programs (so the target does not notice theirs are missing)
|
||||
sync_programs = TRUE
|
||||
sync_overwrite = FALSE
|
||||
if("Overwrite") //Replace target's programs with the source
|
||||
sync_programs = TRUE
|
||||
sync_overwrite = TRUE
|
||||
if(setting == "Cloud Overwrite")
|
||||
var/overwrite_type = input("Choose what to do with the target's Cloud ID", name) as null|anything in list("Overwrite","Disable","Keep")
|
||||
if(!overwrite_type)
|
||||
return
|
||||
switch(overwrite_type)
|
||||
if("Keep") //Don't change the cloud ID
|
||||
overwrite_cloud = FALSE
|
||||
set_cloud = 0
|
||||
if("Disable") //Set the cloud ID to disabled
|
||||
overwrite_cloud = TRUE
|
||||
set_cloud = 0
|
||||
if("Overwrite") //Set the cloud ID to what we choose
|
||||
var/new_cloud = input(user, "Choose the Cloud ID to set on infected nanites (1-100)", name, null) as null|num
|
||||
if(isnull(new_cloud))
|
||||
return
|
||||
overwrite_cloud = TRUE
|
||||
set_cloud = CLAMP(round(new_cloud, 1), 1, 100)
|
||||
|
||||
/datum/nanite_program/viral/get_extra_setting(setting)
|
||||
if(setting == "Program Overwrite")
|
||||
if(!sync_programs)
|
||||
return "Ignore"
|
||||
else if(sync_overwrite)
|
||||
return "Overwrite"
|
||||
else
|
||||
return "Add To"
|
||||
if(setting == "Cloud Overwrite")
|
||||
if(!overwrite_cloud)
|
||||
return "None"
|
||||
else if(set_cloud == 0)
|
||||
return "Disable"
|
||||
else
|
||||
return set_cloud
|
||||
|
||||
/datum/nanite_program/viral/copy_extra_settings_to(datum/nanite_program/viral/target)
|
||||
target.overwrite_cloud = overwrite_cloud
|
||||
target.set_cloud = set_cloud
|
||||
target.sync_programs = sync_programs
|
||||
target.sync_overwrite = sync_overwrite
|
||||
|
||||
/datum/nanite_program/viral/active_effect()
|
||||
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)
|
||||
|
||||
/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/triggered/self_scan
|
||||
name = "Host Scan"
|
||||
desc = "The nanites display a detailed readout of a body scan to the host."
|
||||
unique = FALSE
|
||||
trigger_cost = 3
|
||||
trigger_cooldown = 50
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
extra_settings = list("Scan Type")
|
||||
var/scan_type = "Medical"
|
||||
|
||||
/datum/nanite_program/triggered/self_scan/set_extra_setting(user, setting)
|
||||
if(setting == "Scan Type")
|
||||
var/list/scan_types = list("Medical","Chemical","Nanite")
|
||||
var/new_scan_type = input("Choose the scan type", name) as null|anything in scan_types
|
||||
if(!new_scan_type)
|
||||
return
|
||||
scan_type = new_scan_type
|
||||
|
||||
/datum/nanite_program/triggered/self_scan/get_extra_setting(setting)
|
||||
if(setting == "Scan Type")
|
||||
return scan_type
|
||||
|
||||
/datum/nanite_program/triggered/self_scan/copy_extra_settings_to(datum/nanite_program/triggered/self_scan/target)
|
||||
target.scan_type = scan_type
|
||||
|
||||
/datum/nanite_program/triggered/self_scan/trigger()
|
||||
if(!..())
|
||||
return
|
||||
if(host_mob.stat == DEAD)
|
||||
return
|
||||
switch(scan_type)
|
||||
if("Medical")
|
||||
healthscan(host_mob, host_mob)
|
||||
if("Chemical")
|
||||
chemscan(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 hide their activity and programming from superficial scans."
|
||||
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/relay
|
||||
name = "Relay"
|
||||
desc = "The nanites receive and relay long-range nanite signals."
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
extra_settings = list("Relay Channel")
|
||||
var/relay_channel = 1
|
||||
|
||||
/datum/nanite_program/relay/set_extra_setting(user, setting)
|
||||
if(setting == "Relay Channel")
|
||||
var/new_channel = input(user, "Set the relay channel (1-9999):", name, null) as null|num
|
||||
if(isnull(new_channel))
|
||||
return
|
||||
relay_channel = CLAMP(round(new_channel, 1), 1, 9999)
|
||||
|
||||
/datum/nanite_program/relay/get_extra_setting(setting)
|
||||
if(setting == "Relay Channel")
|
||||
return relay_channel
|
||||
|
||||
/datum/nanite_program/relay/copy_extra_settings_to(datum/nanite_program/relay/target)
|
||||
target.relay_channel = relay_channel
|
||||
|
||||
/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
|
||||
if(relay_code != relay_channel)
|
||||
return
|
||||
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, code, source)
|
||||
|
||||
/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."
|
||||
use_rate = -0.5 //generates nanites
|
||||
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_WELL_FED)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/metabolic_synthesis/active_effect()
|
||||
host_mob.nutrition -= 0.5
|
||||
|
||||
/datum/nanite_program/triggered/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."
|
||||
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/triggered/access/trigger()
|
||||
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)
|
||||
|
||||
/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))
|
||||
target_hosts += L
|
||||
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("[key_name(infectee)] was infected by spreading nanites by [key_name(host_mob)]", INVESTIGATE_NANITES)
|
||||
|
||||
/datum/nanite_program/mitosis
|
||||
name = "Mitosis"
|
||||
desc = "The nanites gain the ability to self-replicate, using bluespace to power the process, instead of drawing from a template. This rapidly speeds up the replication rate,\
|
||||
but it causes occasional software errors due to faulty copies. Not compatible with cloud sync."
|
||||
use_rate = 0
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
/datum/nanite_program/mitosis/active_effect()
|
||||
if(nanites.cloud_id)
|
||||
return
|
||||
var/rep_rate = round(nanites.nanite_volume / 50, 1) //0.5 per 50 nanite volume
|
||||
rep_rate *= 0.5
|
||||
nanites.adjust_nanites(rep_rate)
|
||||
if(prob(rep_rate))
|
||||
var/datum/nanite_program/fault = pick(nanites.programs)
|
||||
if(fault == src)
|
||||
return
|
||||
fault.software_error()
|
||||
@@ -0,0 +1,200 @@
|
||||
//Programs specifically engineered to cause harm to either the user or its surroundings (as opposed to ones that only do it due to broken programming)
|
||||
//Very dangerous!
|
||||
|
||||
/datum/nanite_program/flesh_eating
|
||||
name = "Cellular Breakdown"
|
||||
desc = "The nanites destroy cellular structures in the host's body, causing brute damage."
|
||||
use_rate = 1.5
|
||||
rogue_types = list(/datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/flesh_eating/active_effect()
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
C.take_bodypart_damage(1, 0, 0)
|
||||
else
|
||||
host_mob.adjustBruteLoss(1, TRUE)
|
||||
if(prob(3))
|
||||
to_chat(host_mob, "<span class='warning'>You feel a stab of pain from somewhere inside you.</span>")
|
||||
|
||||
/datum/nanite_program/poison
|
||||
name = "Poisoning"
|
||||
desc = "The nanites deliver poisonous chemicals to the host's internal organs, causing toxin damage and vomiting."
|
||||
use_rate = 1.5
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
/datum/nanite_program/poison/active_effect()
|
||||
host_mob.adjustToxLoss(1)
|
||||
if(prob(2))
|
||||
to_chat(host_mob, "<span class='warning'>You feel nauseous.</span>")
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
C.vomit(20)
|
||||
|
||||
/datum/nanite_program/memory_leak
|
||||
name = "Memory Leak"
|
||||
desc = "This program invades the memory space used by other programs, causing frequent corruptions and errors."
|
||||
use_rate = 0
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
/datum/nanite_program/memory_leak/active_effect()
|
||||
if(prob(6))
|
||||
var/datum/nanite_program/target = pick(nanites.programs)
|
||||
if(target == src)
|
||||
return
|
||||
target.software_error()
|
||||
|
||||
/datum/nanite_program/aggressive_replication
|
||||
name = "Aggressive Replication"
|
||||
desc = "Nanites will consume organic matter to improve their replication rate, damaging the host. The efficiency increases with the volume of nanites, requiring 200 to break even."
|
||||
use_rate = 1
|
||||
rogue_types = list(/datum/nanite_program/necrotic)
|
||||
|
||||
/datum/nanite_program/aggressive_replication/active_effect()
|
||||
var/extra_regen = round(nanites.nanite_volume / 200, 0.1)
|
||||
nanites.adjust_nanites(extra_regen)
|
||||
host_mob.adjustBruteLoss(extra_regen / 2, TRUE)
|
||||
|
||||
/datum/nanite_program/meltdown
|
||||
name = "Meltdown"
|
||||
desc = "Causes an internal meltdown inside the nanites, causing internal burns inside the host as well as rapidly destroying the nanite population.\
|
||||
Sets the nanites' safety threshold to 0 when activated."
|
||||
use_rate = 10
|
||||
rogue_types = list(/datum/nanite_program/glitch)
|
||||
|
||||
/datum/nanite_program/meltdown/active_effect()
|
||||
host_mob.adjustFireLoss(3.5)
|
||||
|
||||
/datum/nanite_program/meltdown/enable_passive_effect()
|
||||
. = ..()
|
||||
to_chat(host_mob, "<span class='userdanger'>Your blood is burning!</span>")
|
||||
nanites.safety_threshold = 0
|
||||
|
||||
/datum/nanite_program/meltdown/disable_passive_effect()
|
||||
. = ..()
|
||||
to_chat(host_mob, "<span class='warning'>Your blood cools down, and the pain gradually fades.</span>")
|
||||
|
||||
/datum/nanite_program/triggered/explosive
|
||||
name = "Chain Detonation"
|
||||
desc = "Detonates all the nanites inside the host in a chain reaction when triggered."
|
||||
trigger_cost = 25 //plus every idle nanite left afterwards
|
||||
trigger_cooldown = 100 //Just to avoid double-triggering
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
/datum/nanite_program/triggered/explosive/trigger()
|
||||
if(!..())
|
||||
return
|
||||
host_mob.visible_message("<span class='warning'>[host_mob] starts emitting a high-pitched buzzing, and [host_mob.p_their()] skin begins to glow...</span>",\
|
||||
"<span class='userdanger'>You start emitting a high-pitched buzzing, and your skin begins to glow...</span>")
|
||||
addtimer(CALLBACK(src, .proc/boom), CLAMP((nanites.nanite_volume * 0.35), 25, 150))
|
||||
|
||||
/datum/nanite_program/triggered/explosive/proc/boom()
|
||||
var/nanite_amount = nanites.nanite_volume
|
||||
var/dev_range = FLOOR(nanite_amount/200, 1) - 1
|
||||
var/heavy_range = FLOOR(nanite_amount/100, 1) - 1
|
||||
var/light_range = FLOOR(nanite_amount/50, 1) - 1
|
||||
explosion(host_mob, dev_range, heavy_range, light_range)
|
||||
qdel(nanites)
|
||||
|
||||
//TODO make it defuse if triggered again
|
||||
|
||||
/datum/nanite_program/triggered/heart_stop
|
||||
name = "Heart-Stopper"
|
||||
desc = "Stops the host's heart when triggered; restarts it if triggered again."
|
||||
trigger_cost = 12
|
||||
trigger_cooldown = 10
|
||||
rogue_types = list(/datum/nanite_program/nerve_decay)
|
||||
|
||||
/datum/nanite_program/triggered/heart_stop/trigger()
|
||||
if(!..())
|
||||
return
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
var/obj/item/organ/heart/heart = C.getorganslot(ORGAN_SLOT_HEART)
|
||||
if(heart)
|
||||
if(heart.beating)
|
||||
heart.Stop()
|
||||
else
|
||||
heart.Restart()
|
||||
|
||||
/datum/nanite_program/triggered/emp
|
||||
name = "Electromagnetic Resonance"
|
||||
desc = "The nanites cause an elctromagnetic pulse around the host when triggered. Will corrupt other nanite programs!"
|
||||
trigger_cost = 10
|
||||
program_flags = NANITE_EMP_IMMUNE
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
/datum/nanite_program/triggered/emp/trigger()
|
||||
if(!..())
|
||||
return
|
||||
empulse(host_mob, 1, 2)
|
||||
|
||||
/datum/nanite_program/pyro/active_effect()
|
||||
host_mob.fire_stacks += 1
|
||||
host_mob.IgniteMob()
|
||||
|
||||
/datum/nanite_program/pyro
|
||||
name = "Sub-Dermal Combustion"
|
||||
desc = "The nanites cause buildup of flammable fluids under the host's skin, then ignites them."
|
||||
use_rate = 4
|
||||
rogue_types = list(/datum/nanite_program/skin_decay, /datum/nanite_program/cryo)
|
||||
|
||||
/datum/nanite_program/pyro/check_conditions()
|
||||
if(host_mob.fire_stacks >= 10 && host_mob.on_fire)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/pyro/active_effect()
|
||||
host_mob.fire_stacks += 1
|
||||
host_mob.IgniteMob()
|
||||
|
||||
/datum/nanite_program/cryo
|
||||
name = "Cryogenic Treatment"
|
||||
desc = "The nanites rapidly skin heat through the host's skin, lowering their temperature."
|
||||
use_rate = 1
|
||||
rogue_types = list(/datum/nanite_program/skin_decay, /datum/nanite_program/pyro)
|
||||
|
||||
/datum/nanite_program/cryo/check_conditions()
|
||||
if(host_mob.bodytemperature <= 70)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/nanite_program/cryo/active_effect()
|
||||
host_mob.adjust_bodytemperature(-rand(15,25), 50)
|
||||
|
||||
/datum/nanite_program/mind_control
|
||||
name = "Mind Control"
|
||||
desc = "The nanites imprint an absolute directive onto the host's brain while they're active."
|
||||
use_rate = 3
|
||||
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
|
||||
var/directive = "..."
|
||||
|
||||
/datum/nanite_program/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
|
||||
|
||||
/datum/nanite_program/mind_control/get_extra_setting(setting)
|
||||
if(setting == "Directive")
|
||||
return directive
|
||||
|
||||
/datum/nanite_program/mind_control/copy_extra_settings_to(datum/nanite_program/mind_control/target)
|
||||
target.directive = directive
|
||||
|
||||
/datum/nanite_program/mind_control/enable_passive_effect()
|
||||
if(world.time < cooldown)
|
||||
return
|
||||
. = ..()
|
||||
brainwash(host_mob, directive)
|
||||
log_game("A mind control nanite program brainwashed [key_name(host_mob)] with the objective '[directive]'.")
|
||||
|
||||
/datum/nanite_program/mind_control/disable_passive_effect()
|
||||
. = ..()
|
||||
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
|
||||
Reference in New Issue
Block a user