diff --git a/code/__defines/_reagents.dm b/code/__defines/_reagents.dm
index 48ed8b6bf7..bd947977d7 100644
--- a/code/__defines/_reagents.dm
+++ b/code/__defines/_reagents.dm
@@ -283,6 +283,14 @@
#define REAGENT_ID_PHORONVIRUSFOOD "phoronvirusfood"
#define REAGENT_WEAKPHORONVIRUSFOOD "Weakened phoronic virus food"
#define REAGENT_ID_WEAKPHORONVIRUSFOOD "weakphoronvirusfood"
+#define REAGENT_URANIUMVIRUSFOOD "Unstable virus food"
+#define REAGENT_ID_URANIUMVIRUSFOOD "uraniumvirusfood"
+#define REAGENT_UNSTABLEURANIUMVIRUSFOOD "Unstable uranium gel"
+#define REAGENT_ID_UNSTABLEURANIUMVIRUSFOOD "unstableuraniumvirusfood"
+#define REAGENT_STABLEURANIUMVIRUSFOOD "Stable uranium gel"
+#define REAGENT_ID_STABLEURANIUMVIRUSFOOD_ALT "stableuraniumvirusfood_alt"
+#define REAGENT_STABLEURANIUMVIRUSFOOD_ALT "Stable uranium gel"
+#define REAGENT_ID_STABLEURANIUMVIRUSFOOD "stableuraniumvirusfood"
#define REAGENT_SIZEVIRUSFOOD "Sizeoxadone virus food"
#define REAGENT_ID_SIZEVIRUSFOOD "sizevirusfood"
diff --git a/code/__defines/diseases.dm b/code/__defines/diseases.dm
index 3dd0d595ec..b546b3e0dc 100644
--- a/code/__defines/diseases.dm
+++ b/code/__defines/diseases.dm
@@ -18,6 +18,7 @@
#define DISEASE_SPREAD_FLUIDS (1<<3)
#define DISEASE_SPREAD_CONTACT (1<<4)
#define DISEASE_SPREAD_AIRBORNE (1<<5)
+#define DISEASE_SPREAD_FALTERED (1<<6)
//Severity Defines
#define DISEASE_BENEFICIAL "Beneficial"
@@ -39,6 +40,8 @@
#define CARRIER 0x20 /// If we are a carrier for the virus but we will not be affected by it.
#define BYPASSES_IMMUNITY 0x40 /// If this virus bypasses immunity.
#define DISCOVERED 0x80 /// If applied, this virus will show up on medical HUDs. Automatically set when it reaches mid-stage.
+#define DORMANT 0x100 /// If applied, the virus is dormant and will not act or spread.
+#define FALTERED 0x200 /// If applied, the virus is faltered and will only spread by intentional injection.
#define EXTRAPOLATOR_RESULT_DISEASES "extrapolator_result_disease"
#define EXTRAPOLATOR_RESULT_ACT_PRIORITY "extrapolator_result_action_priority"
diff --git a/code/__defines/traits.dm b/code/__defines/traits.dm
index 3a05f89586..0cb55c1911 100644
--- a/code/__defines/traits.dm
+++ b/code/__defines/traits.dm
@@ -211,5 +211,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define FERVEATIUM_TRAIT "ferveatium"
*/
+#define STRONG_IMMUNITY_TRAIT "strongimmunity"
+
#define ORGANICS 1
#define SYNTHETICS 2
diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm
index ca694bee03..53809e85b8 100644
--- a/code/datums/diseases/_MobProcs.dm
+++ b/code/datums/diseases/_MobProcs.dm
@@ -5,6 +5,10 @@
return TRUE
return FALSE
+/mob/proc/addDisease(datum/disease/D)
+ LAZYADD(viruses, D)
+ return TRUE
+
/mob/proc/RemoveDisease(datum/disease/D)
LAZYREMOVE(viruses, D)
return TRUE
@@ -29,8 +33,13 @@
if(HasDisease(D))
return FALSE
- if(istype(D, /datum/disease/advance) && count_by_type(GetViruses(), /datum/disease/advance) > 0)
- return FALSE
+ if(istype(D, /datum/disease/advance))
+ var/active_diseases = 0
+ for(var/datum/disease/AD in GetViruses())
+ if(!(AD.virus_modifiers & DORMANT)) // You can have as many dormant diseases as you want
+ active_diseases++
+ if(active_diseases > 0) // But ONLY one active disease
+ return FALSE
var/compatible_type = FALSE
for(var/type_to_test in D.viable_mobtypes)
@@ -50,31 +59,9 @@
/mob/proc/ContractDisease(datum/disease/D, var/target_zone)
if(!CanContractDisease(D))
return 0
- AddDisease(D)
+ D.infect(src)
return TRUE
-/mob/proc/AddDisease(datum/disease/D, respect_carrier = FALSE)
- var/datum/disease/DD = new D.type(1, D, 0)
- DD.start_cure_timer()
- viruses += DD
- DD.affected_mob = src
- GLOB.active_diseases += DD
-
- var/list/skipped = list("affected_mob", "holder", "carrier", "stage", "type", "parent_type", "vars", "transformed", "_active_timers")
- if(respect_carrier)
- skipped -= "carrier"
- for(var/V in DD.vars)
- if(V in skipped)
- continue
- if(istype(DD.vars[V],/list))
- var/list/L = D.vars[V]
- if(islist(L))
- DD.vars[V] = L.Copy()
- else
- DD.vars[V] = D.vars[V]
-
- log_admin("[key_name(src)] has contracted the virus \"[DD]\"")
-
/mob/living/carbon/human/ContractDisease(datum/disease/D, target_zone)
if(!CanContractDisease(D))
return FALSE
@@ -144,7 +131,7 @@
passed = prob((Cl.permeability_coefficient*100) - 1)
if(passed)
- AddDisease(D)
+ D.infect(src)
/mob/living/proc/AirborneContractDisease(datum/disease/D, force_spread)
if(((D.spread_flags & DISEASE_SPREAD_AIRBORNE) || force_spread) && prob(50*D.spreading_modifier) - 1)
@@ -161,7 +148,7 @@
if(!CanContractDisease(D))
return FALSE
- AddDisease(D, respect_carrier)
+ D.infect(src, respect_carrier)
return TRUE
/mob/living/carbon/human/CanContractDisease(datum/disease/D)
diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm
index c42ff2665d..7b2922155e 100644
--- a/code/datums/diseases/_disease.dm
+++ b/code/datums/diseases/_disease.dm
@@ -44,6 +44,14 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease))
End()
return ..()
+/datum/disease/proc/infect(var/mob/living/infectee, make_copy = TRUE)
+ var/datum/disease/D = make_copy ? Copy() : src
+ infectee.addDisease(D)
+ D.affected_mob = infectee
+ GLOB.active_diseases += D
+
+ log_admin("[key_name(src)] has contracted the virus \"[D]\"")
+
/datum/disease/proc/stage_act()
if(!affected_mob)
return FALSE
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 2bb672a23b..0b088cb74f 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -58,6 +58,8 @@ GLOBAL_LIST_INIT(advance_cures, list(
/datum/disease/advance/stage_act()
if(!..())
return FALSE
+ if(global_flag_check(virus_modifiers, DORMANT))
+ return FALSE
if(symptoms && length(symptoms))
if(!s_processing)
@@ -92,6 +94,8 @@ GLOBAL_LIST_INIT(advance_cures, list(
QDEL_LIST(A.symptoms)
for(var/datum/symptom/S as anything in symptoms)
A.symptoms += S.Copy()
+ A.virus_modifiers = virus_modifiers
+ A.spread_flags = spread_flags
A.disease_flags = disease_flags
A.resistance = resistance
A.stealth = stealth
@@ -213,7 +217,7 @@ GLOBAL_LIST_INIT(advance_cures, list(
/datum/disease/advance/proc/AssignProperties()
- if(stealth >= 2)
+ if(global_flag_check(virus_modifiers, DORMANT) || stealth >= 2)
visibility_flags |= HIDDEN_SCANNER
else
visibility_flags &= ~HIDDEN_SCANNER
@@ -226,16 +230,23 @@ GLOBAL_LIST_INIT(advance_cures, list(
GenerateCure()
/datum/disease/advance/proc/SetSpread()
- switch(transmission)
- if(-INFINITY to 5)
- spread_flags = DISEASE_SPREAD_BLOOD
- spread_text = "Blood"
- if(6 to 10)
- spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_FLUIDS
- spread_text = "Fluids"
- if(11 to INFINITY)
- spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_FLUIDS | DISEASE_SPREAD_CONTACT
- spread_text = "On Contact"
+ if(global_flag_check(virus_modifiers, FALTERED))
+ spread_flags = DISEASE_SPREAD_FALTERED
+ spread_text = "Intentional Injection"
+ if(global_flag_check(virus_modifiers, DORMANT))
+ spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS
+ spread_text = "None"
+ else
+ switch(transmission)
+ if(-INFINITY to 5)
+ spread_flags = DISEASE_SPREAD_BLOOD
+ spread_text = "Blood"
+ if(6 to 10)
+ spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_FLUIDS
+ spread_text = "Fluids"
+ if(11 to INFINITY)
+ spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_FLUIDS | DISEASE_SPREAD_CONTACT
+ spread_text = "On Contact"
/datum/disease/advance/proc/SetSeverity(level_sev)
@@ -299,6 +310,15 @@ GLOBAL_LIST_INIT(advance_cures, list(
NeuterSymptom(s)
Refresh(TRUE)
+// Falter the disease, making it non-spreadable.
+/datum/disease/advance/proc/Falter()
+ if(global_flag_check(virus_modifiers, FALTERED))
+ return
+ else
+ virus_modifiers |= FALTERED
+ spread_flags = DISEASE_SPREAD_BLOOD
+ spread_text = "Intentional Injection"
+
// Name the disease.
/datum/disease/advance/proc/AssignName(new_name = "Unknown")
Refresh()
@@ -378,6 +398,7 @@ GLOBAL_LIST_INIT(advance_cures, list(
// Should be only 1 entry left, but if not let's only return a single entry
var/datum/disease/advance/to_return = pick(diseases)
+ to_return.disease_flags &= ~DORMANT
to_return.Refresh(new_name = TRUE)
return to_return
@@ -448,3 +469,11 @@ GLOBAL_LIST_INIT(advance_cures, list(
log_admin("[key_name_admin(src)] infected [key_name_admin(H)] with [D.name]. It has these symptoms: [english_list(name_symptoms)]")
return TRUE
+
+/datum/disease/advance/infect(var/mob/living/infectee, make_copy = TRUE)
+ var/datum/disease/advance/A = make_copy ? Copy() : src
+ infectee.addDisease(A)
+ A.affected_mob = infectee
+ GLOB.active_diseases += A
+
+ log_admin("[key_name(src)] has contracted the virus \"[A]\"")
diff --git a/code/datums/diseases/advance/disease_preset.dm b/code/datums/diseases/advance/disease_preset.dm
index 0478603009..3c03ef81af 100644
--- a/code/datums/diseases/advance/disease_preset.dm
+++ b/code/datums/diseases/advance/disease_preset.dm
@@ -35,6 +35,32 @@
symptoms += new guaranteed_symptom
Finalize()
+/mob/living/carbon/human/proc/give_random_dormant_disease(biohazard = 25, min_symptoms = 2, max_symptoms = 4, min_level = 4, max_level = 9, list/guaranteed_symptoms = list())
+ . = FALSE
+ var/sickrisk = 1
+
+ if(isSynthetic() || species.virus_immune || HAS_TRAIT(src, STRONG_IMMUNITY_TRAIT)) // Don't bother
+ return
+
+ switch(get_species())
+ if(SPECIES_UNATHI, SPECIES_TAJARAN) // Mice devourers
+ sickrisk = 0.5
+ if(SPECIES_XENOCHIMERA)
+ // Ronoake Syndrome will go here :)
+ return
+ if(SPECIES_PROMETHEAN) // Too clean
+ return
+
+ if(prob(min(100, (biohazard * sickrisk))))
+ var/symptom_amt = rand(min_symptoms, max_symptoms)
+ var/datum/disease/advance/dormant_disease = new /datum/disease/advance/random(symptom_amt, max_level, min_level, guaranteed_symptoms)
+ dormant_disease.virus_modifiers |= DORMANT
+ dormant_disease.spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS
+ dormant_disease.spread_text = "None"
+ dormant_disease.visibility_flags |= HIDDEN_SCANNER
+ ForceContractDisease(dormant_disease, TRUE)
+ return TRUE
+
/datum/disease/advance/random/macrophage
setsymptom = /datum/symptom/macrophage
diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm
index 440bbc7340..e0ef528eef 100644
--- a/code/datums/diseases/advance/symptoms/cough.dm
+++ b/code/datums/diseases/advance/symptoms/cough.dm
@@ -32,10 +32,10 @@ BONUS
threshold_descs = list(
"Resistance 3" = "Host will drop small items when coughing.",
- "Resistance 10" = "Occasonally causes coughing fits that stun the host.",
+ "Resistance 10" = "Occasionally causes coughing fits that stun the host.",
"Stage Speed 6" = "Increases cough frequency",
"Stealth 4" = "The symptom remains hidden until active.",
- "Transmission 11" = "The hosts coughing will occasonally spread the virus."
+ "Transmission 11" = "The hosts coughing will occasionally spread the virus."
)
/datum/symptom/cough/severityset(datum/disease/advance/A)
@@ -82,5 +82,5 @@ BONUS
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob, emote), "cough"), 1 SECONDS)
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob, emote), "cough"), 3 SECONDS)
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob, emote), "cough"), 6 SECONDS)
- if(infective && prob(50))
+ if(infective && !(A.spread_flags & DISEASE_SPREAD_FALTERED) && prob(50))
addtimer(CALLBACK(A, TYPE_PROC_REF(/datum/disease, spread), 2), 20)
diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm
index abb9a24f25..0896422a90 100644
--- a/code/datums/diseases/advance/symptoms/fire.dm
+++ b/code/datums/diseases/advance/symptoms/fire.dm
@@ -74,13 +74,13 @@ Bonus
/datum/symptom/fire/proc/Firestacks_stage_4(mob/living/M, datum/disease/advance/A)
M.adjust_fire_stacks(1 * power)
M.take_overall_damage(burn = 2 * power)
- if(infective)
+ if(infective && !(A.spread_flags & DISEASE_SPREAD_FALTERED))
M.visible_message(span_danger("[M] bursts into flames, spreading burning sparks about the area!"))
return TRUE
/datum/symptom/fire/proc/Firestacks_stage_5(mob/living/M, datum/disease/advance/A)
M.adjust_fire_stacks(3 * power)
M.take_overall_damage(burn = 5 * power)
- if(infective)
+ if(infective && !(A.spread_flags & DISEASE_SPREAD_FALTERED))
M.visible_message(span_danger("[M] bursts into flames, spreading burning sparks about the area!"))
return TRUE
diff --git a/code/datums/diseases/advance/symptoms/macrophage.dm b/code/datums/diseases/advance/symptoms/macrophage.dm
index 77ccb5d2e8..f5ea92b790 100644
--- a/code/datums/diseases/advance/symptoms/macrophage.dm
+++ b/code/datums/diseases/advance/symptoms/macrophage.dm
@@ -91,7 +91,7 @@ BONUS
if(A.transmission >= 12)
for(var/datum/disease/D in M.GetViruses())
- if((D.spread_flags & DISEASE_SPREAD_SPECIAL) || (D.spread_flags & DISEASE_SPREAD_CONTACT))
+ if((D.spread_flags & DISEASE_SPREAD_SPECIAL) || (D.spread_flags & DISEASE_SPREAD_CONTACT) || (D.spread_flags & DISEASE_SPREAD_FALTERED))
continue
if(D == A)
continue
diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm
index 5c9d681206..2ab63957c9 100644
--- a/code/datums/diseases/advance/symptoms/sneeze.dm
+++ b/code/datums/diseases/advance/symptoms/sneeze.dm
@@ -53,7 +53,7 @@ Bonus
M.emote("sniff")
else
M.emote("sneeze")
- if(infective)
+ if(infective && !(A.spread_flags & DISEASE_SPREAD_FALTERED))
addtimer(CALLBACK(A, TYPE_PROC_REF(/datum/disease, spread), 4), 20)
/*
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index b22e8e8d77..adf62dd5f8 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -70,6 +70,8 @@
VAR_PROTECTED/exclusive_mail_goodies = FALSE // If this job's mail goodies compete with generic goodies.
VAR_PROTECTED/mail_color = "#FFF"
+ var/list/symptoms // A list of symptoms that this job might have when we roll a dormant diseas.
+
/datum/job/New()
. = ..()
department_accounts = department_accounts || departments_managed
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index de4f38e087..da02cc495a 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -461,9 +461,10 @@ var/global/datum/controller/occupations/job_master
// Stick their fingerprints on literally everything
job.apply_fingerprints(H)
- // Only non-silicons get post-job-equip equipment
+ // Only non-silicons get post-job-equip equipment and dormant diseases
if(!(job.mob_type & JOB_SILICON))
H.equip_post_job()
+ H.give_random_dormant_disease(guaranteed_symptoms = job.symptoms)
// If some custom items could not be equipped before, try again now.
for(var/thing in custom_equip_leftovers)
diff --git a/code/game/objects/items/devices/extrapolator.dm b/code/game/objects/items/devices/extrapolator.dm
index 3aecfab6ce..59bc9f1b8c 100644
--- a/code/game/objects/items/devices/extrapolator.dm
+++ b/code/game/objects/items/devices/extrapolator.dm
@@ -162,7 +162,9 @@
var/list/properties
if(global_flag_check(advance_disease.virus_modifiers, CARRIER))
LAZYADD(properties, "carrier")
- message += "[advance_disease.name][LAZYLEN(properties) ? " ([properties.Join(", ")])" : ""], stage [advance_disease.stage]/5"
+ if(global_flag_check(advance_disease.virus_modifiers, FALTERED))
+ LAZYADD(properties, "faltered")
+ message += span_info("[advance_disease.name][LAZYLEN(properties) ? " ([properties.Join(", ")])" : ""], [global_flag_check(advance_disease.virus_modifiers, DORMANT) ? "dormant virus" : "stage [advance_disease.stage]/5"]")
if(extracted_ids[advance_disease.GetDiseaseID()])
message += "This virus has been extracted by \the [src] previously."
message += "[advance_disease.name] has the following symptoms:"
@@ -234,23 +236,21 @@
/obj/item/extrapolator/proc/create_culture(mob/living/user, datum/disease/advance/disease)
. = FALSE
- var/datum/disease/advance/D = disease.Copy()
+ disease = disease.Copy()
+ disease.virus_modifiers &= ~DORMANT
var/list/data = list("viruses" = list(disease))
if(user.get_active_hand() != src)
to_chat(user, span_warning("The extrapolator must be held in your active hand to work!"))
return
var/obj/item/reagent_containers/glass/beaker/vial/culture_bottle = new(user.drop_location())
- culture_bottle.name = "[D.name] culture bottle"
- culture_bottle.desc = "A small bottle. Contains [D.agent] culture in synthblood medium."
+ culture_bottle.name = "[disease.name] culture bottle"
+ culture_bottle.desc = "A small bottle. Contains [disease.agent] culture in synthblood medium."
culture_bottle.reagents.add_reagent(REAGENT_ID_BLOOD, 5, data)
user.put_in_hands(culture_bottle)
playsound(src, 'sound/machines/ping.ogg', vol = 30, vary = TRUE)
COOLDOWN_START(src, usage_cooldown, 1 SECONDS)
- extracted_ids[D.GetDiseaseID()] = TRUE
+ extracted_ids[disease.GetDiseaseID()] = TRUE
return TRUE
-/obj/item/extrapolator/tier4
- default_scanning_module = /obj/item/stock_parts/scanning_module/hyper
-
/obj/item/extrapolator/tier5
default_scanning_module = /obj/item/stock_parts/scanning_module/omni
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index e66059ae9c..2b3bf4d875 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -134,6 +134,21 @@
icon_state = "syringe"
starts_with = list(/obj/item/reagent_containers/syringe = 7)
+/obj/item/storage/box/old_syringes
+ name = "box of syringes"
+ desc = "A box full of syringes. They look old."
+ icon_state = "syringe"
+ starts_with = list(/obj/item/reagent_containers/syringe/old = 2) // Old syringes guaranteed in each box!
+
+/obj/item/storage/box/old_syringes/Initialize(mapload)
+ var/syringe
+ for(var/i in 1 to 8)
+ if(prob(25))
+ continue
+ syringe = pick(subtypesof(/obj/item/reagent_containers/syringe))
+ new syringe(src)
+ . = ..()
+
/obj/item/storage/box/syringegun
name = "box of syringe gun cartridges"
desc = "A box full of compressed gas cartridges."
diff --git a/code/game/objects/random/maintenance.dm b/code/game/objects/random/maintenance.dm
index 25c7393fff..91aad93139 100644
--- a/code/game/objects/random/maintenance.dm
+++ b/code/game/objects/random/maintenance.dm
@@ -199,6 +199,7 @@ something, make sure it's not in one of the other lists.*/
prob(3);/obj/item/storage/box/beakers,
prob(2);/obj/item/storage/box/bodybags,
prob(3);/obj/item/storage/box/syringes,
+ prob(3);/obj/item/storage/box/old_syringes,
prob(3);/obj/item/storage/box/gloves,
prob(2);/obj/item/storage/belt/medical/emt,
prob(2);/obj/item/storage/belt/medical,
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index de1fa84390..662f864300 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -102,7 +102,7 @@
return FALSE
if(H.GetViruses())
for(var/datum/disease/D in H.GetSpreadableViruses())
- if(D.danger == DISEASE_POSITIVE || D.danger == DISEASE_BENEFICIAL)
+ if(D.danger == DISEASE_POSITIVE || D.danger == DISEASE_BENEFICIAL || D.disease_flags & DORMANT || D.spread_flags & DISEASE_SPREAD_FALTERED)
continue
return FALSE
return TRUE
diff --git a/code/game/objects/structures/loot_piles.dm b/code/game/objects/structures/loot_piles.dm
index e2b8e37c69..616d2b78d6 100644
--- a/code/game/objects/structures/loot_piles.dm
+++ b/code/game/objects/structures/loot_piles.dm
@@ -218,7 +218,8 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/pda,
/obj/item/radio/headset,
/obj/item/paicard,
- /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose
+ /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose,
+ /obj/item/reagent_containers/syringe/old
)
uncommon_loot = list(
@@ -276,7 +277,8 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/poster/custom,
/obj/item/newspaper,
/obj/item/paper/crumpled,
- /obj/item/paper/crumpled/bloody
+ /obj/item/paper/crumpled/bloody,
+ /obj/item/reagent_containers/syringe/old
)
uncommon_loot = list(
@@ -323,7 +325,8 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/storage/box/smokes,
/obj/item/storage/box/metalfoam,
/obj/item/storage/box/handcuffs,
- /obj/item/storage/box/seccarts
+ /obj/item/storage/box/seccarts,
+ /obj/item/storage/box/old_syringes,
)
rare_loot = list(
diff --git a/code/game/objects/structures/trash_pile_vr.dm b/code/game/objects/structures/trash_pile_vr.dm
index fbec657561..34d79de63e 100644
--- a/code/game/objects/structures/trash_pile_vr.dm
+++ b/code/game/objects/structures/trash_pile_vr.dm
@@ -306,6 +306,7 @@
prob(3);/obj/item/clothing/accessory/knuckledusters,
prob(3);/obj/item/clothing/gloves/heavy_engineer,
prob(3);/obj/item/reagent_containers/syringe/drugs,
+ prob(3);/obj/item/reagent_containers/syringe/old,
prob(2);/obj/item/implanter/sizecontrol,
prob(2);/obj/item/handcuffs/fuzzy,
prob(2);/obj/item/handcuffs/legcuffs/fuzzy,
diff --git a/code/modules/mob/living/carbon/human/species/station/traits/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits/neutral.dm
index bb53567a64..34dc8b6e33 100644
--- a/code/modules/mob/living/carbon/human/species/station/traits/neutral.dm
+++ b/code/modules/mob/living/carbon/human/species/station/traits/neutral.dm
@@ -1714,3 +1714,26 @@
cost = 0
hidden = FALSE //Disabled on Virgo // CHOMPEdit
added_component_path = /datum/component/nutrition_size_change/shrinking
+
+/datum/trait/neutral/disease_carrier
+ name = "Disease Carrier"
+ desc = "Your species is a carrier of diseases! Watch out for virologists."
+ excludes = list(/datum/trait/neutral/strongimmunesystem)
+ cost = 0
+ can_take = ORGANICS
+ custom_only = FALSE
+
+/datum/trait/neutral/disease_carrier/apply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
+ ..()
+ H.give_random_dormant_disease(200, 2, 3, 1, 9)
+
+/datum/trait/neutral/strongimmunesystem
+ name = "Strong Immune System"
+ desc = "Your immune system is so strong, that not even dormant diseases can survive in you."
+ cost = 0
+
+ can_take = ORGANICS
+
+/datum/trait/neutral/strongimmunesystem/apply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
+ ..()
+ ADD_TRAIT(H, STRONG_IMMUNITY_TRAIT, ROUNDSTART_TRAIT)
diff --git a/code/modules/mob/living/carbon/human/species/station/traits/positive.dm b/code/modules/mob/living/carbon/human/species/station/traits/positive.dm
index 06c0bae7e2..c0327ec089 100644
--- a/code/modules/mob/living/carbon/human/species/station/traits/positive.dm
+++ b/code/modules/mob/living/carbon/human/species/station/traits/positive.dm
@@ -492,3 +492,11 @@
desc = "Allows you to build a cocoon around yourself, using it to transform your body if you desire."
cost = 0
category = 0
+
+/datum/trait/positive/virus_immune
+ name = "Virus Immune"
+ desc = "You are immune to viruses."
+ cost = 1
+
+ can_take = ORGANICS
+ var_changes = list("virus_immune" = TRUE)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
index 0b58f2e72c..d0649cf76b 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
@@ -96,7 +96,7 @@
if (body_color == "black")
holder_type = /obj/item/holder/mouse/black
- if(prob(25))
+ if(prob(40))
LAZYINITLIST(rat_diseases)
rat_diseases += new /datum/disease/advance/random(rand(1, 5), 9, 1)
diff --git a/code/modules/reagents/reactions/instant/virology.dm b/code/modules/reagents/reactions/instant/virology.dm
index de517a456c..aa9e82431d 100644
--- a/code/modules/reagents/reactions/instant/virology.dm
+++ b/code/modules/reagents/reactions/instant/virology.dm
@@ -40,9 +40,37 @@
required_reagents = list(REAGENT_ID_INAPROVALINE = 1, REAGENT_ID_MUTAGENVIRUSFOOD = 1)
result_amount = 2
+/decl/chemical_reaction/instant/virus_food_uranium
+ name = REAGENT_URANIUMVIRUSFOOD
+ id = REAGENT_ID_URANIUMVIRUSFOOD
+ result = REAGENT_ID_URANIUMVIRUSFOOD
+ required_reagents = list(REAGENT_ID_URANIUM = 1, REAGENT_ID_VIRUSFOOD = 1)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/virus_food_uranium_unstable
+ name = REAGENT_UNSTABLEURANIUMVIRUSFOOD
+ id = REAGENT_ID_UNSTABLEURANIUMVIRUSFOOD
+ result = REAGENT_ID_UNSTABLEURANIUMVIRUSFOOD
+ required_reagents = list(REAGENT_ID_URANIUM = 1, REAGENT_ID_PHORONVIRUSFOOD = 1)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/virus_food_uranium_stable
+ name = REAGENT_STABLEURANIUMVIRUSFOOD
+ id = REAGENT_ID_STABLEURANIUMVIRUSFOOD
+ result = REAGENT_ID_STABLEURANIUMVIRUSFOOD
+ required_reagents = list(REAGENT_ID_PHORON = 5, REAGENT_ID_URANIUM = 5, REAGENT_ID_SILVER = 5)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/virus_food_uranium_stable_alt
+ name = REAGENT_STABLEURANIUMVIRUSFOOD_ALT
+ id = REAGENT_ID_STABLEURANIUMVIRUSFOOD_ALT
+ result = REAGENT_ID_STABLEURANIUMVIRUSFOOD
+ required_reagents = list(REAGENT_ID_PHORON = 5, REAGENT_ID_URANIUM = 5, REAGENT_ID_GOLD = 5)
+ result_amount = 1
+
/decl/chemical_reaction/instant/virus_food_size
name = REAGENT_SIZEVIRUSFOOD
- id = "sizeoxadonevirusfood"
+ id = REAGENT_ID_SIZEVIRUSFOOD
result = REAGENT_ID_SIZEVIRUSFOOD
required_reagents = list(REAGENT_ID_SIZEOXADONE = 1, REAGENT_ID_PHORONVIRUSFOOD = 1)
result_amount = 2
@@ -129,6 +157,27 @@
level_min = 1
level_max = 1
+/decl/chemical_reaction/instant/mix_virus/mix_virus_10
+ name = "Mix Virus 10"
+ id = "mixvirus10"
+ required_reagents = list(REAGENT_ID_URANIUMVIRUSFOOD = 1)
+ level_min = 6
+ level_max = 7
+
+/decl/chemical_reaction/instant/mix_virus/mix_virus_11
+ name = "Mix Virus 11"
+ id = "mixvirus11"
+ required_reagents = list(REAGENT_ID_UNSTABLEURANIUMVIRUSFOOD = 1)
+ level_min = 7
+ level_max = 7
+
+/decl/chemical_reaction/instant/mix_virus/mix_virus_12
+ name = "Mix Virus 12"
+ id = "mixvirus12"
+ required_reagents = list(REAGENT_ID_STABLEURANIUMVIRUSFOOD = 1)
+ level_min = 8
+ level_max = 8
+
/decl/chemical_reaction/instant/mix_virus/picky/size
name = "Mix Virus Size"
id = "mixvirussize"
@@ -172,3 +221,16 @@
var/datum/disease/advance/D = locate(/datum/disease/advance) in B.data["viruses"]
if(D)
D.Neuter()
+
+/decl/chemical_reaction/instant/falter_virus
+ name = "Falter Virus"
+ id = "faltervirus"
+ required_reagents = list(REAGENT_ID_SPACEACILLIN = 1)
+ catalysts = list(REAGENT_ID_BLOOD = 1)
+
+/decl/chemical_reaction/instant/falter_virus/on_reaction(var/datum/reagents/holder)
+ var/datum/reagent/blood/B = locate(/datum/reagent/blood) in holder.reagent_list
+ if(B && B.data)
+ var/datum/disease/advance/D = locate(/datum/disease/advance) in B.data["viruses"]
+ if(D)
+ D.Falter()
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index e1a0d9d632..59c17ae82b 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -38,7 +38,6 @@
drop_sound = 'sound/items/drop/glass.ogg'
pickup_sound = 'sound/items/pickup/glass.ogg'
-
/obj/item/reagent_containers/syringe/Initialize(mapload)
. = ..()
update_icon()
@@ -496,6 +495,17 @@
icon_state = "[rounded_vol]"
item_state = "syringe_[rounded_vol]"
+/obj/item/reagent_containers/syringe/old
+ name = "old syringe"
+ desc = "An old, broken syringe. Are you sure it's a good idea to pick it up without gloves?"
+ mode = SYRINGE_BROKEN
+
+/obj/item/reagent_containers/syringe/old/Initialize(mapload)
+ . = ..()
+ if(prob(75))
+ var/datum/disease/advance/new_disease = new /datum/disease/advance/random(rand(1, 3), rand(7, 9), 2)
+ src.viruses += new_disease
+
#undef SYRINGE_DRAW
#undef SYRINGE_INJECT
#undef SYRINGE_BROKEN
diff --git a/code/modules/reagents/reagents/virology.dm b/code/modules/reagents/reagents/virology.dm
index a4f3471ff8..a90b3a414f 100644
--- a/code/modules/reagents/reagents/virology.dm
+++ b/code/modules/reagents/reagents/virology.dm
@@ -48,6 +48,23 @@
description = "Mutates viruses when mixed in blood. This one seems to have been weakened, but still strong."
color = "#CEC3C6"
+/datum/reagent/uranium/uraniumvirusfood
+ name = REAGENT_URANIUMVIRUSFOOD
+ id = REAGENT_ID_URANIUMVIRUSFOOD
+ description = "Mutates viruses when mixed in blood. This one seems to glow lightly."
+ color = "#D18AA5"
+
+/datum/reagent/uranium/uraniumvirusfood/unstable
+ name = REAGENT_UNSTABLEURANIUMVIRUSFOOD
+ id = REAGENT_ID_UNSTABLEURANIUMVIRUSFOOD
+ description = "Mutates viruses when mixed in blood. This one seems be lightly warm."
+ color = "#D18AA5"
+
+/datum/reagent/uranium/uraniumvirusfood/stable
+ name = REAGENT_STABLEURANIUMVIRUSFOOD
+ id = REAGENT_ID_STABLEURANIUMVIRUSFOOD
+ description = "Mutates viruses when mixed in blood. This one seems to be stable."
+
/datum/reagent/toxin/phoron/phoronvirusfood/sizevirusfood
name = REAGENT_SIZEVIRUSFOOD
id = REAGENT_ID_SIZEVIRUSFOOD