mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-31 09:08:30 +01:00
* Fixes infective nanite programs not syncing cloud id (#54793) ## About The Pull Request I have always meant to have infective programs copy over every property of the infector nanites, and i've only recently noticed from some log diving that this wasn't the case, and cloud IDs were defaulting to 0 (unsynced). I probably never updated it since i made cloud nanites the default, assuming that the AddComponent handled it on its own. Since an unsynced cloud ID causes constant software errors, this makes the infective programs much less useful than they're meant to be. **Note: I'd also love to make the infectee's cloud ID a customizable parameter to allow for a wider range of possible uses, but avoided doing so to not violate the feature freeze. I'd gladly add that part if a maintainer gives the ok.** ## Why It's Good For The Game Makes Viral Replica not obligatory for anyone who wants to use a spreading nanite program. Without it, the cloud IDs of infectees are defaulted to 0, causing degenerative software errors due to lack of cloud sync, which are likely to ruin any gimmick that involves infecting unsuspecting victims. * Fixes infective nanite programs not syncing cloud id Co-authored-by: XDTM <heliumt@yahoo.it>
360 lines
13 KiB
Plaintext
360 lines
13 KiB
Plaintext
//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, also overriding or disabling their cloud sync."
|
|
use_rate = 0.5
|
|
rogue_types = list(/datum/nanite_program/toxic)
|
|
var/pulse_cooldown = 0
|
|
|
|
/datum/nanite_program/viral/register_extra_settings()
|
|
extra_settings[NES_PROGRAM_OVERWRITE] = new /datum/nanite_extra_setting/type("Add To", list("Overwrite", "Add To", "Ignore"))
|
|
extra_settings[NES_CLOUD_OVERWRITE] = new /datum/nanite_extra_setting/number(0, 0, 100)
|
|
|
|
/datum/nanite_program/viral/active_effect()
|
|
if(world.time < pulse_cooldown)
|
|
return
|
|
var/datum/nanite_extra_setting/program = extra_settings[NES_PROGRAM_OVERWRITE]
|
|
var/datum/nanite_extra_setting/cloud = extra_settings[NES_CLOUD_OVERWRITE]
|
|
for(var/mob/M in orange(host_mob, 5))
|
|
if(SEND_SIGNAL(M, COMSIG_NANITE_IS_STEALTHY))
|
|
continue
|
|
switch(program.get_value())
|
|
if("Overwrite")
|
|
SEND_SIGNAL(M, COMSIG_NANITE_SYNC, nanites, TRUE)
|
|
if("Add To")
|
|
SEND_SIGNAL(M, COMSIG_NANITE_SYNC, nanites, FALSE)
|
|
SEND_SIGNAL(M, COMSIG_NANITE_SET_CLOUD, cloud.get_value())
|
|
pulse_cooldown = world.time + 75
|
|
|
|
/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()
|
|
. = ..()
|
|
ADD_TRAIT(host_mob, TRAIT_NANITE_MONITORING, "nanites") //Shows up in diagnostic and medical HUDs as a small blinking icon
|
|
if(ishuman(host_mob))
|
|
GLOB.nanite_sensors_list |= host_mob
|
|
host_mob.hud_set_nanite_indicator()
|
|
|
|
/datum/nanite_program/monitoring/disable_passive_effect()
|
|
. = ..()
|
|
REMOVE_TRAIT(host_mob, TRAIT_NANITE_MONITORING, "nanites")
|
|
if(ishuman(host_mob))
|
|
GLOB.nanite_sensors_list -= host_mob
|
|
|
|
host_mob.hud_set_nanite_indicator()
|
|
|
|
/datum/nanite_program/self_scan
|
|
name = "Host Scan"
|
|
desc = "The nanites display a detailed readout of a body scan to the host."
|
|
unique = FALSE
|
|
can_trigger = TRUE
|
|
trigger_cost = 3
|
|
trigger_cooldown = 50
|
|
rogue_types = list(/datum/nanite_program/toxic)
|
|
|
|
/datum/nanite_program/self_scan/register_extra_settings()
|
|
extra_settings[NES_SCAN_TYPE] = new /datum/nanite_extra_setting/type("Medical", list("Medical", "Chemical", "Wound", "Nanite"))
|
|
|
|
/datum/nanite_program/self_scan/on_trigger(comm_message)
|
|
if(host_mob.stat == DEAD)
|
|
return
|
|
var/datum/nanite_extra_setting/NS = extra_settings[NES_SCAN_TYPE]
|
|
switch(NS.get_value())
|
|
if("Medical")
|
|
healthscan(host_mob, host_mob)
|
|
if("Chemical")
|
|
chemscan(host_mob, host_mob)
|
|
if("Wound")
|
|
woundscan(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 mask their activity from superficial scans, becoming undetectable by HUDs and non-specialized scanners."
|
|
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/nanite_debugging
|
|
name = "Nanite Debugging"
|
|
desc = "Enables various high-cost diagnostics in the nanites, making them able to communicate their program list to portable scanners. \
|
|
Doing so uses some power, slightly decreasing their replication speed."
|
|
rogue_types = list(/datum/nanite_program/toxic)
|
|
use_rate = 0.1
|
|
|
|
/datum/nanite_program/nanite_debugging/enable_passive_effect()
|
|
. = ..()
|
|
nanites.diagnostics = TRUE
|
|
|
|
/datum/nanite_program/nanite_debugging/disable_passive_effect()
|
|
. = ..()
|
|
nanites.diagnostics = FALSE
|
|
|
|
/datum/nanite_program/relay
|
|
name = "Relay"
|
|
desc = "The nanites receive and relay long-range nanite signals."
|
|
rogue_types = list(/datum/nanite_program/toxic)
|
|
|
|
/datum/nanite_program/relay/register_extra_settings()
|
|
extra_settings[NES_RELAY_CHANNEL] = new /datum/nanite_extra_setting/number(1, 1, 9999)
|
|
|
|
/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
|
|
var/datum/nanite_extra_setting/NS = extra_settings[NES_RELAY_CHANNEL]
|
|
if(relay_code != NS.get_value())
|
|
return
|
|
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, code, source)
|
|
|
|
/datum/nanite_program/relay/proc/relay_comm_signal(comm_code, relay_code, comm_message)
|
|
if(!activated)
|
|
return
|
|
if(!host_mob)
|
|
return
|
|
var/datum/nanite_extra_setting/NS = extra_settings[NES_RELAY_CHANNEL]
|
|
if(relay_code != NS.get_value())
|
|
return
|
|
SEND_SIGNAL(host_mob, COMSIG_NANITE_COMM_SIGNAL, comm_code, comm_message)
|
|
|
|
/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.adjust_nutrition(-0.5)
|
|
|
|
/datum/nanite_program/research
|
|
name = "Distributed Computing"
|
|
desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
|
|
use_rate = 0.2
|
|
rogue_types = list(/datum/nanite_program/toxic)
|
|
|
|
/datum/nanite_program/research/active_effect()
|
|
if(!iscarbon(host_mob))
|
|
return
|
|
var/points = 1
|
|
if(!host_mob.client) //less brainpower
|
|
points *= 0.25
|
|
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
|
|
|
|
/datum/nanite_program/researchplus
|
|
name = "Neural Network"
|
|
desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts."
|
|
use_rate = 0.3
|
|
rogue_types = list(/datum/nanite_program/brain_decay)
|
|
|
|
/datum/nanite_program/researchplus/enable_passive_effect()
|
|
. = ..()
|
|
if(!iscarbon(host_mob))
|
|
return
|
|
if(host_mob.client)
|
|
SSnanites.neural_network_count++
|
|
else
|
|
SSnanites.neural_network_count += 0.25
|
|
|
|
/datum/nanite_program/researchplus/disable_passive_effect()
|
|
. = ..()
|
|
if(!iscarbon(host_mob))
|
|
return
|
|
if(host_mob.client)
|
|
SSnanites.neural_network_count--
|
|
else
|
|
SSnanites.neural_network_count -= 0.25
|
|
|
|
/datum/nanite_program/researchplus/active_effect()
|
|
if(!iscarbon(host_mob))
|
|
return
|
|
var/mob/living/carbon/C = host_mob
|
|
var/points = round(SSnanites.neural_network_count / 12, 0.1)
|
|
if(!C.client) //less brainpower
|
|
points *= 0.25
|
|
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
|
|
|
|
/datum/nanite_program/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."
|
|
can_trigger = TRUE
|
|
trigger_cost = 3
|
|
trigger_cooldown = 30
|
|
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/access/on_trigger(comm_message)
|
|
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)
|
|
var/spread_cooldown = 0
|
|
|
|
/datum/nanite_program/spreading/active_effect()
|
|
if(world.time < spread_cooldown)
|
|
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)
|
|
SEND_SIGNAL(infectee, COMSIG_NANITE_SET_CLOUD, nanites.cloud_id)
|
|
infectee.investigate_log("was infected by spreading nanites by [key_name(host_mob)] at [AREACOORD(infectee)].", INVESTIGATE_NANITES)
|
|
|
|
/datum/nanite_program/nanite_sting
|
|
name = "Nanite Sting"
|
|
desc = "When triggered, projects a nearly invisible spike of nanites that attempts to infect a nearby non-host with a copy of the host's nanites cluster."
|
|
can_trigger = TRUE
|
|
trigger_cost = 5
|
|
trigger_cooldown = 100
|
|
rogue_types = list(/datum/nanite_program/glitch, /datum/nanite_program/toxic)
|
|
|
|
/datum/nanite_program/nanite_sting/on_trigger(comm_message)
|
|
var/list/mob/living/target_hosts = list()
|
|
for(var/mob/living/L in oview(1, host_mob))
|
|
if(!(L.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD)) || SEND_SIGNAL(L, COMSIG_HAS_NANITES) || !L.Adjacent(host_mob))
|
|
continue
|
|
target_hosts += L
|
|
if(!target_hosts.len)
|
|
consume_nanites(-5)
|
|
return
|
|
var/mob/living/infectee = pick(target_hosts)
|
|
if(prob(100 - (infectee.get_permeability_protection() * 100)))
|
|
//unlike with Infective Exo-Locomotion, this can't take over existing nanites, because Nanite Sting only targets non-hosts.
|
|
infectee.AddComponent(/datum/component/nanites, 5)
|
|
SEND_SIGNAL(infectee, COMSIG_NANITE_SYNC, nanites)
|
|
SEND_SIGNAL(infectee, COMSIG_NANITE_SET_CLOUD, nanites.cloud_id)
|
|
infectee.investigate_log("was infected by a nanite cluster by [key_name(host_mob)] at [AREACOORD(infectee)].", INVESTIGATE_NANITES)
|
|
to_chat(infectee, "<span class='warning'>You feel a tiny prick.</span>")
|
|
|
|
/datum/nanite_program/mitosis
|
|
name = "Mitosis"
|
|
desc = "The nanites gain the ability to self-replicate, using bluespace to power the process. Becomes more effective the more nanites are already in the host.\
|
|
The replication has also a chance to corrupt the nanite programming due to copy faults - cloud sync is highly recommended."
|
|
use_rate = 0
|
|
rogue_types = list(/datum/nanite_program/toxic)
|
|
|
|
/datum/nanite_program/mitosis/active_effect()
|
|
var/rep_rate = round(nanites.nanite_volume / 50, 1) //0.5 per 50 nanite volume
|
|
rep_rate *= 0.5
|
|
nanites.adjust_nanites(null, rep_rate)
|
|
if(prob(rep_rate))
|
|
var/datum/nanite_program/fault = pick(nanites.programs)
|
|
if(fault == src)
|
|
return
|
|
fault.software_error()
|
|
|
|
/datum/nanite_program/dermal_button
|
|
name = "Dermal Button"
|
|
desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
|
|
unique = FALSE
|
|
var/datum/action/innate/nanite_button/button
|
|
|
|
/datum/nanite_program/dermal_button/register_extra_settings()
|
|
extra_settings[NES_SENT_CODE] = new /datum/nanite_extra_setting/number(1, 1, 9999)
|
|
extra_settings[NES_BUTTON_NAME] = new /datum/nanite_extra_setting/text("Button")
|
|
extra_settings[NES_ICON] = new /datum/nanite_extra_setting/type("power", list("one","two","three","four","five","plus","minus","power"))
|
|
extra_settings[NES_COLOR] = new /datum/nanite_extra_setting/type("green", list("green","red","yellow","blue"))
|
|
|
|
/datum/nanite_program/dermal_button/enable_passive_effect()
|
|
. = ..()
|
|
var/datum/nanite_extra_setting/bn_name = extra_settings[NES_BUTTON_NAME]
|
|
var/datum/nanite_extra_setting/bn_icon = extra_settings[NES_ICON]
|
|
var/datum/nanite_extra_setting/bn_color = extra_settings[NES_COLOR]
|
|
if(!button)
|
|
button = new(src, bn_name.get_value(), bn_icon.get_value(), bn_color.get_value())
|
|
button.target = host_mob
|
|
button.Grant(host_mob)
|
|
|
|
/datum/nanite_program/dermal_button/disable_passive_effect()
|
|
. = ..()
|
|
if(button)
|
|
button.Remove(host_mob)
|
|
|
|
/datum/nanite_program/dermal_button/on_mob_remove()
|
|
. = ..()
|
|
qdel(button)
|
|
|
|
/datum/nanite_program/dermal_button/proc/press()
|
|
if(activated)
|
|
host_mob.visible_message("<span class='notice'>[host_mob] presses a button on [host_mob.p_their()] forearm.</span>",
|
|
"<span class='notice'>You press the nanite button on your forearm.</span>", null, 2)
|
|
var/datum/nanite_extra_setting/sent_code = extra_settings[NES_SENT_CODE]
|
|
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, sent_code.get_value(), "a [name] program")
|
|
|
|
/datum/action/innate/nanite_button
|
|
name = "Button"
|
|
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
|
check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS
|
|
button_icon_state = "power_green"
|
|
var/datum/nanite_program/dermal_button/program
|
|
|
|
/datum/action/innate/nanite_button/New(datum/nanite_program/dermal_button/_program, _name, _icon, _color)
|
|
..()
|
|
program = _program
|
|
name = _name
|
|
button_icon_state = "[_icon]_[_color]"
|
|
|
|
/datum/action/innate/nanite_button/Activate()
|
|
program.press()
|