diff --git a/code/__defines/diseases.dm b/code/__defines/diseases.dm index 97f0025228..ac34e469b5 100644 --- a/code/__defines/diseases.dm +++ b/code/__defines/diseases.dm @@ -5,9 +5,10 @@ #define HIDDEN_PANDEMIC (1<<1) //Disease Flags -#define CURABLE (1<<0) -#define CAN_CARRY (1<<1) -#define CAN_RESIST (1<<2) +#define CURABLE (1<<0) +#define CAN_CARRY (1<<1) +#define CAN_RESIST (1<<2) +#define CAN_NOT_POPULATE (1<<3) //Spread Flags #define SPECIAL (1<<0) diff --git a/code/controllers/subsystems/supply.dm b/code/controllers/subsystems/supply.dm index 97184302aa..af1fe2b9a5 100644 --- a/code/controllers/subsystems/supply.dm +++ b/code/controllers/subsystems/supply.dm @@ -121,6 +121,20 @@ SUBSYSTEM_DEF(supply) EC.contents[EC.contents.len]["quantity"] = cashmoney.worth EC.value += EC.contents[EC.contents.len]["value"] + if(istype(A, /obj/item/reagent_containers/glass/bottle/vaccine)) + var/obj/item/reagent_containers/glass/bottle/vaccine/sale_bottle = A + if(!istype(CR, /obj/structure/closet/crate/freezer)) + EC.contents = list( + "error" = "Error: Product was improperly packaged. Send conents in freezer crate to preserve contents for transport." + ) + else if(sale_bottle.reagents.reagent_list.len != 1 || sale_bottle.reagents.get_reagent_amount(REAGENT_ID_VACCINE) < sale_bottle.volume) + EC.contents = list( + "error" = "Error: Tainted product in batch. Was opened, contaminated, or was full. Payment rendered null under terms of agreement." + ) + else + EC.contents[EC.contents.len]["value"] = 5 + EC.value += EC.contents[EC.contents.len]["value"] + // CHOMPAdd Start - Sell salvage if(istype(A, /obj/item/salvage)) var/obj/item/salvage/salvagedStuff = A diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm index 6505817fb5..7859cf1a82 100644 --- a/code/datums/diseases/_MobProcs.dm +++ b/code/datums/diseases/_MobProcs.dm @@ -36,6 +36,7 @@ /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 active_diseases += DD @@ -83,14 +84,7 @@ if(nutrition > 300 && prob(nutrition/50)) return - var/list/zone_weights = list( - 1 = head_ch, - 2 = body_ch, - 3 = hands_ch, - 4 = feet_ch - ) - - var/target_zone = pick(zone_weights) + var/target_zone = pick(head_ch;1,body_ch;2,hands_ch;3,feet_ch;4) if(ishuman(src)) var/mob/living/carbon/human/H = src diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm index 48552997fb..290dc1a4d8 100644 --- a/code/datums/diseases/_disease.dm +++ b/code/datums/diseases/_disease.dm @@ -42,6 +42,7 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease)) var/allow_dead = FALSE var/infect_synthetics = FALSE var/processing = FALSE + var/has_timer = FALSE /datum/disease/Destroy() affected_mob = null @@ -147,6 +148,23 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease)) remove_virus() qdel(src) +/datum/disease/proc/start_cure_timer() + if(has_timer) + return + if(!(disease_flags & CURABLE)) + return + has_timer = TRUE + addtimer(CALLBACK(src, PROC_REF(check_natural_immunity)), (1 HOUR) + rand( -20 MINUTES, 30 MINUTES), TIMER_DELETE_ME) + +/datum/disease/proc/check_natural_immunity() + if(!(disease_flags & CURABLE)) + return + if(prob(rand(10, 15))) + has_timer = FALSE + cure() + return + addtimer(CALLBACK(src, PROC_REF(check_natural_immunity)), rand(5 MINUTES, 10 MINUTES), TIMER_DELETE_ME) + /datum/disease/proc/IsSame(datum/disease/D) if(ispath(D)) return istype(src, D) @@ -173,8 +191,14 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease)) /datum/disease/proc/remove_virus() affected_mob.viruses -= src +// Called when a disease is added onto a mob /datum/disease/proc/Start() return +// Called when a disease is removed from a mob /datum/disease/proc/End() return + +// Called when the mob dies +/datum/disease/proc/OnDeath() + return diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index ecf4ff22fc..f2be67bf46 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -1,10 +1,19 @@ GLOBAL_LIST_EMPTY(archive_diseases) GLOBAL_LIST_INIT(advance_cures, list( - REAGENT_ID_SODIUMCHLORIDE, REAGENT_ID_SUGAR, REAGENT_ID_ORANGEJUICE, - REAGENT_ID_SPACEACILLIN, REAGENT_ID_GLUCOSE, REAGENT_ID_ETHANOL, - REAGENT_ID_LEPORAZINE, REAGENT_ID_IMPEDREZENE, REAGENT_ID_HEPANEPHRODAXON, - REAGENT_ID_SILVER, REAGENT_ID_GOLD + REAGENT_ID_SPACEACILLIN, + REAGENT_ID_ORANGEJUICE, + REAGENT_ID_ETHANOL, + REAGENT_ID_GLUCOSE, + REAGENT_ID_COPPER, + REAGENT_ID_LEAD, + REAGENT_ID_LITHIUM, + REAGENT_ID_RADIUM, + REAGENT_ID_MERCURY, + REAGENT_ID_BLISS, + REAGENT_ID_MUTAGEN, + REAGENT_ID_PHORON, + REAGENT_ID_SACID )) /datum/disease/advance @@ -13,6 +22,7 @@ GLOBAL_LIST_INIT(advance_cures, list( form = "Advance Disease" agent = "advance microbes" max_stages = 5 + disease_flags = CAN_NOT_POPULATE spread_text = "Unknown" viable_mobtypes = list(/mob/living/carbon/human) diff --git a/code/datums/diseases/advance/disease_preset.dm b/code/datums/diseases/advance/disease_preset.dm index d30bbf2ebb..b253db77a5 100644 --- a/code/datums/diseases/advance/disease_preset.dm +++ b/code/datums/diseases/advance/disease_preset.dm @@ -1,3 +1,49 @@ +/datum/disease/advance/random + name = "Experimental Disease" + var/randomname = TRUE + var/datum/symptom/setsymptom = null + var/max_symptoms_override + +/datum/disease/advance/random/minor + name = "Minor Experimental Disease" + max_symptoms_override = 4 + +/datum/disease/advance/random/New(max_symptoms, max_level = 6, min_level = 1, list/guaranteed_symptoms = setsymptom) + if(!max_symptoms) + max_symptoms = (2 + rand(1, (VIRUS_SYMPTOM_LIMIT - 2))) + if(max_symptoms_override) + max_symptoms = (max_symptoms_override - rand(0, 2)) + if(guaranteed_symptoms) + if(islist(guaranteed_symptoms)) + max_symptoms -= length(guaranteed_symptoms) + else + guaranteed_symptoms = list(guaranteed_symptoms) + max_symptoms -= 1 + + var/list/datum/symptom/possible_symptoms = list() + for(var/datum/symptom/symptom as anything in subtypesof(/datum/symptom)) + if(symptom in guaranteed_symptoms) + continue + if(initial(symptom.level) > max_level || initial(symptom.level) < min_level) + continue + if(initial(symptom.level) <= -1) + continue + possible_symptoms += symptom + for(var/i in 1 to max_symptoms) + var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms) + if(chosen_symptom) + symptoms += new chosen_symptom + for(var/guaranteed_symptom in guaranteed_symptoms) + symptoms += new guaranteed_symptom + +/datum/disease/advance/random/macrophage + name = "Unknown Disease" + setsymptom = /datum/symptom/macrophage + +/datum/disease/advance/random/blob + name = "Blob Spores" + setsymptom = /datum/symptom/blobspores + // Cold /datum/disease/advance/cold/New(process = 1, datum/disease/advance/D, copy = 0) @@ -14,3 +60,19 @@ name = "Flu" symptoms = list(new /datum/symptom/cough) ..(process, D, copy) + +// Macrophages + +/datum/disease/advance/macrophage/New(process = 1, datum/disease/advance/D, copy = 0) + if(!D) + name = "Macrophages" + symptoms = list(new /datum/symptom/macrophage) + ..(process, D, copy) + +// Blob Spores + +/datum/disease/advance/blobspores/New(process = 1, datum/disease/advance/D, copy = 0) + if(!D) + name = "Blob Spores" + symptoms = list(new /datum/symptom/blobspores) + ..(process, D, copy) diff --git a/code/datums/diseases/advance/symptoms/blobspores.dm b/code/datums/diseases/advance/symptoms/blobspores.dm new file mode 100644 index 0000000000..8c8ef33d62 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/blobspores.dm @@ -0,0 +1,93 @@ +/* +////////////////////////////////////// +Blob Spores + + Slightly hidden + Major Increases to resistance. + Reduces stage speed. + Slight boost to transmission + Admin Level. + +BONUS + The host coughs up blob spores + +////////////////////////////////////// +*/ +/datum/symptom/blobspores + name = "Blob Spores" + stealth = 1 + resistance = 5 + stage_speed = -2 + transmittable = 1 + level = -1 + severity = 3 + + var/ready_to_pop + var/factory_blob + var/strong_blob + var/node_blob + +/datum/symptom/blobspores/Start(datum/disease/advance/A) + if(!..()) + return + + if(A.totalResistance() >= 8) + factory_blob = TRUE + if(A.totalResistance() >= 5) + strong_blob = TRUE + if(A.totalResistance() >= 10) + node_blob = TRUE + +/datum/symptom/blobspores/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + + switch(A.stage) + if(1) + if(prob(2)) + to_chat(M, span_notice("You feel bloated.")) + + if(prob(3) && !M.jitteriness) + to_chat(M, span_notice("You feel a bit jittery.")) + M.jitteriness = 10 + + if(2) + if(prob(1) && ishuman(M)) + var/mob/living/carbon/human/H = M + H.vomit(TRUE, FALSE) + if(3, 4) + if(prob(10)) + to_chat(M, span_notice("You feel blobby?")) + + if(5) + ready_to_pop = TRUE + if(prob(5)) + M.audible_emote("coughs up a small amount of blood!") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/bleeding_rng = rand(1, 2) + H.drip(bleeding_rng) + +/datum/symptom/blobspores/OnDeath(datum/disease/advance/A) + var/mob/living/M = A.affected_mob + M.visible_message(span_danger("[M] starts swelling grotesquely!")) + addtimer(CALLBACK(src, PROC_REF(pop), A, M), 10 SECONDS) + +/datum/symptom/blobspores/proc/pop(datum/disease/advance/A, mob/living/M) + if(!A || !M) + return + var/list/blob_options = list(/obj/structure/blob/normal) + if(factory_blob) + blob_options += /obj/structure/blob/factory + if(strong_blob) + blob_options += /obj/structure/blob/shield + if(node_blob) + blob_options += /obj/structure/blob/node + var/pick_blob = pick(blob_options) + if(ready_to_pop) + for(var/i in 1 to rand(1, 6)) + new /mob/living/simple_mob/blob/spore(M.loc) + new pick_blob(M.loc) + + M.visible_message(span_danger("A huge mass of blob and blob spores burst out of [M]!")) diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm index f4a3059d7c..efe4b39f17 100644 --- a/code/datums/diseases/advance/symptoms/shivering.dm +++ b/code/datums/diseases/advance/symptoms/shivering.dm @@ -27,10 +27,10 @@ Bonus /datum/symptom/shivering/Activate(datum/disease/advance/A) ..() if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/carbon/M = A.affected_mob - to_chat(M, span_warning(pick("You feel cold.", "You start shivering."))) - if(M.bodytemperature > BODYTEMP_COLD_DAMAGE_LIMIT) - Chill(M, A) + var/mob/living/L = A.affected_mob + to_chat(L, span_warning(pick("You feel cold.", "You start shivering."))) + if(L.bodytemperature > BODYTEMP_COLD_DAMAGE_LIMIT) + Chill(L, A) return /datum/symptom/shivering/proc/Chill(mob/living/M, datum/disease/advance/A) diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm index 22865e0417..5f9fa910df 100644 --- a/code/datums/diseases/advance/symptoms/sneeze.dm +++ b/code/datums/diseases/advance/symptoms/sneeze.dm @@ -87,34 +87,33 @@ Bonus return -/datum/symptom/sneeze/bluespace/proc/SneezeTeleport(datum/disease/advance/A, var/mob/living/M) +/datum/symptom/sneeze/bluespace/proc/SneezeTeleport(datum/disease/advance/A, var/mob/living/mob) var/list/destination = list() - var/mob/living/carbon/human/H = M var/place - for(var/mob/living/carbon/human/B in range(A.stage, M)) - if(B.can_be_drop_pred && H.can_be_drop_prey && H.devourable) + for(var/mob/living/carbon/human/B in range(A.stage, mob)) + if(B.can_be_drop_pred && mob.can_be_drop_prey && mob.devourable) destination += B.vore_selected - for(var/turf/T in range(A.stage, H)) + for(var/turf/T in range(A.stage, mob)) if(istype(T, /turf/space)) // No danger, this is just a fun/vore symptom continue destination += T if(isemptylist(destination)) - to_chat(H, span_warning("You go to sneeze, but can't.")) + to_chat(mob, span_warning("You go to sneeze, but can't.")) return FALSE place = safepick(destination) - var/mob/living/carbon/human/unlucky = locate() in place + var/mob/living/unlucky = locate() in place if(unlucky && !unlucky.is_incorporeal()) // CHOMPEdit - if(unlucky.can_be_drop_pred && H.can_be_drop_prey && H.devourable) + if(unlucky.can_be_drop_pred && mob.can_be_drop_prey && mob.devourable) place = unlucky.vore_selected - else if(unlucky.devourable && unlucky.can_be_drop_prey && H.can_be_drop_pred) - unlucky.forceMove(H.vore_selected) + else if(unlucky.devourable && unlucky.can_be_drop_prey && mob.can_be_drop_pred) + unlucky.forceMove(mob.vore_selected) - H.emote("sneeze") - do_teleport(H, place) + mob.emote("sneeze") + do_teleport(mob, place) return TRUE diff --git a/code/datums/diseases/advance/symptoms/stimulant.dm b/code/datums/diseases/advance/symptoms/stimulant.dm index 665fad2a6d..4861a44240 100644 --- a/code/datums/diseases/advance/symptoms/stimulant.dm +++ b/code/datums/diseases/advance/symptoms/stimulant.dm @@ -36,7 +36,7 @@ Bonus if(3, 4) L.jitteriness += 10 else - if(L.reagents.get_reagent_amount(REAGENT_ID_HYPERZINE < 10)) + if(L.reagents.get_reagent_amount(REAGENT_ID_HYPERZINE) < 10) L.reagents.add_reagent(REAGENT_ID_HYPERZINE, 5) if(prob(30)) L.jitteriness += 15 diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm index 90b39fab3b..df5954f97b 100644 --- a/code/datums/diseases/advance/symptoms/symptoms.dm +++ b/code/datums/diseases/advance/symptoms/symptoms.dm @@ -32,5 +32,10 @@ GLOBAL_LIST_INIT(list_symptoms, subtypesof(/datum/symptom)) /datum/symptom/proc/End(datum/disease/advance/A) return +// Called when the disease activates. It's what makes your diseases work! /datum/symptom/proc/Activate(datum/disease/advance/A) return + +// Called when the host dies +/datum/symptom/proc/OnDeath(datum/disease/advance/A) + return diff --git a/code/datums/diseases/advance/symptoms/telepathy.dm b/code/datums/diseases/advance/symptoms/telepathy.dm index dd3424b7c6..10a42cc6ad 100644 --- a/code/datums/diseases/advance/symptoms/telepathy.dm +++ b/code/datums/diseases/advance/symptoms/telepathy.dm @@ -25,13 +25,15 @@ Bonus severity = 0 /datum/symptom/telepathy/Start(datum/disease/advance/A) - var/mob/living/carbon/human/H = A.affected_mob - H.dna.SetSEState(REMOTETALKBLOCK, 1) - domutcheck(H, null, TRUE) - to_chat(H, span_notice("Your mind expands...")) + if(iscarbon(A)) + var/mob/living/carbon/human/H = A.affected_mob + H.dna.SetSEState(REMOTETALKBLOCK, 1) + domutcheck(H, null, TRUE) + to_chat(H, span_notice("Your mind expands...")) /datum/symptom/telepathy/End(datum/disease/advance/A) - var/mob/living/carbon/human/H = A.affected_mob - H.dna.SetSEState(REMOTETALKBLOCK, 0) - domutcheck(H, null, TRUE) - to_chat(H, span_notice("Everything feels... Normal.")) + if(iscarbon(A)) + var/mob/living/carbon/human/H = A.affected_mob + H.dna.SetSEState(REMOTETALKBLOCK, 0) + domutcheck(H, null, TRUE) + to_chat(H, span_notice("Everything feels... Normal.")) diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm index d74b0c6a5d..2710124db4 100644 --- a/code/datums/diseases/advance/symptoms/vision.dm +++ b/code/datums/diseases/advance/symptoms/vision.dm @@ -27,24 +27,25 @@ Bonus /datum/symptom/visionloss/Activate(datum/disease/advance/A) ..() if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/carbon/M = A.affected_mob - var/obj/item/organ/internal/eyes/eyes = M.internal_organs_by_name[O_EYES] - if(!eyes) - return - switch(A.stage) - if(1, 2) - to_chat(M, span_warning("Your eyes itch.")) - if(3, 4) - to_chat(M, span_boldwarning("Your eyes burn!")) - M.eye_blurry = 20 - eyes.take_damage(1) - else - to_chat(M, span_userdanger("Your eyes burn horrificly!")) - M.eye_blurry = 40 - eyes.take_damage(5) - if(eyes.damage >= 10) - M.disabilities |= NEARSIGHTED - if(prob(eyes.damage - 10 + 1)) - if(!M.eye_blind) - to_chat(M, span_userdanger("You go blind!")) - M.Blind(20) + if(iscarbon(A)) + var/mob/living/carbon/M = A.affected_mob + var/obj/item/organ/internal/eyes/eyes = M.internal_organs_by_name[O_EYES] + if(!eyes) + return + switch(A.stage) + if(1, 2) + to_chat(M, span_warning("Your eyes itch.")) + if(3, 4) + to_chat(M, span_boldwarning("Your eyes burn!")) + M.eye_blurry = 20 + eyes.take_damage(1) + else + to_chat(M, span_userdanger("Your eyes burn horrificly!")) + M.eye_blurry = 40 + eyes.take_damage(5) + if(eyes.damage >= 10) + M.disabilities |= NEARSIGHTED + if(prob(eyes.damage - 10 + 1)) + if(!M.eye_blind) + to_chat(M, span_userdanger("You go blind!")) + M.Blind(20) diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index 6b38902b6d..6b9266718f 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -9,7 +9,7 @@ viable_mobtypes = list(/mob/living/carbon/human) desc = "If left untreated the subject will become very weak, and may vomit often." severity = MINOR - disease_flags = CAN_CARRY|CAN_RESIST + disease_flags = CAN_CARRY|CAN_RESIST|CAN_NOT_POPULATE visibility_flags = HIDDEN_PANDEMIC required_organs = list(/obj/item/organ/internal/appendix) bypasses_immunity = TRUE diff --git a/code/datums/diseases/fake_gbs.dm b/code/datums/diseases/fake_gbs.dm index a7831689d1..4ab932e8cd 100644 --- a/code/datums/diseases/fake_gbs.dm +++ b/code/datums/diseases/fake_gbs.dm @@ -23,7 +23,7 @@ else if(prob(5)) affected_mob.emote("gasp") if(prob(10)) - to_chat(span_danger("You're starting to feel very weak...")) + to_chat(affected_mob, span_danger("You're starting to feel very weak...")) if(4) if(prob(10)) affected_mob.emote("cough") diff --git a/code/datums/diseases/food_poisoning.dm b/code/datums/diseases/food_poisoning.dm index 1cd43b25f2..bfb9aa445a 100644 --- a/code/datums/diseases/food_poisoning.dm +++ b/code/datums/diseases/food_poisoning.dm @@ -11,7 +11,7 @@ viable_mobtypes = list(/mob/living/carbon/human) desc = "Nausea, sickness, and vomitting." severity = MINOR - disease_flags = CURABLE + disease_flags = CURABLE|CAN_NOT_POPULATE virus_heal_resistant = TRUE /datum/disease/food_poisoning/stage_act() diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index 0c61fd309b..10f7bc0011 100644 --- a/code/datums/diseases/gbs.dm +++ b/code/datums/diseases/gbs.dm @@ -9,6 +9,7 @@ agent = "Gravitokinetic Bipotential SADS+" viable_mobtypes = list(/mob/living/carbon/human) severity = BIOHAZARD + disease_flags = CAN_NOT_POPULATE /datum/disease/gbs/stage_act() if(!..()) diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm index f58b4a8d59..8fc32760b8 100644 --- a/code/datums/supplypacks/medical.dm +++ b/code/datums/supplypacks/medical.dm @@ -421,6 +421,26 @@ containername = "Virology biohazard equipment" access = access_medical_equip +/datum/supply_pack/med/disease + name = "Experimental Disease crate" + desc = "An experimental disease. Contains a multitude of symptoms." + contains = list( + /obj/item/reagent_containers/glass/bottle/culture/random_virus = 1 + ) + cost = 60 + containertype = /obj/structure/closet/crate/freezer + access = access_medical_equip + +/datum/supply_pack/med/disease_minor + name = "Minor Experimental Disease crate" + desc = "An experimental disease. Contains a weakened, untested viral culture." + contains = list( + /obj/item/reagent_containers/glass/bottle/culture/random_virus/minor = 1 + ) + cost = 40 + containertype = /obj/structure/closet/crate/freezer + access = access_medical_equip + /datum/supply_pack/med/compactdefib name = "Compact Defibrillator crate" desc = "A compact defibrillator. Requires Medical Equipment access." diff --git a/code/game/machinery/pandemic.dm b/code/game/machinery/pandemic.dm index ea490d10ca..54791587ed 100644 --- a/code/game/machinery/pandemic.dm +++ b/code/game/machinery/pandemic.dm @@ -12,6 +12,12 @@ var/selected_strain_index = 1 var/obj/item/reagent_containers/beaker = null +// PanDEMIC Bottle +/obj/item/reagent_containers/glass/bottle/vaccine + icon_state = "bottle10" + possible_transfer_amounts = (list(5, 10, 15)) + volume = 15 + /obj/machinery/computer/pandemic/Initialize(mapload) . = ..() update_icon() @@ -67,13 +73,20 @@ return icon_state = "pandemic[(beaker)?"1":"0"][!(stat & NOPOWER) ? "" : "_nopower"]" -/obj/machinery/computer/pandemic/proc/create_culture(name, bottle_type = "culture", cooldown = 50) - var/obj/item/reagent_containers/glass/bottle/B = new/obj/item/reagent_containers/glass/bottle(loc) - B.icon_state = "bottle10" +/obj/machinery/computer/pandemic/proc/create_culture(name, bottle_type = "culture", cooldown = 50, vaccine = FALSE) + + var/obj/item/reagent_containers/glass/bottle/B + if(vaccine) + B = new /obj/item/reagent_containers/glass/bottle/vaccine(loc) + B.name = "[name] vaccine" + else + B = new(loc) + B.icon_state = "bottle10" + B.name = "[name] [bottle_type] bottle" + B.pixel_x = rand(-3, 3) B.pixel_y = rand(-3, 3) replicator_cooldown(cooldown) - B.name = "[name] [bottle_type] bottle" return B /obj/machinery/computer/pandemic/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state) @@ -146,8 +159,13 @@ atom_say("Unable to synthesize requested antibody.") return - var/obj/item/reagent_containers/glass/bottle/B = create_culture(vaccine_name, REAGENT_ID_VACCINE, 200) + var/obj/item/reagent_containers/glass/bottle/vaccine/B = create_culture(vaccine_name, REAGENT_ID_VACCINE, 200, TRUE) B.reagents.add_reagent(REAGENT_ID_VACCINE, 15, list(vaccine_type)) + if(beaker && beaker.reagents && length(beaker.reagents.reagent_list)) + beaker.reagents.remove_reagent(REAGENT_ID_BLOOD, 5) + if(!length(beaker.reagents.reagent_list)) + update_tgui_static_data(ui.user) + if("eject_beaker") eject_beaker() update_tgui_static_data(ui.user) @@ -361,17 +379,17 @@ if(I.has_tool_quality(TOOL_SCREWDRIVER)) eject_beaker() return - if(istype(I, /obj/item/reagent_containers/glass) && I.is_open_container()) + if(istype(I, /obj/item/reagent_containers/glass) && I.is_open_container() || istype(I, /obj/item/reagent_containers/syringe)) if(stat & (NOPOWER|BROKEN)) return if(beaker) - to_chat(user, span_warning("A beaker is already loaded into the machine!")) + to_chat(user, span_warning("A [beaker] is already loaded into the machine!")) return user.drop_item() beaker = I beaker.loc = src - to_chat(user, span_notice("You add the beaker to the machine.")) + to_chat(user, span_notice("You add \the [I] to the machine.")) update_tgui_static_data(user) icon_state = "pandemic1" else diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index be8ee51f25..e753d19c22 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -1,11 +1,6 @@ GLOBAL_LIST_EMPTY(current_pending_diseases) /datum/event/disease_outbreak var/datum/disease/chosen_disease - var/list/disease_blacklist = list( - /datum/disease/advance, - /datum/disease/food_poisoning, - /datum/disease/gbs // Terrible. It's only in the code to scare people. - ) var/static/list/transmissable_symptoms = list() var/static/list/diseases_minor = list() var/static/list/diseases_moderate_major = list() @@ -85,7 +80,7 @@ GLOBAL_LIST_EMPTY(current_pending_diseases) /datum/event/disease_outbreak/proc/populate_diseases() for(var/candidate in subtypesof(/datum/disease)) var/datum/disease/CD = new candidate - if(is_type_in_list(CD, disease_blacklist)) + if(CD.disease_flags & CAN_NOT_POPULATE) continue switch(CD.severity) if(NONTHREAT, MINOR) diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 2f68b646d6..2c9682d941 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -100,6 +100,16 @@ drop_r_hand() drop_l_hand() + if(viruses) + for(var/datum/disease/D in viruses) + if(istype(D, /datum/disease/advance)) + var/datum/disease/advance/AD = D + for(var/symptom in AD.symptoms) + var/datum/symptom/S = symptom + S.OnDeath(AD) + else + D.OnDeath() + if(healths) healths.overlays = null // This is specific to humans but the relevant code is here; shouldn't mess with other mobs. healths.icon_state = "health6" diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/macrophage.dm b/code/modules/mob/living/simple_mob/subtypes/vore/macrophage.dm index edfbaa5dc1..2c402df5f1 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/macrophage.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/macrophage.dm @@ -5,8 +5,25 @@ icon_state = "macrophage-1" faction = FACTION_MACROBACTERIA - maxHealth = 60 - health = 60 + maxHealth = 20 + health = 20 + + minbodytemp = T0C-30 + heat_damage_per_tick = 40 + cold_damage_per_tick = 40 + + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + unsuitable_atoms_damage = 0 + shock_resist = 0.5 + taser_kill = FALSE + water_resist = 1 var/datum/disease/base_disease = null var/list/infections = list() @@ -30,13 +47,37 @@ can_be_drop_prey = FALSE allow_mind_transfer = TRUE - ai_holder_type = /datum/ai_holder/simple_mob/melee + pass_flags = PASSTABLE | PASSMOB + mob_size = MOB_TINY + + ai_holder_type = /datum/ai_holder/simple_mob/melee/macrophage + +/mob/living/simple_mob/vore/aggressive/macrophage/giant + name = "Giant Germ" + desc = "An incredibly huge virus!" + + size_multiplier = 1.5 + + maxHealth = 40 + health = 40 + + pass_flags = PASSTABLE | PASSGRILLE + +/mob/living/simple_mob/vore/aggressive/macrophage/Initialize() + . = ..() + var/datum/disease/advance/random/macrophage/D = new + health += D.totalResistance() + maxHealth += D.totalResistance() + melee_damage_lower += max(0, D.totalResistance()) + melee_damage_upper += max(0, D.totalResistance()) + infections += D + base_disease = D /mob/living/simple_mob/vore/aggressive/macrophage/proc/deathcheck() if(locate(/mob/living/carbon/human) in vore_selected) addtimer(CALLBACK(src, TYPE_PROC_REF(/mob/living/simple_mob/vore/aggressive/macrophage, deathcheck)), 3000) else - dust() + death() /mob/living/simple_mob/vore/aggressive/macrophage/green icon_state = "macrophage-2" @@ -47,6 +88,27 @@ /mob/living/simple_mob/vore/aggressive/macrophage/blue icon_state = "macrophage-4" +/mob/living/simple_mob/vore/aggressive/macrophage/do_attack(atom/A, turf/T) + . = ..() + if(iscarbon(A)) + var/mob/living/carbon/human/victim = A + if((victim.HasDisease(base_disease) || !victim.CanContractDisease(base_disease)) && prob(75)) + ai_holder.lose_target() + victim.ContractDisease(base_disease) + +/mob/living/simple_mob/vore/aggressive/macrophage/death() + ..() + visible_message(span_warning("\The [src] shrivels up and dies, unable to survive!")) + if(isbelly(loc)) + var/obj/belly/belly = loc + if(belly) + var/mob/living/pred = belly.owner + pred.ForceContractDisease(base_disease) + else + var/obj/effect/decal/cleanable/mucus/sick = new(loc) + sick.viruses += base_disease + qdel(src) + /obj/belly/macrophage name = "capsid" fancy_vore = TRUE @@ -67,3 +129,17 @@ var/obj/belly/B = new /obj/belly/macrophage(src) vore_selected = B + +/datum/ai_holder/simple_mob/melee/macrophage + var/datum/disease/virus = null + +/datum/ai_holder/simple_mob/melee/macrophage/list_targets() + var/list/our_targets = ..() + var/mob/living/simple_mob/vore/aggressive/macrophage/macrophage = holder + for(var/list_target in our_targets) + var/mob/living/victim = list_target + if(victim.viruses) + if(victim.HasDisease(macrophage.base_disease) && prob(75)) // Less likely to be a target if you're infected + our_targets -= list_target + continue + return our_targets diff --git a/code/modules/reagents/reagent_containers/virology.dm b/code/modules/reagents/reagent_containers/virology.dm index f09c34a4aa..79765d83b6 100644 --- a/code/modules/reagents/reagent_containers/virology.dm +++ b/code/modules/reagents/reagent_containers/virology.dm @@ -24,3 +24,43 @@ diseases += new /datum/disease/advance/flu data["viruses"] = diseases reagents.add_reagent(REAGENT_ID_BLOOD, 10, data) + +/obj/item/reagent_containers/glass/bottle/culture/blobspores + name = "blob spores culture" + desc = "A bottle with blob spores" + +/obj/item/reagent_containers/glass/bottle/culture/blobspores/Initialize() + . = ..() + diseases += new /datum/disease/advance/blobspores + data["viruses"] = diseases + reagents.add_reagent(REAGENT_ID_BLOOD, 10, data) + +/obj/item/reagent_containers/glass/bottle/culture/macrophages + name = "macrophages culture" + desc = "A bottle with giant viruses" + +/obj/item/reagent_containers/glass/bottle/culture/macrophages/Initialize() + . = ..() + diseases += new /datum/disease/advance/macrophage + data["viruses"] = diseases + reagents.add_reagent(REAGENT_ID_BLOOD, 10, data) + +/obj/item/reagent_containers/glass/bottle/culture/random_virus + name = "experimental disease culture bottle" + desc = "A small bottle. Contains an untested viral culture." + +/obj/item/reagent_containers/glass/bottle/culture/random_virus/Initialize() + . = ..() + diseases += new /datum/disease/advance/random + data["viruses"] = diseases + reagents.add_reagent(REAGENT_ID_BLOOD, 10, data) + +/obj/item/reagent_containers/glass/bottle/culture/random_virus/minor + name = "minor experimental disease culture bottle" + desc = "A small bottle. Contains a weak version of an untested viral culture." + +/obj/item/reagent_containers/glass/bottle/culture/random_virus/minor/Initialize() + . = ..() + diseases += new /datum/disease/advance/random/minor + data["viruses"] = diseases + reagents.add_reagent(REAGENT_ID_BLOOD, 10, data) diff --git a/code/modules/reagents/reagents/other.dm b/code/modules/reagents/reagents/other.dm index 5ac51a8f36..734cff113c 100644 --- a/code/modules/reagents/reagents/other.dm +++ b/code/modules/reagents/reagents/other.dm @@ -445,6 +445,10 @@ var/mob/living/carbon/C = M C.clean_blood(TRUE) + if(istype(M, /mob/living/simple_mob/vore/aggressive/macrophage)) // Big ouch for viruses + var/mob/living/simple_mob/macrophage = M + macrophage.adjustToxLoss(20) + /datum/reagent/space_cleaner/touch_obj(var/obj/O) ..() O.clean_blood() @@ -463,6 +467,9 @@ for(var/mob/living/simple_mob/slime/M in T) M.adjustToxLoss(rand(5, 10)) + for(var/mob/living/simple_mob/vore/aggressive/macrophage/virus in T) + virus.adjustToxLoss(rand(5, 10)) + T.apply_fire_protection() // CHOMPAdd - Apply fire protection /datum/reagent/space_cleaner/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) diff --git a/vorestation.dme b/vorestation.dme index 68a2aa16be..40f358da83 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -530,6 +530,7 @@ #include "code\datums\diseases\magnitis.dm" #include "code\datums\diseases\advance\advance.dm" #include "code\datums\diseases\advance\disease_preset.dm" +#include "code\datums\diseases\advance\symptoms\blobspores.dm" #include "code\datums\diseases\advance\symptoms\choking.dm" #include "code\datums\diseases\advance\symptoms\confusion.dm" #include "code\datums\diseases\advance\symptoms\cough.dm"