Adds a set of nanite storage protocols as a Bepis research, plus small nanite adjustments (#54710)

Adds a new set of nanite protocol programs as a researchable Bepis tech.
Protocol programs are programs that are mutually exclusive within their time, so remember that only one of the following can be active at once in the same host.

    Hive Protocol: Makes nanites use space more efficiently, increasing maximum volume by 250 (500 -> 750)
    Zip Protocol: Makes nanites use a compression routine when not in use, increasing maximum volume by 500 (500 -> 1000) but consuming 0.2 nanites per tick to perform the zipping/unzipping
    Free-Range Protocol: Makes nanite use looser storage routines, reducing the maximum volume by 250 (500 -> 250) but gaining 0.5 nanite replication rate
    S.L.O.P. (Safety Level Override Protocol): Removes nanite storage safety measures, allowing them to reach up to 2000 volume. However, when the volume surpasses the maximum recommended volume (500) the host will start to suffer from side effects, manifesting in slow organ damage. The more the nanite volume approaches the physical limit, the more harmful it becomes.

Replaced the Tinker Nanite Replication Protocol with the Pyramid Protocol, which gives an extra 1.2 regeneration rate, but only while the nanites are at 80% volume or above.
Renamed the Offline Production Protocol to Eclipse Protocol.

Chain detonation now uses dyn_explosion(), at a rate of 1 power per 50 nanite volume. The power level should be similar to how it was for normal nanite volumes, but it should scale more linearly when going above the limit with the new programs.

If nanite volume is suddenly significantly higher than the maximum allowed (likely caused by deleting an active storage protocol) the extra nanites will be forcefully expelled from the host's body, which can range from minor oozing, to vomiting puddles of nanites, to nanites rapidly bursting from eyes, ears, and skin pores.
Despite how it looks, this process causes no lasting damage, since it's a security feature made to prevent acute nanite poisoning.

Added some comments on a few nanite functions.
Refactored vomit code to make it a bit more customizable. The toxic arg (supposedly used to choose an alternate vomit icon, but in fact not functional) is now vomit_type, and purge (which determined vomit would remove 10% of reagents or 67% of reagents) is now purge_ratio, which accepts custom values. Made the refactor mostly to allow a 0% ratio, but it can be handy in other future uses.

Adds extra content to Bepis research, giving a little more reason to invest money into it.
Creates more options to customize a previously rigid parameter in nanites, maximum nanite volume. This opens up strategies that involve storing up large amounts of nanites for special occasions, or viceversa reducing the maximum rate to get more constant replication rate to sustain continued programs.
This commit is contained in:
XDTM
2020-11-20 12:07:20 -08:00
committed by GitHub
parent dbecf5fe05
commit 03de3dfb07
17 changed files with 337 additions and 69 deletions
+1
View File
@@ -474,6 +474,7 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE)))
#define VOMIT_TOXIC 1
#define VOMIT_PURPLE 2
#define VOMIT_NANITE 3
//chem grenades defines
#define GRENADE_EMPTY 1
+5
View File
@@ -12,6 +12,11 @@
#define NANITE_CLOUD_DISABLE 2
#define NANITE_CLOUD_ENABLE 3
//Nanite excess thresholds
#define NANITE_EXCESS_MINOR 25
#define NANITE_EXCESS_VOMIT 100
#define NANITE_EXCESS_BURST 350
///Nanite Protocol types
#define NANITE_PROTOCOL_REPLICATION "nanite_replication"
#define NANITE_PROTOCOL_STORAGE "nanite_storage"
+60 -4
View File
@@ -121,13 +121,13 @@
next_sync = world.time + NANITE_SYNC_DELAY
set_nanite_bar()
///Deletes nanites!
/datum/component/nanites/proc/delete_nanites()
SIGNAL_HANDLER
qdel(src)
//Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status)
///Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status)
/datum/component/nanites/proc/sync(datum/signal_source, datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE)
SIGNAL_HANDLER
@@ -149,6 +149,7 @@
var/datum/nanite_program/SNP = X
add_program(null, SNP.copy())
///Syncs the nanites to their assigned cloud copy, if it is available. If it is not, there is a small chance of a software error instead.
/datum/component/nanites/proc/cloud_sync()
if(cloud_id)
var/datum/nanite_cloud_backup/backup = SSnanites.get_cloud_backup(cloud_id)
@@ -162,6 +163,7 @@
var/datum/nanite_program/NP = pick(programs)
NP.software_error()
///Adds a nanite program, replacing existing unique programs of the same type. A source program can be specified to copy its programming onto the new one.
/datum/component/nanites/proc/add_program(datum/source, datum/nanite_program/new_program, datum/nanite_program/source_program)
SIGNAL_HANDLER
@@ -183,13 +185,67 @@
adjust_nanites(null, -amount)
return (nanite_volume > 0)
///Modifies the current nanite volume, then checks if the nanites are depleted or exceeding the maximum amount
/datum/component/nanites/proc/adjust_nanites(datum/source, amount)
SIGNAL_HANDLER
nanite_volume = clamp(nanite_volume + amount, 0, max_nanites)
nanite_volume += amount
if(nanite_volume > max_nanites)
reject_excess_nanites()
if(nanite_volume <= 0) //oops we ran out
qdel(src)
/**
* Handles how nanites leave the host's body if they find out that they're currently exceeding the maximum supported amount
*
* IC explanation:
* Normally nanites simply discard excess volume by slowing replication or 'sweating' it out in imperceptible amounts,
* but if there is a large excess volume, likely due to a programming change that leaves them unable to support their current volume,
* the nanites attempt to leave the host as fast as necessary to prevent nanite poisoning. This can range from minor oozing to nanites
* rapidly bursting out from every possible pathway, causing temporary inconvenience to the host.
*/
/datum/component/nanites/proc/reject_excess_nanites()
var/excess = nanite_volume - max_nanites
nanite_volume = max_nanites
switch(excess)
if(0 to NANITE_EXCESS_MINOR) //Minor excess amount, the extra nanites are quietly expelled without visible effects
return
if((NANITE_EXCESS_MINOR + 0.1) to NANITE_EXCESS_VOMIT) //Enough nanites getting rejected at once to be visible to the naked eye
host_mob.visible_message("<span class='warning'>A grainy grey slurry starts oozing out of [host_mob].</span>", "<span class='warning'>A grainy grey slurry starts oozing out of your skin.</span>", null, 4);
if((NANITE_EXCESS_VOMIT + 0.1) to NANITE_EXCESS_BURST) //Nanites getting rejected in massive amounts, but still enough to make a semi-orderly exit through vomit
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
host_mob.visible_message("<span class='warning'>[host_mob] vomits a grainy grey slurry!</span>", "<span class='warning'>You suddenly vomit a metallic-tasting grainy grey slurry!</span>", null);
C.vomit(0, FALSE, TRUE, FLOOR(excess / 100, 1), FALSE, VOMIT_NANITE, FALSE, TRUE, 0)
else
host_mob.visible_message("<span class='warning'>A metallic grey slurry bursts out of [host_mob]'s skin!</span>", "<span class='userdanger'>A metallic grey slurry violently bursts out of your skin!</span>", null);
if(isturf(host_mob.drop_location()))
var/turf/T = host_mob.drop_location()
T.add_vomit_floor(host_mob, VOMIT_NANITE, 0)
if((NANITE_EXCESS_BURST + 0.1) to INFINITY) //Way too many nanites, they just leave through the closest exit before they harm/poison the host
host_mob.visible_message("<span class='warning'>A torrent of metallic grey slurry violently bursts out of [host_mob]'s face and floods out of [host_mob.p_their()] skin!</span>",
"<span class='userdanger'>A torrent of metallic grey slurry violently bursts out of your eyes, ears, and mouth, and floods out of your skin!</span>");
host_mob.blind_eyes(15) //nanites coming out of your eyes
host_mob.Paralyze(120)
if(iscarbon(host_mob))
var/mob/living/carbon/C = host_mob
var/obj/item/organ/ears/ears = C.getorganslot(ORGAN_SLOT_EARS)
if(ears)
ears.adjustEarDamage(0, 30) //nanites coming out of your ears
C.vomit(0, FALSE, TRUE, 2, FALSE, VOMIT_NANITE, FALSE, TRUE, 0) //nanites coming out of your mouth
//nanites everywhere
if(isturf(host_mob.drop_location()))
var/turf/T = host_mob.drop_location()
T.add_vomit_floor(host_mob, VOMIT_NANITE, 0)
for(var/turf/adjacent_turf in oview(host_mob, 1))
if(adjacent_turf.density || !adjacent_turf.Adjacent(T))
continue
adjacent_turf.add_vomit_floor(host_mob, VOMIT_NANITE, 0)
///Updates the nanite volume bar visible in diagnostic HUDs
/datum/component/nanites/proc/set_nanite_bar(remove = FALSE)
var/image/holder = host_mob.hud_list[DIAG_NANITE_FULL_HUD]
var/icon/I = icon(host_mob.icon, host_mob.icon_state, host_mob.dir)
@@ -285,7 +341,7 @@
/datum/component/nanites/proc/set_max_volume(datum/source, amount)
SIGNAL_HANDLER
max_nanites = max(1, max_nanites)
max_nanites = max(1, amount)
/datum/component/nanites/proc/set_cloud(datum/source, amount)
SIGNAL_HANDLER
+10 -8
View File
@@ -540,7 +540,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
/turf/AllowDrop()
return TRUE
/turf/proc/add_vomit_floor(mob/living/M, toxvomit = NONE, purge = FALSE)
/turf/proc/add_vomit_floor(mob/living/M, toxvomit = NONE, purge_ratio = 0.1)
var/obj/effect/decal/cleanable/vomit/V = new /obj/effect/decal/cleanable/vomit(src, M.get_static_viruses())
@@ -549,21 +549,23 @@ GLOBAL_LIST_EMPTY(station_turfs)
V = locate() in src
if(!V)
return
// Make toxins and blazaam vomit look different
// Apply the proper icon set based on vomit type
if(toxvomit == VOMIT_PURPLE)
V.icon_state = "vomitpurp_[pick(1,4)]"
else if (toxvomit == VOMIT_TOXIC)
V.icon_state = "vomittox_[pick(1,4)]"
if (iscarbon(M))
clear_reagents_to_vomit_pool(M, V, purge)
else if (toxvomit == VOMIT_NANITE)
V.name = "metallic slurry"
V.desc = "A puddle of metallic slurry that looks vaguely like very fine sand. It almost seems like it's moving..."
V.icon_state = "vomitnanite_[pick(1,4)]"
if (purge_ratio && iscarbon(M))
clear_reagents_to_vomit_pool(M, V, purge_ratio)
/proc/clear_reagents_to_vomit_pool(mob/living/carbon/M, obj/effect/decal/cleanable/vomit/V, purge = FALSE)
/proc/clear_reagents_to_vomit_pool(mob/living/carbon/M, obj/effect/decal/cleanable/vomit/V, purge_ratio = 0.1)
var/obj/item/organ/stomach/belly = M.getorganslot(ORGAN_SLOT_STOMACH)
if(!belly?.reagents.total_volume)
return
var/chemicals_lost = belly.reagents.total_volume * 0.1
if(purge)
chemicals_lost = belly.reagents.total_volume * 0.67 //For detoxification surgery, we're manually pumping the stomach out of chemcials, so it's far more efficient.
var/chemicals_lost = belly.reagents.total_volume * purge_ratio
belly.reagents.trans_to(V, chemicals_lost, transfered_by = M)
//clear the stomach of anything even not food
for(var/bile in belly.reagents.reagent_list)
@@ -23,7 +23,7 @@
O.Remove(user)
if(iscarbon(user))
var/mob/living/carbon/C = user
C.vomit(0, toxic = TRUE)
C.vomit(0)
O.forceMove(get_turf(user))
user.reagents.add_reagent(/datum/reagent/medicine/mutadone, 10)
+3 -8
View File
@@ -449,7 +449,7 @@
return 0
return ..()
/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, toxic = FALSE, harm = TRUE, force = FALSE, purge = FALSE)
/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
if((HAS_TRAIT(src, TRAIT_NOHUNGER) || HAS_TRAIT(src, TRAIT_TOXINLOVER)) && !force)
return TRUE
@@ -482,7 +482,6 @@
adjust_nutrition(-lost_nutrition)
adjustToxLoss(-3)
var/obj/item/organ/stomach/belly = getorganslot(ORGAN_SLOT_STOMACH)
for(var/i=0 to distance)
if(blood)
if(T)
@@ -490,12 +489,8 @@
if(harm)
adjustBruteLoss(3)
else
if(belly?.reagents.has_reagent(/datum/reagent/consumable/ethanol/blazaam, needs_metabolizing = TRUE))
if(T)
T.add_vomit_floor(src, VOMIT_PURPLE)
else
if(T)
T.add_vomit_floor(src, VOMIT_TOXIC, purge) //toxic barf looks different || call purge when doing detoxicfication to pump more chems out of the stomach.
if(T)
T.add_vomit_floor(src, vomit_type, purge_ratio) //toxic barf looks different || call purge when doing detoxicfication to pump more chems out of the stomach.
T = get_step(T, dir)
if (T?.is_blocked_turf())
break
@@ -914,7 +914,7 @@
override = dna.species.override_float
..()
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, toxic = FALSE, harm = TRUE, force = FALSE, purge = FALSE)
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
if(blood && (NOBLOOD in dna.species.species_traits) && !HAS_TRAIT(src, TRAIT_TOXINLOVER))
if(message)
visible_message("<span class='warning'>[src] dry heaves!</span>", \
+1 -1
View File
@@ -292,7 +292,7 @@
if(getToxLoss() >= 45 && nutrition > 20)
lastpuke += prob(50)
if(lastpuke >= 50) // about 25 second delay I guess
vomit(20, toxic = TRUE)
vomit(20)
lastpuke = 0
@@ -71,7 +71,7 @@
if(locate(/datum/reagent/consumable) in reagents.reagent_list)
var/mob/living/carbon/body = owner
// we do not loss any nutrition as a fly when vomiting out food
body.vomit(0, FALSE, FALSE, 2, TRUE, force=TRUE, purge=TRUE)
body.vomit(0, FALSE, FALSE, 2, TRUE, force=TRUE, purge_ratio = 0.67)
playsound(get_turf(owner), 'sound/effects/splat.ogg', 50, TRUE)
body.visible_message("<span class='danger'>[body] vomits on the floor!</span>", \
"<span class='userdanger'>You throw up on the floor!</span>")
@@ -409,7 +409,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
/datum/reagent/consumable/ethanol/amaretto
name = "Amaretto"
description = "A gentle drink that carries a sweet aroma."
color = "#E17600"
color = "#E17600"
boozepwr = 25
taste_description = "fruity and nutty sweetness"
glass_icon_state = "amarettoglass"
@@ -2222,7 +2222,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
if(prob(10))
stored_teleports += rand(2,6)
if(prob(70))
M.vomit()
M.vomit(vomit_type = VOMIT_PURPLE)
return ..()
@@ -2313,7 +2313,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_icon_state = "godfather"
glass_name = "Godfather"
glass_desc = "A classic from old Italy and enjoyed by gangsters, pray the orange peel doesnt end up in your mouth."
/datum/reagent/consumable/ethanol/godmother
name = "Godmother"
description = "A twist on a classic, liked more by mature women."
@@ -2324,4 +2324,4 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_icon_state = "godmother"
glass_name = "Godmother"
glass_desc = "A lovely fresh smelling cocktail, a true Sicilian delight."
@@ -736,7 +736,7 @@
/datum/reagent/toxin/spewium/on_mob_life(mob/living/carbon/C)
.=..()
if(current_cycle >=11 && prob(min(50,current_cycle)))
C.vomit(10, prob(10), prob(50), rand(0,4), TRUE, prob(30))
C.vomit(10, prob(10), prob(50), rand(0,4), TRUE)
for(var/datum/reagent/toxin/R in C.reagents.reagent_list)
if(R != src)
C.reagents.remove_reagent(R.type,1)
@@ -550,16 +550,45 @@
program_type = /datum/nanite_program/protocol/factory
category = list("Protocols_Nanites")
/datum/design/nanites/tinker
name = "Tinker Protocol"
desc = "Replication Protocol: the nanites learn to use metallic material in the host's bloodstream to speed up the replication process."
id = "tinker_nanites"
program_type = /datum/nanite_program/protocol/tinker
/datum/design/nanites/pyramid
name = "Pyramid Protocol"
desc = "Replication Protocol: the nanites implement an alternate cooperative replication protocol that is more efficient as long as the saturation level is above 80%."
id = "pyramid_nanites"
program_type = /datum/nanite_program/protocol/pyramid
category = list("Protocols_Nanites")
/datum/design/nanites/offline
name = "Offline Production Protocol"
name = "Eclipse Protocol"
desc = "Replication Protocol: while the host is asleep or otherwise unconcious, the nanites exploit the reduced interference to replicate more quickly."
id = "offline_nanites"
program_type = /datum/nanite_program/protocol/offline
category = list("Protocols_Nanites")
/datum/design/nanites/hive
name = "Hive Protocol"
desc = "Storage Protocol: the nanites use a more efficient grid arrangment for volume storage, increasing maximum volume in a host."
id = "hive_nanites"
program_type = /datum/nanite_program/protocol/hive
category = list("Protocols_Nanites")
/datum/design/nanites/zip
name = "Zip Protocol"
desc = "Storage Protocol: the nanites are disassembled and compacted when unused, greatly increasing the maximum volume while in a host. However, the process slows down the replication rate slightly."
id = "zip_nanites"
program_type = /datum/nanite_program/protocol/zip
category = list("Protocols_Nanites")
/datum/design/nanites/free_range
name = "Free-range Protocol"
desc = "Storage Protocol: the nanites discard their default storage protocols in favour of a cheaper and more organic approach. Reduces maximum volume, but increases the replication rate."
id = "free_range_nanites"
program_type = /datum/nanite_program/protocol/free_range
category = list("Protocols_Nanites")
/datum/design/nanites/unsafe_storage
name = "S.L.O. Protocol"
desc = "Storage Protocol: 'S.L.O.P.', or Storage Level Override Protocol, completely disables the safety measures normally present in nanites,\
allowing them to reach much higher saturation levels, but at the risk of causing internal damage to the host."
id = "unsafe_storage_nanites"
program_type = /datum/nanite_program/protocol/unsafe_storage
category = list("Protocols_Nanites")
@@ -46,43 +46,25 @@
factory_efficiency = min(factory_efficiency + 1, max_efficiency)
nanites.adjust_nanites(null, round(0.002 * factory_efficiency, 0.1))
/datum/nanite_program/protocol/tinker
name = "Tinker Protocol"
desc = "Replication Protocol: the nanites learn to use metallic material in the host's bloodstream to speed up the replication process."
/datum/nanite_program/protocol/pyramid
name = "Pyramid Protocol"
desc = "Replication Protocol: the nanites implement an alternate cooperative replication protocol that is more efficient as long as the saturation level is above 80%."
use_rate = 0
rogue_types = list(/datum/nanite_program/necrotic)
protocol_class = NANITE_PROTOCOL_REPLICATION
var/boost = 2
var/list/valid_reagents = list(
/datum/reagent/iron,
/datum/reagent/copper,
/datum/reagent/gold,
/datum/reagent/silver,
/datum/reagent/mercury,
/datum/reagent/aluminium,
/datum/reagent/silicon)
var/boost = 1.2
/datum/nanite_program/protocol/tinker/check_conditions()
if(!nanites.host_mob.reagents)
/datum/nanite_program/protocol/pyramid/check_conditions()
if((nanites.nanite_volume / nanites.max_nanites) < 0.8)
return FALSE
var/found_reagent = FALSE
var/datum/reagents/R = nanites.host_mob.reagents
for(var/VR in valid_reagents)
if(R.has_reagent(VR, 0.5))
R.remove_reagent(VR, 0.5)
found_reagent = TRUE
break
if(!found_reagent)
return FALSE
return ..()
/datum/nanite_program/protocol/tinker/active_effect()
/datum/nanite_program/protocol/pyramid/active_effect()
nanites.adjust_nanites(null, boost)
/datum/nanite_program/protocol/offline
name = "Offline Production Protocol"
name = "Eclipse Protocol"
desc = "Replication Protocol: while the host is asleep or otherwise unconcious, the nanites exploit the reduced interference to replicate more quickly."
use_rate = 0
rogue_types = list(/datum/nanite_program/necrotic)
@@ -98,3 +80,195 @@
/datum/nanite_program/protocol/offline/active_effect()
nanites.adjust_nanites(null, boost)
/datum/nanite_program/protocol/hive
name = "Hive Protocol"
desc = "Storage Protocol: the nanites use a more efficient grid arrangment for volume storage, increasing maximum volume in a host."
use_rate = 0
rogue_types = list(/datum/nanite_program/necrotic)
protocol_class = NANITE_PROTOCOL_STORAGE
var/extra_volume = 250
/datum/nanite_program/protocol/hive/enable_passive_effect()
. = ..()
nanites.set_max_volume(null, nanites.max_nanites + extra_volume)
/datum/nanite_program/protocol/hive/disable_passive_effect()
. = ..()
nanites.set_max_volume(null, nanites.max_nanites - extra_volume)
/datum/nanite_program/protocol/zip
name = "Zip Protocol"
desc = "Storage Protocol: the nanites are disassembled and compacted when unused, greatly increasing the maximum volume while in a host. However, the process slows down the replication rate slightly."
use_rate = 0.2
rogue_types = list(/datum/nanite_program/necrotic)
protocol_class = NANITE_PROTOCOL_STORAGE
var/extra_volume = 500
/datum/nanite_program/protocol/zip/enable_passive_effect()
. = ..()
nanites.set_max_volume(null, nanites.max_nanites + extra_volume)
/datum/nanite_program/protocol/zip/disable_passive_effect()
. = ..()
nanites.set_max_volume(null, nanites.max_nanites - extra_volume)
/datum/nanite_program/protocol/free_range
name = "Free-range Protocol"
desc = "Storage Protocol: the nanites discard their default storage protocols in favour of a cheaper and more organic approach. Reduces maximum volume, but increases the replication rate."
use_rate = 0
rogue_types = list(/datum/nanite_program/necrotic)
protocol_class = NANITE_PROTOCOL_STORAGE
var/boost = 0.5
var/extra_volume = -250
/datum/nanite_program/protocol/free_range/enable_passive_effect()
. = ..()
nanites.set_max_volume(null, nanites.max_nanites + extra_volume)
/datum/nanite_program/protocol/free_range/disable_passive_effect()
. = ..()
nanites.set_max_volume(null, nanites.max_nanites - extra_volume)
/datum/nanite_program/protocol/free_range/active_effect()
nanites.adjust_nanites(null, boost)
/datum/nanite_program/protocol/unsafe_storage
name = "S.L.O. Protocol"
desc = "Storage Protocol: 'S.L.O.P.', or Storage Level Override Protocol, completely disables the safety measures normally present in nanites,\
allowing them to reach much higher saturation levels, but at the risk of causing internal damage to the host."
use_rate = 0
rogue_types = list(/datum/nanite_program/necrotic)
protocol_class = NANITE_PROTOCOL_STORAGE
var/extra_volume = 1500
var/next_warning = 0
var/min_warning_cooldown = 120
var/max_warning_cooldown = 350
var/volume_warnings_stage_1 = list("You feel a dull pain in your abdomen.",
"You feel a tickling sensation in your abdomen.")
var/volume_warnings_stage_2 = list("You feel a dull pain in your stomach.",
"You feel a dull pain when breathing.",
"Your stomach grumbles.",
"You feel a tickling sensation in your throat.",
"You feel a tickling sensation in your lungs.",
"You feel a tickling sensation in your stomach.",
"Your lungs feel stiff.")
var/volume_warnings_stage_3 = list("You feel a dull pain in your chest.",
"You hear a faint buzzing coming from nowhere.",
"You hear a faint buzzing inside your head.",
"Your head aches.")
var/volume_warnings_stage_4 = list("You feel a dull pain in your ears.",
"You feel a dull pain behind your eyes.",
"You hear a loud, echoing buzz inside your ears.",
"You feel dizzy.",
"You feel an itch coming from behind your eyes.",
"Your eardrums itch.",
"You see tiny grey motes drifting in your field of view.")
var/volume_warnings_stage_5 = list("You feel sick.",
"You feel a dull pain from every part of your body.",
"You feel nauseous.")
var/volume_warnings_stage_6 = list("Your skin itches and burns.",
"Your muscles ache.",
"You feel tired.",
"You feel something skittering under your skin.",)
/datum/nanite_program/protocol/unsafe_storage/enable_passive_effect()
. = ..()
nanites.set_max_volume(null, nanites.max_nanites + extra_volume)
/datum/nanite_program/protocol/unsafe_storage/disable_passive_effect()
. = ..()
nanites.set_max_volume(null, nanites.max_nanites - extra_volume)
/datum/nanite_program/protocol/unsafe_storage/active_effect()
if(!iscarbon(host_mob))
if(prob(10))
host_mob.adjustBruteLoss(((max(nanites.nanite_volume - 450, 0) / 450) ** 2 ) * 0.5) // 0.5 -> 2 -> 4.5 -> 8 damage per successful tick
return
var/mob/living/carbon/C = host_mob
if(nanites.nanite_volume < 500)
return
var/current_stage = 0
if(nanites.nanite_volume > 500) //Liver is the main hub of nanite replication and the first to be threatened by excess volume
if(prob(10))
var/obj/item/organ/liver/liver = C.getorganslot(ORGAN_SLOT_LIVER)
if(liver)
liver.applyOrganDamage(0.6)
current_stage++
if(nanites.nanite_volume > 750) //Extra volume spills out in other central organs
if(prob(10))
var/obj/item/organ/stomach/stomach = C.getorganslot(ORGAN_SLOT_STOMACH)
if(stomach)
stomach.applyOrganDamage(0.75)
if(prob(10))
var/obj/item/organ/lungs/lungs = C.getorganslot(ORGAN_SLOT_LUNGS)
if(lungs)
lungs.applyOrganDamage(0.75)
current_stage++
if(nanites.nanite_volume > 1000) //Extra volume spills out in more critical organs
if(prob(10))
var/obj/item/organ/heart/heart = C.getorganslot(ORGAN_SLOT_HEART)
if(heart)
heart.applyOrganDamage(0.75)
if(prob(10))
var/obj/item/organ/brain/brain = C.getorganslot(ORGAN_SLOT_BRAIN)
if(brain)
brain.applyOrganDamage(0.75)
current_stage++
if(nanites.nanite_volume > 1250) //Excess nanites start invading smaller organs for more space, including sensory organs
if(prob(13))
var/obj/item/organ/eyes/eyes = C.getorganslot(ORGAN_SLOT_EYES)
if(eyes)
eyes.applyOrganDamage(0.75)
if(prob(13))
var/obj/item/organ/ears/ears = C.getorganslot(ORGAN_SLOT_EARS)
if(ears)
ears.applyOrganDamage(0.75)
current_stage++
if(nanites.nanite_volume > 1500) //Nanites start spilling into the bloodstream, causing toxicity
if(prob(15))
C.adjustToxLoss(0.5, TRUE, forced = TRUE) //Not healthy for slimepeople either
current_stage++
if(nanites.nanite_volume > 1750) //Nanites have almost reached their physical limit, and the pressure itself starts causing tissue damage
if(prob(15))
C.adjustBruteLoss(0.75, TRUE)
current_stage++
volume_warning(current_stage)
/datum/nanite_program/protocol/unsafe_storage/proc/volume_warning(tier)
if(world.time < next_warning)
return
var/list/main_warnings
var/list/extra_warnings
switch(tier)
if(1)
main_warnings = volume_warnings_stage_1
extra_warnings = null
if(2)
main_warnings = volume_warnings_stage_2
extra_warnings = volume_warnings_stage_1
if(3)
main_warnings = volume_warnings_stage_3
extra_warnings = volume_warnings_stage_1 + volume_warnings_stage_2
if(4)
main_warnings = volume_warnings_stage_4
extra_warnings = volume_warnings_stage_1 + volume_warnings_stage_2 + volume_warnings_stage_3
if(5)
main_warnings = volume_warnings_stage_5
extra_warnings = volume_warnings_stage_1 + volume_warnings_stage_2 + volume_warnings_stage_3 + volume_warnings_stage_4
if(6)
main_warnings = volume_warnings_stage_6
extra_warnings = volume_warnings_stage_1 + volume_warnings_stage_2 + volume_warnings_stage_3 + volume_warnings_stage_4 + volume_warnings_stage_5
if(prob(35))
to_chat(host_mob, "<span class='warning'>[pick(main_warnings)]</span>")
next_warning = world.time + rand(min_warning_cooldown, max_warning_cooldown)
else if(islist(extra_warnings))
to_chat(host_mob, "<span class='warning'>[pick(extra_warnings)]</span>")
next_warning = world.time + rand(min_warning_cooldown, max_warning_cooldown)
@@ -88,11 +88,7 @@
addtimer(CALLBACK(src, .proc/boom), clamp((nanites.nanite_volume * 0.35), 25, 150))
/datum/nanite_program/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)
dyn_explosion(get_turf(host_mob), nanites.nanite_volume / 50)
qdel(nanites)
//TODO make it defuse if triggered again
+12 -2
View File
@@ -900,9 +900,19 @@
/datum/techweb_node/nanite_replication_protocols
id = "nanite_replication_protocols"
display_name = "Nanite Replication Protocols"
description = "Advanced behaviours that allow nanites to exploit certain circumstances to replicate faster."
description = "Protocols that overwrite the default nanite replication routine to achieve more efficiency in certain circumstances."
prereq_ids = list("nanite_smart")
design_ids = list("kickstart_nanites","factory_nanites","tinker_nanites","offline_nanites")
design_ids = list("kickstart_nanites","factory_nanites","pyramid_nanites","offline_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000, TECHWEB_POINT_TYPE_NANITES = 2500)
hidden = TRUE
experimental = TRUE
/datum/techweb_node/nanite_storage_protocols
id = "nanite_storage_protocols"
display_name = "Nanite Storage Protocols"
description = "Protocols that overwrite the default nanite storage routine to achieve more efficiency or greater capacity."
prereq_ids = list("nanite_smart")
design_ids = list("hive_nanites","zip_nanites","free_range_nanites","unsafe_storage_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000, TECHWEB_POINT_TYPE_NANITES = 2500)
hidden = TRUE
experimental = TRUE
+1 -1
View File
@@ -39,7 +39,7 @@
display_results(user, target, "<span class='notice'>[user] forces [H] to vomit, cleansing their stomach of some chemicals!</span>",
"<span class='notice'>[user] forces [H] to vomit, cleansing their stomach of some chemicals!</span>",
"[user] forces [H] to vomit!")
H.vomit(20, FALSE, TRUE, 1, TRUE, FALSE, purge = TRUE) //called with purge as true to lose more reagents
H.vomit(20, FALSE, TRUE, 1, TRUE, FALSE, purge_ratio = 0.67) //higher purge ratio than regular vomiting
return ..()
/datum/surgery_step/stomach_pump/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 115 KiB