diff --git a/code/__defines/diseases.dm b/code/__defines/diseases.dm new file mode 100644 index 00000000000..30f1d6252be --- /dev/null +++ b/code/__defines/diseases.dm @@ -0,0 +1,30 @@ +#define VIRUS_SYMPTOM_LIMIT 6 + +//Visibility Flags +#define HIDDEN_SCANNER (1<<0) +#define HIDDEN_PANDEMIC (1<<1) + +//Disease Flags +#define CURABLE (1<<0) +#define CAN_CARRY (1<<1) +#define CAN_RESIST (1<<2) + +//Spread Flags +#define SPECIAL (1<<0) +#define NON_CONTAGIOUS (1<<1) +#define BLOOD (1<<2) +#define CONTACT_FEET (1<<3) +#define CONTACT_HANDS (1<<4) +#define CONTACT_GENERAL (1<<5) +#define AIRBORNE (1<<6) + + +//Severity Defines +#define NONTHREAT "No threat" +#define MINOR "Minor" +#define MEDIUM "Medium" +#define HARMFUL "Harmful" +#define DANGEROUS "Dangerous!" +#define BIOHAZARD "BIOHAZARD THREAT!" + +#define SYMPTOM_ACTIVATION_PROB 3 diff --git a/code/__defines/math.dm b/code/__defines/math.dm index f4539605f22..846753ab568 100644 --- a/code/__defines/math.dm +++ b/code/__defines/math.dm @@ -220,3 +220,9 @@ #define ROUNDUPTOPOWEROFTWO(x) (2 ** -round(-log(2,x))) #define DEFAULT(a, b) (a? a : b) + +// sqrt, but if you give it a negative number, you get 0 instead of a runtime +/proc/sqrtor0(num) + if(num < 0) + return 0 + return sqrt(num) diff --git a/code/controllers/subsystems/statpanel.dm b/code/controllers/subsystems/statpanel.dm index 42c1ecd5f28..6e97b992292 100644 --- a/code/controllers/subsystems/statpanel.dm +++ b/code/controllers/subsystems/statpanel.dm @@ -173,7 +173,9 @@ SUBSYSTEM_DEF(statpanels) target.stat_panel.send_message("update_examine", examine_update) /datum/controller/subsystem/statpanels/proc/set_tickets_tab(client/target) - var/list/tickets = GLOB.ahelp_tickets.stat_entry(target) + var/list/tickets = list() + if(check_rights(R_ADMIN|R_SERVER|R_MOD,FALSE,target)) //Prevents non-staff from opening the list of ahelp tickets + tickets += GLOB.ahelp_tickets.stat_entry(target) tickets += GLOB.mhelp_tickets.stat_entry(target) target.stat_panel.send_message("update_tickets", tickets) diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm new file mode 100644 index 00000000000..a24fa9264f8 --- /dev/null +++ b/code/datums/diseases/_MobProcs.dm @@ -0,0 +1,195 @@ +/mob/proc/HasDisease(datum/disease/D) + for(var/thing in GetViruses()) + var/datum/disease/DD = thing + if(DD.IsSame(D)) + return TRUE + return FALSE + +/mob/proc/CanContractDisease(datum/disease/D) + if(stat == DEAD && !D.allow_dead) + return FALSE + + if(D.GetDiseaseID() in GetResistances()) + return FALSE + + if(HasDisease(D)) + return FALSE + + if(istype(D, /datum/disease/advance) && count_by_type(GetViruses(), /datum/disease/advance) > 0) + return FALSE + + if(!(type in D.viable_mobtypes)) + return -1 + + if(isSynthetic()) + if(D.infect_synthetics) + return TRUE + return FALSE + + return TRUE + +/mob/proc/ContractDisease(datum/disease/D) + if(!CanContractDisease(D)) + return 0 + AddDisease(D) + return TRUE + +/mob/proc/AddDisease(datum/disease/D, respect_carrier = FALSE) + var/datum/disease/DD = new D.type(1, D, 0) + viruses += DD + DD.affected_mob = src + active_diseases += DD + + var/list/skipped = list("affected_mob", "holder", "carrier", "stage", "type", "parent_type", "vars", "transformed") + 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] + DD.vars[V] = L.Copy() + else + DD.vars[V] = D.vars[V] + + log_admin("[key_name(usr)] has contracted the virus \"[DD]\"") + +/mob/living/carbon/ContractDisease(datum/disease/D) + if(!CanContractDisease(D)) + return 0 + + var/obj/item/clothing/Cl = null + var/passed = 1 + + var/head_ch = 100 + var/body_ch = 100 + var/hands_ch = 25 + var/feet_ch = 25 + + if(D.spread_flags & CONTACT_HANDS) + head_ch = 0 + body_ch = 0 + hands_ch = 100 + feet_ch = 0 + if(D.spread_flags & CONTACT_FEET) + head_ch = 0 + body_ch = 0 + hands_ch = 0 + feet_ch = 100 + + if(prob(15/D.permeability_mod)) + return + + if(nutrition > 300 && prob(nutrition/10)) + return + + var/list/zone_weights = list( + 1 = head_ch, + 2 = body_ch, + 3 = hands_ch, + 4 = feet_ch + ) + + var/target_zone = pick(zone_weights) + + if(ishuman(src)) + var/mob/living/carbon/human/H = src + + switch(target_zone) + if(1) + if(isobj(H.head) && !istype(H.head, /obj/item/paper)) + Cl = H.head + passed = prob((Cl.permeability_coefficient*100) - 1) + if(passed && isobj(H.wear_mask)) + Cl = H.wear_mask + passed = prob((Cl.permeability_coefficient*100) - 1) + if(2) + if(isobj(H.wear_suit)) + Cl = H.wear_suit + passed = prob((Cl.permeability_coefficient*100) - 1) + if(passed && isobj(H.w_uniform)) + Cl = H.w_uniform + passed = prob((Cl.permeability_coefficient*100) - 1) + if(3) + if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered & HANDS) + Cl = H.wear_suit + passed = prob((Cl.permeability_coefficient*100) - 1) + + if(passed && isobj(H.gloves)) + Cl = H.gloves + passed = prob((Cl.permeability_coefficient*100) - 1) + if(4) + if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered & FEET) + Cl = H.wear_suit + passed = prob((Cl.permeability_coefficient*100) - 1) + + if(passed && isobj(H.shoes)) + Cl = H.shoes + passed = prob((Cl.permeability_coefficient*100) - 1) + if(!passed && (D.spread_flags & AIRBORNE) && !internal) + passed = (prob((50*D.permeability_mod) -1)) + + if(passed) + AddDisease(D) + return passed + +/mob/proc/ForceContractDisease(datum/disease/D, respect_carrier) + if(!CanContractDisease(D)) + return FALSE + + AddDisease(D, respect_carrier) + return TRUE + +/mob/living/carbon/human/CanContractDisease(datum/disease/D) + if(species.virus_immune && !D.bypasses_immunity) + return FALSE + + for(var/organ in D.required_organs) + if(locate(organ) in internal_organs) + continue + if(locate(organ) in organs) + continue + return FALSE + return ..() + +/mob/living/carbon/human/monkey/CanContractDisease(datum/disease/D) + . = ..() + if(. == -1) + if(D.viable_mobtypes.Find(/mob/living/carbon/human)) + return 1 + +/mob/living/proc/handle_diseases() + return + +/mob/proc/GetViruses() + LAZYINITLIST(viruses) + return viruses + +/mob/proc/GetResistances() + LAZYINITLIST(resistances) + return resistances + +/client/proc/ReleaseVirus() + set category = "Fun.Event Kit" + set name = "Release Virus" + set desc = "Release a pre-set virus." + + if(!is_admin()) + return FALSE + + var/datum/disease/D = tgui_input_list(usr, "Choose virus", "Viruses", subtypesof(/datum/disease), subtypesof(/datum/disease)) + var/mob/living/carbon/human/H = null + + if(isnull(D)) + return FALSE + + for(var/thing in shuffle(human_mob_list)) + H = thing + if(H.stat == DEAD) + continue + if(!H.HasDisease(D)) + H.ForceContractDisease(D) + break + + message_admins("[key_name_admin(usr)] has triggered a virus outbreak of [D.name]! Affected mob: [key_name_admin(H)]") + log_admin("[key_name_admin(usr)] infected [key_name_admin(H)] with [D.name]") diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm new file mode 100644 index 00000000000..6ae5cdbb9e0 --- /dev/null +++ b/code/datums/diseases/_disease.dm @@ -0,0 +1,167 @@ +GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease)) + +/datum/disease + //Flags + var/visibility_flags = 0 + var/disease_flags = CURABLE|CAN_CARRY|CAN_RESIST + var/spread_flags = AIRBORNE + + //Fluff + /// Used for identification of viruses in the Medical Records Virus Database + var/medical_name + var/form = "Virus" + var/name = "No disease" + var/desc = "" + var/agent = "some microbes" + var/spread_text = "" + var/cure_text = "" + + //Stages + var/stage = 1 + var/max_stages = 0 + var/stage_prob = 4 + /// The fraction of stages the virus must at least be at to show up on medical HUDs. Rounded up. + var/discovery_threshold = 0.5 + /// If TRUE, this virus will show up on medical HUDs. Automatically set when it reaches mid-stage. + var/discovered = FALSE + + // Other + var/list/viable_mobtypes = list() + var/mob/living/carbon/affected_mob + var/list/cures = list() + var/infectivity = 65 + var/cure_chance = 8 + var/carrier = FALSE + var/bypasses_immunity = FALSE + var/virus_heal_resistant = FALSE + var/permeability_mod = 1 + var/severity = NONTHREAT + var/list/required_organs = list() + var/needs_all_cures = TRUE + var/list/strain_data = list() + var/allow_dead = FALSE + var/infect_synthetics = FALSE + var/processing = FALSE + +/datum/disease/Destroy() + affected_mob = null + active_diseases.Remove(src) + if(processing) + End() + return ..() + +/datum/disease/proc/stage_act() + if(!affected_mob) + return FALSE + var/cure = has_cure() + + if(carrier && !cure) + return FALSE + + if(!processing) + processing = TRUE + Start() + + stage = min(stage, max_stages) + + handle_stage_advance(cure) + + return handle_cure_testing(cure) + +/datum/disease/proc/handle_stage_advance(has_cure = FALSE) + if(!has_cure && prob(stage_prob)) + stage = min(stage + 1, max_stages) + if(!discovered && stage >= CEILING(max_stages * discovery_threshold, 1)) + discovered = TRUE + BITSET(affected_mob.hud_updateflag, STATUS_HUD) + +/datum/disease/proc/handle_cure_testing(has_cure = FALSE) + if(has_cure && prob(cure_chance)) + stage = max(stage -1, 1) + + if(disease_flags & CURABLE) + if(has_cure && prob(cure_chance)) + cure() + return FALSE + return TRUE + +/datum/disease/proc/has_cure() + if(!(disease_flags & CURABLE)) + return 0 + + var/cures_found = 0 + for(var/C_id in cures) + if(affected_mob.reagents.has_reagent(C_id)) + cures_found++ + + if(needs_all_cures && cures_found < length(cures)) + return FALSE + + return cures_found + +/datum/disease/proc/spread(force_spread = 0) + if(!affected_mob) + return + + if((spread_flags & SPECIAL || spread_flags & NON_CONTAGIOUS || spread_flags & BLOOD) && !force_spread) + return + + if(affected_mob.reagents.has_reagent("spaceacilin") || (affected_mob.nutrition > 300 && prob(affected_mob.nutrition/10))) + return + + var/spread_range = 1 + + if(force_spread) + spread_range = force_spread + + if(spread_flags & AIRBORNE) + spread_range++ + + var/turf/target = affected_mob.loc + if(istype(target)) + for(var/mob/living/carbon/C in oview(spread_range, affected_mob)) + var/turf/current = get_turf(C) + if(current) + while(TRUE) + if(current == target) + C.ContractDisease(src) + break + var/direction = get_dir(current, target) + var/turf/next = get_step(current, direction) + current = next + +/datum/disease/proc/cure() + if(affected_mob) + if(disease_flags & CAN_RESIST) + if(!(type in affected_mob.GetResistances())) + affected_mob.resistances += type + remove_virus() + qdel(src) + +/datum/disease/proc/IsSame(datum/disease/D) + if(ispath(D)) + return istype(src, D) + return istype(src, D.type) + +/datum/disease/proc/Copy() + var/datum/disease/D = new type() + D.strain_data = strain_data.Copy() + return D + +/datum/disease/proc/GetDiseaseID() + return type + +/datum/disease/proc/IsSpreadByTouch() + if(spread_flags & CONTACT_FEET || spread_flags & CONTACT_HANDS || spread_flags & CONTACT_GENERAL) + return 1 + return 0 + +/datum/disease/proc/remove_virus() + affected_mob.viruses -= src + BITSET(affected_mob.hud_updateflag, STATUS_HUD) + +/datum/disease/proc/Start() + return + +/datum/disease/proc/End() + return diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm new file mode 100644 index 00000000000..73ef6649988 --- /dev/null +++ b/code/datums/diseases/advance/advance.dm @@ -0,0 +1,404 @@ +GLOBAL_LIST_EMPTY(archive_diseases) + +GLOBAL_LIST_INIT(advance_cures, list( + "sodiumchloride", "sugar", "orangejuice", + "spaceacilin", "glucose", "ethanol", + "dyloteane", "impedrezene", "hepanephrodaxon", + "gold", "silver" +)) + +/datum/disease/advance + name = "Unknown" + desc = "An engineered disease which can contain a multitude of symptoms." + form = "Advance Disease" + agent = "advance microbes" + max_stages = 5 + spread_text = "Unknown" + viable_mobtypes = list(/mob/living/carbon/human) + + var/list/symptoms = list() + var/id = "" + +/datum/disease/advance/New(process = 1, datum/disease/advance/D) + if(!istype(D)) + D = null + + if(!symptoms || !length(symptoms)) + + if(!D || !D.symptoms || !length(D.symptoms)) + symptoms = GenerateSymptoms(0, 2) + else + for(var/datum/symptom/S in D.symptoms) + symptoms += new S.type + + Refresh() + ..(process, D) + return + +/datum/disease/advance/Destroy() + if(processing) + for(var/datum/symptom/S in symptoms) + S.End(src) + return ..() + +/datum/disease/advance/stage_act() + if(!..()) + return FALSE + if(symptoms && length(symptoms)) + + if(!processing) + processing = TRUE + for(var/datum/symptom/S in symptoms) + S.Start(src) + + for(var/datum/symptom/S in symptoms) + S.Activate(src) + else + CRASH("We do not have any symptoms during stage_act()!") + return TRUE + +/datum/disease/advance/IsSame(datum/disease/advance/D) + if(ispath(D)) + return FALSE + + if(!istype(D, /datum/disease/advance)) + return FALSE + + if(GetDiseaseID() != D.GetDiseaseID()) + return FALSE + + return TRUE + +/datum/disease/advance/cure(resistance=1) + if(affected_mob) + var/id = "[GetDiseaseID()]" + if(resistance && !(id in affected_mob.GetResistances())) + affected_mob.GetResistances()[id] = id + remove_virus() + qdel(src) + +/datum/disease/advance/Copy(process = 0) + return new /datum/disease/advance(process, src, 1) + +/datum/disease/advance/proc/Mix(datum/disease/advance/D) + if(!(IsSame(D))) + var/list/possible_symptoms = shuffle(D.symptoms) + for(var/datum/symptom/S in possible_symptoms) + AddSymptom(new S.type) + +/datum/disease/advance/proc/HasSymptom(datum/symptom/S) + for(var/datum/symptom/symp in symptoms) + if(symp.id == S.id) + return 1 + return 0 + +/datum/disease/advance/proc/GenerateSymptomsBySeverity(sev_min, sev_max, amount = 1) + + var/list/generated = list() + + var/list/possible_symptoms = list() + for(var/symp in GLOB.list_symptoms) + var/datum/symptom/S = new symp + if(S.severity >= sev_min && S.severity <= sev_max) + if(!HasSymptom(S)) + possible_symptoms += S + + if(!length(possible_symptoms)) + return generated + + for(var/i = 1 to amount) + generated += pick_n_take(possible_symptoms) + + return generated + +/datum/disease/advance/proc/GenerateSymptoms(level_min, level_max, amount_get = 0) + + var/list/generated = list() + + // Generate symptoms. By default, we only choose non-deadly symptoms. + var/list/possible_symptoms = list() + for(var/symp in GLOB.list_symptoms) + var/datum/symptom/S = new symp + if(S.level >= level_min && S.level <= level_max) + if(!HasSymptom(S)) + possible_symptoms += S + + if(!length(possible_symptoms)) + return generated + + // Random chance to get more than one symptom + var/number_of = amount_get + if(!amount_get) + number_of = 1 + while(prob(20)) + number_of += 1 + + for(var/i = 1; number_of >= i && length(possible_symptoms); i++) + generated += pick_n_take(possible_symptoms) + + return generated + +/datum/disease/advance/proc/Refresh(new_name = FALSE, archive = FALSE) + var/list/properties = GenerateProperties() + AssignProperties(properties) + id = null + + if(!GLOB.archive_diseases[GetDiseaseID()]) + if(new_name) + AssignName() + GLOB.archive_diseases[GetDiseaseID()] = src // So we don't infinite loop + GLOB.archive_diseases[GetDiseaseID()] = new /datum/disease/advance(0, src, 1) + + var/datum/disease/advance/A = GLOB.archive_diseases[GetDiseaseID()] + AssignName(A.name) + +/datum/disease/advance/proc/GenerateProperties() + + if(!symptoms || !length(symptoms)) + CRASH("We did not have any symptoms before generating properties.") + + var/list/properties = list("resistance" = 1, "stealth" = 0, "stage rate" = 1, "transmittable" = 1, "severity" = 0) + + for(var/datum/symptom/S in symptoms) + + properties["resistance"] += S.resistance + properties["stealth"] += S.stealth + properties["stage rate"] += S.stage_speed + properties["transmittable"] += S.transmittable + properties["severity"] = max(properties["severity"], S.severity) // severity is based on the highest severity symptom + + return properties + +/datum/disease/advance/proc/AssignProperties(list/properties = list()) + + if(properties && length(properties)) + switch(properties["stealth"]) + if(2) + visibility_flags = HIDDEN_SCANNER + if(3 to INFINITY) + visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC + + // The more symptoms we have, the less transmittable it is but some symptoms can make up for it. + SetSpread(clamp(2 ** (properties["transmittable"] - length(symptoms)), BLOOD, AIRBORNE)) + permeability_mod = max(CEILING(0.4 * properties["transmittable"], 1), 1) + cure_chance = 15 - clamp(properties["resistance"], -5, 5) // can be between 10 and 20 + stage_prob = max(properties["stage rate"], 2) + SetSeverity(properties["severity"]) + GenerateCure(properties) + else + CRASH("Our properties were empty or null!") + +/datum/disease/advance/proc/SetSpread(spread_id) + switch(spread_id) + if(NON_CONTAGIOUS, SPECIAL) + spread_text = "Non-contagious" + if(CONTACT_GENERAL, CONTACT_HANDS, CONTACT_FEET) + spread_text = "On contact" + if(AIRBORNE) + spread_text = "Airborne" + if(BLOOD) + spread_text = "Blood" + + spread_flags = spread_id + +/datum/disease/advance/proc/SetSeverity(level_sev) + + switch(level_sev) + + if(-INFINITY to 0) + severity = NONTHREAT + if(1) + severity = MINOR + if(2) + severity = MEDIUM + if(3) + severity = HARMFUL + if(4) + severity = DANGEROUS + if(5 to INFINITY) + severity = BIOHAZARD + else + severity = "Unknown" + +/datum/disease/advance/proc/GenerateCure(list/properties = list()) + if(properties && length(properties)) + var/res = clamp(properties["resistance"] - (length(symptoms) / 2), 1, length(GLOB.advance_cures)) + cures = list(GLOB.advance_cures[res]) + cure_text = cures[1] + return + +// Randomly generate a symptom, has a chance to lose or gain a symptom. +/datum/disease/advance/proc/Evolve(min_level, max_level) + var/s = safepick(GenerateSymptoms(min_level, max_level, 1)) + if(s) + AddSymptom(s) + Refresh(1) + return + +// Randomly remove a symptom. +/datum/disease/advance/proc/Devolve() + if(length(symptoms) > 1) + var/s = safepick(symptoms) + if(s) + RemoveSymptom(s) + Refresh(1) + return + +// Name the disease. +/datum/disease/advance/proc/AssignName(name = "Unknown") + src.name = name + return + +// Return a unique ID of the disease. +/datum/disease/advance/GetDiseaseID() + if(!id) + var/list/L = list() + for(var/datum/symptom/S in symptoms) + L += S.id + L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in. + var/result = jointext(L, ":") + id = result + return id + +// Add a symptom, if it is over the limit (with a small chance to be able to go over) +// we take a random symptom away and add the new one. +/datum/disease/advance/proc/AddSymptom(datum/symptom/S) + + if(HasSymptom(S)) + return + + if(length(symptoms) < (VIRUS_SYMPTOM_LIMIT - 1) + rand(-1, 1)) + symptoms += S + else + RemoveSymptom(pick(symptoms)) + symptoms += S + return + +// Simply removes the symptom. +/datum/disease/advance/proc/RemoveSymptom(datum/symptom/S) + symptoms -= S + return + +// Mix a list of advance diseases and return the mixed result. +/proc/Advance_Mix(list/D_list) + + var/list/diseases = list() + + for(var/datum/disease/advance/A in D_list) + diseases += A.Copy() + + if(!length(diseases)) + return null + if(length(diseases) <= 1) + return pick(diseases) // Just return the only entry. + + var/i = 0 + // Mix our diseases until we are left with only one result. + while(i < 20 && length(diseases) > 1) + + i++ + + var/datum/disease/advance/D1 = pick(diseases) + diseases -= D1 + + var/datum/disease/advance/D2 = pick(diseases) + D2.Mix(D1) + + // 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.Refresh(1) + return to_return + +/proc/SetViruses(datum/reagent/R, list/data) + if(data) + var/list/preserve = list() + if(istype(data) && data["viruses"]) + for(var/datum/disease/A in data["viruses"]) + preserve += A.Copy() + R.data = data.Copy() + if(length(preserve)) + R.data["viruses"] = preserve + +/client/proc/AdminCreateVirus() + set category = "Fun.Event Kit" + set name = "Create Advanced Virus" + set desc = "Create an advanced virus and release it." + + if(!is_admin()) + return FALSE + + var/i = VIRUS_SYMPTOM_LIMIT + var/mob/living/carbon/human/H = null + + var/datum/disease/advance/D = new(0, null) + D.symptoms = list() + + var/list/symptoms = list() + symptoms += "Done" + symptoms += GLOB.list_symptoms.Copy() + do + if(usr) + var/symptom = tgui_input_list(usr, "Choose a symptom to add ([i] remaining)", "Choose a Symptom", symptoms) + if(isnull(symptom)) + return + else if(istext(symptom)) + i = 0 + else if(ispath(symptom)) + var/datum/symptom/S = new symptom + if(!D.HasSymptom(S)) + D.symptoms += S + i -= 1 + while(i > 0) + + if(length(D.symptoms) > 0) + + var/new_name = tgui_input_text(usr, "Name your new disease.", "New Name") + if(!new_name) + return + D.AssignName(new_name) + D.Refresh() + + for(var/datum/disease/advance/AD in active_diseases) + AD.Refresh() + + for(var/thing in shuffle(human_mob_list)) + H = thing + if(H.stat == DEAD) + continue + if(!H.HasDisease(D)) + H.ForceContractDisease(D) + break + + var/list/name_symptoms = list() + for(var/datum/symptom/S in D.symptoms) + name_symptoms += S.name + message_admins("[key_name_admin(usr)] has triggered a custom virus outbreak of [D.name]! It has these symptoms: [english_list(name_symptoms)]") + log_admin("[key_name_admin(usr)] infected [key_name_admin(H)] with [D.name]. It has these symptoms: [english_list(name_symptoms)]") + +/datum/disease/advance/proc/totalStageSpeed() + var/total_stage_speed = 0 + for(var/i in symptoms) + var/datum/symptom/S = i + total_stage_speed += S.stage_speed + return total_stage_speed + +/datum/disease/advance/proc/totalStealth() + var/total_stealth = 0 + for(var/i in symptoms) + var/datum/symptom/S = i + total_stealth += S.stealth + return total_stealth + +/datum/disease/advance/proc/totalResistance() + var/total_resistance = 0 + for(var/i in symptoms) + var/datum/symptom/S = i + total_resistance += S.resistance + return total_resistance + +/datum/disease/advance/proc/totalTransmittable() + var/total_transmittable = 0 + for(var/i in symptoms) + var/datum/symptom/S = i + total_transmittable += S.transmittable + return total_transmittable diff --git a/code/datums/diseases/advance/disease_preset.dm b/code/datums/diseases/advance/disease_preset.dm new file mode 100644 index 00000000000..d30bbf2ebb5 --- /dev/null +++ b/code/datums/diseases/advance/disease_preset.dm @@ -0,0 +1,16 @@ +// Cold + +/datum/disease/advance/cold/New(process = 1, datum/disease/advance/D, copy = 0) + if(!D) + name = "Cold" + symptoms = list(new /datum/symptom/sneeze) + ..(process, D, copy) + + +// Flu + +/datum/disease/advance/flu/New(process = 1, datum/disease/advance/D, copy = 0) + if(!D) + name = "Flu" + symptoms = list(new /datum/symptom/cough) + ..(process, D, copy) diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm new file mode 100644 index 00000000000..24be1c1a153 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/choking.dm @@ -0,0 +1,52 @@ +/* +////////////////////////////////////// + +Choking + + Very very noticable. + Lowers resistance. + Decreases stage speed. + Decreases transmittablity tremendously. + Moderate Level. + +Bonus + Inflicts spikes of oxyloss + +////////////////////////////////////// +*/ + +/datum/symptom/choking + name = "Choking" + stealth = -3 + resistance = -2 + stage_speed = -2 + transmittable = -4 + level = 3 + severity = 3 + +/datum/symptom/choking/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2) + to_chat(M, span_warning(pick("You're having difficulty breathing.", "Your breathing becomes heavy."))) + if(3, 4) + to_chat(M, span_boldwarning(pick("Your windpipe feels like a straw.", "Your breathing becomes tremendously difficult."))) + Choke_stage_3_4(M, A) + M.emote("gasp") + else + to_chat(M, span_userdanger(pick("You're choking!", "You can't breathe!"))) + Choke(M, A) + M.emote("gasp") + return + +/datum/symptom/choking/proc/Choke_stage_3_4(mob/living/M, datum/disease/advance/A) + var/get_damage = sqrtor0(21+A.totalStageSpeed()*0.5)+sqrtor0(16+A.totalStealth()) + M.adjustOxyLoss(get_damage) + return 1 + +/datum/symptom/choking/proc/Choke(mob/living/M, datum/disease/advance/A) + var/get_damage = sqrtor0(21+A.totalStageSpeed()*0.5)+sqrtor0(16+A.totalStealth()*5) + M.adjustOxyLoss(get_damage) + return 1 diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm new file mode 100644 index 00000000000..039d9ad8db6 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/confusion.dm @@ -0,0 +1,40 @@ +/* +////////////////////////////////////// + +Confusion + + Little bit hidden. + Lowers resistance. + Decreases stage speed. + Not very transmittable. + Intense Level. + +Bonus + Makes the affected mob be confused for short periods of time. + +////////////////////////////////////// +*/ + +/datum/symptom/confusion + + name = "Confusion" + stealth = 1 + resistance = -1 + stage_speed = -3 + transmittable = 0 + level = 4 + severity = 2 + + +/datum/symptom/confusion/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) + to_chat(M, span_warning(pick("Your head hurts.", "Your mind blanks for a moment."))) + else + to_chat(M, span_userdanger("You can't think straight!")) + M.AdjustConfused(rand(16, 200)) + + return diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm new file mode 100644 index 00000000000..bdf04a9fdf4 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/cough.dm @@ -0,0 +1,39 @@ +/* +////////////////////////////////////// + +Coughing + + Noticable. + Little Resistance. + Doesn't increase stage speed much. + Transmittable. + Low Level. + +BONUS + Will force the affected mob to drop small items! + +////////////////////////////////////// +*/ + +/datum/symptom/cough + name = "Cough" + stealth = -1 + resistance = 3 + stage_speed = 1 + transmittable = 2 + level = 1 + severity = 1 + +/datum/symptom/cough/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3) + to_chat(M, span_warning(pick("You swallow excess mucus", "You lightly cough."))) + else + M.emote("cough") + var/obj/item/I = M.get_active_hand() + if(I && I.w_class == ITEMSIZE_SMALL) + M.drop_item() + return diff --git a/code/datums/diseases/advance/symptoms/damage_converter.dm b/code/datums/diseases/advance/symptoms/damage_converter.dm new file mode 100644 index 00000000000..f2a299469b1 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/damage_converter.dm @@ -0,0 +1,59 @@ +/* +////////////////////////////////////// + +Damage Converter + + Little bit hidden. + Lowers resistance tremendously. + Decreases stage speed tremendously. + Reduced transmittablity + Intense Level. + +Bonus + Slowly converts brute/fire damage to toxin. + +////////////////////////////////////// +*/ + +/datum/symptom/damage_converter + name = "Toxic Compensation" + stealth = 1 + resistance = -4 + stage_speed = -4 + transmittable = -2 + level = 4 + +/datum/symptom/damage_converter/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB * 10)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(4, 5) + Convert(M) + return + +/datum/symptom/damage_converter/proc/Convert(mob/living/M) + + var/get_damage = rand(1, 2) + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + + var/list/parts = H.get_damaged_organs(TRUE, TRUE) + + if(!length(parts)) + return + var/healed = 0 + for(var/obj/item/organ/external/E in parts) + healed += min(E.brute_dam, get_damage) + min(E.burn_dam, get_damage) + E.heal_damage(get_damage, get_damage, 0, 0) + M.adjustToxLoss(healed) + + else + if(M.getFireLoss() > 0 || M.getBruteLoss() > 0) + M.adjustFireLoss(-get_damage) + M.adjustBruteLoss(-get_damage) + M.adjustToxLoss(get_damage) + else + return + return TRUE diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm new file mode 100644 index 00000000000..fdedcba79c0 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/dizzy.dm @@ -0,0 +1,38 @@ +/* +////////////////////////////////////// + +Dizziness + + Hidden. + Lowers resistance considerably. + Decreases stage speed. + Reduced transmittability + Intense Level. + +Bonus + Shakes the affected mob's screen for short periods. + +////////////////////////////////////// +*/ + +/// Not the egg +/datum/symptom/dizzy + name = "Dizziness" + stealth = 2 + resistance = -2 + stage_speed = -3 + transmittable = -1 + level = 4 + severity = 2 + +/datum/symptom/dizzy/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) + to_chat(M, span_warning(pick("You feel dizzy.", "Your head spins."))) + else + to_chat(M, span_userdanger("A wave of dizziness washes over you!")) + M.make_dizzy(10) + return diff --git a/code/datums/diseases/advance/symptoms/fever.dm b/code/datums/diseases/advance/symptoms/fever.dm new file mode 100644 index 00000000000..a9e027da9cd --- /dev/null +++ b/code/datums/diseases/advance/symptoms/fever.dm @@ -0,0 +1,40 @@ +/* +////////////////////////////////////// + +Fever + + No change to hidden. + Increases resistance. + Increases stage speed. + Little transmittable. + Low level. + +Bonus + Heats up your body. + +////////////////////////////////////// +*/ + +/datum/symptom/fever + name = "Fever" + stealth = 0 + resistance = 3 + stage_speed = 3 + transmittable = 2 + level = 2 + severity = 2 + +/datum/symptom/fever/Activate(var/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 hot.", "You feel like you're burning."))) + if(M.bodytemperature < BODYTEMP_HEAT_DAMAGE_LIMIT) + Heat(M, A) + + return + +/datum/symptom/fever/proc/Heat(var/mob/living/M, var/datum/disease/advance/A) + var/get_heat = (sqrt(21+A.totalTransmittable()*2))+(sqrt(20+A.totalStageSpeed()*3)) + M.bodytemperature = min(M.bodytemperature + (get_heat * A.stage), BODYTEMP_HEAT_DAMAGE_LIMIT - 1) + return TRUE diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm new file mode 100644 index 00000000000..956d778f5d5 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/fire.dm @@ -0,0 +1,56 @@ +/* +////////////////////////////////////// + +Spontaneous Combustion + + Slightly hidden. + Lowers resistance tremendously. + Decreases stage tremendously. + Decreases transmittablity tremendously. + Fatal Level. + +Bonus + Ignites infected mob. + +////////////////////////////////////// +*/ + +/datum/symptom/fire + name = "Spontaneous Combustion" + stealth = 1 + resistance = -4 + stage_speed = -4 + transmittable = -4 + level = 6 + severity = 5 + +/datum/symptom/fire/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(3) + to_chat(M, span_warning(pick("You feel hot.", "You hear a crackling noise.", "You smell smoke."))) + if(4) + Firestacks_stage_4(M, A) + M.IgniteMob() + to_chat(M, span_userdanger("Your skin bursts into flames!")) + M.emote("scream") + if(5) + Firestacks_stage_5(M, A) + M.IgniteMob() + to_chat(M, span_userdanger("Your skin erupts into an inferno!")) + M.emote("scream") + return + +/datum/symptom/fire/proc/Firestacks_stage_4(mob/living/M, datum/disease/advance/A) + var/get_stacks = max((sqrtor0(20 + A.totalStageSpeed() * 2)) - (sqrtor0(16 + A.totalStealth())), 1) + M.adjust_fire_stacks(get_stacks) + M.adjustFireLoss(get_stacks * 0.5) + return 1 + +/datum/symptom/fire/proc/Firestacks_stage_5(mob/living/M, datum/disease/advance/A) + var/get_stacks = max((sqrtor0(20 + A.totalStageSpeed() * 3))-(sqrtor0(16 + A.totalStealth())), 1) + M.adjust_fire_stacks(get_stacks) + M.adjustFireLoss(get_stacks) + return 1 diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm new file mode 100644 index 00000000000..28c9002c3a1 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm @@ -0,0 +1,42 @@ +/* +////////////////////////////////////// + +Necrotizing Fasciitis (AKA Flesh-Eating Disease) + + Very very noticable. + Lowers resistance tremendously. + No changes to stage speed. + Decreases transmittablity temrendously. + Fatal Level. + +Bonus + Deals brute damage over time. + +////////////////////////////////////// +*/ + +/datum/symptom/flesh_eating + name = "Necrotizing Fasciitis" + stealth = -3 + resistance = -4 + stage_speed = 0 + transmittable = -4 + level = 6 + severity = 5 + +/datum/symptom/flesh_eating/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(2,3) + to_chat(M, span_warning(pick("You feel a sudden pain across your body.", "Drops of blood appear suddenly on your skin."))) + if(4,5) + to_chat(M, span_userdanger(pick("You cringe as a violent pain takes over your body.", "It feels like your body is eating itself inside out.", "IT HURTS."))) + Flesheat(M, A) + return + +/datum/symptom/flesh_eating/proc/Flesheat(mob/living/M, datum/disease/advance/A) + var/get_damage = ((sqrt(16-A.totalStealth()))*5) + M.adjustBruteLoss(get_damage) + return 1 diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm new file mode 100644 index 00000000000..4bd1e44401d --- /dev/null +++ b/code/datums/diseases/advance/symptoms/hallucigen.dm @@ -0,0 +1,40 @@ +/* +////////////////////////////////////// + +Hallucigen + + Very noticable. + Lowers resistance considerably. + Decreases stage speed. + Reduced transmittable. + Critical Level. + +Bonus + Makes the affected mob be hallucinated for short periods of time. + +////////////////////////////////////// +*/ + +/datum/symptom/hallucigen + name = "Hallucigen" + stealth = -2 + resistance = -3 + stage_speed = -3 + transmittable = -1 + level = 5 + severity = 3 + +/datum/symptom/hallucigen/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(1, 2) + to_chat(M, span_warning(pick("Something appears in your peripheral vision, then winks out.", "You hear a faint whisper with no source.", "Your head aches."))) + if(3, 4) + to_chat(M, span_boldwarning(pick("Something is following you.", "You are being watched.", "You hear a whisper in your ear.", "Thumping footsteps slam toward you from nowhere."))) + else + to_chat(M, span_userdanger(pick("Oh, your head...", "Your head pounds.", "They're everywhere! Run!", "Something in the shadows..."))) + M.hallucination = rand(5, 10) + + return diff --git a/code/datums/diseases/advance/symptoms/headache.dm b/code/datums/diseases/advance/symptoms/headache.dm new file mode 100644 index 00000000000..431ed9b6703 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/headache.dm @@ -0,0 +1,33 @@ +/* +////////////////////////////////////// + +Headache + + Noticable. + Highly resistant. + Increases stage speed. + Not transmittable. + Low Level. + +BONUS + Displays an annoying message! + Should be used for buffing your disease. + +////////////////////////////////////// +*/ + +/datum/symptom/headache + name = "Headache" + stealth = -1 + resistance = 4 + stage_speed = 2 + transmittable = 0 + level = 1 + severity = 1 + +/datum/symptom/headache/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + to_chat(M, span_warning(pick("Your head hurts.", "Your head starts pounding."))) + return diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm new file mode 100644 index 00000000000..1c219598722 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -0,0 +1,150 @@ +/* +////////////////////////////////////// + +Healing + + Little bit hidden. + Lowers resistance tremendously. + Decreases stage speed tremendously. + Decreases transmittablity temrendously. + Fatal Level. + +Bonus + Heals toxins in the affected mob's blood stream. + +////////////////////////////////////// +*/ + +/datum/symptom/heal + name = "Toxic Filter" + stealth = 1 + resistance = -4 + stage_speed = -4 + transmittable = -4 + level = 6 + +/datum/symptom/heal/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB * 10)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(4, 5) + Heal(M, A) + return + +/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A) + var/get_damage = (sqrt(20+A.totalStageSpeed())*(1+rand())) + M.adjustToxLoss(-get_damage) + return TRUE + +/* +////////////////////////////////////// + +Metabolism + + Little bit hidden. + Lowers resistance. + Decreases stage speed. + Decreases transmittablity temrendously. + High Level. + +Bonus + Cures all diseases (except itself) and creates anti-bodies for them until the symptom dies. + +////////////////////////////////////// +*/ + +/datum/symptom/heal/metabolism + name = "Anti-Bodies Metabolism" + stealth = -1 + resistance = -1 + stage_speed = -1 + transmittable = -4 + level = 3 + var/list/cured_diseases = list() + +/datum/symptom/heal/metabolism/Heal(mob/living/M, datum/disease/advance/A) + var/cured = 0 + for(var/thing in M.GetViruses()) + var/datum/disease/D = thing + if(D.virus_heal_resistant) + continue + if(D != A) + cured = TRUE + cured_diseases += D.GetDiseaseID() + D.cure() + if(cured) + to_chat(M, span_notice("You feel much better.")) + +/datum/symptom/heal/metabolism/End(datum/disease/advance/A) + var/mob/living/M = A.affected_mob + if(istype(M)) + if(length(cured_diseases)) + for(var/res in M.GetResistances()) + M.resistances -= res + to_chat(M, span_warning("You feel weaker.")) + +/* +////////////////////////////////////// + +Longevity + + Medium hidden boost. + Large resistance boost. + Large stage speed boost. + Large transmittablity boost. + High Level. + +Bonus + After a certain amount of time the symptom will cure itself. + +////////////////////////////////////// +*/ + +/datum/symptom/heal/longevity + name = "Longevity" + stealth = 3 + resistance = 4 + stage_speed = 4 + transmittable = 4 + level = 3 + var/longevity = 30 + +/datum/symptom/heal/longevity/Heal(mob/living/M, datum/disease/advance/A) + longevity -= 1 + if(!longevity) + A.cure() + +/datum/symptom/heal/longevity/Start(datum/disease/advance/A) + longevity = rand(initial(longevity) - 5, initial(longevity) + 5) + +/* +////////////////////////////////////// + + DNA Restoration + + Not well hidden. + Lowers resistance minorly. + Does not affect stage speed. + Decreases transmittablity greatly. + Very high level. + +Bonus + Heals brain damage, treats radiation. + +////////////////////////////////////// +*/ + +/datum/symptom/heal/dna + name = "Deoxyribonucleic Acid Restoration" + stealth = -1 + resistance = -1 + stage_speed = 0 + transmittable = -3 + level = 5 + +/datum/symptom/heal/dna/Heal(var/mob/living/carbon/M, var/datum/disease/advance/A) + var/amt_healed = (sqrt(20+A.totalStageSpeed()*(3+rand())))-(sqrt(16+A.totalStealth()*rand())) + M.adjustBrainLoss(-amt_healed) + M.radiation = max(M.radiation - 3, 0) + return TRUE diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm new file mode 100644 index 00000000000..fdf2f5f5e4f --- /dev/null +++ b/code/datums/diseases/advance/symptoms/itching.dm @@ -0,0 +1,33 @@ +/* +////////////////////////////////////// + +Itching + + Not noticable or unnoticable. + Resistant. + Increases stage speed. + Little transmittable. + Low Level. + +BONUS + Displays an annoying message! + Should be used for buffing your disease. + +////////////////////////////////////// +*/ + +/datum/symptom/itching + name = "Itching" + stealth = 0 + resistance = 3 + stage_speed = 3 + transmittable = 1 + level = 1 + severity = 1 + +/datum/symptom/itching/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + to_chat(M, span_warning("Your [pick("back", "arm", "leg", "elbow", "head")] itches.")) + return diff --git a/code/datums/diseases/advance/symptoms/language.dm b/code/datums/diseases/advance/symptoms/language.dm new file mode 100644 index 00000000000..3ffa7c06bb6 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/language.dm @@ -0,0 +1,31 @@ +/* +////////////////////////////////////// + +Lingual Disocation + + Improves stealth. + Increases resistance. + Decreases stage speed. + Slightly decreases transmissibility. + Moderate Level. + +Bonus + Forces the affected mob to vomit + +////////////////////////////////////// +*/ + +/datum/symptom/language + name = "Lingual Disocation" + stealth = 3 + resistance = 2 + stage_speed = -2 + transmittable = -1 + level = 3 + +/datum/symptom/language/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/carbon/human/H = A.affected_mob + H.apply_default_language(pick(H.languages)) + return diff --git a/code/datums/diseases/advance/symptoms/macrophage.dm b/code/datums/diseases/advance/symptoms/macrophage.dm new file mode 100644 index 00000000000..5769fadaa6c --- /dev/null +++ b/code/datums/diseases/advance/symptoms/macrophage.dm @@ -0,0 +1,73 @@ +/* +////////////////////////////////////// + +Macrophages + + Very noticeable. + Lowers resistance slightly. + Decreases stage speed. + Increases transmittablity + Fatal leve. + +BONUS + The virus grows and ceases to be microscopic. + +////////////////////////////////////// +*/ + +/datum/symptom/macrophage + name = "Macrophage" + stealth = -4 + resistance = -1 + stage_speed = -2 + transmittable = 2 + level = 6 + severity = 2 + + var/gigagerms = FALSE + var/netspeed = 0 + var/phagecounter = 10 + +/datum/symptom/macrophage/Start(datum/disease/advance/A) + netspeed = max(1, A.stage) + if(A.severity >= HARMFUL) + gigagerms = TRUE + +/datum/symptom/macrophage/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3) + to_chat(M, span_notice("Your skin crawls.")) + if(4) + M.visible_message(span_danger("Lumps form on [M]'s skin!"), span_userdanger("You cringe in pain as lumps form and move around on your skin!")) + if(5) + phagecounter -= max(2, A.totalStageSpeed()) + if(gigagerms && phagecounter <= 0) + Burst(A, M, TRUE) + phagecounter += 10 + while(phagecounter <= 0) + phagecounter += 5 + Burst(A, M) + +/datum/symptom/macrophage/proc/Burst(datum/disease/advance/A, var/mob/living/M, var/gigagerms = FALSE) + var/mob/living/simple_mob/vore/aggressive/macrophage/phage + phage = new(M.loc) + M.apply_damage(rand(1, 7)) + phage.viruses = A.Copy() + phage.health += A.totalResistance() + phage.maxHealth += A.totalResistance() + phage.infections += A + phage.base_disease = A + + if(A.spread_flags & CONTACT_GENERAL) + for(var/datum/disease/D in M.GetViruses()) + if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS)) + continue + if(D == A) + continue + phage.viruses += D + + M.visible_message(span_danger("A strange crearure bursts out of [M]!"), span_userdanger("A slimy creature bursts forth from your flesh!")) + addtimer(CALLBACK(phage, TYPE_PROC_REF(/mob/living/simple_mob/vore/aggressive/macrophage, dust)), 3000) diff --git a/code/datums/diseases/advance/symptoms/mlem.dm b/code/datums/diseases/advance/symptoms/mlem.dm new file mode 100644 index 00000000000..fdb8672c276 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/mlem.dm @@ -0,0 +1,33 @@ +/* +////////////////////////////////////// + +Mlemingtong + + Not noticable or unnoticable. + Resistant. + Increases stage speed. + Little transmittable. + Low Level. + +BONUS + Mlem. Mlem. Mlem. + Should be used for buffing your disease. + +////////////////////////////////////// +*/ + +/datum/symptom/mlem + name = "Mlemington" + stealth = 0 + resistance = 3 + stage_speed = 3 + transmittable = 1 + level = 1 + severity = 1 + +/datum/symptom/itching/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + M.emote("mlem") + return diff --git a/code/datums/diseases/advance/symptoms/necrotic_agent.dm b/code/datums/diseases/advance/symptoms/necrotic_agent.dm new file mode 100644 index 00000000000..24a3e9ff065 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/necrotic_agent.dm @@ -0,0 +1,31 @@ +/* +////////////////////////////////////// + +Necrotic Agent + + Very Noticable. + Lowers resistance resistance considerably. + Decreases stage speed. + Reduced transmittable. + Critical Level. + +Bonus + Makes the disease work on corpses + +////////////////////////////////////// +*/ + +/datum/symptom/necrotic_agent + name = "Necrotic Agent" + stealth = -2 + resistance = -3 + stage_speed = -3 + transmittable = 0 + level = 6 + severity = 3 + +/datum/symptom/necrotic_agent/Start(datum/disease/advance/A) + A.allow_dead = TRUE + +/datum/symptom/necrotic_agent/End(datum/disease/advance/A) + A.allow_dead = FALSE diff --git a/code/datums/diseases/advance/symptoms/oxygen.dm b/code/datums/diseases/advance/symptoms/oxygen.dm new file mode 100644 index 00000000000..3f9fbd8eee5 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/oxygen.dm @@ -0,0 +1,37 @@ +/* +////////////////////////////////////// + +Self-Respiration + + Slightly hidden. + Lowers resistance significantly. + Decreases stage speed significantly. + Decreases transmittablity tremendously. + Fatal Level. + +Bonus + The body generates dexalin. + +////////////////////////////////////// +*/ + +/datum/symptom/oxygen + name = "Self-Respiration" + stealth = 1 + resistance = -3 + stage_speed = -3 + transmittable = -4 + level = 6 + +/datum/symptom/oxygen/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB * 5)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(4, 5) + if(M.reagents.get_reagent_amount("dexalin") < 10) + M.reagents.add_reagent("dexalin", 10) + else + if(prob(SYMPTOM_ACTIVATION_PROB * 5)) + to_chat(M, span_notice(pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe."))) + return diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm new file mode 100644 index 00000000000..6f1f3ac9d36 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -0,0 +1,63 @@ +/* +////////////////////////////////////// +Sensory-Restoration + Very very very very noticable. + Lowers resistance tremendously. + Decreases stage speed tremendously. + Decreases transmittablity tremendously. + Fatal. +Bonus + The body generates Sensory restorational chemicals. + imidazoline for eyes + removes alcohol + removes hallucinogens + alkysine to kickstart the mind + +////////////////////////////////////// +*/ +/datum/symptom/mind_restoration + name = "Mind Restoration" + stealth = -3 + resistance = -4 + stage_speed = -4 + transmittable = -3 + level = 5 + severity = 0 + +/datum/symptom/mind_restoration/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB * 3)) + var/mob/living/M = A.affected_mob + + if(A.stage >= 3) + M.slurring = min(0, M.slurring-4) + M.druggy = min(0, M.druggy-4) + M.reagents.remove_reagent("ethanol", 3) + if(A.stage >= 4) + M.drowsyness = min(0, M.drowsyness-4) + if(M.reagents.has_reagent("bliss")) + M.reagents.del_reagent("bliss") + M.hallucination = min(0, M.hallucination-4) + if(A.stage >= 5) + if(M.reagents.get_reagent_amount("alkysine") < 10) + M.reagents.add_reagent("alkysine", 5) + +/datum/symptom/sensory_restoration + name = "Sensory Restoration" + stealth = -1 + resistance = -3 + stage_speed = -2 + transmittable = -4 + level = 4 + +/datum/symptom/sensory_restoration/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB * 5)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(4, 5) + if(M.reagents.get_reagent_amount("imidazoline") < 10) + M.reagents.add_reagent("imidazoline", 5) + else + if(prob(SYMPTOM_ACTIVATION_PROB)) + to_chat(M, span_notice(pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink."))) diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm new file mode 100644 index 00000000000..375850ef40f --- /dev/null +++ b/code/datums/diseases/advance/symptoms/shivering.dm @@ -0,0 +1,39 @@ +/* +////////////////////////////////////// + +Shivering + + No change to hidden. + Increases resistance. + Increases stage speed. + Little transmittable. + Low level. + +Bonus + Cools down your body. + +////////////////////////////////////// +*/ + +/datum/symptom/shivering + name = "Shivering" + stealth = 0 + resistance = 2 + stage_speed = 2 + transmittable = 2 + level = 2 + severity = 2 + +/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) + return + +/datum/symptom/shivering/proc/Chill(mob/living/M, datum/disease/advance/A) + var/get_cold = (sqrt(16+A.totalStealth()*2))+(sqrt(21+A.totalResistance()*2)) + M.bodytemperature = max(M.bodytemperature - (get_cold * A.stage), BODYTEMP_COLD_DAMAGE_LIMIT + 1) + return 1 diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm new file mode 100644 index 00000000000..d60baaa11a2 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/sneeze.dm @@ -0,0 +1,42 @@ +/* +////////////////////////////////////// + +Sneezing + + Very Noticable. + Increases resistance. + Doesn't increase stage speed. + Very transmittable. + Low Level. + +Bonus + Forces a spread type of AIRBORNE + with extra range! + +////////////////////////////////////// +*/ + +/datum/symptom/sneeze + name = "Sneezing" + stealth = -2 + resistance = 3 + stage_speed = 0 + transmittable = 4 + level = 1 + severity = 1 + +/datum/symptom/sneeze/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3) + M.emote("sniff") + else + M.emote("sneeze") + A.spread(5) + if(prob(30)) + var/obj/effect/decal/cleanable/mucus/icky = new(get_turf(M)) + icky.viruses |= A.Copy() + + return diff --git a/code/datums/diseases/advance/symptoms/spin.dm b/code/datums/diseases/advance/symptoms/spin.dm new file mode 100644 index 00000000000..995be34071b --- /dev/null +++ b/code/datums/diseases/advance/symptoms/spin.dm @@ -0,0 +1,40 @@ +/* +////////////////////////////////////// + +Spyndrome + + Slightly hidden. + No change to resistance. + Increases stage speed. + Little transmittable. + Low Level. + +BONUS + Makes the host spin. + Should be used for buffing your disease. + +////////////////////////////////////// +*/ + +/datum/symptom/mlem + name = "Spyndrome" + stealth = 2 + resistance = 0 + stage_speed = 3 + transmittable = 1 + level = 1 + severity = 1 + var/list/directions = list(2,4,1,8,2,4,1,8,2,4,1,8,2,4,1,8,2,4,1,8) + +/datum/symptom/mlem/Activate(var/datum/disease/advance/A) + ..() + + if(prob(SYMPTOM_ACTIVATION_PROB)) + if(A.affected_mob.buckled()) + to_chat(viewers(A.affected_mob), span_warning("[A.affected_mob.name] struggles violently against their restraints!")) + else + to_chat(viewers(A.affected_mob), span_warning("[A.affected_mob.name] spins around violently!")) + for(var/D in directions) + A.affected_mob.dir = D + A.affected_mob.dir = pick(2,4,1,8) + return diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm new file mode 100644 index 00000000000..90b39fab3bd --- /dev/null +++ b/code/datums/diseases/advance/symptoms/symptoms.dm @@ -0,0 +1,36 @@ +// Symptoms are the effects that engineered advanced diseases do. + +GLOBAL_LIST_INIT(list_symptoms, subtypesof(/datum/symptom)) + +/datum/symptom + // Buffs/Debuffs the symptom has to the overall engineered disease. + var/name = "" + var/stealth = 0 + var/resistance = 0 + var/stage_speed = 0 + var/transmittable = 0 + // The type level of the symptom. Higher is harder to generate. + var/level = 0 + // The severity level of the symptom. Higher is more dangerous. + var/severity = 0 + // The hash tag for our diseases, we will add it up with our other symptoms to get a unique id! ID MUST BE UNIQUE!!! + var/id = "" + +/datum/symptom/New() + var/list/S = GLOB.list_symptoms + for(var/i = 1; i <= length(S); i++) + if(type == S[i]) + id = "[i]" + return + CRASH("We couldn't assign an ID!") + +// Called when processing of the advance disease, which holds this symptom, starts. +/datum/symptom/proc/Start(datum/disease/advance/A) + return + +// Called when the advance disease is going to be deleted or when the advance disease stops processing. +/datum/symptom/proc/End(datum/disease/advance/A) + return + +/datum/symptom/proc/Activate(datum/disease/advance/A) + return diff --git a/code/datums/diseases/advance/symptoms/synthetic_infection.dm b/code/datums/diseases/advance/symptoms/synthetic_infection.dm new file mode 100644 index 00000000000..cb17d88c812 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/synthetic_infection.dm @@ -0,0 +1,32 @@ +/* +////////////////////////////////////// + +Sneezing + + Slightly hidden. + Increases resistance. + Doesn't increase stage speed. + Slightly transmittable. + High Level. + +Bonus + Allows the disease to infect synthetics + +////////////////////////////////////// +*/ + +/datum/symptom/infect_synthetics + name = "Synthetic Infection" + stealth = 1 + resistance = 2 + stage_speed = 0 + transmittable = 1 + level = 5 + severity = 3 + id = "synthetic_infection" + +/datum/symptom/infect_synthetics/Start(datum/disease/advance/A) + A.infect_synthetics = TRUE + +/datum/symptom/infect_synthetics/End(datum/disease/advance/A) + A.infect_synthetics = FALSE diff --git a/code/datums/diseases/advance/symptoms/telepathy.dm b/code/datums/diseases/advance/symptoms/telepathy.dm new file mode 100644 index 00000000000..3e02ec94d83 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/telepathy.dm @@ -0,0 +1,36 @@ +/* +////////////////////////////////////// + +Telepathy + + Hidden. + Decreases resistance. + Decreases stage speed significantly. + Decreases transmittablity tremendously. + Critical Level. + +Bonus + The user gains telepathy. + +////////////////////////////////////// +*/ + +/datum/symptom/telepathy + name = "Pineal Gland Decalcification" + stealth = 2 + resistance = -2 + stage_speed = -3 + transmittable = -4 + level = 5 + +/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...")) + +/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.")) diff --git a/code/datums/diseases/advance/symptoms/viral.dm b/code/datums/diseases/advance/symptoms/viral.dm new file mode 100644 index 00000000000..3da1de698ca --- /dev/null +++ b/code/datums/diseases/advance/symptoms/viral.dm @@ -0,0 +1,65 @@ +/* +////////////////////////////////////// +Viral adaptation + + Moderate stealth boost. + Major Increases to resistance. + Reduces stage speed. + No change to transmission + Critical Level. + +BONUS + Extremely useful for buffing viruses + +////////////////////////////////////// +*/ +/datum/symptom/viraladaptation + name = "Viral self-adaptation" + stealth = 3 + resistance = 5 + stage_speed = -3 + transmittable = 0 + level = 3 + +/datum/symptom/viraladaptation/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1) + to_chat(M, span_notice("You feel off, but no different from before.")) + if(5) + to_chat(M, span_notice("You feel better, but nothing interesting happens.")) + +/* +////////////////////////////////////// +Viral evolution + + Moderate stealth reductopn. + Major decreases to resistance. + increases stage speed. + increase to transmission + Critical Level. + +BONUS + Extremely useful for buffing viruses + +////////////////////////////////////// +*/ +/datum/symptom/viralevolution + name = "Viral evolutionary acceleration" + stealth = -2 + resistance = -3 + stage_speed = 5 + transmittable = 3 + level = 3 + +/datum/symptom/viralevolution/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1) + to_chat(M, span_notice("You feel better, but no different from before.")) + if(5) + to_chat(M,span_notice("You feel off, but nothing interesting happens.")) diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm new file mode 100644 index 00000000000..d74b0c6a5dc --- /dev/null +++ b/code/datums/diseases/advance/symptoms/vision.dm @@ -0,0 +1,50 @@ +/* +////////////////////////////////////// + +Hyphema (Eye bleeding) + + Slightly noticable. + Lowers resistance tremendously. + Decreases stage speed tremendously. + Decreases transmittablity. + Critical Level. + +Bonus + Causes blindness. + +////////////////////////////////////// +*/ + +/datum/symptom/visionloss + name = "Hyphema" + stealth = -1 + resistance = -4 + stage_speed = -4 + transmittable = -3 + level = 5 + severity = 4 + +/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) diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm new file mode 100644 index 00000000000..06c2b0fafbf --- /dev/null +++ b/code/datums/diseases/advance/symptoms/vomit.dm @@ -0,0 +1,34 @@ +/* +////////////////////////////////////// + +Vomiting + + Noticeable. + No change to resistance. + Slightly increases stage speed. + Increases transmissibility. + Medium Level. + +Bonus + Forces the affected mob to vomit + +////////////////////////////////////// +*/ + +/datum/symptom/vomit + name = "Vomiting" + stealth = -2 + resistance = 0 + stage_speed = 1 + transmittable = 2 + level = 3 + severity = 1 + +/datum/symptom/vomit/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + if(prob(2)) + to_chat(M, span_warning(pick("you feel nauseated.", "You feel like you're going to throw up!"))) + if(prob(SYMPTOM_ACTIVATION_PROB)) + M.vomit() diff --git a/code/datums/diseases/advance/symptoms/weakness.dm b/code/datums/diseases/advance/symptoms/weakness.dm new file mode 100644 index 00000000000..917be5a46ce --- /dev/null +++ b/code/datums/diseases/advance/symptoms/weakness.dm @@ -0,0 +1,43 @@ +/* +////////////////////////////////////// + +Weakness + + Slightly noticeable. + Lowers resistance slightly. + Decreases stage speed moderately. + Decreases transmittablity moderately. + Moderate Level. + +Bonus + Weakens the host + +////////////////////////////////////// +*/ + +/datum/symptom/weakness + name = "Weakness" + stealth = -1 + resistance = -1 + stage_speed = -2 + transmittable = -2 + level = 3 + severity = 3 + +/datum/symptom/weakness/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2) + to_chat(M, span_warning(pick("You feel weak.", "You feel lazy."))) + if(3, 4) + to_chat(M, span_boldwarning(pick("You feel very frail.", "You think you might faint."))) + M.Weaken(10) + else + to_chat(M, span_userdanger(pick("You feel tremendously weak!", "Your body trembles as exhaustion creeps over you."))) + M.Weaken(20) + if(M.weakened > 60 && !M.stat) + M.visible_message(span_warning("[M] faints!"), span_userdanger("You swoon and faint...")) + M.AdjustSleeping(10) + return diff --git a/code/datums/diseases/advance/symptoms/weigh.dm b/code/datums/diseases/advance/symptoms/weigh.dm new file mode 100644 index 00000000000..ceca8a77f59 --- /dev/null +++ b/code/datums/diseases/advance/symptoms/weigh.dm @@ -0,0 +1,37 @@ +/* +////////////////////////////////////// + +Weight Loss + + Very Very Noticable. + Decreases resistance. + Decreases stage speed. + Reduced Transmittable. + High level. + +Bonus + Decreases the weight of the mob, + forcing it to be skinny. + +////////////////////////////////////// +*/ + +/datum/symptom/weight_loss + name = "Weight Loss" + stealth = -3 + resistance = -2 + stage_speed = -2 + transmittable = -2 + level = 3 + severity = 1 + +/datum/symptom/weight_loss/Activate(datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) + to_chat(M, span_warning(pick("You feel hungry.", "You crave for food."))) + else + to_chat(M, span_warning(pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you..."))) + M.adjust_nutrition(-20) diff --git a/code/datums/diseases/anxiety.dm b/code/datums/diseases/anxiety.dm new file mode 100644 index 00000000000..78b630bc152 --- /dev/null +++ b/code/datums/diseases/anxiety.dm @@ -0,0 +1,53 @@ +/datum/disease/anxiety + name = "Severe Anxiety" + form = "Infection" + max_stages = 4 + spread_text = "On contact" + spread_flags = CONTACT_GENERAL + cure_text = "Ethanol" + cures = list("ethanol") + agent = "Excess Lepdopticides" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) + desc = "If left untreated subject will regurgitate butterflies." + severity = MINOR + +/datum/disease/anxiety/stage_act() + if(!..()) + return FALSE + switch(stage) + if(2) + if(prob(15)) + to_chat(affected_mob, span_notice("You feel anxious.")) + if(3) + if(prob(10)) + to_chat(affected_mob, span_notice("Your stomach flutters.")) + if(prob(5)) + to_chat(affected_mob, span_notice("You feel panicky.")) + if(prob(2)) + to_chat(affected_mob, span_danger("You're overtaken with panic!")) + affected_mob.AdjustConfused(rand(4, 6)) + if(4) + if(prob(10)) + to_chat(affected_mob, span_danger("You feel butterflies in your stomach.")) + if(prob(5)) + affected_mob.visible_message( + span_danger("[affected_mob] stumbles around in a panic"), + span_userdanger("You have a panic attack!") + ) + affected_mob.AdjustConfused(rand(12, 16)) + affected_mob.jitteriness = rand(12, 16) + if(prob(2)) + affected_mob.visible_message( + span_danger("[affected_mob] coughs up butterflies!"), + span_userdanger("You cough up butterflies!") + ) + affected_mob.emote("cough") + for(var/i in 1 to 2) + var/mob/living/simple_mob/animal/sif/glitterfly/B = new(affected_mob.loc) + addtimer(CALLBACK(B, TYPE_PROC_REF(/mob/living/simple_mob/animal/sif/glitterfly, decompose)), rand(5, 25) SECONDS) + +/mob/living/simple_mob/animal/sif/glitterfly/proc/decompose() + visible_message( + span_notice("[src] decomposes due to being outside of its original habitat for too long!"), + span_userdanger("You decompose for being too long out of your habitat!")) + dust() diff --git a/code/datums/diseases/beesease.dm b/code/datums/diseases/beesease.dm new file mode 100644 index 00000000000..a867c8d9d97 --- /dev/null +++ b/code/datums/diseases/beesease.dm @@ -0,0 +1,36 @@ +/datum/disease/beesease + name = "Beesease" + form = "Infection" + max_stages = 4 + spread_text = "On contact" + spread_flags = CONTACT_GENERAL + cure_text = "Sugar" + cures = list("sugar") + agent = "Apidae Infection" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) + desc = "If left untreated, subject will regurgitate bees." + severity = BIOHAZARD + +/datum/disease/beesease/stage_act() + if(!..()) + return FALSE + switch(stage) + if(2) + if(prob(2)) + to_chat(affected_mob, span_notice("You tastey hone in your mouth.")) + if(3) + if(prob(10)) + to_chat(affected_mob, span_notice("Your stomach rumbles")) + if(prob(2)) + to_chat(affected_mob, span_notice("Your stomach stings painfully.")) + if(prob(20)) + affected_mob.adjustToxLoss(2) + if(4) + if(prob(10)) + affected_mob.visible_message(span_danger("[affected_mob] buzzles loudly"), span_userdanger("Your stomach buzzles violently!")) + if(prob(5)) + to_chat(affected_mob, span_danger("You feel something moving in your throat.")) + if(prob(1)) + affected_mob.visible_message(span_danger("[affected_mob] coughs up a swarm of bees!"), span_userdanger("You cough up a swarm of bees!")) + new /mob/living/simple_mob/vore/bee(affected_mob.loc) + return diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm new file mode 100644 index 00000000000..57899ef2014 --- /dev/null +++ b/code/datums/diseases/brainrot.dm @@ -0,0 +1,43 @@ +/datum/disease/brainrot + name = "Brainrot" + max_stages = 4 + spread_text = "On contact" + spread_flags = CONTACT_GENERAL + cure_text = "Alkysine" + cures = list("alkysine") + agent = "Cryptococcus Cosmosis" + viable_mobtypes = list(/mob/living/carbon/human) + cure_chance = 15 + desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication." + required_organs = list(/obj/item/organ/internal/brain) + severity = HARMFUL + +/datum/disease/brainrot/stage_act() + if(!..()) + return FALSE + switch(stage) + if(2) + if(prob(2)) + affected_mob.say("*blink") + if(prob(2)) + affected_mob.say("*yawn") + if(prob(2)) + to_chat(affected_mob, span_danger("You don't feel like yourself.")) + if(prob(5)) + affected_mob.adjustBrainLoss(1) + if(3) + if(prob(2)) + affected_mob.say("*stare") + if(prob(3)) + affected_mob.say("*drool") + if(prob(10) && affected_mob.getBrainLoss() < 100) + affected_mob.adjustBrainLoss(3) + if(prob(2)) + to_chat(affected_mob, span_danger("Strange buzzing fills your head, removing all thoughts.")) + if(prob(3)) + to_chat(affected_mob, span_danger("You lose consciousness...")) + affected_mob.Sleeping(rand(5, 10)) + if(prob(1)) + affected_mob.emote("snore") + if(prob(15)) + affected_mob.apply_effect(5, STUTTER) diff --git a/code/datums/diseases/choreomania.dm b/code/datums/diseases/choreomania.dm new file mode 100644 index 00000000000..9fd41c4cd6f --- /dev/null +++ b/code/datums/diseases/choreomania.dm @@ -0,0 +1,38 @@ +/datum/disease/choreomania + name = "Choreomania" + max_stages = 3 + spread_text = "Airborne" + cure_text = "Adranol" + cures = list("adranol") + cure_chance = 10 + agent = "TAP-DAnC3" + viable_mobtypes = list(/mob/living/carbon/human) + permeability_mod = 0.75 + desc = "If left untreated the subject... Won't stop dancing!" + severity = MINOR + + var/list/dance = list(2,4,8,2,4,8,2,4,8,2,4,8,1,4,1,4,1,4,2,4,8,2) + +/datum/disease/choreomania/stage_act() + if(!..()) + return FALSE + switch(stage) + if(2) + if(prob(1)) + to_chat(affected_mob, span_notice("You feel like dancing like a maniac, maniac...")) + if(prob(1)) + affected_mob.emote("whistle") + if(3) + if(prob(1)) + to_chat(affected_mob, span_notice("You feel like dancing like a maniac, maniac...")) + if(prob(1)) + to_chat(affected_mob, span_notice("You really want to start a conga line!")) + if(prob(2)) + for(var/D in dance) + affected_mob.dir = D + animate(affected_mob, pixel_x = 5, time = 5) + sleep(3) + animate(affected_mob, pixel_x = -5, time = 5) + animate(pixel_x = affected_mob.default_pixel_x, pixel_y = affected_mob.default_pixel_x, time = 2) + sleep(3) + return diff --git a/code/datums/diseases/cold.dm b/code/datums/diseases/cold.dm new file mode 100644 index 00000000000..c6b6cf0f17e --- /dev/null +++ b/code/datums/diseases/cold.dm @@ -0,0 +1,64 @@ +/datum/disease/cold + name = "The Cold" + max_stages = 3 + spread_text = "Airborne" + spread_flags = AIRBORNE + cure_text = "Rest & Spaceacilin" + cures = list("spaceacilin") + agent = "XY-rhinovirus" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) + permeability_mod = 0.5 + desc = "If left untreated the subject will contract the flu." + severity = MINOR + +/datum/disease/cold/stage_act() + if(!..()) + return FALSE + switch(stage) + if(2) + if(affected_mob.stat == UNCONSCIOUS && prob(40)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(affected_mob.lying && prob(10)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(prob(1) && prob(5)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, span_notice("Your throat feels sore.")) + if(prob(1)) + to_chat(affected_mob, span_notice("Mucous runs down the back of your throat.")) + if(3) + if(affected_mob.stat == UNCONSCIOUS && prob(25)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(affected_mob.lying && prob(5)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(prob(1) && prob(1)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, span_notice("Your throat feels sore.")) + if(prob(1)) + to_chat(affected_mob, span_notice("Mucous runs down the back of your throat.")) + if(prob(1) && prob(50)) + if(!affected_mob.resistances.Find(/datum/disease/flu)) + var/datum/disease/Flu = new /datum/disease/flu(0) + affected_mob.ContractDisease(Flu) + cure() diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm new file mode 100644 index 00000000000..a0fa6919764 --- /dev/null +++ b/code/datums/diseases/cold9.dm @@ -0,0 +1,30 @@ +/datum/disease/cold9 + name = "The Cold" + medical_name = "ICE9 Cold" + max_stages = 3 + spread_text = "On contact" + spread_flags = CONTACT_GENERAL + cure_text = "Spaceacillin" + cures = list("spaceacillin") + agent = "ICE9-rhinovirus" + viable_mobtypes = list(/mob/living/carbon/human) + desc = "If left untreated the subject will slow, as if partly frozen." + severity = HARMFUL + +/datum/disease/cold9/stage_act() + if(!..()) + return FALSE + if(stage < 2) + return + + var/stage_factor = stage - 1 + affected_mob.bodytemperature -= 7.5 * stage_factor + if(prob(2 * stage_factor)) + affected_mob.say("*sneeze") + if(prob(2 * stage_factor)) + affected_mob.say("*cough") + if(prob(3 * stage_factor)) + to_chat(affected_mob, span_danger("Your throat feels sore.")) + if(prob(5 * stage_factor)) + to_chat(affected_mob, span_danger("You feel stiff.")) + affected_mob.adjustFireLoss(1) diff --git a/code/datums/diseases/darkness.dm b/code/datums/diseases/darkness.dm new file mode 100644 index 00000000000..b340ca5d45d --- /dev/null +++ b/code/datums/diseases/darkness.dm @@ -0,0 +1,10 @@ +/datum/disease/darkness + name = "Dark Exposure" + form = "Bluespace Micro-fissures" + max_stages = 4 + spread = NON_CONTAGIOUS + cure_text = "Exposure to light and the real world" + agent = "Bluespace Exposure" + viable_mobtypes = list(/mob/living/carbon/human) + desc = "If left untreated, subject will lose grip on reality." + severity = HARMFUL diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm new file mode 100644 index 00000000000..6a30af6f859 --- /dev/null +++ b/code/datums/diseases/flu.dm @@ -0,0 +1,50 @@ +/datum/disease/flu + name = "The Flu" + max_stages = 3 + spread_text = "Airborne" + cure_text = "Spaceacilin" + cures = list("spaceacilin") + cure_chance = 10 + agent = "H13N1 flu virion" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) + permeability_mod = 0.75 + desc = "If left untreated the subject will feel quite unwell." + severity = MINOR + +/datum/disease/flu/stage_act() + if(!..()) + return FALSE + switch(stage) + if(2) + if(affected_mob.lying && prob(20)) + to_chat(affected_mob, span_notice("You feel better.")) + stage-- + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, span_danger("Your muscles ache.")) + if(prob(20)) + affected_mob.apply_damage(1) + if(prob(1)) + to_chat(affected_mob, span_danger("Your stomach hurts.")) + affected_mob.adjustToxLoss(1) + if(3) + if(affected_mob.lying && prob(15)) + to_chat(affected_mob, span_notice("You feel better.")) + stage-- + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, span_danger("Your muscles ache.")) + if(prob(20)) + affected_mob.apply_damage(1) + if(prob(1)) + to_chat(affected_mob, span_danger("Your stomach hurts.")) + affected_mob.adjustToxLoss(1) + return diff --git a/code/datums/diseases/food_poisoning.dm b/code/datums/diseases/food_poisoning.dm new file mode 100644 index 00000000000..cbb7a0c8046 --- /dev/null +++ b/code/datums/diseases/food_poisoning.dm @@ -0,0 +1,67 @@ +/datum/disease/food_poisoning + name = "Food Poisoning" + max_stages = 3 + stage_prob = 5 + spread_text = "Non-Contagious" + spread_flags = NON_CONTAGIOUS + cure_text = "Sleep" + agent = "Salmonella" + cures = list("chicken_soup") + cure_chance = 10 + viable_mobtypes = list(/mob/living/carbon/human) + desc = "Nausea, sickness, and vomitting." + severity = MINOR + disease_flags = CURABLE + virus_heal_resistant = TRUE + +/datum/disease/food_poisoning/stage_act() + if(!..()) + return FALSE + if(affected_mob.stat == UNCONSCIOUS && prob(33)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + switch(stage) + if(1) + if(prob(5)) + to_chat(affected_mob, span_danger("Your stomach feels weird.")) + if(prob(5)) + to_chat(affected_mob, span_danger("You feel queasy.")) + if(2) + if(affected_mob.stat == UNCONSCIOUS && prob(40)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(prob(1) && prob(10)) + to_chat(affected_mob, span_notice("You feel better.")) + if(prob(10)) + affected_mob.emote("groan") + if(prob(5)) + to_chat(affected_mob, span_danger("Your stomach aches.")) + if(prob(5)) + to_chat(affected_mob, span_danger("You feel nauseous")) + if(3) + if(affected_mob.stat == UNCONSCIOUS && prob(25)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(prob(1) && prob(10)) + to_chat(affected_mob, span_notice("You feel better.")) + cure() + return + if(prob(10)) + affected_mob.emote("moan") + if(prob(10)) + affected_mob.emote("groan") + if(prob(1)) + to_chat(affected_mob, span_danger("Your stomach hurts.")) + if(prob(1)) + to_chat(affected_mob, span_danger("You feel sick.")) + if(prob(5)) + if(affected_mob.nutrition > 10) + affected_mob.emote("vomit") + else + to_chat(affected_mob, span_danger("Your stomach lurches painfully")) + affected_mob.visible_message(span_danger("[affected_mob] gags and retches!")) + affected_mob.Stun(rand(4, 8)) + affected_mob.Weaken(rand(4, 8)) diff --git a/code/datums/diseases/lycancoughy.dm b/code/datums/diseases/lycancoughy.dm new file mode 100644 index 00000000000..6d8f1061638 --- /dev/null +++ b/code/datums/diseases/lycancoughy.dm @@ -0,0 +1,64 @@ +/datum/disease/lycan + name = "Lycancoughy" + form = "Infection" + max_stages = 4 + spread_text = "On contact" + spread_flags = CONTACT_GENERAL + cure_text = "Ethanol" + cures = list("ethanol") + agent = "Excess Snuggles" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) + desc = "If left untreated subject will regurgitate... puppies." + severity = HARMFUL + var/barklimit + var/list/puppy_types = list(/mob/living/simple_mob/animal/passive/dog/corgi/puppy) + var/list/plush_types = list(/obj/item/toy/plushie/orange_fox, /obj/item/toy/plushie/corgi, /obj/item/toy/plushie/robo_corgi, /obj/item/toy/plushie/pink_fox) + +/datum/disease/lycan/stage_act() + if(!..()) + return FALSE + + var/mob/living/carbon/human/H = affected_mob + + switch(stage) + if(2) + if(prob(2)) + H.emote("cough") + if(prob(3)) + to_chat(H, span_notice("You itch.")) + H.adjustBruteLoss(rand(4, 6)) + if(3) + var/obj/item/organ/external/stomach = H.organs_by_name[pick("torso", "groin")] + + if(prob(3)) + H.emote("cough") + stomach.take_damage(BRUTE, rand(0, 5)) + if(prob(3)) + to_chat(H, span_notice("You hear a faint barking.")) + stomach.take_damage(BRUTE, rand(4, 6)) + if(prob(2)) + to_chat(H, span_notice("You crave meat.")) + if(prob(3)) + to_chat(H, span_danger("Your stomach growls!")) + stomach.take_damage(BRUTE, rand(5, 10)) + if(4) + var/obj/item/organ/external/stomach = H.organs_by_name[pick("torso", "groin")] + + if(prob(5)) + H.emote("cough") + stomach.take_damage(BRUTE, rand(0, 5)) + if(prob(5)) + H.emote("awoo2") + H.Confuse(rand(12, 16)) + stomach.take_damage(rand(0, 5)) + if(prob(5)) + if(!barklimit) + to_chat(H, span_danger("Your stomach growls!")) + stomach.take_damage(BRUTE, rand(5, 10)) + else + var/atom/hairball = pick(prob(50) ? puppy_types : plush_types) + H.visible_message(span_danger("[H] coughs up \a [initial(hairball.name)]!"), span_userdanger("You cough up \a [initial(hairball.name)]?!")) + H.emote("cough") + new hairball(H.loc) + barklimit-- + stomach.take_damage(BRUTE, rand(10, 15)) diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm new file mode 100644 index 00000000000..24b2261cdaa --- /dev/null +++ b/code/datums/diseases/magnitis.dm @@ -0,0 +1,63 @@ +/datum/disease/magnitis + name = "Magnitis" + max_stages = 4 + spread_text = "Airbone" + cure_text = "Iron" + cures = list("iron") + agent = "Fukkos Miracos" + viable_mobtypes = list(/mob/living/carbon/human) + permeability_mod = 0.75 + desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field." + severity = MINOR + +/datum/disease/magnitis/stage_act() + if(!..()) + return FALSE + switch(stage) + if(2) + if(prob(2)) + to_chat(affected_mob, span_danger("You feel a slight shock course through your body.")) + if(prob(2)) + for(var/obj/M in orange(2, affected_mob)) + if(!M.anchored && prob(5)) + INVOKE_ASYNC(M, TYPE_PROC_REF(/atom/movable, throw_at), affected_mob, rand(3, 10), rand(1, 3), src) + for(var/mob/living/silicon/S in orange(2, affected_mob)) + if(isAI(S)) continue + INVOKE_ASYNC(S, TYPE_PROC_REF(/atom/movable, throw_at), affected_mob, rand(3, 10), rand(1, 3), src) + if(3) + if(prob(2)) + to_chat(affected_mob, span_danger("You feel a strong shock course through your body.")) + if(prob(2)) + to_chat(affected_mob, span_danger("You feel like clowning aound.")) + if(prob(4)) + for(var/obj/M in orange(4, affected_mob)) + if(!M.anchored && prob(5)) + var/i + var/iter = rand(1,2) + for(i=0,i (occupant.getMaxHealth() / 2) ? span_blue(health_text) : span_red(health_text)) dat += "
" - if(occupant.virus2.len) - dat += span_red("Viral pathogen detected in blood stream.") + "
" + if(occupant.viruses.len) + for(var/datum/disease/D in occupant.GetViruses()) + if(D.visibility_flags & HIDDEN_SCANNER) + continue + else + dat += span_red("Viral pathogen detected in blood stream.") + "
" var/damage_string = null damage_string = "\t-Brute Damage %: [occupant.getBruteLoss()]" diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 1fb04554760..00339ac2737 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -172,8 +172,10 @@ medical["empty"] = 1 if(MED_DATA_V_DATA) data["virus"] = list() - for(var/ID in virusDB) - var/datum/data/record/v = virusDB[ID] + for(var/datum/disease/D in active_diseases) + if(!D.discovered) + continue + var/datum/data/record/v = active_diseases[D] data["virus"] += list(list("name" = v.fields["name"], "D" = "\ref[v]")) if(MED_DATA_MEDBOT) data["medbots"] = list() diff --git a/code/game/machinery/pandemic.dm b/code/game/machinery/pandemic.dm new file mode 100644 index 00000000000..ae8687d6657 --- /dev/null +++ b/code/game/machinery/pandemic.dm @@ -0,0 +1,377 @@ +/obj/machinery/computer/pandemic + name = "PanD.E.M.I.C 2200" + desc = "Used to work with viruses." + density = TRUE + anchored = TRUE + icon = 'icons/obj/pandemic.dmi' + icon_state = "pandemic0" + var/temp_html = "" + var/printing = null + var/wait = null + var/selected_strain_index = 1 + var/obj/item/reagent_containers/beaker = null + +/obj/machinery/computer/pandemic/Initialize(mapload) + . = ..() + update_icon() + +/obj/machinery/computer/pandemic/set_broken() + stat |= BROKEN + update_icon() + +/obj/machinery/computer/pandemic/proc/GetViruses() + if(beaker && beaker.reagents) + if(length(beaker.reagents.reagent_list)) + var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list + if(BL) + if(BL.data && BL.data["viruses"]) + var/list/viruses = BL.data["viruses"] + return viruses + +/obj/machinery/computer/pandemic/proc/GetVirusByIndex(index) + var/list/viruses = GetViruses() + if(viruses && index > 0 && index <= length(viruses)) + return viruses[index] + +/obj/machinery/computer/pandemic/proc/GetResistances() + if(beaker && beaker.reagents) + if(length(beaker.reagents.reagent_list)) + var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list + if(BL) + if(BL.data && BL.data["resistances"]) + var/list/resistances = BL.data["resistances"] + return resistances + +/obj/machinery/computer/pandemic/proc/GetResistancesByIndex(index) + var/list/resistances = GetResistances() + if(resistances && index > 0 && index <= length(resistances)) + return resistances[index] + +/obj/machinery/computer/pandemic/proc/GetVirusTypeByIndex(index) + var/datum/disease/D = GetVirusByIndex(index) + if(D) + return D.GetDiseaseID() + +/obj/machinery/computer/pandemic/proc/replicator_cooldown(waittime) + wait = 1 + update_icon() + spawn(waittime) + wait = null + update_icon() + playsound(loc, 'sound/machines/ping.ogg', 30, 1) + +/obj/machinery/computer/pandemic/update_icon() + if(stat & BROKEN) + icon_state = (beaker ? "pandemic1_b" : "pandemic0_b") + 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" + 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) + if(..()) + return + if(inoperable()) + return + + . = TRUE + + switch(action) + if("clone_strain") + if(wait) + atom_say("The replicator is not ready yet.") + return + + var/strain_index = text2num(params["strain_index"]) + if(isnull(strain_index)) + atom_say("Unable to respond to command.") + return + var/datum/disease/virus = GetVirusByIndex(strain_index) + var/datum/disease/D = null + if(!virus) + atom_say("Unable to find requested strain.") + return + var/type = virus.GetDiseaseID() + if(!ispath(type)) + var/datum/disease/advance/A = GLOB.archive_diseases[type] + if(A) + D = new A.type(0, A) + else if(type) + if(type in GLOB.diseases) // Make sure this is a disease + D = new type(0, null) + if(!D) + atom_say("Unable to synthesize requested strain.") + return + var/default_name = "" + if(D.name == "Unknown" || D.name == "") + default_name = replacetext(beaker.name, new/regex(" culture bottle\\Z", "g"), "") + else + default_name = D.name + var/name = tgui_input_text(usr, "Name:", "Name the culture", default_name, MAX_NAME_LEN) + if(name == null || wait) + return + var/obj/item/reagent_containers/glass/bottle/B = create_culture(name) + B.desc = "A small bottle. Contains [D.agent] culture in synthblood medium." + B.reagents.add_reagent("blood", 20, list("viruses" = list(D))) + if("clone_vaccine") + if(wait) + atom_say("The replicator is not ready yet.") + return + + var/resistance_index = text2num(params["resistance_index"]) + if(isnull(resistance_index)) + atom_say("Unable to find requested antibody.") + return + var/vaccine_type = GetResistancesByIndex(resistance_index) + var/vaccine_name = "Unknown" + if(!ispath(vaccine_type)) + if(GLOB.archive_diseases[vaccine_type]) + var/datum/disease/D = GLOB.archive_diseases[vaccine_type] + if(D) + vaccine_name = D.name + else if(vaccine_type) + var/datum/disease/D = new vaccine_type(0, null) + if(D) + vaccine_name = D.name + + if(!vaccine_type) + atom_say("Unable to synthesize requested antibody.") + return + + var/obj/item/reagent_containers/glass/bottle/B = create_culture(vaccine_name, "vaccine", 200) + B.reagents.add_reagent("vaccine", 15, list(vaccine_type)) + if("eject_beaker") + eject_beaker() + update_tgui_static_data(ui.user) + if("destroy_eject_beaker") + beaker.reagents.clear_reagents() + eject_beaker() + update_tgui_static_data(ui.user) + if("print_release_forms") + var/strain_index = text2num(params["strain_index"]) + if(isnull(strain_index)) + atom_say("Unable to respond to command.") + return + var/type = GetVirusTypeByIndex(strain_index) + if(!type) + atom_say("Unable to find requested strain.") + return + var/datum/disease/advance/A = GLOB.archive_diseases[type] + if(!A) + atom_say("Unable to find requested strain.") + return + print_form(A, usr) + if("name_strain") + var/strain_index = text2num(params["strain_index"]) + if(isnull(strain_index)) + atom_say("Unable to respond to command.") + return + var/type = GetVirusTypeByIndex(strain_index) + if(!type) + atom_say("Unable to find requested strain.") + return + var/datum/disease/advance/A = GLOB.archive_diseases[type] + if(!A) + atom_say("Unable to find requested strain.") + return + if(A.name != "Unknown") + atom_say("Request rejected. Strain already has a name.") + return + var/new_name = tgui_input_text(usr, "Name the Strain", "New Name", max_length = MAX_NAME_LEN) + if(!new_name) + return + A.AssignName(new_name) + for(var/datum/disease/advance/AD in active_diseases) + AD.Refresh() + update_tgui_static_data(ui.user) + if("switch_strain") + var/strain_index = text2num(params["strain_index"]) + if(isnull(strain_index) || strain_index < 1) + atom_say("Unable to respond to command.") + return + var/list/viruses = GetViruses() + if(strain_index > length(viruses)) + atom_say("Unable to find requested strain.") + return + selected_strain_index = strain_index; + else + return FALSE + +/obj/machinery/computer/pandemic/tgui_state(mob/user) + return GLOB.tgui_default_state + +/obj/machinery/computer/pandemic/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PanDEMIC", name) + ui.open() + +/obj/machinery/computer/pandemic/tgui_data(mob/user) + var/datum/reagent/blood/Blood = null + if(beaker) + var/datum/reagents/R = beaker.reagents + for(var/datum/reagent/blood/B in R.reagent_list) + if(B) + Blood = B + break + + var/list/data = list( + "synthesisCooldown" = wait ? TRUE : FALSE, + "beakerLoaded" = beaker ? TRUE : FALSE, + "beakerContainsBlood" = Blood ? TRUE : FALSE, + "beakerContainsVirus" = length(Blood?.data["viruses"]) != 0, + "selectedStrainIndex" = selected_strain_index, + ) + + return data + +/obj/machinery/computer/pandemic/tgui_static_data(mob/user) + var/list/data = list() + . = data + + var/datum/reagent/blood/Blood = null + if(beaker) + var/datum/reagents/R = beaker.reagents + for(var/datum/reagent/blood/B in R.reagent_list) + if(B) + Blood = B + break + + var/list/strains = list() + for(var/datum/disease/D in GetViruses()) + if(D.visibility_flags & HIDDEN_PANDEMIC) + continue + + var/list/symptoms = list() + if(istype(D, /datum/disease/advance)) + var/datum/disease/advance/A = D + D = GLOB.archive_diseases[A.GetDiseaseID()] + if(!D) + CRASH("We weren't able to get the advance disease from the archive.") + for(var/datum/symptom/S in A.symptoms) + symptoms += list(list( + "name" = S.name, + "stealth" = S.stealth, + "resistance" = S.resistance, + "stageSpeed" = S.stage_speed, + "transmissibility" = S.transmittable, + "complexity" = S.level, + )) + + strains += list(list( + "commonName" = D.name, + "description" = D.desc, + "bloodDNA" = Blood.data["blood_DNA"], + "bloodType" = Blood.data["blood_type"], + "diseaseAgent" = D.agent, + "possibleTreatments" = D.cure_text, + "transmissionRoute" = D.spread_text, + "symptoms" = symptoms, + "isAdvanced" = istype(D, /datum/disease/advance), + )) + data["strains"] = strains + + var/list/resistances = list() + for(var/resistance in GetResistances()) + if(!ispath(resistance)) + var/datum/disease/D = GLOB.archive_diseases[resistance] + if(D) + resistances += list(D.name) + else if(resistance) + var/datum/disease/D = new resistance(0, null) + if(D) + resistances += list(D.name) + data["resistances"] = resistances + +/obj/machinery/computer/pandemic/proc/eject_beaker() + set name = "Eject Beaker" + set category = "Object" + set src in oview(1) + + if(usr.stat != 0) + return + + beaker.forceMove(loc) + beaker = null + icon_state = "pandemic0" + selected_strain_index = 1 + +/obj/machinery/computer/pandemic/proc/print_form(datum/disease/advance/D, mob/living/user) + D = GLOB.archive_diseases[D.GetDiseaseID()] + if(!(printing) && D) + var/reason = tgui_input_text(user,"Enter a reason for the release", "Write", multiline = TRUE) + if(!reason) + return + reason += "" + var/english_symptoms = list() + for(var/I in D.symptoms) + var/datum/symptom/S = I + english_symptoms += S.name + var/symtoms = english_list(english_symptoms) + + var/signature + if(tgui_alert(user, "Would you like to add your signature?", "Signature", list("Yes","No")) == "Yes") + signature = "[user ? user.real_name : "Anonymous"]" + else + signature = "" + + printing = 1 + var/obj/item/paper/P = new /obj/item/paper(loc) + visible_message(span_notice("[src] rattles and prints out a sheet of paper.")) + // playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1) + + P.info = "
Releasing Virus
" + P.info += "
" + P.info += "Name of the Virus: [D.name]
" + P.info += "Symptoms: [symtoms]
" + P.info += "Spreads by: [D.spread_text]
" + P.info += "Cured by: [D.cure_text]
" + P.info += "
" + P.info += "Reason for releasing: [reason]" + P.info += "
" + P.info += "The Virologist is responsible for any biohazards caused by the virus released.
" + P.info += "Virologist's sign: [signature]
" + P.info += "If approved, stamp below with the Chief Medical Officer's stamp, and/or the Captain's stamp if required:" + P.updateinfolinks() + P.name = "Releasing Virus - [D.name]" + printing = null + +/obj/machinery/computer/pandemic/attack_ai(mob/user) + return attack_hand(user) + +/obj/machinery/computer/pandemic/attack_hand(mob/user) + if(..()) + return + tgui_interact(user) + +/obj/machinery/computer/pandemic/attack_ghost(mob/user) + tgui_interact(user) + +/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params) + if(default_unfasten_wrench(user, I, 4 SECONDS)) + return + if(I.has_tool_quality(TOOL_SCREWDRIVER)) + eject_beaker() + return + if(istype(I, /obj/item/reagent_containers/glass) && I.is_open_container()) + if(stat & (NOPOWER|BROKEN)) + return + if(beaker) + 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.")) + update_tgui_static_data(user) + icon_state = "pandemic1" + else + return ..() diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 18660273f7d..84b47051aa1 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -19,7 +19,7 @@ var/global/list/image/splatter_cache=list() blood_DNA = list() var/basecolor="#A10808" // Color when wet. var/synthblood = 0 - var/list/datum/disease2/disease/virus2 = list() + var/list/datum/disease/viruses = list() var/amount = 5 generic_filth = TRUE persistent = FALSE @@ -242,7 +242,7 @@ var/global/list/image/splatter_cache=list() icon_state = "mucus" random_icon_states = list("mucus") - var/list/datum/disease2/disease/virus2 = list() + var/list/datum/disease/viruses = list() var/dry = 0 // Keeps the lag down /obj/effect/decal/cleanable/mucus/Initialize() @@ -252,11 +252,10 @@ var/global/list/image/splatter_cache=list() //This version should be used for admin spawns and pre-mapped virus vectors (e.g. in PoIs), this version does not dry /obj/effect/decal/cleanable/mucus/mapped/Initialize() . = ..() - virus2 |= new /datum/disease2/disease - virus2[1].makerandom() + viruses |= new /datum/disease/advance /obj/effect/decal/cleanable/mucus/mapped/Destroy() - virus2.Cut() + viruses.Cut() return ..() #undef DRYING_TIME diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index c15734b89d4..e8a6083fed9 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -113,7 +113,7 @@ icon = 'icons/effects/blood.dmi' icon_state = "vomit_1" random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") - var/list/datum/disease2/disease/virus2 = list() + var/list/datum/disease/viruses = list() /obj/effect/decal/cleanable/tomato_smudge name = "tomato smudge" diff --git a/code/game/objects/items/devices/scanners/guide.dm b/code/game/objects/items/devices/scanners/guide.dm index de728cd8544..403a81f9747 100644 --- a/code/game/objects/items/devices/scanners/guide.dm +++ b/code/game/objects/items/devices/scanners/guide.dm @@ -97,8 +97,12 @@ dat += span_bold("Genetic damage") + " - Utilize cryogenic pod with appropriate chemicals (i.e. Cryoxadone) and below 70 K, or give Rezadone.
" if(bone) dat += span_bold("Bone fracture") + " - Splint damaged area. Treat with bone repair surgery or Osteodaxon after treating brute damage.
" - if(M.virus2.len) - dat += span_bold("Viral infection") + " - Proceed with virology pathogen curing procedures or apply antiviral chemicals (i.e. Corophizine).
" + if(M.viruses.len) + for(var/datum/disease/D in M.GetViruses()) + if(D.visibility_flags & HIDDEN_SCANNER) + continue + else + dat += span_bold("Viral Infection") + " - Inform a Virologist or the Chief Medical Officer and administer antiviral chemicals such as Spaceacilin. Limit exposure to other personnel.
" if(robotparts) dat += span_bold("Robotic body parts") + " - Should not be repaired by medical personnel, refer to robotics if damaged." diff --git a/code/game/objects/items/devices/scanners/health.dm b/code/game/objects/items/devices/scanners/health.dm index ec9a6b257ce..c9927024305 100644 --- a/code/game/objects/items/devices/scanners/health.dm +++ b/code/game/objects/items/devices/scanners/health.dm @@ -248,14 +248,14 @@ else dat += span_warning("Unknown substance[(unknown > 1)?"s":""] found in subject's dermis.") dat += "
" - if(C.virus2.len) - for (var/ID in C.virus2) - if (ID in virusDB) - var/datum/data/record/V = virusDB[ID] - dat += span_warning("Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]") + if(C.resistances.len) + for (var/datum/disease/virus in C.GetViruses()) + if(virus.visibility_flags & HIDDEN_SCANNER || virus.visibility_flags & HIDDEN_PANDEMIC) + continue + if(virus.discovered) + dat += span_warning("Warning: [virus.name] detected in subject's blood.") dat += "
" - else - dat += span_warning("Warning: Unknown pathogen detected in subject's blood.") + dat += span_warning("Severity: [virus.severity]") dat += "
" if (M.getCloneLoss()) dat += span_warning("Subject appears to have been imperfectly cloned.") diff --git a/code/game/objects/items/weapons/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm index c340f4958a7..09535b45f54 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm @@ -154,14 +154,6 @@ build_path = /obj/machinery/computer/operating origin_tech = list(TECH_DATA = 2, TECH_BIO = 2) -/obj/item/circuitboard/curefab - name = T_BOARD("cure fabricator") - build_path = /obj/machinery/computer/curer - -/obj/item/circuitboard/splicer - name = T_BOARD("disease splicer") - build_path = /obj/machinery/computer/diseasesplicer - /obj/item/circuitboard/mining_shuttle name = T_BOARD("mining shuttle console") build_path = /obj/machinery/computer/shuttle_control/mining @@ -226,4 +218,4 @@ /obj/item/circuitboard/stockexchange name = T_BOARD("stock exchange console") build_path = /obj/machinery/computer/stockexchange - origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 1) \ No newline at end of file + origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 1) diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index e27d9ade0cc..0e51b19eec8 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -453,7 +453,7 @@ max_storage_space = ITEMSIZE_COST_SMALL * 12 max_w_class = ITEMSIZE_NORMAL w_class = ITEMSIZE_SMALL - can_hold = list(/obj/item/reagent_containers/glass/beaker/vial/,/obj/item/virusdish/) + can_hold = list(/obj/item/reagent_containers/glass/beaker/vial/) // ----------------------------- // Food Bag diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 4412b8af019..36f22f6f452 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -244,7 +244,6 @@ /obj/item/flashlight, /obj/item/cell/device, /obj/item/extinguisher/mini, - /obj/item/antibody_scanner, // VOREstation edit start /obj/item/sleevemate, /obj/item/mass_spectrometer, /obj/item/surgical, diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 3704524cf12..d1df4043337 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -300,7 +300,7 @@ /obj/item/storage/box/syndie_kit/viral starts_with = list( - /obj/item/virusdish/random = 3 + // /obj/item/virusdish/random = 3 ) /obj/item/storage/secure/briefcase/rifle diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 841ab7286ba..6b46ba2acbe 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -174,7 +174,7 @@ B.blood_DNA = list() if(!B.blood_DNA[M.dna.unique_enzymes]) B.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - B.virus2 = virus_copylist(M.virus2) + B.viruses = M.viruses.Copy() return 1 //we bloodied the floor blood_splatter(src,M.get_blood(M.vessel),1) return 1 //we bloodied the floor diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm index 28c9550ef81..4b29645516b 100644 --- a/code/modules/admin/admin_verb_lists_vr.dm +++ b/code/modules/admin/admin_verb_lists_vr.dm @@ -187,7 +187,6 @@ var/list/admin_verbs_spawn = list( /client/proc/cmd_admin_droppod_spawn, /client/proc/respawn_character, /client/proc/spawn_character_mob, //VOREStation Add, - /client/proc/virus2_editor, /client/proc/spawn_chemdisp_cartridge, /client/proc/map_template_load, /client/proc/map_template_upload, @@ -196,7 +195,9 @@ var/list/admin_verbs_spawn = list( /client/proc/generic_structure, //VOREStation Add /client/proc/generic_item, //VOREStation Add /client/proc/create_gm_message, - /client/proc/remove_gm_message + /client/proc/remove_gm_message, + /client/proc/AdminCreateVirus, + /client/proc/ReleaseVirus ) var/list/admin_verbs_server = list( @@ -563,8 +564,9 @@ var/list/admin_verbs_event_manager = list( /client/proc/toggle_random_events, /client/proc/modify_server_news, /client/proc/toggle_spawning_with_recolour, - /client/proc/start_vote - + /client/proc/start_vote, + /client/proc/AdminCreateVirus, + /client/proc/ReleaseVirus ) /client/proc/add_admin_verbs() diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 65b85e4aa47..7bd3b1e4c15 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -283,37 +283,6 @@ message_admins(span_blue("[ckey] creating an admin explosion at [epicenter.loc].")) feedback_add_details("admin_verb","DB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/give_disease2(mob/T as mob in mob_list) // -- Giacom - set category = "Fun.Event Kit" - set name = "Give Disease" - set desc = "Gives a Disease to a mob." - - var/datum/disease2/disease/D = new /datum/disease2/disease() - - var/severity = 1 - var/greater = tgui_input_list(usr, "Is this a lesser, greater, or badmin disease?", "Give Disease", list("Lesser", "Greater", "Badmin")) - switch(greater) - if ("Lesser") severity = 1 - if ("Greater") severity = 2 - if ("Badmin") severity = 99 - - D.makerandom(severity) - D.infectionchance = tgui_input_number(usr, "How virulent is this disease? (1-100)", "Give Disease", D.infectionchance, 100, 1) - - if(istype(T,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = T - if (H.species) - D.affected_species = list(H.species.get_bodytype()) - if(H.species.primitive_form) - D.affected_species |= H.species.primitive_form - if(H.species.greater_form) - D.affected_species |= H.species.greater_form - infect_virus2(T,D,1) - - feedback_add_details("admin_verb","GD2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].") - message_admins(span_blue("[key_name_admin(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance]."), 1) - /client/proc/admin_give_modifier(var/mob/living/L) set category = "Debug.Game" set name = "Give Modifier" diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm index fc2b9189894..e59daf02ef6 100644 --- a/code/modules/admin/view_variables/topic.dm +++ b/code/modules/admin/view_variables/topic.dm @@ -129,18 +129,6 @@ href_list["datumrefresh"] = href_list["give_wound_internal"] - - else if(href_list["give_disease2"]) - if(!check_rights(R_ADMIN|R_FUN|R_EVENT)) return - - var/mob/M = locate(href_list["give_disease2"]) - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_disease2(M) - href_list["datumrefresh"] = href_list["give_spell"] - else if(href_list["godmode"]) if(!check_rights(R_REJUVINATE)) return diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm new file mode 100644 index 00000000000..25e1ea5c4f1 --- /dev/null +++ b/code/modules/events/disease_outbreak.dm @@ -0,0 +1,98 @@ +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 + ) + var/static/list/transmissable_symptoms = list() + var/static/list/diseases_minor = list() + var/static/list/diseases_moderate_major = list() + +/datum/event/disease_outbreak/setup() + if(isemptylist(diseases_minor) && isemptylist(diseases_moderate_major)) + populate_diseases() + if(isemptylist(transmissable_symptoms)) + populate_symptoms() + var/datum/disease/virus + if(prob(50)) + switch(severity) + if(EVENT_LEVEL_MODERATE) + virus = pick(diseases_minor) + if(EVENT_LEVEL_MAJOR) + virus = pick(diseases_moderate_major) + else + stack_trace("Disease Outbreak: Invalid Event Level [severity]. Expected: 1-2") + virus = /datum/disease/cold + chosen_disease = new virus() + else + if(severity == EVENT_LEVEL_MAJOR) + chosen_disease = create_virus(severity * pick(2,3)) //50% chance for a major disease instead of a moderate one + else + chosen_disease = create_virus(severity * 2) + + chosen_disease.carrier = TRUE + +/datum/event/disease_outbreak/start() + GLOB.current_pending_diseases += chosen_disease + + var/list/candidates = list() + for(var/mob/living/carbon/human/G in player_list) + if(G.mind && G.stat != DEAD && G.is_client_active(5) && !player_is_antag(G.mind)) + var/area/A = get_area(G) + if(!A) + continue + if(!(A.z in using_map.station_levels)) + continue + if(A.flags & RAD_SHIELDED) + continue + if(isbelly(G.loc)) + continue + if(!G.CanContractDisease()) + continue + candidates += G + + var/chosen_infect = rand(3, 5) + + while(chosen_infect) + var/mob/living/carbon/human/H = pick(candidates) + H.ContractDisease(chosen_disease) + candidates -= H + + +//Creates a virus with a harmful effect, guaranteed to be spreadable by contact or airborne +/datum/event/disease_outbreak/proc/create_virus(max_severity = 6) + var/datum/disease/advance/A = new /datum/disease/advance + A.symptoms = A.GenerateSymptomsBySeverity(max_severity - 1, max_severity, 2) //Choose "Payload" symptoms + A.AssignProperties(A.GenerateProperties()) + var/list/symptoms_to_try = transmissable_symptoms.Copy() + while(length(symptoms_to_try)) + if(A.spread_text != "Blood") + break + if(length(A.symptoms) < VIRUS_SYMPTOM_LIMIT) //Ensure the virus is spreadable by adding symptoms that boost transmission + var/datum/symptom/TS = pick_n_take(symptoms_to_try) + A.AddSymptom(new TS) + else + popleft(A.symptoms) //We have a full symptom list but are still not transmittable. Try removing one of the "payloads" + + A.AssignProperties(A.GenerateProperties()) + A.name = pick(alphabet_uppercase) + num2text(rand(1,9)) + pick(alphabet_uppercase) + num2text(rand(1,9)) + pick("v", "V", "-" + num2text(game_year), "") + A.Refresh() + return A + +/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)) + continue + switch(CD.severity) + if(NONTHREAT, MINOR) + diseases_minor += candidate + if(MEDIUM, HARMFUL, DANGEROUS, BIOHAZARD) + diseases_moderate_major += candidate + +/datum/event/disease_outbreak/proc/populate_symptoms() + for(var/candidate in subtypesof(/datum/symptom)) + var/datum/symptom/CS = candidate + if(initial(CS.transmittable) > 1) + transmissable_symptoms += candidate diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm index 96c14683b05..08d40416daf 100644 --- a/code/modules/food/food/snacks.dm +++ b/code/modules/food/food/snacks.dm @@ -6892,6 +6892,7 @@ "zombiepowder", "cryptobiolin", "psilocybin")), 5) + reagents.add_reagent("salmonella", 5) /obj/item/reagent_containers/food/snacks/old/pizza name = "\improper Pizza!" diff --git a/code/modules/food/kitchen/smartfridge/medical.dm b/code/modules/food/kitchen/smartfridge/medical.dm index 0e7f17663f0..1f9091bd366 100644 --- a/code/modules/food/kitchen/smartfridge/medical.dm +++ b/code/modules/food/kitchen/smartfridge/medical.dm @@ -31,9 +31,7 @@ icon_contents = "viro" /obj/machinery/smartfridge/virology/accept_check(var/obj/item/O as obj) - if(istype(O,/obj/item/reagent_containers/glass/beaker/vial/)) - return 1 - if(istype(O,/obj/item/virusdish/)) + if(istype(O,/obj/item/storage/pill_bottle) || istype(O,/obj/item/reagent_containers) || istype(O,/obj/item/reagent_containers/glass/)) return 1 return 0 @@ -44,9 +42,7 @@ req_access = list(access_virology) /obj/machinery/smartfridge/secure/virology/accept_check(var/obj/item/O as obj) - if(istype(O,/obj/item/reagent_containers/glass/beaker/vial/)) - return 1 - if(istype(O,/obj/item/virusdish/)) + if(istype(O,/obj/item/storage/pill_bottle) || istype(O,/obj/item/reagent_containers) || istype(O,/obj/item/reagent_containers/glass/)) return 1 return 0 diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index 9d5ea0cc5e9..90af4ee63f4 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -508,14 +508,6 @@ I said no! ) result = /obj/item/reagent_containers/food/snacks/icecreamsandwich -// Fuck Science! -/datum/recipe/ruinedvirusdish - items = list( - /obj/item/virusdish - ) - result = /obj/item/ruinedvirusdish - - /datum/recipe/onionsoup fruit = list("onion" = 1) reagents = list("water" = 10) diff --git a/code/modules/gamemaster/event2/events/medical/virus.dm b/code/modules/gamemaster/event2/events/medical/virus.dm deleted file mode 100644 index ad221c0d043..00000000000 --- a/code/modules/gamemaster/event2/events/medical/virus.dm +++ /dev/null @@ -1,69 +0,0 @@ -/datum/event2/meta/virus - name = "viral infection" - event_class = "virus" - departments = list(DEPARTMENT_MEDICAL, DEPARTMENT_EVERYONE) - chaos = 40 - chaotic_threshold = EVENT_CHAOS_THRESHOLD_HIGH_IMPACT - event_type = /datum/event2/event/virus - -/datum/event2/meta/virus/superbug - name = "viral superbug" - chaos = 60 - event_type = /datum/event2/event/virus/superbug - -/datum/event2/meta/virus/outbreak - name = "viral outbreak" - chaos = 60 - event_type = /datum/event2/event/virus/outbreak - -/datum/event2/meta/virus/get_weight() - var/list/virologists = metric.get_people_with_alt_title(/datum/job/doctor, /datum/alt_title/virologist) - virologists += metric.get_people_with_job(/datum/job/cmo) - - return virologists.len * 25 - - - -/datum/event2/event/virus - announce_delay_lower_bound = 1 MINUTE - announce_delay_upper_bound = 3 MINUTES - var/number_of_viruses = 1 - var/virus_power = 2 // Ranges from 1 to 3, with 1 being the weakest. - var/list/candidates = list() - -// A single powerful virus. -/datum/event2/event/virus/superbug - virus_power = 3 - -// A lot of weaker viruses. -/datum/event2/event/virus/outbreak - virus_power = 1 - number_of_viruses = 3 - - - -/datum/event2/event/virus/set_up() - for(var/mob/living/carbon/human/H in player_list) - if(H.client && !H.isSynthetic() && H.stat != DEAD && !player_is_antag(H.mind) && !isbelly(H.loc)) - candidates += H - candidates = shuffle(candidates) - -/datum/event2/event/virus/announce() - command_announcement.Announce("Confirmed outbreak of level 7 biohazard aboard \the [location_name()]. \ - All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg') - -/datum/event2/event/virus/start() - if(!candidates.len) - log_debug("Virus event could not find any valid targets to infect. Aborting.") - abort() - return - - for(var/i = 1 to number_of_viruses) - var/mob/living/carbon/human/H = LAZYACCESS(candidates, 1) - if(!H) - return - var/datum/disease2/disease/D = new() - D.makerandom(virus_power) - log_debug("Virus event is now infecting \the [H] with a new random virus.") - infect_mob(H, D) - candidates -= H diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index fbf72f59bb5..9b6f1210c81 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -11,8 +11,6 @@ /mob/living/carbon/Life() ..() - handle_viruses() - // Increase germ_level regularly if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level germ_level++ @@ -398,7 +396,10 @@ return ..() if(istype(A, /mob/living/carbon) && prob(10)) - spread_disease_to(A, "Contact") + var/mob/living/carbon/human/H = A + for(var/datum/disease/D in GetViruses()) + if(D.spread_flags & CONTACT_GENERAL) + H.ContractDisease(D) /mob/living/carbon/cannot_use_vents() return @@ -542,3 +543,12 @@ if(allergen_type in species.food_preference) return species.food_preference_bonus return 0 + +/mob/living/carbon/handle_diseases() + for(var/thing in GetViruses()) + var/datum/disease/D = thing + if(prob(D.infectivity)) + D.spread() + + if(stat != DEAD || D.allow_dead) + D.stage_act() diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 8dc29e6d3b8..24a03592974 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -3,7 +3,6 @@ blocks_emissive = EMISSIVE_BLOCK_UNIQUE // BLEH, this could be improved for transparent species and stuff! And blocks glowing eyes?! var/datum/species/species //Contains icon generation and language information, set during New(). var/list/stomach_contents = list() - var/list/datum/disease2/disease/virus2 = list() var/list/antibodies = list() var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm @@ -29,4 +28,4 @@ //these two help govern taste. The first is the last time a taste message was shown to the plaer. //the second is the message in question. var/last_taste_time = 0 - var/last_taste_text = "" \ No newline at end of file + var/last_taste_text = "" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index eb89d073647..5756af7e0a6 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1062,10 +1062,6 @@ sync_organ_dna() // end vorestation addition - for (var/ID in virus2) - var/datum/disease2/disease/V = virus2[ID] - V.cure(src) - losebreath = 0 ..() diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index ddcc522f210..542dafb6f68 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -44,6 +44,17 @@ if(!temp || !temp.is_usable()) to_chat(H, span_warning("You can't use your hand.")) return + + for(var/thing in GetViruses()) + var/datum/disease/D = thing + if(D.IsSpreadByTouch()) + H.ContractDisease(D) + + for(var/thing in H.GetViruses()) + var/datum/disease/D = thing + if(D.IsSpreadByTouch()) + ContractDisease(D) + if(H.lying) return M.break_cloak() @@ -65,8 +76,9 @@ return FALSE if(istype(M,/mob/living/carbon)) - var/mob/living/carbon/C = M - C.spread_disease_to(src, "Contact") + for(var/datum/disease/D in M.GetViruses()) + if(D.spread_flags & CONTACT_HANDS) + ContractDisease(D) switch(M.a_intent) if(I_HELP) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 7d64ac51cfe..3d071559965 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -504,9 +504,12 @@ /mob/living/carbon/human/handle_post_breath(datum/gas_mixture/breath) ..() //spread some viruses while we are at it - if(breath && virus2.len > 0 && prob(10)) - for(var/mob/living/carbon/M in view(1,src)) - src.spread_disease_to(M) + if(breath && !isnull(viruses) && prob(10)) + for(var/datum/disease/D in GetViruses()) + if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS)) + continue + for(var/mob/living/carbon/M in view(1,src)) + ContractDisease(D) /mob/living/carbon/human/get_breath_from_internal(volume_needed=BREATH_VOLUME) @@ -2031,8 +2034,8 @@ if (BITTEST(hud_updateflag, STATUS_HUD)) var/foundVirus = 0 - for (var/ID in virus2) - if (ID in virusDB) + for (var/datum/disease/D in GetViruses()) + if(D.discovered) foundVirus = 1 break @@ -2054,8 +2057,10 @@ holder2.icon_state = "hudbrainworm" else holder.icon_state = "hudhealthy" - if(virus2.len) - holder2.icon_state = "hudill" + if(viruses.len) + for(var/datum/disease/D in GetViruses()) + if(D.discovered) + holder2.icon_state = "hudill" else holder2.icon_state = "hudhealthy" if(block_hud) diff --git a/code/modules/mob/living/carbon/viruses.dm b/code/modules/mob/living/carbon/viruses.dm deleted file mode 100644 index f57bc878a00..00000000000 --- a/code/modules/mob/living/carbon/viruses.dm +++ /dev/null @@ -1,48 +0,0 @@ -/mob/living/carbon/proc/handle_viruses() - - if(status_flags & GODMODE) return 0 //godmode - - if(bodytemperature > 406) - for (var/ID in virus2) - var/datum/disease2/disease/V = virus2[ID] - V.cure(src) - - if(life_tick % 3) //don't spam checks over all objects in view every tick. - for(var/obj/effect/decal/cleanable/O in view(1,src)) - if(istype(O,/obj/effect/decal/cleanable/blood)) - var/obj/effect/decal/cleanable/blood/B = O - if(B.virus2.len) - for (var/ID in B.virus2) - var/datum/disease2/disease/V = B.virus2[ID] - infect_virus2(src,V) - - else if(istype(O,/obj/effect/decal/cleanable/mucus)) - var/obj/effect/decal/cleanable/mucus/M = O - if(M.virus2.len) - for (var/ID in M.virus2) - var/datum/disease2/disease/V = M.virus2[ID] - infect_virus2(src,V) - - else if(istype(O,/obj/effect/decal/cleanable/vomit)) - var/obj/effect/decal/cleanable/vomit/Vom = O - if(Vom.virus2.len) - for (var/ID in Vom.virus2) - var/datum/disease2/disease/V = Vom.virus2[ID] - infect_virus2(src,V) - - if(virus2.len) - for (var/ID in virus2) - var/datum/disease2/disease/V = virus2[ID] - if(isnull(V)) // Trying to figure out a runtime error that keeps repeating - CRASH("virus2 nulled before calling activate()") - else - V.activate(src) - // activate may have deleted the virus - if(!V) continue - - // check if we're immune - var/list/common_antibodies = V.antigen & src.antibodies - if(common_antibodies.len) - V.dead = 1 - - return \ No newline at end of file diff --git a/code/modules/mob/living/default_language.dm b/code/modules/mob/living/default_language.dm index fba38e21f52..66cdcb28adb 100644 --- a/code/modules/mob/living/default_language.dm +++ b/code/modules/mob/living/default_language.dm @@ -1,10 +1,28 @@ /mob/living var/datum/language/default_language -/mob/living/verb/set_default_language(language as null|anything in languages) +/mob/living/verb/set_default_language() set name = "Set Default Language" set category = "IC.Settings" + var/language = tgui_input_list(usr, "Select your default language", "Available languages", languages) + + apply_default_language(language) + +// Silicons can't neccessarily speak everything in their languages list +/mob/living/silicon/set_default_language() + var/language = tgui_input_list(usr, "Select your default language", "Available languages", speech_synthesizer_langs) + // Silicons have no species language usually. So let's default them to GALCOM + if(!language) + to_chat(src, span_notice("You will now speak your standard default language, common, if you do not specify a language when speaking.")) + for(var/datum/language/lang in speech_synthesizer_langs) + if(lang.name == LANGUAGE_GALCOM) + default_language = lang + break + return + apply_default_language(language) + +/mob/living/proc/apply_default_language(var/language) if (only_species_language && language != GLOB.all_languages[src.species_language]) to_chat(src, span_notice("You can only speak your species language, [src.species_language].")) return 0 @@ -22,10 +40,6 @@ to_chat(src, span_notice("You will now speak whatever your standard default language is if you do not specify one when speaking.")) default_language = language -// Silicons can't neccessarily speak everything in their languages list -/mob/living/silicon/set_default_language(language as null|anything in speech_synthesizer_langs) - ..() - /mob/living/verb/check_default_language() set name = "Check Default Language" set category = "IC.Game" diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index a15b0e115ea..a599ff38e2e 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -51,6 +51,10 @@ //Chemicals in the body, this is moved over here so that blood can be added after death handle_chemicals_in_body() + // Handle viruses - Dead or not! + if(LAZYLEN(viruses)) + handle_diseases() + //Handle temperature/pressure differences between body and environment if(environment) handle_environment(environment) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/macrophage.dm b/code/modules/mob/living/simple_mob/subtypes/vore/macrophage.dm new file mode 100644 index 00000000000..dacbebb57da --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/macrophage.dm @@ -0,0 +1,63 @@ +/mob/living/simple_mob/vore/aggressive/macrophage + name = "Germ" + desc = "A giant virus!" + icon = 'icons/mob/macrophage.dmi' + icon_state = "macrophage-1" + + faction = FACTION_MACROBACTERIA + maxHealth = 60 + health = 60 + + var/datum/disease/base_disease = null + var/list/infections = list() + + melee_damage_lower = 1 + melee_damage_upper = 5 + grab_resist = 100 + see_in_dark = 8 + + response_help = "shoos" + response_disarm = "swats away" + response_harm = "squashes" + attacktext = list("squashed") + friendly = list("shoos", "rubs") + + vore_bump_chance = "attempts to absorb" + + vore_active = TRUE + vore_capacity = 1 + + can_be_drop_prey = FALSE + allow_mind_transfer = TRUE + + ai_holder_type = /datum/ai_holder/simple_mob/melee + +/mob/living/simple_mob/vore/aggressive/macrophage/green + icon_state = "macrophage-2" + +/mob/living/simple_mob/vore/aggressive/macrophage/pink + icon_state = "macrophage-3" + +/mob/living/simple_mob/vore/aggressive/macrophage/blue + icon_state = "macrophage-4" + +/obj/belly/macrophage + name = "capsid" + fancy_vore = TRUE + contamination_color = "green" + vore_verb = "absorb" + escapable = TRUE + escapable = 5 + desc = "In an attempt to get away from the giant virus, it's oversized envelope proteins dragged you right past it's matrix, encapsulating you deep inside it's capsid... The strange walls kneading and keeping you tight along within it's nucleoprotein." + belly_fullscreen = "VBO_gematically_angular" + belly_fullscreen_color = "#87d8d8" + digest_mode = DM_ABSORB + affects_vore_sprites = FALSE + +/mob/living/simple_mob/vore/aggressive/macrophage/init_vore() + + if(LAZYLEN(vore_organs)) + return TRUE + + var/obj/belly/B = new /obj/belly/macrophage(src) + vore_selected = B diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 26118480b04..1b069023250 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -239,3 +239,6 @@ var/list/list/misc_tabs = list() var/list/datum/action/actions + + var/list/viruses + var/list/resistances diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 74894542c58..72b24602f9e 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -246,10 +246,19 @@ var/const/CE_STABLE_THRESHOLD = 0.5 //set reagent data B.data["donor"] = src - if (!B.data["virus2"]) - B.data["virus2"] = list() - B.data["virus2"] |= virus_copylist(src.virus2) - B.data["antibodies"] = src.antibodies + if(!B.data["viruses"]) + B.data["viruses"] = list() + + for(var/datum/disease/D in GetViruses()) + if(D.spread_flags & SPECIAL || D.spread_flags & NON_CONTAGIOUS) + continue + B.data["viruses"] |= D.Copy() + + if(!B.data["resistances"]) + B.data["resistances"] = list() + + if(B.data["resistances"]) + B.data["resistances"] |= GetResistances() B.data["blood_DNA"] = copytext(src.dna.unique_enzymes,1,0) B.data["blood_type"] = copytext(src.dna.b_type,1,0) @@ -282,10 +291,14 @@ var/const/CE_STABLE_THRESHOLD = 0.5 /mob/living/carbon/proc/inject_blood(var/datum/reagent/blood/injected, var/amount) if (!injected || !istype(injected)) return - var/list/sniffles = virus_copylist(injected.data["virus2"]) + var/list/sniffles = injected.data["viruses"] for(var/ID in sniffles) - var/datum/disease2/disease/sniffle = sniffles[ID] - infect_virus2(src,sniffle,1) + var/datum/disease/D = ID + if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS)) // You can't put non-contagius diseases in blood, but just in case + continue + ContractDisease(D) + if (injected.data["resistances"] && prob(5)) + antibodies |= injected.data["resistances"] if (injected.data["antibodies"] && prob(5)) antibodies |= injected.data["antibodies"] var/list/chems = list() @@ -426,8 +439,8 @@ var/const/CE_STABLE_THRESHOLD = 0.5 B.blood_DNA[source.data["blood_DNA"]] = "O+" // Update virus information. - if(source.data["virus2"]) - B.virus2 = virus_copylist(source.data["virus2"]) + if(source.data["viruses"]) + B.viruses = source.data["viruses"] B.fluorescent = 0 B.invisibility = 0 diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index e963b548493..5379ab7f423 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -18,7 +18,7 @@ var/emp_proof = FALSE var/static/cell_uid = 1 // Unique ID of this power cell. Used to reduce bunch of uglier code in nanoUI. var/c_uid - var/charge = 0 // note %age conveted to actual charge in New + var/charge = 1000 // maximum charge on spawn var/maxcharge = 1000 var/rigged = 0 // true if rigged to explode var/minor_fault = 0 //If not 100% reliable, it will build up faults. @@ -36,10 +36,9 @@ var/standard_overlays = TRUE var/last_overlay_state = null // Used to optimize update_icon() calls. -/obj/item/cell/New() - ..() +/obj/item/cell/Initialize() + . = ..() c_uid = cell_uid++ - charge = maxcharge update_icon() if(self_recharge) START_PROCESSING(SSobj, src) diff --git a/code/modules/power/cells/device_cells.dm b/code/modules/power/cells/device_cells.dm index fd93e450f14..4179cf6c2db 100644 --- a/code/modules/power/cells/device_cells.dm +++ b/code/modules/power/cells/device_cells.dm @@ -10,15 +10,14 @@ force = 0 throw_speed = 5 throw_range = 7 + charge = 480 maxcharge = 480 charge_amount = 5 matter = list(MAT_STEEL = 350, MAT_GLASS = 50) preserve_item = 1 -/obj/item/cell/device/empty/Initialize() - . = ..() +/obj/item/cell/device/empty charge = 0 - update_icon() /* * Crap Device @@ -29,16 +28,15 @@ description_fluff = "You can't top the rust top." //TOTALLY TRADEMARK INFRINGEMENT origin_tech = list(TECH_POWER = 0) icon_state = "device_crap" + charge = 240 maxcharge = 240 matter = list(MAT_STEEL = 350, MAT_GLASS = 30) /obj/item/cell/device/crap/update_icon() //No visible charge indicator return -/obj/item/cell/device/crap/empty/Initialize() - . = ..() +/obj/item/cell/device/crap/empty charge = 0 - update_icon() /* * Hyper Device @@ -47,13 +45,12 @@ name = "hyper device power cell" desc = "A small power cell designed to power handheld devices. Has a better charge than a standard device cell." icon_state = "hype_device_cell" + charge = 600 maxcharge = 600 matter = list(MAT_STEEL = 400, MAT_GLASS = 60) -/obj/item/cell/device/hyper/empty/Initialize() - . = ..() +/obj/item/cell/device/hyper/empty charge = 0 - update_icon() /* * EMP Proof Device @@ -65,10 +62,8 @@ matter = list(MAT_STEEL = 400, MAT_GLASS = 60) emp_proof = TRUE -/obj/item/cell/device/empproof/empty/Initialize() - . = ..() +/obj/item/cell/device/empproof/empty charge = 0 - update_icon() /* * Weapon @@ -77,13 +72,12 @@ name = "weapon power cell" desc = "A small power cell designed to power handheld weaponry." icon_state = "weapon_cell" + charge = 2400 maxcharge = 2400 charge_amount = 20 -/obj/item/cell/device/weapon/empty/Initialize() - . = ..() +/obj/item/cell/device/weapon/empty charge = 0 - update_icon() /* * EMP Proof Weapon @@ -95,10 +89,8 @@ matter = list(MAT_STEEL = 400, MAT_GLASS = 60) emp_proof = TRUE -/obj/item/cell/device/weapon/empproof/empty/Initialize() - . = ..() +/obj/item/cell/device/weapon/empproof/empty charge = 0 - update_icon() /* * Self-charging Weapon @@ -139,7 +131,7 @@ value = CATALOGUER_REWARD_EASY /obj/item/cell/device/weapon/recharge/alien - name = "void cell" + name = "void cell (device)" desc = "An alien technology that produces energy seemingly out of nowhere. Its small, cylinderal shape means it might be able to be used with human technology, perhaps?" catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/alien_void_cell) icon = 'icons/obj/abductor.dmi' @@ -147,6 +139,24 @@ charge_amount = 120 // 5%. charge_delay = 50 // Every five seconds, bit faster than the default. origin_tech = list(TECH_POWER = 8, TECH_ENGINEERING = 6) + var/swaps_to = /obj/item/cell/void + standard_overlays = FALSE /obj/item/cell/device/weapon/recharge/alien/update_icon() - return // No overlays please. \ No newline at end of file + return // No overlays please. + +/obj/item/cell/device/weapon/recharge/alien/attack_self(var/mob/user) + user.remove_from_mob(src) + to_chat(user, span_notice("You swap [src] to 'machinery cell' mode.")) + var/obj/item/cell/newcell = new swaps_to(null) + user.put_in_active_hand(newcell) + var/percentage = charge/maxcharge + newcell.charge = newcell.maxcharge * percentage + newcell.persist_storable = persist_storable + qdel(src) + +// Bloo friendlier hybrid tech +/obj/item/cell/device/weapon/recharge/alien/hybrid + icon = 'icons/obj/power_vr.dmi' + icon_state = "cellb" + swaps_to = /obj/item/cell/void/hybrid diff --git a/code/modules/power/cells/device_cells_vr.dm b/code/modules/power/cells/device_cells_vr.dm deleted file mode 100644 index 8a62f646aae..00000000000 --- a/code/modules/power/cells/device_cells_vr.dm +++ /dev/null @@ -1,53 +0,0 @@ - -//The device cell -/obj/item/cell/device/weapon/recharge/alien - name = "void cell (device)" - var/swaps_to = /obj/item/cell/void - standard_overlays = FALSE - -/obj/item/cell/device/weapon/recharge/alien/attack_self(var/mob/user) - user.remove_from_mob(src) - to_chat(user, span_notice("You swap [src] to 'machinery cell' mode.")) - var/obj/item/cell/newcell = new swaps_to(null) - user.put_in_active_hand(newcell) - var/percentage = charge/maxcharge - newcell.charge = newcell.maxcharge * percentage - newcell.persist_storable = persist_storable - qdel(src) - -//The machine cell -/obj/item/cell/void - name = "void cell (machinery)" - desc = "An alien technology that produces energy seemingly out of nowhere. Its small, cylinderal shape means it might be able to be used with human technology, perhaps?" - origin_tech = list(TECH_POWER = 8, TECH_ENGINEERING = 6) - icon = 'icons/obj/abductor.dmi' - icon_state = "cell" - maxcharge = 4800 //10x the device version - charge_amount = 1200 //10x the device version - self_recharge = TRUE - charge_delay = 50 - matter = null - standard_overlays = FALSE - var/swaps_to = /obj/item/cell/device/weapon/recharge/alien - robot_durability = 100 - -/obj/item/cell/void/attack_self(var/mob/user) - user.remove_from_mob(src) - to_chat(user, span_notice("You swap [src] to 'device cell' mode.")) - var/obj/item/cell/newcell = new swaps_to(null) - user.put_in_active_hand(newcell) - var/percentage = charge/maxcharge - newcell.charge = newcell.maxcharge * percentage - newcell.persist_storable = persist_storable - qdel(src) - -// Bloo friendlier hybrid tech -/obj/item/cell/device/weapon/recharge/alien/hybrid - icon = 'icons/obj/power_vr.dmi' - icon_state = "cellb" - swaps_to = /obj/item/cell/void/hybrid - -/obj/item/cell/void/hybrid - icon = 'icons/obj/power_vr.dmi' - icon_state = "cellb" - swaps_to = /obj/item/cell/device/weapon/recharge/alien/hybrid diff --git a/code/modules/power/cells/esoteric_cells.dm b/code/modules/power/cells/esoteric_cells.dm index aeacc6b3e67..925a8f55437 100644 --- a/code/modules/power/cells/esoteric_cells.dm +++ b/code/modules/power/cells/esoteric_cells.dm @@ -4,6 +4,7 @@ desc = "A modified power cell sitting in a highly conductive chassis." origin_tech = list(TECH_POWER = 2) icon_state = "modded" + charge = 10000 maxcharge = 10000 matter = list(MAT_STEEL = 1000, MAT_GLASS = 80, MAT_SILVER = 100) self_recharge = TRUE diff --git a/code/modules/power/cells/power_cells.dm b/code/modules/power/cells/power_cells.dm index f4a7c9d1aa0..3722b6832f5 100644 --- a/code/modules/power/cells/power_cells.dm +++ b/code/modules/power/cells/power_cells.dm @@ -1,8 +1,7 @@ /* * Empty */ -/obj/item/cell/empty/New() - ..() +/obj/item/cell/empty charge = 0 /* @@ -14,6 +13,7 @@ description_fluff = "You can't top the rust top." //TOTALLY TRADEMARK INFRINGEMENT origin_tech = list(TECH_POWER = 0) icon_state = "crap" + charge = 500 maxcharge = 500 matter = list(MAT_STEEL = 700, MAT_GLASS = 40) robot_durability = 20 @@ -21,8 +21,7 @@ /obj/item/cell/crap/update_icon() //No visible charge indicator return -/obj/item/cell/crap/empty/New() - ..() +/obj/item/cell/crap/empty charge = 0 /* @@ -32,6 +31,7 @@ name = "heavy-duty power cell" origin_tech = list(TECH_POWER = 1) icon_state = "apc" + charge = 5000 maxcharge = 5000 matter = list(MAT_STEEL = 700, MAT_GLASS = 50) @@ -40,6 +40,7 @@ */ /obj/item/cell/robot_station name = "standard robot power cell" + charge = 7500 maxcharge = 7500 /* @@ -49,14 +50,13 @@ name = "high-capacity power cell" origin_tech = list(TECH_POWER = 2) icon_state = "high" + charge = 10000 maxcharge = 10000 matter = list(MAT_STEEL = 700, MAT_GLASS = 60) robot_durability = 55 -/obj/item/cell/high/empty/New() - ..() +/obj/item/cell/high/empty charge = 0 - update_icon() /* * Super @@ -65,14 +65,13 @@ name = "super-capacity power cell" origin_tech = list(TECH_POWER = 5) icon_state = "super" + charge = 20000 maxcharge = 20000 matter = list(MAT_STEEL = 700, MAT_GLASS = 70) robot_durability = 60 -/obj/item/cell/super/empty/New() - ..() +/obj/item/cell/super/empty charge = 0 - update_icon() /* * Syndicate @@ -81,6 +80,7 @@ name = "syndicate robot power cell" description_fluff = "Almost as good as a hyper." icon_state = "super" //We don't want roboticists confuse it with a low standard cell + charge = 25000 maxcharge = 25000 robot_durability = 65 @@ -91,14 +91,13 @@ name = "hyper-capacity power cell" origin_tech = list(TECH_POWER = 6) icon_state = "hyper" + charge = 30000 maxcharge = 30000 matter = list(MAT_STEEL = 700, MAT_GLASS = 80) robot_durability = 70 -/obj/item/cell/hyper/empty/New() - ..() +/obj/item/cell/hyper/empty charge = 0 - update_icon() /* * Mecha @@ -146,6 +145,7 @@ name = "infinite-capacity power cell!" icon_state = "infinity" origin_tech = null + charge = 30000 maxcharge = 30000 //determines how badly mobs get shocked matter = list(MAT_STEEL = 700, MAT_GLASS = 80) robot_durability = 200 @@ -180,6 +180,7 @@ icon_state = "yellow slime extract" //"potato_battery" connector_type = "slime" description_info = "This 'cell' holds a max charge of 10k and self recharges over time." + charge = 10000 maxcharge = 10000 matter = null self_recharge = TRUE @@ -191,6 +192,7 @@ /obj/item/cell/emergency_light name = "miniature power cell" desc = "A tiny power cell with a very low power capacity. Used in light fixtures to power them in the event of an outage." + charge = 120 maxcharge = 120 //Emergency lights use 0.2 W per tick, meaning ~10 minutes of emergency power from a cell matter = list(MAT_GLASS = 20) icon_state = "em_light" @@ -247,3 +249,35 @@ cut_overlays() target.adjust_nutrition(amount) user.custom_emote(message = "connects \the [src] to [user == target ? "their" : "[target]'s"] charging port, expending it.") + +//The machine cell +/obj/item/cell/void + name = "void cell (machinery)" + desc = "An alien technology that produces energy seemingly out of nowhere. Its small, cylinderal shape means it might be able to be used with human technology, perhaps?" + origin_tech = list(TECH_POWER = 8, TECH_ENGINEERING = 6) + icon = 'icons/obj/abductor.dmi' + icon_state = "cell" + charge = 4800 + maxcharge = 4800 //10x the device version + charge_amount = 1200 //10x the device version + self_recharge = TRUE + charge_delay = 50 + matter = null + standard_overlays = FALSE + var/swaps_to = /obj/item/cell/device/weapon/recharge/alien + robot_durability = 100 + +/obj/item/cell/void/attack_self(var/mob/user) + user.remove_from_mob(src) + to_chat(user, span_notice("You swap [src] to 'device cell' mode.")) + var/obj/item/cell/newcell = new swaps_to(null) + user.put_in_active_hand(newcell) + var/percentage = charge/maxcharge + newcell.charge = newcell.maxcharge * percentage + newcell.persist_storable = persist_storable + qdel(src) + +/obj/item/cell/void/hybrid + icon = 'icons/obj/power_vr.dmi' + icon_state = "cellb" + swaps_to = /obj/item/cell/device/weapon/recharge/alien/hybrid diff --git a/code/modules/reagents/reactions/instant/virology.dm b/code/modules/reagents/reactions/instant/virology.dm new file mode 100644 index 00000000000..f8d50383267 --- /dev/null +++ b/code/modules/reagents/reactions/instant/virology.dm @@ -0,0 +1,133 @@ +/decl/chemical_reaction/instant/virus_food_mutagen + name = "mutagenic agar" + id = "mutagenvirusfood" + result = "mutagenvirusfood" + required_reagents = list("mutagen" = 1, "virusfood" = 1) + result_amount = 1 + +/decl/chemical_reaction/instant/virus_food_adranol + name = "virus rations" + id = "adranolvirusfood" + result = "adranolvirusfood" + required_reagents = list("adranol" = 1, "virusfood" = 1) + result_amount = 1 + +/decl/chemical_reaction/instant/virus_food_phoron + name = "phoronic virus food" + id = "phoronvirusfood" + result = "phoronvirusfood" + required_reagents = list("phoron" = 1, "virusfood" = 1) + result_amount = 1 + +/decl/chemical_reaction/instant/virus_food_phoron_adranol + name = "weakened phoronic virus food" + id = "weakphoronvirusfood" + result = "weakphoronvirusfood" + required_reagents = list("adranol" = 1, "phoronvirusfood" = 1) + result_amount = 2 + +/decl/chemical_reaction/instant/virus_food_mutagen_sugar + name = "sucrose agar" + id = "sugarvirusfood" + result = "sugarvirusfood" + required_reagents = list("sugar" = 1, "mutagenvirusfood" = 1) + result_amount = 2 + +/decl/chemical_reaction/instant/virus_food_mutagen_inaprovaline + name = "sucrose agar" + id = "inaprovalinevirusfood" + result = "sugarvirusfood" + required_reagents = list("inaprovaline" = 1, "mutagenvirusfood" = 1) + result_amount = 2 + +/decl/chemical_reaction/instant/mix_virus + name = "Mix Virus" + id = "mixvirus" + required_reagents = list("virusfood" = 1) + catalysts = list("blood" = 1) + var/level_min = 0 + var/level_max = 2 + +/decl/chemical_reaction/instant/mix_virus/on_reaction(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.Evolve(level_min, level_max) + +/decl/chemical_reaction/instant/mix_virus/mix_virus_2 + name = "Mix Virus 2" + id = "mixvirus2" + required_reagents = list("mutagen" = 1) + level_min = 2 + level_max = 4 + +/decl/chemical_reaction/instant/mix_virus/mix_virus_3 + name = "Mix Virus 3" + id = "mixvirus3" + required_reagents = list("phoron" = 1) + level_min = 4 + level_max = 6 + +/decl/chemical_reaction/instant/mix_virus/mix_virus_4 + name = "Mix Virus 4" + id = "mixvirus4" + required_reagents = list("uranium" = 1) + level_min = 5 + level_max = 6 + +/decl/chemical_reaction/instant/mix_virus/mix_virus_5 + name = "Mix Virus 5" + id = "mixvirus5" + required_reagents = list("mutagenvirusfood" = 1) + level_min = 3 + level_max = 3 + +/decl/chemical_reaction/instant/mix_virus/mix_virus_6 + name = "Mix Virus 6" + id = "mixvirus6" + required_reagents = list("sugarvirusfood" = 1) + level_min = 4 + level_max = 4 + +/decl/chemical_reaction/instant/mix_virus/mix_virus_7 + name = "Mix Virus 7" + id = "mixvirus7" + required_reagents = list("weakphoronvirusfood" = 1) + level_min = 5 + level_max = 5 + +/decl/chemical_reaction/instant/mix_virus/mix_virus_8 + name = "Mix Virus 8" + id = "mixvirus8" + required_reagents = list("phoronvirusfood" = 1) + level_min = 6 + level_max = 6 + +/decl/chemical_reaction/instant/mix_virus/mix_virus_9 + name = "Mix Virus 9" + id = "mixvirus9" + required_reagents = list("adranolvirusfood" = 1) + level_min = 1 + level_max = 1 + +/decl/chemical_reaction/instant/mix_virus/rem_virus + name = "Devolve Virus" + id = "remvirus" + required_reagents = list("adranol" = 1) + catalysts = list("blood" = 1) + +/decl/chemical_reaction/instant/mix_virus/rem_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.Devolve() + +/decl/chemical_reaction/instant/antibodies + name = "Antibodies" + id = "antibodiesmix" + result = "antibodies" + required_reagents = list("vaccine") + catalysts = list("inaprovaline" = 0.1) + result_amount = 0.5 diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index cc4229e3896..0298998d7f4 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -39,17 +39,16 @@ /obj/item/storage/secure/safe, /obj/machinery/iv_drip, /obj/structure/medical_stand, //VOREStation Add, - /obj/machinery/disease2/incubator, /obj/machinery/disposal, /mob/living/simple_mob/animal/passive/cow, /mob/living/simple_mob/animal/goat, - /obj/machinery/computer/centrifuge, /obj/machinery/sleeper, /obj/machinery/smartfridge/, /obj/machinery/biogenerator, /obj/structure/frame, /obj/machinery/radiocarbon_spectrometer, - /obj/machinery/portable_atmospherics/powered/reagent_distillery + /obj/machinery/portable_atmospherics/powered/reagent_distillery, + /obj/machinery/computer/pandemic ) /obj/item/reagent_containers/glass/Initialize() diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index fb98d48483e..0ba23194183 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -381,5 +381,4 @@ /obj/item/reagent_containers/hypospray/autoinjector/biginjector/contaminated/do_injection(mob/living/carbon/human/H, mob/living/user) . = ..() if(.) // Will occur if successfully injected. - infect_mob_random_lesser(H) add_attack_logs(user, H, "Infected \the [H] with \the [src], by \the [user].") diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index bc472d3424c..7c5c3cc9c68 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -32,7 +32,7 @@ var/used = FALSE var/dirtiness = 0 var/list/targets - var/list/datum/disease2/disease/viruses + var/list/datum/disease/viruses drop_sound = 'sound/items/drop/glass.ogg' pickup_sound = 'sound/items/pickup/glass.ogg' @@ -402,10 +402,10 @@ targets |= hash //Grab any viruses they have - if(iscarbon(target) && LAZYLEN(target.virus2.len)) + if(iscarbon(target) && LAZYLEN(target.viruses.len)) LAZYINITLIST(viruses) - var/datum/disease2/disease/virus = pick(target.virus2.len) - viruses[hash] = virus.getcopy() + var/datum/disease/virus = pick(target.viruses.len) + viruses[hash] = virus.Copy() //Dirtiness should be very low if you're the first injectee. If you're spam-injecting 4 people in a row around you though, //This gives the last one a 30% chance of infection. @@ -421,8 +421,8 @@ if(LAZYLEN(viruses) && prob(75)) var/old_hash = pick(viruses) if(hash != old_hash) //Same virus you already had? - var/datum/disease2/disease/virus = viruses[old_hash] - infect_virus2(target,virus.getcopy()) + var/datum/disease/virus = viruses[old_hash] + target.ContractDisease(virus) if(!used) START_PROCESSING(SSobj, src) diff --git a/code/modules/reagents/reagent_containers/virology.dm b/code/modules/reagents/reagent_containers/virology.dm new file mode 100644 index 00000000000..a1d4403900f --- /dev/null +++ b/code/modules/reagents/reagent_containers/virology.dm @@ -0,0 +1,26 @@ +/obj/item/reagent_containers/glass/bottle/culture + name = "virus culture" + desc = "A bottle with a virus culture" + icon_state = "bottle-1" + var/list/data = list("donor" = null, "viruses" = null, "blood_DNA" = null, "blood_type" = null, "resistances" = null, "trace_chems" = null) + var/list/diseases = list() + +/obj/item/reagent_containers/glass/bottle/culture/cold + name = "cold virus culture" + desc = "A bottle with the common cold culture" + +/obj/item/reagent_containers/glass/bottle/culture/cold/Initialize() + . = ..() + diseases += new /datum/disease/advance/cold + data["viruses"] = diseases + reagents.add_reagent("blood", 10, data) + +/obj/item/reagent_containers/glass/bottle/culture/flu + name = "flu virus culture" + desc = "A bottle with the flu culture" + +/obj/item/reagent_containers/glass/bottle/culture/flu/Initialize() + . = ..() + diseases += new /datum/disease/advance/flu + data["viruses"] = diseases + reagents.add_reagent("blood", 10, data) diff --git a/code/modules/reagents/reagents/core.dm b/code/modules/reagents/reagents/core.dm index 10a50a3b982..8157632742d 100644 --- a/code/modules/reagents/reagents/core.dm +++ b/code/modules/reagents/reagents/core.dm @@ -23,9 +23,9 @@ /datum/reagent/blood/get_data() // Just in case you have a reagent that handles data differently. var/t = data.Copy() - if(t["virus2"]) - var/list/v = t["virus2"] - t["virus2"] = v.Copy() + if(t["viruses"]) + var/list/v = t["viruses"] + t["viruses"] = v.Copy() return t /datum/reagent/blood/touch_turf(var/turf/simulated/T) @@ -70,13 +70,16 @@ if(effective_dose > 15) if(!is_vampire) //VOREStation Edit. M.adjustToxLoss(removed) //VOREStation Edit. - if(data && data["virus2"]) - var/list/vlist = data["virus2"] + if(data && data["viruses"]) + var/list/vlist = data["viruses"] if(vlist.len) for(var/ID in vlist) - var/datum/disease2/disease/V = vlist[ID] - if(V.spreadtype == "Contact") - infect_virus2(M, V.getcopy()) + if(!ID) + continue + var/datum/disease/D = ID + if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS)) + continue + M.ContractDisease(D) /datum/reagent/blood/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) if(ishuman(M)) @@ -86,15 +89,59 @@ if(alien == IS_SLIME) affect_ingest(M, alien, removed) return - if(data && data["virus2"]) - var/list/vlist = data["virus2"] + if(data && data["viruses"]) + var/list/vlist = data["viruses"] if(vlist.len) for(var/ID in vlist) - var/datum/disease2/disease/V = vlist[ID] - if(V.spreadtype == "Contact") - infect_virus2(M, V.getcopy()) - if(data && data["antibodies"]) - M.antibodies |= data["antibodies"] + var/datum/disease/D = ID + if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS)) + continue + M.ContractDisease(D) + if(data && data["resistances"]) + M.resistances |= data["resistances"] + +/datum/reagent/blood/mix_data(newdata, newamount) + if(!data || !newdata) + return + + if(data["viruses"] || newdata["viruses"]) + var/list/mix1 = data["viruses"] + var/list/mix2 = newdata["viruses"] + + var/list/to_mix = list() + var/list/preserve = list() + + for(var/datum/disease/advance/AD in mix1) + to_mix += AD + for(var/datum/disease/advance/AD in mix2) + to_mix += AD + + var/datum/disease/advance/mixed_AD = Advance_Mix(to_mix) + + if(mixed_AD) + preserve += mixed_AD + + for(var/datum/disease/D1 in mix1) + if(!istype(D1, /datum/disease/advance)) + var/keep = TRUE + for(var/datum/disease/D2 in preserve) + if(D1.IsSame(D2)) + keep = FALSE + break + if(keep) + preserve += D1 + + for(var/datum/disease/D1 in mix2) + if(!istype(D1, /datum/disease/advance)) + var/keep = TRUE + for(var/datum/disease/D2 in preserve) + if(D1.IsSame(D2)) + keep = FALSE + break + if(keep) + preserve += D1 + + data["viruses"] = preserve /datum/reagent/blood/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) if(alien == IS_SLIME) //They don't have blood, so it seems weird that they would instantly 'process' the chemical like another species does. diff --git a/code/modules/reagents/reagents/dispenser.dm b/code/modules/reagents/reagents/dispenser.dm index add0a751561..dcdc0f7c50b 100644 --- a/code/modules/reagents/reagents/dispenser.dm +++ b/code/modules/reagents/reagents/dispenser.dm @@ -319,20 +319,7 @@ /datum/reagent/radium/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) if(issmall(M)) removed *= 2 - M.apply_effect(10 * removed, IRRADIATE, 0) // Radium may increase your chances to cure a disease - if(M.virus2.len) - for(var/ID in M.virus2) - var/datum/disease2/disease/V = M.virus2[ID] - if(prob(5)) - M.antibodies |= V.antigen - if(prob(50)) - M.apply_effect(50, IRRADIATE, check_protection = 0) // curing it that way may kill you instead - var/absorbed = 0 - var/obj/item/organ/internal/diona/nutrients/rad_organ = locate() in M.internal_organs - if(rad_organ && !rad_organ.is_broken()) - absorbed = 1 - if(!absorbed) - M.adjustToxLoss(100) + M.apply_effect(10 * removed, IRRADIATE, 0) /datum/reagent/radium/touch_turf(var/turf/T) ..() diff --git a/code/modules/reagents/reagents/toxins.dm b/code/modules/reagents/reagents/toxins.dm index 26b70123304..c0545b8b068 100644 --- a/code/modules/reagents/reagents/toxins.dm +++ b/code/modules/reagents/reagents/toxins.dm @@ -973,3 +973,15 @@ /datum/reagent/neurophage_nanites/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) M.adjustBrainLoss(2 * removed) // Their job is to give you a bad time. M.adjustBruteLoss(2 * removed) + +/datum/reagent/salmonella + name = "Salmonella" + id = "salmonella" + description = "A nasty bacteria found in spoiled food." + reagent_state = LIQUID + color = "#1E4600" + taste_mult = 0 + +/datum/reagent/salmonella/on_mob_life(mob/living/carbon/M) + M.ForceContractDisease(new /datum/disease/food_poisoning(0)) + return ..() diff --git a/code/modules/reagents/reagents/virology.dm b/code/modules/reagents/reagents/virology.dm new file mode 100644 index 00000000000..4556b1ed09c --- /dev/null +++ b/code/modules/reagents/reagents/virology.dm @@ -0,0 +1,47 @@ +/datum/reagent/vaccine + name = "Vaccine" + id = "vaccine" + color = "#C81040" + taste_description = "antibodies" + +/datum/reagent/vaccine/affect_blood(mob/living/carbon/M, alien, removed) + if(islist(data)) + for(var/thing in M.GetViruses()) + var/datum/disease/D = thing + if(D.GetDiseaseID() in data) + D.cure() + M.resistances |= data + +/datum/reagent/vaccines/mix_data(newdata, newamount) + if(islist(newdata)) + var/list/newdatalist = newdata + data |= newdatalist.Copy() + +/datum/reagent/mutagen/mutagenvirusfood + name = "Mutagenic agar" + id = "mutagenvirusfood" + description = "mutates blood" + color = "#A3C00F" + +/datum/reagent/mutagen/mutagenvirusfood/sugar + name = "Sucrose agar" + id = "sugarvirusfood" + color = "#41B0C0" + taste_mult = 1.5 + +/datum/reagent/medicine/adranol/adranolvirusfood + name = "Virus rations" + id = "adranolvirusfood" + description = "mutates blood" + color = "#D18AA5" + +/datum/reagent/phoron_dust/phoronvirusfood + name = "Phoronic virus food" + id = "phoronvirusfood" + description = "mutates blood" + color = "#A69DA9" + +/datum/reagent/phoron_dust/phoronvirusfood/weak + name = "Weakened phoronic virus food" + id = "weakphoronvirusfood" + color = "#CEC3C6" diff --git a/code/modules/virus2/admin.dm b/code/modules/virus2/admin.dm deleted file mode 100644 index e08d7e59573..00000000000 --- a/code/modules/virus2/admin.dm +++ /dev/null @@ -1,222 +0,0 @@ -/datum/disease2/disease/Topic(href, href_list) - . = ..() - if(.) return - - if(href_list["info"]) - // spawn or admin privileges to see info about viruses - if(!check_rights(R_ADMIN|R_SPAWN|R_EVENT)) return - - to_chat(usr, "Infection chance: [infectionchance]; Speed: [speed]; Spread type: [spreadtype]") - to_chat(usr, "Affected species: [english_list(affected_species)]") - to_chat(usr, "Effects:") - for(var/datum/disease2/effectholder/E in effects) - to_chat(usr, "[E.stage]: [E.effect.name]; chance=[E.chance]; multiplier=[E.multiplier]") - to_chat(usr, "Antigens: [antigens2string(antigen)]; Resistance: [resistance]") - - return 1 - -/datum/disease2/disease/vv_get_header() - . = list() - for(var/datum/disease2/effectholder/E in effects) - . += "[E.stage]: [E.effect.name]" - . = list({" - [name()]
- [jointext(., "
")]
- "}) - -/datum/disease2/disease/get_view_variables_options() - return ..() + {" - - "} - -/datum/admins/var/datum/virus2_editor/virus2_editor_datum = new -/client/proc/virus2_editor() - set name = "Virus Editor" - set category = "Admin.Events" - if(!holder || !check_rights(R_SPAWN)) return // spawn privileges to create viruses - - holder.virus2_editor_datum.show_ui(src) - -/datum/virus2_editor - var/list/s = list(/datum/disease2/effect/invisible,/datum/disease2/effect/invisible,/datum/disease2/effect/invisible,/datum/disease2/effect/invisible) - var/list/s_chance = list(1,1,1,1) - var/list/s_multiplier = list(1,1,1,1) - var/species = list() - var/infectionchance = 70 - var/spreadtype = "Contact" - var/list/antigens = list() - var/speed = 1 - var/resistance = 10 - var/mob/living/carbon/infectee = null - - // this holds spawned viruses so that the "Info" links work after the proc exits - var/list/spawned_viruses = list() - -/datum/virus2_editor/proc/select(mob/user, stage) - if(stage < 1 || stage > 4) return - - var/list/L = list() - - for(var/datum/disease2/effect/f as anything in subtypesof(/datum/disease2/effect)) - if(initial(f.stage) <= stage) - L[initial(f.name)] = f - - var/datum/disease2/effect/Eff = s[stage] - - var/C = tgui_input_list(usr, "Select effect for stage [stage]:", "Stage [stage]", L, Eff) - if(!C) return - return L[C] - -/datum/virus2_editor/proc/show_ui(mob/user) - var/H = {" -

Virus2 Virus Editor


- Effects:
- "} - for(var/i = 1 to 4) - var/datum/disease2/effect/Eff = s[i] - H += {" - [initial(Eff.name)] - Chance: [s_chance[i]] - Multiplier: [s_multiplier[i]] -
- "} - H += {" -
- Infectable Species:
- "} - var/f = 1 - for(var/k in GLOB.all_species) - var/datum/species/S = GLOB.all_species[k] - if(S.get_virus_immune()) - continue - if(!f) H += " | " - else f = 0 - H += "[k]" - H += {" - Reset -
- Infection Chance: [infectionchance]
- Spread Type: [spreadtype]
- Speed: [speed]
- Resistance: [resistance]
-
- "} - f = 1 - for(var/k in ALL_ANTIGENS) - if(!f) H += " | " - else f = 0 - H += "[k]" - H += {" - Reset -
-
- Initial infectee: [infectee ? infectee : "(choose)"] - RELEASE - "} - - user << browse(H, "window=virus2edit") - -/datum/virus2_editor/Topic(href, href_list) - switch(href_list["what"]) - if("effect") - var/stage = text2num(href_list["stage"]) - if(href_list["effect"]) - var/datum/disease2/effect/E = select(usr,stage) - if(!E) return - s[stage] = E - // set a default chance and multiplier of half the maximum (roughly average) - s_chance[stage] = max(1, round(initial(E.chance_maxm)/2)) - s_multiplier[stage] = max(1, round(initial(E.maxm)/2)) - else if(href_list["chance"]) - var/datum/disease2/effect/Eff = s[stage] - var/I = tgui_input_number(usr, "Chance, per tick, of this effect happening (min 0, max [initial(Eff.chance_maxm)])", "Effect Chance", s_chance[stage], initial(Eff.chance_maxm), 0) - if(I == null || I < 0 || I > initial(Eff.chance_maxm)) return - s_chance[stage] = I - else if(href_list["multiplier"]) - var/datum/disease2/effect/Eff = s[stage] - var/I = tgui_input_number(usr, "Multiplier for this effect (min 1, max [initial(Eff.maxm)])", "Effect Multiplier", s_multiplier[stage], initial(Eff.maxm), 1) - if(I == null || I < 1 || I > initial(Eff.maxm)) return - s_multiplier[stage] = I - if("species") - if(href_list["toggle"]) - var/T = href_list["toggle"] - if(T in species) - species -= T - else - species |= T - else if(href_list["reset"]) - species = list() - if(infectee) - if(!infectee.species || !(infectee.species.get_bodytype() in species)) - infectee = null - if("ichance") - var/I = tgui_input_number(usr, "Input infection chance", "Infection Chance", infectionchance, 100) - if(!I) return - infectionchance = I - if("stype") - var/S = tgui_alert(usr, "Which spread type?", "Spread Type", list("Contact", "Airborne", "Blood")) - if(!S) return - spreadtype = S - if("speed") - var/S = tgui_input_number(usr, "Input speed", "Speed", speed) - if(!S) return - speed = S - if("antigen") - if(href_list["toggle"]) - var/T = href_list["toggle"] - if(length(T) != 1) return - if(T in antigens) - antigens -= T - else - antigens |= T - else if(href_list["reset"]) - antigens = list() - if("resistance") - var/S = tgui_input_number(usr, "Input % resistance to antibiotics", "Resistance", resistance, 100) - if(!S) return - resistance = S - if("infectee") - var/list/candidates = list() - for(var/mob/living/carbon/G in living_mob_list) - if(G.stat != DEAD && G.species && !isbelly(G.loc)) - if(G.species.get_bodytype() in species) - candidates["[G.name][G.client ? "" : " (no client)"]"] = G - else - candidates["[G.name] ([G.species.get_bodytype()])[G.client ? "" : " (no client)"]"] = G - if(!candidates.len) - to_chat(usr, "No possible candidates found!") - - var/I = tgui_input_list(usr, "Choose initial infectee", "Infectee", candidates) - if(!I || !candidates[I]) return - infectee = candidates[I] - species |= infectee.species.get_bodytype() - if("go") - if(!antigens.len) - var/a = tgui_alert(usr, "This disease has no antigens; it will be impossible to permanently immunise anyone without them.\ - It is strongly recommended to set at least one antigen. Do you want to go back and edit your virus?", "Antigens", list("Yes", "No")) - if(!a || a == "Yes") return - var/datum/disease2/disease/D = new - D.infectionchance = infectionchance - D.spreadtype = spreadtype - D.antigen = antigens - D.affected_species = species - D.speed = speed - D.resistance = resistance - for(var/i in 1 to 4) - var/datum/disease2/effectholder/E = new - var/Etype = s[i] - E.effect = new Etype() - E.effect.generate() - E.chance = s_chance[i] - E.multiplier = s_multiplier[i] - E.stage = i - - D.effects += E - - spawned_viruses += D - - message_admins(span_danger("[key_name_admin(usr)] infected [key_name_admin(infectee)] with a virus (Info)")) - log_admin("[key_name_admin(usr)] infected [key_name_admin(infectee)] with a virus!") - infect_virus2(infectee, D, forced=1) - - show_ui(usr) diff --git a/code/modules/virus2/analyser.dm b/code/modules/virus2/analyser.dm deleted file mode 100644 index f9522caea8a..00000000000 --- a/code/modules/virus2/analyser.dm +++ /dev/null @@ -1,73 +0,0 @@ -/obj/machinery/disease2/diseaseanalyser - name = "disease analyser" - desc = "Analyzes diseases to find out information about them!" - icon = 'icons/obj/virology_vr.dmi' //VOREStation Edit - icon_state = "analyser" - anchored = TRUE - density = TRUE - - var/scanning = 0 - var/pause = 0 - - var/obj/item/virusdish/dish = null - -/obj/machinery/disease2/diseaseanalyser/attackby(var/obj/O as obj, var/mob/user as mob) - if(default_unfasten_wrench(user, O, 20)) - return - - else if(!istype(O,/obj/item/virusdish)) return - - if(dish) - to_chat(user, "\The [src] is already loaded.") - return - - dish = O - user.drop_item() - O.loc = src - - user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!") - -/obj/machinery/disease2/diseaseanalyser/process() - if(stat & (NOPOWER|BROKEN)) - return - - if(scanning) - scanning -= 1 - if(scanning == 0) - if (dish.virus2.addToDB()) - ping("\The [src] pings, \"New pathogen added to data bank.\"") - - var/obj/item/paper/P = new /obj/item/paper(src.loc) - P.name = "paper - [dish.virus2.name()]" - - var/r = dish.virus2.get_info() - P.info = {" - [virology_letterhead("Post-Analysis Memo")] - [r] -
- Additional Notes:  -"} - dish.basic_info = dish.virus2.get_basic_info() - dish.info = r - dish.name = "[initial(dish.name)] ([dish.virus2.name()])" - dish.analysed = 1 - dish.loc = src.loc - dish = null - - icon_state = "analyser" - src.state("\The [src] prints a sheet of paper.") - - else if(dish && !scanning && !pause) - if(dish.virus2 && dish.growth > 50) - dish.growth -= 10 - scanning = 5 - icon_state = "analyser_processing" - else - pause = 1 - spawn(25) - dish.loc = src.loc - dish = null - - src.state("\The [src] buzzes, \"Insufficient growth density to complete analysis.\"") - pause = 0 - return diff --git a/code/modules/virus2/antibodies.dm b/code/modules/virus2/antibodies.dm deleted file mode 100644 index cecb0709406..00000000000 --- a/code/modules/virus2/antibodies.dm +++ /dev/null @@ -1,26 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -var/global/list/ALL_ANTIGENS = list( - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" - ) - -/hook/startup/proc/randomise_antigens_order() - ALL_ANTIGENS = shuffle(ALL_ANTIGENS) - return 1 - -// iterate over the list of antigens and see what matches -/proc/antigens2string(list/antigens, none="None") - if(!istype(antigens)) - CRASH("Illegal type!") - if(!antigens.len) - return none - - var/code = "" - for(var/V in ALL_ANTIGENS) - if(V in antigens) - code += V - - if(!code) - return none - - return code diff --git a/code/modules/virus2/biohazard destroyer.dm b/code/modules/virus2/biohazard destroyer.dm deleted file mode 100644 index 37eaf06561c..00000000000 --- a/code/modules/virus2/biohazard destroyer.dm +++ /dev/null @@ -1,20 +0,0 @@ -/obj/machinery/disease2/biodestroyer - name = "Biohazard destroyer" - icon = 'icons/obj/pipes/disposal.dmi' - icon_state = "disposalbio" - var/list/accepts = list(/obj/item/clothing,/obj/item/virusdish/,/obj/item/cureimplanter,/obj/item/diseasedisk,/obj/item/reagent_containers) - density = TRUE - anchored = TRUE - -/obj/machinery/disease2/biodestroyer/attackby(var/obj/I as obj, var/mob/user as mob) - for(var/path in accepts) - if(I.type in typesof(path)) - user.drop_item() - qdel(I) - add_overlay("dispover-handle") - return - user.drop_item() - I.loc = src.loc - - for(var/mob/O in hearers(src, null)) - O.show_message(span_blue("[icon2html(src, O.client)] The [src.name] beeps."), 2) diff --git a/code/modules/virus2/centrifuge.dm b/code/modules/virus2/centrifuge.dm deleted file mode 100644 index 7c17ea24e9a..00000000000 --- a/code/modules/virus2/centrifuge.dm +++ /dev/null @@ -1,208 +0,0 @@ -/obj/machinery/computer/centrifuge - name = "isolation centrifuge" - desc = "Used to separate things with different weight. Spin 'em round, round, right round." - icon = 'icons/obj/virology_vr.dmi' //VOREStation Edit - icon_state = "centrifuge" - var/curing - var/isolating - - var/obj/item/reagent_containers/glass/beaker/vial/sample = null - var/datum/disease2/disease/virus2 = null - -/obj/machinery/computer/centrifuge/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(O.has_tool_quality(TOOL_SCREWDRIVER)) - return ..(O,user) - - if(default_unfasten_wrench(user, O, 20)) - return - - if(istype(O,/obj/item/reagent_containers/glass/beaker/vial)) - if(sample) - to_chat(user, "\The [src] is already loaded.") - return - - sample = O - user.drop_item() - O.loc = src - - user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!") - SStgui.update_uis(src) - - src.attack_hand(user) - -/obj/machinery/computer/centrifuge/update_icon() - ..() - if(! (stat & (BROKEN|NOPOWER)) && (isolating || curing)) - icon_state = "centrifuge_moving" - -/obj/machinery/computer/centrifuge/attack_hand(var/mob/user as mob) - if(..()) - return - tgui_interact(user) - -/obj/machinery/computer/centrifuge/tgui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "IsolationCentrifuge", name) - ui.open() - -/obj/machinery/computer/centrifuge/tgui_data(mob/user) - var/list/data = list() - data["antibodies"] = null - data["pathogens"] = list() - data["is_antibody_sample"] = null - data["busy"] = null - data["sample_inserted"] = !!sample - - if(curing) - data["busy"] = "Isolating antibodies..." - else if(isolating) - data["busy"] = "Isolating pathogens..." - else - if(sample) - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list - if(B) - data["antibodies"] = antigens2string(B.data["antibodies"], none=null) - - var/list/pathogens[0] - var/list/virus = B.data["virus2"] - for (var/ID in virus) - var/datum/disease2/disease/V = virus[ID] - pathogens.Add(list(list("name" = V.name(), "spread_type" = V.spreadtype, "reference" = "\ref[V]"))) - - data["pathogens"] = pathogens - - else - var/datum/reagent/antibodies/A = locate(/datum/reagent/antibodies) in sample.reagents.reagent_list - if(A) - data["antibodies"] = antigens2string(A.data["antibodies"], none=null) - data["is_antibody_sample"] = 1 - - return data - -/obj/machinery/computer/centrifuge/process() - ..() - if(stat & (NOPOWER|BROKEN)) return - - if(curing) - curing -= 1 - if(curing == 0) - cure() - - if(isolating) - isolating -= 1 - if(isolating == 0) - isolate() - -/obj/machinery/computer/centrifuge/tgui_act(action, params) - if(..()) - return TRUE - - var/mob/user = usr - add_fingerprint(user) - - - switch(action) - if("print") - print(user) - . = TRUE - if("isolate") - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list - if(B) - var/datum/disease2/disease/virus = locate(params["isolate"]) - virus2 = virus.getcopy() - isolating = 40 - update_icon() - . = TRUE - if("antibody") - var/delay = 20 - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list - if(!B) - state("\The [src] buzzes, \"No antibody carrier detected.\"", "blue") - return TRUE - - var/has_toxins = locate(/datum/reagent/toxin) in sample.reagents.reagent_list - var/has_radium = sample.reagents.has_reagent("radium") - if(has_toxins || has_radium) - state("\The [src] beeps, \"Pathogen purging speed above nominal.\"", "blue") - if(has_toxins) - delay = delay/2 - if(has_radium) - delay = delay/2 - - curing = round(delay) - playsound(src, 'sound/machines/juicer.ogg', 50, 1) - update_icon() - . = TRUE - if("sample") - if(sample) - sample.loc = src.loc - sample = null - . = TRUE - - -/obj/machinery/computer/centrifuge/proc/cure() - if(!sample) return - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list - if(!B) return - - var/list/data = list("antibodies" = B.data["antibodies"]) - var/amt= sample.reagents.get_reagent_amount("blood") - sample.reagents.remove_reagent("blood", amt) - sample.reagents.add_reagent("antibodies", amt, data) - - SStgui.update_uis(src) - update_icon() - ping("\The [src] pings, \"Antibody isolated.\"") - -/obj/machinery/computer/centrifuge/proc/isolate() - if(!sample) return - var/obj/item/virusdish/dish = new/obj/item/virusdish(loc) - dish.virus2 = virus2 - virus2 = null - - SStgui.update_uis(src) - update_icon() - ping("\The [src] pings, \"Pathogen isolated.\"") - -/obj/machinery/computer/centrifuge/proc/print(var/mob/user) - var/obj/item/paper/P = new /obj/item/paper(loc) - P.name = "paper - Pathology Report" - P.info = {" - [virology_letterhead("Pathology Report")] - Sample: [sample.name]
-"} - - if(user) - P.info += "Generated By: [user.name]
" - - P.info += "
" - - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list - if(B) - P.info += "Antibodies: " - P.info += antigens2string(B.data["antibodies"]) - P.info += "
" - - var/list/virus = B.data["virus2"] - P.info += "Pathogens:
" - if(virus.len > 0) - for (var/ID in virus) - var/datum/disease2/disease/V = virus[ID] - P.info += "[V.name()]
" - else - P.info += "None
" - - else - var/datum/reagent/antibodies/A = locate(/datum/reagent/antibodies) in sample.reagents.reagent_list - if(A) - P.info += "The following antibodies have been isolated from the blood sample: " - P.info += antigens2string(A.data["antibodies"]) - P.info += "
" - - P.info += {" -
- Additional Notes: -"} - - state("The nearby computer prints out a pathology report.") diff --git a/code/modules/virus2/curer.dm b/code/modules/virus2/curer.dm deleted file mode 100644 index fda185f15f2..00000000000 --- a/code/modules/virus2/curer.dm +++ /dev/null @@ -1,105 +0,0 @@ -/obj/machinery/computer/curer - name = "cure research machine" - icon_keyboard = "med_key" - icon_screen = "dna" - circuit = /obj/item/circuitboard/curefab - var/curing - var/virusing - - var/obj/item/reagent_containers/container = null - -/obj/machinery/computer/curer/attackby(var/obj/I as obj, var/mob/user as mob) - if(istype(I,/obj/item/reagent_containers)) - var/mob/living/carbon/C = user - if(!container) - container = I - C.drop_item() - I.loc = src - return - if(istype(I,/obj/item/virusdish)) - if(virusing) - to_chat(user, span_infoplain(span_bold("The pathogen materializer is still recharging..."))) - return - var/obj/item/reagent_containers/glass/beaker/product = new(src.loc) - - var/list/data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"virus2"=list(),"antibodies"=list()) - data["virus2"] |= I:virus2 - product.reagents.add_reagent("blood",30,data) - - virusing = 1 - spawn(1200) virusing = 0 - - state("The [src.name] Buzzes", "blue") - return - ..() - return - -/obj/machinery/computer/curer/attack_ai(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/curer/attack_hand(var/mob/user as mob) - if(..()) - return - user.machine = src - var/dat - if(curing) - dat = "Antibody production in progress" - else if(virusing) - dat = "Virus production in progress" - else if(container) - // see if there's any blood in the container - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in container.reagents.reagent_list - - if(B) - dat = "Blood sample inserted." - dat += "
Antibodies: [antigens2string(B.data["antibodies"])]" - dat += "
Begin antibody production" - else - dat += "
Please check container contents." - dat += "
Eject container" - else - dat = "Please insert a container." - - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - -/obj/machinery/computer/curer/process() - ..() - - if(stat & (NOPOWER|BROKEN)) - return - use_power(500) - - if(curing) - curing -= 1 - if(curing == 0) - if(container) - createcure(container) - return - -/obj/machinery/computer/curer/Topic(href, href_list) - if(..()) - return 1 - usr.machine = src - - if (href_list["antibody"]) - curing = 10 - else if(href_list["eject"]) - container.loc = src.loc - container = null - - src.add_fingerprint(usr) - src.updateUsrDialog() - - -/obj/machinery/computer/curer/proc/createcure(var/obj/item/reagent_containers/container) - var/obj/item/reagent_containers/glass/beaker/product = new(src.loc) - - var/datum/reagent/blood/B = locate() in container.reagents.reagent_list - - var/list/data = list() - data["antibodies"] = B.data["antibodies"] - product.reagents.add_reagent("antibodies",30,data) - - state("\The [src.name] buzzes", "blue") diff --git a/code/modules/virus2/disease2.dm b/code/modules/virus2/disease2.dm deleted file mode 100644 index e8a275e8382..00000000000 --- a/code/modules/virus2/disease2.dm +++ /dev/null @@ -1,320 +0,0 @@ -/datum/disease2/disease - var/infectionchance = 70 - var/speed = 1 - var/spreadtype = "Blood" // Can also be "Contact" or "Airborne" - var/stage = 1 - var/stageprob = 10 - var/dead = 0 - var/clicks = 0 - var/uniqueID = 0 - var/list/datum/disease2/effectholder/effects = list() - var/antigen = list() // 16 bits describing the antigens, when one bit is set, a cure with that bit can dock here - var/max_stage = 4 - var/list/affected_species = list(SPECIES_HUMAN,SPECIES_UNATHI,SPECIES_SKRELL,SPECIES_TAJ) - var/resistance = 10 // % chance a disease will resist cure, up to 100 - -/datum/disease2/disease/New() - uniqueID = rand(0,10000) - ..() - -/datum/disease2/disease/proc/makerandom(var/severity=1) - var/list/excludetypes = list() - for(var/i=1 ; i <= max_stage ; i++ ) - var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder - holder.stage = i - holder.getrandomeffect(severity, excludetypes) - excludetypes += holder.effect.type - effects += holder - uniqueID = rand(0,10000) - switch(severity) - if(1) - infectionchance = 1 - if(2) - infectionchance = rand(10,20) - else - infectionchance = rand(60,90) - - antigen = list(pick(ALL_ANTIGENS)) - antigen |= pick(ALL_ANTIGENS) - spreadtype = prob(70) ? "Airborne" : "Contact" - resistance = rand(15,70) - - if(severity >= 2 && prob(33)) - resistance += 10 - - if(GLOB.all_species.len) - affected_species = get_infectable_species() - -/proc/get_infectable_species() - var/list/meat = list() - var/list/res = list() - for (var/specie in GLOB.all_species) - var/datum/species/S = GLOB.all_species[specie] - if(!S.get_virus_immune()) - meat += S - if(meat.len) - var/num = rand(1,meat.len) - for(var/i=0,i 50) - if(prob(1)) - majormutate() - - //Space antibiotics have a good chance to stop disease completely - if(mob.chem_effects[CE_ANTIBIOTIC]) - if(stage == 1 && prob(70-resistance)) - src.cure(mob) - else - resistance += rand(1,9) - - //VOREStation Add Start - Corophazine can treat higher stages - var/antibiotics = mob.chem_effects[CE_ANTIBIOTIC] - if(antibiotics == ANTIBIO_SUPER) - if(prob(70)) - src.cure(mob) - //VOREStation Add End - - //Resistance is capped at 90 without being manually set to 100 - if(resistance > 90 && resistance < 100) - resistance = 90 - - - //Virus food speeds up disease progress - if(mob.reagents.has_reagent("virusfood")) - mob.reagents.remove_reagent("virusfood",0.1) - clicks += 10 - - if(prob(1) && prob(stage)) // Increasing chance of curing as the virus progresses - src.cure(mob) - mob.antibodies |= src.antigen - - //Moving to the next stage - if(clicks > max(stage*100, 200) && prob(10)) - if((stage <= max_stage) && prob(5)) // ~20% of viruses will be cured by the end of S4 with this - src.cure(mob) - mob.antibodies |= src.antigen - stage++ - clicks = 0 - - //Do nasty effects - for(var/datum/disease2/effectholder/e in effects) - if(prob(33)) - e.runeffect(mob,stage) - - //Short airborne spread - if(src.spreadtype == "Airborne") - for(var/mob/living/carbon/M in oview(1,mob)) - if(airborne_can_reach(get_turf(mob), get_turf(M))) - infect_virus2(M,src) - - //fever - mob.bodytemperature = max(mob.bodytemperature, min(310+5*min(stage,max_stage) ,mob.bodytemperature+5*min(stage,max_stage))) - clicks+=speed - -/datum/disease2/disease/proc/cure(var/mob/living/carbon/mob) - for(var/datum/disease2/effectholder/e in effects) - e.effect.deactivate(mob) - mob.virus2.Remove("[uniqueID]") - BITSET(mob.hud_updateflag, STATUS_HUD) - -/datum/disease2/disease/proc/minormutate() - //uniqueID = rand(0,10000) - var/datum/disease2/effectholder/holder = pick(effects) - holder.minormutate() - //infectionchance = min(50,infectionchance + rand(0,10)) - -/datum/disease2/disease/proc/majormutate() - uniqueID = rand(0,10000) - var/datum/disease2/effectholder/holder = pick(effects) - var/list/exclude = list() - for(var/datum/disease2/effectholder/D in effects) - if(D != holder) - exclude += D.effect.type - holder.majormutate(exclude) - if (prob(5) && prob(100-resistance)) // The more resistant the disease,the lower the chance of randomly developing the antibodies - antigen = list(pick(ALL_ANTIGENS)) - antigen |= pick(ALL_ANTIGENS) - if (prob(5) && GLOB.all_species.len) - affected_species = get_infectable_species() - if (prob(10)) - resistance += rand(1,9) - if(resistance > 90 && resistance < 100) - resistance = 90 - -/datum/disease2/disease/proc/getcopy() - var/datum/disease2/disease/disease = new /datum/disease2/disease - disease.infectionchance = infectionchance - disease.spreadtype = spreadtype - disease.stageprob = stageprob - disease.antigen = antigen - disease.uniqueID = uniqueID - disease.resistance = resistance - disease.affected_species = affected_species.Copy() - for(var/datum/disease2/effectholder/holder in effects) - var/datum/disease2/effectholder/newholder = new /datum/disease2/effectholder - newholder.effect = new holder.effect.type - newholder.effect.generate(holder.effect.data) - newholder.chance = holder.chance - newholder.cure = holder.cure - newholder.multiplier = holder.multiplier - newholder.happensonce = holder.happensonce - newholder.stage = holder.stage - disease.effects += newholder - return disease - -/datum/disease2/disease/proc/issame(var/datum/disease2/disease/disease) - var/list/types = list() - var/list/types2 = list() - for(var/datum/disease2/effectholder/d in effects) - types += d.effect.type - var/equal = 1 - - for(var/datum/disease2/effectholder/d in disease.effects) - types2 += d.effect.type - - for(var/type in types) - if(!(type in types2)) - equal = 0 - - if (antigen != disease.antigen) - equal = 0 - return equal - -/proc/virus_copylist(var/list/datum/disease2/disease/viruses) - var/list/res = list() - for (var/ID in viruses) - var/datum/disease2/disease/V = viruses[ID] - res["[V.uniqueID]"] = V.getcopy() - return res - - -var/global/list/virusDB = list() - -/datum/disease2/disease/proc/name() - .= "stamm #[add_zero("[uniqueID]", 4)]" - if ("[uniqueID]" in virusDB) - var/datum/data/record/V = virusDB["[uniqueID]"] - .= V.fields["name"] - -/datum/disease2/disease/proc/get_basic_info() - var/t = "" - for(var/datum/disease2/effectholder/E in effects) - t += ", [E.effect.name]" - return "[name()] ([copytext(t,3)])" - -/datum/disease2/disease/proc/get_info() - var/r = {" - Analysis determined the existence of a GNAv2-based viral lifeform.
- Designation: [name()]
- Antigen: [antigens2string(antigen)]
- Transmitted By: [spreadtype]
- Rate of Progression: [stageprob * 10]
- Antibiotic Resistance [resistance]%
- Species Affected: [jointext(affected_species, ", ")]
-"} - - r += "Symptoms:
" - for(var/datum/disease2/effectholder/E in effects) - r += "([E.stage]) [E.effect.name] " - r += "Strength: [E.multiplier >= 3 ? "Severe" : E.multiplier > 1 ? "Above Average" : "Average"] " - r += "Aggressiveness: [E.chance * 15]
" - - return r - -/datum/disease2/disease/proc/get_tgui_info() - . = list( - "name" = name(), - "spreadtype" = spreadtype, - "antigen" = antigens2string(antigen), - "rate" = stageprob * 10, - "resistance" = resistance, - "species" = jointext(affected_species, ", "), - "ref" = "\ref[src]", - ) - - var/list/symptoms = list() - for(var/datum/disease2/effectholder/E in effects) - symptoms.Add(list(list( - "stage" = E.stage, - "name" = E.effect.name, - "strength" = "[E.multiplier >= 3 ? "Severe" : E.multiplier > 1 ? "Above Average" : "Average"]", - "aggressiveness" = E.chance * 15, - ))) - .["symptoms"] = symptoms - -/datum/disease2/disease/proc/addToDB() - if ("[uniqueID]" in virusDB) - return 0 - var/datum/data/record/v = new() - v.fields["id"] = uniqueID - v.fields["name"] = name() - v.fields["description"] = get_info() - v.fields["tgui_description"] = get_tgui_info() - v.fields["tgui_description"]["record"] = "\ref[v]" - v.fields["antigen"] = antigens2string(antigen) - v.fields["spread type"] = spreadtype - virusDB["[uniqueID]"] = v - return 1 - -/proc/virus2_lesser_infection() - var/list/candidates = list() //list of candidate keys - - for(var/mob/living/carbon/human/G in player_list) - if(G.client && G.stat != DEAD && !isbelly(G.loc)) - candidates += G - - if(!candidates.len) return - - candidates = shuffle(candidates) - - infect_mob_random_lesser(candidates[1]) - -/proc/virus2_greater_infection() - var/list/candidates = list() //list of candidate keys - - for(var/mob/living/carbon/human/G in player_list) - if(G.client && G.stat != DEAD && !isbelly(G.loc)) - candidates += G - if(!candidates.len) return - - candidates = shuffle(candidates) - - infect_mob_random_greater(candidates[1]) - -/proc/virology_letterhead(var/report_name) - return {" -

[report_name]

-
[station_name()] Virology Lab
-
-"} - -/datum/disease2/disease/proc/can_add_symptom(type) - for(var/datum/disease2/effectholder/H in effects) - if(H.effect.type == type) - return 0 - - return 1 diff --git a/code/modules/virus2/diseasesplicer.dm b/code/modules/virus2/diseasesplicer.dm deleted file mode 100644 index 74f9ad43d48..00000000000 --- a/code/modules/virus2/diseasesplicer.dm +++ /dev/null @@ -1,193 +0,0 @@ -/obj/machinery/computer/diseasesplicer - name = "disease splicer" - icon_keyboard = "med_key" - icon_screen = "crew" - - var/datum/disease2/effectholder/memorybank = null - var/list/species_buffer = null - var/analysed = 0 - var/obj/item/virusdish/dish = null - var/burning = 0 - var/splicing = 0 - var/scanning = 0 - -/obj/machinery/computer/diseasesplicer/attackby(var/obj/item/I as obj, var/mob/user as mob) - if(I.has_tool_quality(TOOL_SCREWDRIVER)) - return ..(I,user) - - if(default_unfasten_wrench(user, I, 20)) - return - - if(istype(I,/obj/item/virusdish)) - var/mob/living/carbon/c = user - if(dish) - to_chat(user, "\The [src] is already loaded.") - return - - dish = I - c.drop_item() - I.loc = src - - if(istype(I,/obj/item/diseasedisk)) - to_chat(user, "You upload the contents of the disk onto the buffer.") - memorybank = I:effect - species_buffer = I:species - analysed = I:analysed - - src.attack_hand(user) - -/obj/machinery/computer/diseasesplicer/attack_ai(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/diseasesplicer/attack_hand(var/mob/user as mob) - if(..()) - return TRUE - tgui_interact(user) - -/obj/machinery/computer/diseasesplicer/tgui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "DiseaseSplicer", name) - ui.open() - -/obj/machinery/computer/diseasesplicer/tgui_data(mob/user) - var/list/data = list() - data["dish_inserted"] = !!dish - - data["buffer"] = null - if(memorybank) - data["buffer"] = list("name" = (analysed ? memorybank.effect.name : "Unknown Symptom"), "stage" = memorybank.effect.stage) - data["species_buffer"] = null - if(species_buffer) - data["species_buffer"] = analysed ? jointext(species_buffer, ", ") : "Unknown Species" - - data["effects"] = null - data["info"] = null - data["growth"] = 0 - data["affected_species"] = null - data["busy"] = null - if(splicing) - data["busy"] = "Splicing..." - else if(scanning) - data["busy"] = "Scanning..." - else if(burning) - data["busy"] = "Copying data to disk..." - else if(dish) - data["growth"] = min(dish.growth, 100) - - if(dish.virus2) - if(dish.virus2.affected_species) - data["affected_species"] = dish.analysed ? dish.virus2.affected_species : list() - - if(dish.growth >= 50) - var/list/effects[0] - for (var/datum/disease2/effectholder/e in dish.virus2.effects) - effects.Add(list(list("name" = (dish.analysed ? e.effect.name : "Unknown"), "stage" = (e.stage), "reference" = "\ref[e]", "badness" = e.effect.badness))) - data["effects"] = effects - else - data["info"] = "Insufficient cell growth for gene splicing." - else - data["info"] = "No virus detected." - else - data["info"] = "No dish loaded." - - return data - -/obj/machinery/computer/diseasesplicer/process() - if(stat & (NOPOWER|BROKEN)) - return - - if(scanning) - scanning -= 1 - if(!scanning) - ping("\The [src] pings, \"Analysis complete.\"") - SStgui.update_uis(src) - if(splicing) - splicing -= 1 - if(!splicing) - ping("\The [src] pings, \"Splicing operation complete.\"") - SStgui.update_uis(src) - if(burning) - burning -= 1 - if(!burning) - var/obj/item/diseasedisk/d = new /obj/item/diseasedisk(src.loc) - d.analysed = analysed - if(analysed) - if(memorybank) - d.name = "[memorybank.effect.name] GNA disk (Stage: [memorybank.effect.stage])" - d.effect = memorybank - else if(species_buffer) - d.name = "[jointext(species_buffer, ", ")] GNA disk" - d.species = species_buffer - else - if(memorybank) - d.name = "Unknown GNA disk (Stage: [memorybank.effect.stage])" - d.effect = memorybank - else if(species_buffer) - d.name = "Unknown Species GNA disk" - d.species = species_buffer - - ping("\The [src] pings, \"Backup disk saved.\"") - SStgui.update_uis(src) - -/obj/machinery/computer/diseasesplicer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) - if(..()) - return TRUE - - var/mob/user = usr - add_fingerprint(user) - - switch(action) - if("grab") - if(dish) - memorybank = locate(params["grab"]) - species_buffer = null - analysed = dish.analysed - dish = null - scanning = 10 - . = TRUE - - if("affected_species") - if(dish) - memorybank = null - species_buffer = dish.virus2.affected_species - analysed = dish.analysed - dish = null - scanning = 10 - . = TRUE - - if("eject") - if(dish) - dish.loc = src.loc - dish = null - . = TRUE - - if("splice") - if(dish) - var/target = text2num(params["splice"]) // target = 1 to 4 for effects, 5 for species - if(memorybank && 0 < target && target <= 4) - if(target < memorybank.effect.stage) return // too powerful, catching this for href exploit prevention - - var/datum/disease2/effectholder/target_holder - var/list/illegal_types = list() - for(var/datum/disease2/effectholder/e in dish.virus2.effects) - if(e.stage == target) - target_holder = e - else - illegal_types += e.effect.type - if(memorybank.effect.type in illegal_types) return - target_holder.effect = memorybank.effect - - else if(species_buffer && target == 5) - dish.virus2.affected_species = species_buffer - - else - return - - splicing = 10 - dish.virus2.uniqueID = rand(0,10000) - . = TRUE - - if("disk") - burning = 10 - . = TRUE diff --git a/code/modules/virus2/dishincubator.dm b/code/modules/virus2/dishincubator.dm deleted file mode 100644 index d6a84991d1d..00000000000 --- a/code/modules/virus2/dishincubator.dm +++ /dev/null @@ -1,201 +0,0 @@ -/obj/machinery/disease2/incubator/ - name = "pathogenic incubator" - desc = "Encourages the growth of diseases. This model comes with a dispenser system and a small radiation generator." - density = TRUE - anchored = TRUE - icon = 'icons/obj/virology_vr.dmi' //VOREStation Edit - icon_state = "incubator" - var/obj/item/virusdish/dish - var/obj/item/reagent_containers/glass/beaker = null - var/radiation = 0 - - var/on = 0 - var/power = 0 - - var/foodsupply = 0 - var/toxins = 0 - -/obj/machinery/disease2/incubator/attackby(var/obj/O as obj, var/mob/user as mob) - if(default_unfasten_wrench(user, O, 20)) - return - - if(istype(O, /obj/item/reagent_containers/glass) || istype(O,/obj/item/reagent_containers/syringe)) - - if(beaker) - to_chat(user, "\The [src] is already loaded.") - return - - beaker = O - user.drop_item() - O.loc = src - - user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!") - SStgui.update_uis(src) - - src.attack_hand(user) - return - - if(istype(O, /obj/item/virusdish)) - - if(dish) - to_chat(user, "The dish tray is aleady full!") - return - - dish = O - user.drop_item() - O.loc = src - - user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!") - SStgui.update_uis(src) - - src.attack_hand(user) - -/obj/machinery/disease2/incubator/attack_hand(mob/user as mob) - if(stat & (NOPOWER|BROKEN)) - return - tgui_interact(user) - -/obj/machinery/disease2/incubator/tgui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "DishIncubator", name) - ui.set_autoupdate(FALSE) - ui.open() - -/obj/machinery/disease2/incubator/tgui_data(mob/user) - var/data[0] - data["chemicals_inserted"] = !!beaker - data["dish_inserted"] = !!dish - data["food_supply"] = foodsupply - data["radiation"] = radiation - data["toxins"] = min(toxins, 100) - data["on"] = on - data["system_in_use"] = foodsupply > 0 || radiation > 0 || toxins > 0 - data["chemical_volume"] = beaker ? beaker.reagents.total_volume : 0 - data["max_chemical_volume"] = beaker ? beaker.volume : 1 - data["virus"] = dish ? dish.virus2 : null - data["growth"] = dish ? min(dish.growth, 100) : 0 - data["infection_rate"] = dish && dish.virus2 ? dish.virus2.infectionchance * 10 : 0 - data["analysed"] = dish && dish.analysed ? 1 : 0 - data["can_breed_virus"] = null - data["blood_already_infected"] = null - - if(beaker) - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in beaker.reagents.reagent_list - data["can_breed_virus"] = dish && dish.virus2 && B - - if(B) - if(!B.data["virus2"]) - B.data["virus2"] = list() - - var/list/virus = B.data["virus2"] - for (var/ID in virus) - data["blood_already_infected"] = virus[ID] - - return data - -/obj/machinery/disease2/incubator/process() - if(dish && on && dish.virus2) - use_power(50,EQUIP) - if(!powered(EQUIP)) - on = 0 - icon_state = "incubator" - - if(foodsupply) - if(dish.growth + 3 >= 100 && dish.growth < 100) - ping("\The [src] pings, \"Sufficient viral growth density achieved.\"") - - foodsupply -= 1 - dish.growth += 3 - SStgui.update_uis(src) - - if(radiation) - if(radiation > 50 & prob(5)) - dish.virus2.majormutate() - if(dish.info) - dish.info = "OUTDATED : [dish.info]" - dish.basic_info = "OUTDATED: [dish.basic_info]" - dish.analysed = 0 - ping("\The [src] pings, \"Mutant viral strain detected.\"") - else if(prob(5)) - dish.virus2.minormutate() - radiation -= 1 - SStgui.update_uis(src) - if(toxins && prob(5)) - dish.virus2.infectionchance -= 1 - SStgui.update_uis(src) - if(toxins > 50) - dish.growth = 0 - dish.virus2 = null - SStgui.update_uis(src) - else if(!dish) - on = 0 - icon_state = "incubator" - SStgui.update_uis(src) - - if(beaker) - if(foodsupply < 100 && beaker.reagents.remove_reagent("virusfood",5)) - if(foodsupply + 10 <= 100) - foodsupply += 10 - SStgui.update_uis(src) - - if(locate(/datum/reagent/toxin) in beaker.reagents.reagent_list && toxins < 100) - for(var/datum/reagent/toxin/T in beaker.reagents.reagent_list) - toxins += max(T.strength,1) - beaker.reagents.remove_reagent(T.id,1) - if(toxins > 100) - toxins = 100 - break - SStgui.update_uis(src) - -/obj/machinery/disease2/incubator/tgui_act(action, params) - if(..()) - return TRUE - - var/mob/user = usr - add_fingerprint(user) - switch(action) - if("ejectchem") - if(beaker) - beaker.loc = src.loc - beaker = null - . = TRUE - - if("power") - if(dish) - on = !on - icon_state = on ? "incubator_on" : "incubator" - . = TRUE - - if("ejectdish") - if(dish) - dish.loc = src.loc - dish = null - . = TRUE - - if("rad") - radiation = min(100, radiation + 10) - . = TRUE - - if("flush") - radiation = 0 - toxins = 0 - foodsupply = 0 - . = TRUE - - if("virus") - if(!dish) - return TRUE - - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in beaker.reagents.reagent_list - if(!B) - return TRUE - - if(!B.data["virus2"]) - B.data["virus2"] = list() - - var/list/virus = list("[dish.virus2.uniqueID]" = dish.virus2.getcopy()) - B.data["virus2"] += virus - - ping("\The [src] pings, \"Injection complete.\"") - . = TRUE diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm deleted file mode 100644 index 8f088ee0e69..00000000000 --- a/code/modules/virus2/effect.dm +++ /dev/null @@ -1,520 +0,0 @@ -/datum/disease2/effectholder - var/name = "Holder" - var/datum/disease2/effect/effect - var/chance = 0 //Chance in percentage each tick - var/cure = "" //Type of cure it requires - var/happensonce = 0 - var/multiplier = 1 //The chance the effects are WORSE - var/stage = 0 - -/datum/disease2/effectholder/proc/runeffect(var/mob/living/carbon/human/mob,var/stage) - if(happensonce > -1 && effect.stage <= stage && prob(chance)) - effect.activate(mob, multiplier) - if(happensonce == 1) - happensonce = -1 - -/datum/disease2/effectholder/proc/getrandomeffect(var/badness = 1, exclude_types=list()) - var/list/datum/disease2/effect/list = list() - for(var/datum/disease2/effect/f as anything in subtypesof(/datum/disease2/effect)) - if(f in exclude_types) - continue - if(initial(f.badness) > badness) //we don't want such strong effects - continue - if(initial(f.stage) <= src.stage) - list += f - var/type = pick(list) - effect = new type() - effect.generate() - chance = rand(0,effect.chance_maxm) - multiplier = rand(1,effect.maxm) - -/datum/disease2/effectholder/proc/minormutate() - switch(pick(1,2,3,4,5)) - if(1) - chance = rand(0,effect.chance_maxm) - if(2) - multiplier = rand(1,effect.maxm) - -/datum/disease2/effectholder/proc/majormutate(exclude_types=list()) - getrandomeffect(3, exclude_types) - -//////////////////////////////////////////////////////////////// -////////////////////////EFFECTS///////////////////////////////// -//////////////////////////////////////////////////////////////// - -/datum/disease2/effect - var/chance_maxm = 50 //note that disease effects only proc once every 3 ticks for humans - var/name = "Blanking effect" - var/stage = 4 - var/maxm = 1 - var/badness = 1 - var/data = null // For semi-procedural effects; this should be generated in generate() if used - -/datum/disease2/effect/proc/activate(var/mob/living/carbon/mob,var/multiplier) -/datum/disease2/effect/proc/deactivate(var/mob/living/carbon/mob) -/datum/disease2/effect/proc/generate(copy_data) // copy_data will be non-null if this is a copy; it should be used to initialise the data for this effect if present - -/datum/disease2/effect/invisible - name = "Waiting Syndrome" - stage = 1 - badness = 3 - -/datum/disease2/effect/invisible/activate(var/mob/living/carbon/mob,var/multiplier) - return - -////////////////////////STAGE 4///////////////////////////////// - -/datum/disease2/effect/nothing - name = "Nil Syndrome" - stage = 4 - badness = 1 - chance_maxm = 0 - -/datum/disease2/effect/gibbingtons - name = "Gibbington's Syndrome" - stage = 4 - badness = 3 - -/datum/disease2/effect/gibbingtons/activate(var/mob/living/carbon/mob,var/multiplier) - // Probabilities have been tweaked to kill in ~2-3 minutes, giving 5-10 messages. - // Probably needs more balancing, but it's better than LOL U GIBBED NOW, especially now that viruses can potentially have no signs up until Gibbingtons. - mob.adjustBruteLoss(10*multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/obj/item/organ/external/O = pick(H.organs) - if(prob(25)) - to_chat(mob, span_warning("Your [O.name] feels as if it might burst!")) - if(prob(10)) - spawn(50) - if(O) - O.droplimb(0,DROPLIMB_BLUNT) - else - if(prob(75)) - to_chat(mob, span_warning("Your whole body feels like it might fall apart!")) - if(prob(10)) - mob.adjustBruteLoss(25*multiplier) - -/datum/disease2/effect/radian - name = "Radian's Syndrome" - stage = 4 - maxm = 3 - badness = 2 - -/datum/disease2/effect/radian/activate(var/mob/living/carbon/mob,var/multiplier) - mob.apply_effect(2*multiplier, IRRADIATE, check_protection = 0) - -/datum/disease2/effect/deaf - name = "Deafness" - stage = 4 - badness = 2 - -/datum/disease2/effect/deaf/activate(var/mob/living/carbon/mob,var/multiplier) - mob.ear_deaf += 20 - -/datum/disease2/effect/monkey - name = "Genome Regression" - stage = 4 - badness = 3 - -/datum/disease2/effect/monkey/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob,/mob/living/carbon/human)) - var/mob/living/carbon/human/h = mob - h.monkeyize() - -/datum/disease2/effect/killertoxins - name = "Autoimmune Response" - stage = 4 - badness = 2 - -/datum/disease2/effect/killertoxins/activate(var/mob/living/carbon/mob,var/multiplier) - mob.adjustToxLoss(15*multiplier) - -/datum/disease2/effect/dna - name = "Catastrophic DNA Degeneration" - stage = 4 - badness = 2 - -/datum/disease2/effect/dna/activate(var/mob/living/carbon/mob,var/multiplier) - mob.bodytemperature = max(mob.bodytemperature, 350) - scramble(0,mob,10) - mob.apply_damage(10, CLONE) - -/datum/disease2/effect/organs - name = "Limb Paralysis" - stage = 4 - badness = 2 - -/datum/disease2/effect/organs/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/organ = pick(list("r_arm","l_arm","r_leg","l_leg")) - var/obj/item/organ/external/E = H.organs_by_name[organ] - if (!(E.status & ORGAN_DEAD)) - E.status |= ORGAN_DEAD - to_chat(H, span_notice("You can't feel your [E.name] anymore...")) - for (var/obj/item/organ/external/C in E.children) - C.status |= ORGAN_DEAD - H.update_icons_body() - mob.adjustToxLoss(15*multiplier) - -/datum/disease2/effect/organs/deactivate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - for (var/obj/item/organ/external/E in H.organs) - E.status &= ~ORGAN_DEAD - for (var/obj/item/organ/external/C in E.children) - C.status &= ~ORGAN_DEAD - H.update_icons_body() - -/datum/disease2/effect/internalorgan - name = "Organ Shutdown" - stage = 4 - badness = 2 - -/datum/disease2/effect/internalorgan/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/organ = pick(list("heart","kidney","liver", "lungs")) - var/obj/item/organ/internal/O = H.organs_by_name[organ] - if (O.robotic != ORGAN_ROBOT) - O.damage += (5*multiplier) - to_chat(H, span_notice("You feel a cramp in your guts.")) - -/datum/disease2/effect/immortal - name = "Hyperaccelerated Aging" - stage = 4 - badness = 2 - -/datum/disease2/effect/immortal/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - for (var/obj/item/organ/external/E in H.organs) - if (E.status & ORGAN_BROKEN && prob(30)) - E.status ^= ORGAN_BROKEN - var/heal_amt = -5*multiplier - mob.apply_damages(heal_amt,heal_amt,heal_amt,heal_amt) - -/datum/disease2/effect/immortal/deactivate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - to_chat(H, span_notice("You suddenly feel hurt and old...")) - H.age += 8 - var/backlash_amt = 5*multiplier - mob.apply_damages(backlash_amt,backlash_amt,backlash_amt,backlash_amt) - -/datum/disease2/effect/bones - name = "Brittle Bones" - stage = 4 - badness = 2 -/datum/disease2/effect/bones/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - for (var/obj/item/organ/external/E in H.organs) - E.min_broken_damage = max(5, E.min_broken_damage - 30) - -/datum/disease2/effect/bones/deactivate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - for (var/obj/item/organ/external/E in H.organs) - E.min_broken_damage = initial(E.min_broken_damage) - -/datum/disease2/effect/combustion - name = "Organic Ignition" - stage = 4 - badness = 3 - -/datum/disease2/effect/combustion/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/obj/item/organ/external/O = pick(H.organs) - if(prob(25)) - to_chat(mob, span_warning("It feels like your [O.name] is on fire and your blood is boiling!")) - H.adjust_fire_stacks(1) - if(prob(10)) - to_chat(mob, span_warning("Flames erupt from your skin, your entire body is burning!")) - H.adjust_fire_stacks(2) - H.IgniteMob() - - -////////////////////////STAGE 3///////////////////////////////// - -/datum/disease2/effect/toxins - name = "Hyperacidity" - stage = 3 - maxm = 3 - -/datum/disease2/effect/toxins/activate(var/mob/living/carbon/mob,var/multiplier) - mob.adjustToxLoss((2*multiplier)) - -/datum/disease2/effect/shakey - name = "Nervous Motor Instability" - stage = 3 - maxm = 3 - -/datum/disease2/effect/shakey/activate(var/mob/living/carbon/mob,var/multiplier) - shake_camera(mob,5*multiplier) - -/datum/disease2/effect/telepathic - name = "Pineal Gland Decalcification" - stage = 3 - -/datum/disease2/effect/telepathic/activate(var/mob/living/carbon/mob,var/multiplier) - mob.dna.SetSEState(REMOTETALKBLOCK,1) - domutcheck(mob, null, MUTCHK_FORCED) - -/datum/disease2/effect/mind - name = "Neurodegeneration" - stage = 3 - -/datum/disease2/effect/mind/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/obj/item/organ/internal/brain/B = H.internal_organs_by_name["brain"] - if (B && B.damage < B.min_broken_damage) - B.take_damage(5) - else - mob.setBrainLoss(10) - -/datum/disease2/effect/hallucinations - name = "Hallucination" - stage = 3 - -/datum/disease2/effect/hallucinations/activate(var/mob/living/carbon/mob,var/multiplier) - mob.hallucination += 25 - -/datum/disease2/effect/minordeaf - name = "Hearing Loss" - stage = 3 - -/datum/disease2/effect/minordeaf/activate(var/mob/living/carbon/mob,var/multiplier) - mob.ear_deaf = 5 - -/datum/disease2/effect/giggle - name = "Uncontrolled Laughter" - stage = 3 - chance_maxm = 20 - -/datum/disease2/effect/giggle/activate(var/mob/living/carbon/mob,var/multiplier) - if(prob(66)) - mob.say("*giggle") - else - to_chat(mob, span_notice("What's so funny?")) - -/datum/disease2/effect/confusion - name = "Topographical Cretinism" - stage = 3 - -/datum/disease2/effect/confusion/activate(var/mob/living/carbon/mob,var/multiplier) - to_chat(mob, span_notice("You have trouble telling right and left apart all of a sudden.")) - mob.Confuse(10) - -/datum/disease2/effect/mutation - name = "DNA Degradation" - stage = 3 - -/datum/disease2/effect/mutation/activate(var/mob/living/carbon/mob,var/multiplier) - mob.apply_damage(2, CLONE) - -/datum/disease2/effect/groan - name = "Phantom Aches" - stage = 3 - chance_maxm = 20 - -/datum/disease2/effect/groan/activate(var/mob/living/carbon/mob,var/multiplier) - if(prob(66)) - mob.say("*groan") - else if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/obj/item/organ/external/E = pick(H.organs) - to_chat(mob, span_warning("Your [E] aches.")) - -/datum/disease2/effect/chem_synthesis - name = "Chemical Synthesis" - stage = 3 - chance_maxm = 25 - -/datum/disease2/effect/chem_synthesis/generate(c_data) - if(c_data) - data = c_data - else - data = pick("bicaridine", "kelotane", "anti_toxin", "inaprovaline", "bliss", "sugar", - "tramadol", "dexalin", "cryptobiolin", "impedrezene", "hyperzine", "ethylredoxrazine", - "mindbreaker", "glucose") - var/datum/reagent/R = SSchemistry.chemical_reagents[data] - name = "[initial(name)] ([initial(R.name)])" - -/datum/disease2/effect/chem_synthesis/activate(var/mob/living/carbon/mob,var/multiplier) - if (mob.reagents.get_reagent_amount(data) < 5) - mob.reagents.add_reagent(data, 2) - -/datum/disease2/effect/nonrejection - name = "Genetic Chameleonism" - stage = 3 - -/datum/disease2/effect/nonrejection/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - var/obj/item/organ/internal/O = H.organs_by_name - for (var/organ in H.organs_by_name) - if (O.robotic != ORGAN_ROBOT) - O.rejecting = 0 - - -////////////////////////STAGE 2///////////////////////////////// - -/datum/disease2/effect/scream - name = "Involuntary Vocalization" - stage = 2 - chance_maxm = 10 - -/datum/disease2/effect/scream/activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*scream") - -/datum/disease2/effect/drowsness - name = "Excessive Sleepiness" - stage = 2 - -/datum/disease2/effect/drowsness/activate(var/mob/living/carbon/mob,var/multiplier) - mob.drowsyness += 10 - -/datum/disease2/effect/sleepy - name = "Narcolepsy" - stage = 2 - chance_maxm = 15 - -/datum/disease2/effect/sleepy/activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*collapse") - -/datum/disease2/effect/blind - name = "Vision Loss" - stage = 2 - -/datum/disease2/effect/blind/activate(var/mob/living/carbon/mob,var/multiplier) - mob.SetBlinded(4) - -/datum/disease2/effect/cough - name = "Severe Cough" - stage = 2 - chance_maxm = 20 - -/datum/disease2/effect/cough/activate(var/mob/living/carbon/mob,var/multiplier) - if(prob(60)) - mob.say("*cough") - for(var/mob/living/carbon/M in oview(2,mob)) - mob.spread_disease_to(M) - else - to_chat(mob, span_warning("Something gets caught in your throat.")) - -/datum/disease2/effect/hungry - name = "Digestive Inefficiency" - stage = 2 - -/datum/disease2/effect/hungry/activate(var/mob/living/carbon/mob,var/multiplier) - mob.adjust_nutrition(-200) - -/datum/disease2/effect/fridge - name = "Reduced Circulation" - stage = 2 - chance_maxm = 25 - -/datum/disease2/effect/fridge/activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*shiver") - -/datum/disease2/effect/hair - name = "Hair Loss" - stage = 2 - -/datum/disease2/effect/hair/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - if(H.species.name == SPECIES_HUMAN && !(H.h_style == "Bald") && !(H.h_style == "Balding Hair")) - to_chat(H, span_danger("Your hair starts to fall out in clumps...")) - spawn(50) - H.h_style = "Balding Hair" - H.update_hair() - -/datum/disease2/effect/stimulant - name = "Overactive Adrenal Gland" - stage = 2 - -/datum/disease2/effect/stimulant/activate(var/mob/living/carbon/mob,var/multiplier) - to_chat(mob, span_notice("You feel a rush of energy inside you!")) - if (mob.reagents.get_reagent_amount("hyperzine") < 10) - mob.reagents.add_reagent("hyperzine", 4) - if (prob(30)) - mob.jitteriness += 10 - -/datum/disease2/effect/ringing - name = "Tinnitus" - stage = 2 - chance_maxm = 25 - -/datum/disease2/effect/ringing/activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = mob - to_chat(H, span_notice("You hear an awful ringing in your ears.")) - H << 'sound/weapons/flash.ogg' - -/datum/disease2/effect/vomiting - name = "Vomiting" - stage = 2 - chance_maxm = 15 - -/datum/disease2/effect/vomiting/activate(var/mob/living/carbon/mob,var/multiplier) - to_chat(mob, span_notice("Your stomach churns!")) - if (prob(50)) - mob.say("*vomit") - -////////////////////////STAGE 1///////////////////////////////// - -/datum/disease2/effect/sneeze - name = "Sneezing" - stage = 1 - chance_maxm = 20 - -/datum/disease2/effect/sneeze/activate(var/mob/living/carbon/mob,var/multiplier) - if(prob(20)) - to_chat(mob, span_warning("You go to sneeze, but it gets caught in your sinuses!")) - else if(prob(80)) - if(prob(30)) - to_chat(mob, span_warning("You feel like you are about to sneeze!")) - spawn(5) //Sleep may have been hanging Mob controller. - mob.say("*sneeze") - for(var/mob/living/carbon/M in get_step(mob,mob.dir)) - mob.spread_disease_to(M) - if (prob(50)) - var/obj/effect/decal/cleanable/mucus/M = new(get_turf(mob)) - M.virus2 = virus_copylist(mob.virus2) - -/datum/disease2/effect/gunck - name = "Mucus Buildup" - stage = 1 - -/datum/disease2/effect/gunck/activate(var/mob/living/carbon/mob,var/multiplier) - to_chat(mob, span_warning("Mucous runs down the back of your throat.")) - -/datum/disease2/effect/drool - name = "Salivary Gland Stimulation" - stage = 1 - chance_maxm = 15 - -/datum/disease2/effect/drool/activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*drool") - if (prob(30)) - var/obj/effect/decal/cleanable/mucus/M = new(get_turf(mob)) - M.virus2 = virus_copylist(mob.virus2) - -/datum/disease2/effect/twitch - name = "Involuntary Twitching" - stage = 1 - chance_maxm = 15 - -/datum/disease2/effect/twitch/activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*twitch") - -/datum/disease2/effect/headache - name = "Headache" - stage = 1 - -/datum/disease2/effect/headache/activate(var/mob/living/carbon/mob,var/multiplier) - to_chat(mob, span_warning("Your head hurts a bit.")) diff --git a/code/modules/virus2/effect_vr.dm b/code/modules/virus2/effect_vr.dm deleted file mode 100644 index 307111f44e8..00000000000 --- a/code/modules/virus2/effect_vr.dm +++ /dev/null @@ -1,63 +0,0 @@ -/////////////////////////////////////////////// -/////////////////// Stage 1 /////////////////// - -/datum/disease2/effect/mlem - name = "Mlemington's Syndrome" - stage = 1 - chance_maxm = 25 - -/datum/disease2/effect/mlem/activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("[pick("Mlem.","MLEM!","Mlem?")]") - -/datum/disease2/effect/spin - name = "Spyndrome" - stage = 1 - chance_maxm = 7 - var/list/directions = list(2,4,1,8,2,4,1,8,2,4,1,8,2,4,1,8,2,4,1,8) - -/datum/disease2/effect/spin/activate(var/mob/living/carbon/mob,var/multiplier) - if(mob.buckled()) - to_chat(viewers(mob),span_warning("[mob.name] struggles violently against their restraints!")) - else - to_chat(viewers(mob),span_warning("[mob.name] spins around violently!")) - for(var/D in directions) - mob.dir = D - sleep(1) - mob.dir = pick(2,4,1,8) //For that added annoyance - -/////////////////////////////////////////////// -/////////////////// Stage 2 /////////////////// - -/datum/disease2/effect/lang - name = "Lingual Dissocation" - stage = 2 - chance_maxm = 2 - -/datum/disease2/effect/lang/activate(var/mob/living/carbon/mob,var/multiplier) - mob.set_default_language(pick(mob.languages)) - -/////////////////////////////////////////////// -/////////////////// Stage 3 /////////////////// - -/datum/disease2/effect/size - name = "Mass Revectoring" - stage = 3 - chance_maxm = 1 - -/datum/disease2/effect/size/activate(var/mob/living/carbon/mob,var/multiplier) - var/newsize = rand (25, 200) - mob.resize(newsize/100) - to_chat(viewers(mob),span_warning("[mob.name] suddenly changes size!")) - -/datum/disease2/effect/flip - name = "Flipponov's Disease" - stage = 3 - chance_maxm = 5 - -/datum/disease2/effect/flip/activate(var/mob/living/carbon/mob,var/multiplier) //Remind me why mob is carbon...? - if(ishuman(mob)) - var/mob/living/carbon/human/H = mob - H.emote("flip") - else - to_chat(viewers(mob),span_warning("[mob.name] does a backflip!")) - mob.SpinAnimation(7,1) diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm deleted file mode 100644 index 053498042ef..00000000000 --- a/code/modules/virus2/helpers.dm +++ /dev/null @@ -1,181 +0,0 @@ -//Returns 1 if mob can be infected, 0 otherwise. -/proc/infection_check(var/mob/living/carbon/M, var/vector = "Airborne") - if (!istype(M)) - return 0 - - var/mob/living/carbon/human/H = M - if(istype(H) && H.species.get_virus_immune(H)) - return 0 - - var/protection = M.getarmor(null, "bio") //gets the full body bio armour value, weighted by body part coverage. - var/score = round(0.06*protection) //scales 100% protection to 6. - - switch(vector) - if("Airborne") - if(M.internal) //not breathing infected air helps greatly - return 0 - var/obj/item/I = M.wear_mask - //masks provide a small bonus and can replace overall bio protection - if(I) - score = max(score, round(0.06*I.armor["bio"])) - if (istype(I, /obj/item/clothing/mask)) - score += 1 //this should be added after - - if("Contact") - if(istype(H)) - //gloves provide a larger bonus - if (istype(H.gloves, /obj/item/clothing/gloves)) - score += 2 - - if(score >= 6) - return 0 - else if(score >= 5 && prob(99)) - return 0 - else if(score >= 4 && prob(95)) - return 0 - else if(score >= 3 && prob(75)) - return 0 - else if(score >= 2 && prob(55)) - return 0 - else if(score >= 1 && prob(35)) - return 0 - return 1 - -//Similar to infection check, but used for when M is spreading the virus. -/proc/infection_spreading_check(var/mob/living/carbon/M, var/vector = "Airborne") - if (!istype(M)) - return 0 - - var/protection = M.getarmor(null, "bio") //gets the full body bio armour value, weighted by body part coverage. - - if (vector == "Airborne") - var/obj/item/I = M.wear_mask - if (istype(I)) - protection = max(protection, I.armor["bio"]) - - return prob(protection) - -//Checks if table-passing table can reach target (5 tile radius) -/proc/airborne_can_reach(turf/source, turf/target) - var/obj/dummy = new(source) - dummy.pass_flags = PASSTABLE - - for(var/i=0, i<5, i++) if(!step_towards(dummy, target)) break - - var/rval = dummy.Adjacent(target) - dummy.loc = null - dummy = null - return rval - -//Attemptes to infect mob M with virus. Set forced to 1 to ignore protective clothnig -/proc/infect_virus2(var/mob/living/carbon/M,var/datum/disease2/disease/disease,var/forced = 0) - if(!istype(disease)) -// log_debug("Bad virus") - return - if(!istype(M)) -// log_debug("Bad mob") - return - if ("[disease.uniqueID]" in M.virus2) - return - // if one of the antibodies in the mob's body matches one of the disease's antigens, don't infect - var/list/antibodies_in_common = M.antibodies & disease.antigen - if(antibodies_in_common.len) - return - if(M.chem_effects[CE_ANTIBIOTIC]) - if(prob(disease.resistance)) - var/datum/disease2/disease/D = disease.getcopy() - D.minormutate() - D.resistance += rand(1,9) -// log_debug("Adding virus") - M.virus2["[D.uniqueID]"] = D - BITSET(M.hud_updateflag, STATUS_HUD) - else - return //Virus prevented by antibiotics - - if(!disease.affected_species.len) - return - - if (!(M.species.get_bodytype() in disease.affected_species)) - if (forced) - disease.affected_species[1] = M.species.get_bodytype() - else - return //not compatible with this species - -// log_debug("Infecting [M]") - - if(forced || (infection_check(M, disease.spreadtype) && prob(disease.infectionchance))) - var/datum/disease2/disease/D = disease.getcopy() - D.minormutate() -// log_debug("Adding virus") - M.virus2["[D.uniqueID]"] = D - BITSET(M.hud_updateflag, STATUS_HUD) - - -//Infects mob M with disease D -/proc/infect_mob(var/mob/living/carbon/M, var/datum/disease2/disease/D) - infect_virus2(M,D,1) - M.hud_updateflag |= 1 << STATUS_HUD - -//Infects mob M with random lesser disease, if he doesn't have one -/proc/infect_mob_random_lesser(var/mob/living/carbon/M) - var/datum/disease2/disease/D = new /datum/disease2/disease - - D.makerandom(1) - infect_mob(M, D) - -//Infects mob M with random greated disease, if he doesn't have one -/proc/infect_mob_random_greater(var/mob/living/carbon/M) - var/datum/disease2/disease/D = new /datum/disease2/disease - - D.makerandom(2) - infect_mob(M, D) - -//Fancy prob() function. -/proc/dprob(var/p) - return(prob(sqrt(p)) && prob(sqrt(p))) - -/mob/living/carbon/proc/spread_disease_to(var/mob/living/carbon/victim, var/vector = "Airborne") - if (src == victim) - return "Neurodegeneration" - -// log_debug("Spreading [vector] diseases from [src] to [victim]") - if (virus2.len > 0) - for (var/ID in virus2) -// log_debug("Attempting virus [ID]") - var/datum/disease2/disease/V = virus2[ID] - if(V.spreadtype != vector) continue - - //It's hard to get other people sick if you're in an airtight suit. - if(!infection_spreading_check(src, V.spreadtype)) continue - - if (vector == "Airborne") - if(airborne_can_reach(get_turf(src), get_turf(victim))) -// log_debug("In range, infecting") - infect_virus2(victim,V) -// else -// log_debug("Could not reach target") - - if (vector == "Contact") - if (Adjacent(victim)) -// log_debug("In range, infecting") - infect_virus2(victim,V) - - //contact goes both ways - if (victim.virus2.len > 0 && vector == "Contact" && Adjacent(victim)) -// log_debug("Spreading [vector] diseases from [victim] to [src]") - var/nudity = 1 - - if (ishuman(victim)) - var/mob/living/carbon/human/H = victim - var/obj/item/organ/external/select_area = H.get_organ(src.zone_sel.selecting) - var/list/clothes = list(H.head, H.wear_mask, H.wear_suit, H.w_uniform, H.gloves, H.shoes) - for(var/obj/item/clothing/C in clothes) - if(C && istype(C)) - if(C.body_parts_covered & select_area.body_part) - nudity = 0 - if (nudity) - for (var/ID in victim.virus2) - var/datum/disease2/disease/V = victim.virus2[ID] - if(V && V.spreadtype != vector) continue - if(!infection_spreading_check(victim, V.spreadtype)) continue - infect_virus2(src,V) diff --git a/code/modules/virus2/isolator.dm b/code/modules/virus2/isolator.dm deleted file mode 100644 index 7e4dc129728..00000000000 --- a/code/modules/virus2/isolator.dm +++ /dev/null @@ -1,211 +0,0 @@ -/obj/machinery/disease2/isolator/ - name = "pathogenic isolator" - desc = "Used to isolate and identify diseases, allowing for comparison with a remote database." - density = TRUE - anchored = TRUE - icon = 'icons/obj/virology_vr.dmi' //VOREStation Edit - icon_state = "isolator" - var/isolating = 0 - var/datum/disease2/disease/virus2 = null - var/obj/item/reagent_containers/syringe/sample = null - -/obj/machinery/disease2/isolator/update_icon() - if (stat & (BROKEN|NOPOWER)) - icon_state = "isolator" - return - - if (isolating) - icon_state = "isolator_processing" - else if (sample) - icon_state = "isolator_in" - else - icon_state = "isolator" - -/obj/machinery/disease2/isolator/attackby(var/obj/O as obj, var/mob/user) - if(default_unfasten_wrench(user, O, 20)) - return - - else if(!istype(O,/obj/item/reagent_containers/syringe)) return - var/obj/item/reagent_containers/syringe/S = O - - if(sample) - to_chat(user, "\The [src] is already loaded.") - return - - sample = S - user.drop_item() - S.loc = src - - user.visible_message("[user] adds \a [O] to \the [src]!", "You add \a [O] to \the [src]!") - SStgui.update_uis(src) - update_icon() - - src.attack_hand(user) - -/obj/machinery/disease2/isolator/attack_hand(mob/user as mob) - if(stat & (NOPOWER|BROKEN)) - return - tgui_interact(user) - -/obj/machinery/disease2/isolator/tgui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "PathogenicIsolator", name) - ui.open() - - -/obj/machinery/disease2/isolator/tgui_data(mob/user) - var/list/data = list() - data["syringe_inserted"] = !!sample - data["isolating"] = isolating - data["pathogen_pool"] = null - data["can_print"] = !isolating - - var/list/pathogen_pool = list() - if(sample) - for(var/datum/reagent/blood/B in sample.reagents.reagent_list) - var/list/virus = B.data["virus2"] - for (var/ID in virus) - var/datum/disease2/disease/V = virus[ID] - var/datum/data/record/R = null - if (ID in virusDB) - R = virusDB[ID] - - var/mob/living/carbon/human/D = B.data["donor"] - pathogen_pool.Add(list(list(\ - "name" = "[istype(D) ? "[D.get_species()] " : ""][B.name]", \ - "dna" = B.data["blood_DNA"], \ - "unique_id" = V.uniqueID, \ - "reference" = "\ref[V]", \ - "is_in_database" = !!R, \ - "record" = "\ref[R]"))) - data["pathogen_pool"] = pathogen_pool - - var/list/db = list() - for(var/ID in virusDB) - var/datum/data/record/r = virusDB[ID] - db.Add(list(list("name" = r.fields["name"], "record" = "\ref[r]"))) - data["database"] = db - data["modal"] = tgui_modal_data(src) - return data - -/obj/machinery/disease2/isolator/process() - if (isolating > 0) - isolating -= 1 - if (isolating == 0) - if (virus2) - var/obj/item/virusdish/d = new /obj/item/virusdish(src.loc) - d.virus2 = virus2.getcopy() - virus2 = null - ping("\The [src] pings, \"Viral strain isolated.\"") - - SStgui.update_uis(src) - update_icon() - -/obj/machinery/disease2/isolator/tgui_act(action, list/params) - if(..()) - return TRUE - - var/mob/user = usr - add_fingerprint(user) - - . = TRUE - switch(tgui_modal_act(src, action, params)) - if(TGUI_MODAL_ANSWER) - return - - switch(action) - if("view_entry") - var/datum/data/record/v = locate(params["vir"]) - if(!istype(v)) - return FALSE - tgui_modal_message(src, "virus", "", null, v.fields["tgui_description"]) - return TRUE - - if("print") - print(user, params) - return TRUE - - if("isolate") - var/datum/disease2/disease/V = locate(params["isolate"]) - if (V) - virus2 = V - isolating = 20 - update_icon() - return TRUE - - if("eject") - if(!sample) - return FALSE - sample.forceMove(loc) - sample = null - update_icon() - return TRUE - -/obj/machinery/disease2/isolator/proc/print(mob/user, list/params) - var/obj/item/paper/P = new /obj/item/paper(loc) - - switch(params["type"]) - if("patient_diagnosis") - if (!sample) return - P.name = "paper - Patient Diagnostic Report" - P.info = {" - [virology_letterhead("Patient Diagnostic Report")] -
CONFIDENTIAL MEDICAL REPORT

- Sample: [sample.name]
-"} - - if (user) - P.info += "Generated By: [user.name]
" - - P.info += "
" - - for(var/datum/reagent/blood/B in sample.reagents.reagent_list) - var/mob/living/carbon/human/D = B.data["donor"] - P.info += "[D.get_species()] [B.name]:
[B.data["blood_DNA"]]
" - - var/list/virus = B.data["virus2"] - P.info += "Pathogens:
" - if (virus.len > 0) - for (var/ID in virus) - var/datum/disease2/disease/V = virus[ID] - P.info += "[V.name()]
" - else - P.info += "None
" - - P.info += {" -
- Additional Notes:  -"} - - if("virus_list") - P.name = "paper - Virus List" - P.info = {" - [virology_letterhead("Virus List")] -"} - - var/i = 0 - for (var/ID in virusDB) - i++ - var/datum/data/record/r = virusDB[ID] - P.info += "[i]. " + r.fields["name"] - P.info += "
" - - P.info += {" -
- Additional Notes:  -"} - - if("virus_record") - var/datum/data/record/v = locate(params["vir"]) - if(!istype(v)) - return FALSE - P.name = "paper - Viral Profile" - P.info = {" - [virology_letterhead("Viral Profile")] - [v.fields["description"]] -
- Additional Notes:  -"} - - state("The nearby computer prints out a report.") diff --git a/code/modules/virus2/items_devices.dm b/code/modules/virus2/items_devices.dm deleted file mode 100644 index ee9d4b63771..00000000000 --- a/code/modules/virus2/items_devices.dm +++ /dev/null @@ -1,114 +0,0 @@ -///////////////ANTIBODY SCANNER/////////////// - -/obj/item/antibody_scanner - name = "antibody scanner" - desc = "Scans living beings for antibodies in their blood." - icon = 'icons/obj/device_vr.dmi' - icon_state = "antibody" - w_class = ITEMSIZE_SMALL - item_state = "electronic" - -/obj/item/antibody_scanner/attack(mob/M as mob, mob/user as mob) - if(!istype(M,/mob/living/carbon/)) - report("Scan aborted: Incompatible target.", user) - return - - var/mob/living/carbon/C = M - if (istype(C,/mob/living/carbon/human/)) - var/mob/living/carbon/human/H = C - if(!H.should_have_organ(O_HEART)) - report("Scan aborted: The target does not have blood.", user) - return - - if(!C.antibodies.len) - report("Scan Complete: No antibodies detected.", user) - return - - if (CLUMSY in user.mutations && prob(50)) - // I was tempted to be really evil and rot13 the output. - report("Antibodies detected: [reverse_text(antigens2string(C.antibodies))]", user) - else - report("Antibodies detected: [antigens2string(C.antibodies)]", user) - -/obj/item/antibody_scanner/proc/report(var/text, mob/user as mob) - to_chat(user, "[span_blue("[icon2html(src, user.client)] \The [src] beeps,")] \"[span_blue("[text]")]\"") - -///////////////VIRUS DISH/////////////// - -/obj/item/virusdish - name = "virus dish" - icon = 'icons/obj/items.dmi' - icon_state = "virussample" - var/datum/disease2/disease/virus2 = null - var/growth = 0 - var/basic_info = null - var/info = 0 - var/analysed = 0 - -/obj/item/virusdish/random - name = "virus sample" - -/obj/item/virusdish/random/New() - ..() - src.virus2 = new /datum/disease2/disease - src.virus2.makerandom() - growth = rand(5, 50) - -/obj/item/virusdish/attackby(var/obj/item/W as obj,var/mob/living/carbon/user as mob) - if(istype(W,/obj/item/hand_labeler) || istype(W,/obj/item/reagent_containers/syringe)) - //VOREstation edit - Actually functional virus dishes - // Originally this returns, THEN calls ..() instead of returning the value of ..() - return ..() - //VOREstation edit end - if(prob(50)) - to_chat(user, span_danger("\The [src] shatters!")) - if(virus2.infectionchance > 0) - for(var/mob/living/carbon/target in view(1, get_turf(src))) - if(airborne_can_reach(get_turf(src), get_turf(target))) - infect_virus2(target, src.virus2) - qdel(src) - -/obj/item/virusdish/examine(mob/user) - . = ..() - if(basic_info) - . += "[basic_info] : More Information" - -/obj/item/virusdish/Topic(href, href_list) - . = ..() - if(.) return 1 - - if(href_list["info"]) - usr << browse(info, "window=info_\ref[src]") - return 1 - -/obj/item/ruinedvirusdish - name = "ruined virus sample" - icon = 'icons/obj/items.dmi' - icon_state = "virussample-ruined" - desc = "The bacteria in the dish are completely dead." - -/obj/item/ruinedvirusdish/attackby(var/obj/item/W as obj,var/mob/living/carbon/user as mob) - if(istype(W,/obj/item/hand_labeler) || istype(W,/obj/item/reagent_containers/syringe)) - return ..() - - if(prob(50)) - to_chat(user, "\The [src] shatters!") - qdel(src) - -///////////////GNA DISK/////////////// - -/obj/item/diseasedisk - name = "blank GNA disk" - icon = 'icons/obj/cloning.dmi' - icon_state = "datadisk0" - w_class = ITEMSIZE_TINY - var/datum/disease2/effectholder/effect = null - var/list/species = null - var/stage = 1 - var/analysed = 1 - -/obj/item/diseasedisk/premade/New() - name = "blank GNA disk (stage: [stage])" - effect = new /datum/disease2/effectholder - effect.effect = new /datum/disease2/effect/invisible - effect.stage = stage diff --git a/icons/mob/macrophage.dmi b/icons/mob/macrophage.dmi new file mode 100644 index 00000000000..4b7518bfc64 Binary files /dev/null and b/icons/mob/macrophage.dmi differ diff --git a/icons/obj/pandemic.dmi b/icons/obj/pandemic.dmi new file mode 100644 index 00000000000..870341bb870 Binary files /dev/null and b/icons/obj/pandemic.dmi differ diff --git a/maps/expedition_vr/beach/submaps/quarantineshuttle.dmm b/maps/expedition_vr/beach/submaps/quarantineshuttle.dmm index 83694ffdc0e..8b7ac40dd50 100644 --- a/maps/expedition_vr/beach/submaps/quarantineshuttle.dmm +++ b/maps/expedition_vr/beach/submaps/quarantineshuttle.dmm @@ -141,6 +141,7 @@ /area/submap/cave/qShuttle) "au" = ( /obj/structure/closet/crate/secure/loot, +/obj/item/reagent_containers/glass/bottle/culture/cold, /turf/simulated/shuttle/floor{ icon_state = "floor_yellow" }, @@ -332,7 +333,8 @@ }, /area/submap/cave/qShuttle) "aV" = ( -/obj/item/virusdish/random, +/obj/structure/closet/crate/secure/loot, +/obj/item/reagent_containers/glass/bottle/culture/flu, /turf/simulated/shuttle/floor{ icon_state = "floor_yellow" }, @@ -472,9 +474,6 @@ name = "Virus Samples - FRAGILE"; opened = 1 }, -/obj/item/virusdish/random, -/obj/item/virusdish/random, -/obj/item/virusdish/random, /turf/simulated/shuttle/floor{ icon_state = "floor_yellow" }, @@ -1311,7 +1310,7 @@ ab ad au aF -aV +aA bj bv bE @@ -1363,7 +1362,7 @@ aa aa ab ad -au +aV aH aW bk @@ -1394,7 +1393,7 @@ ad ad aX aA -aV +aA ad ad ad diff --git a/maps/groundbase/gb-z2.dmm b/maps/groundbase/gb-z2.dmm index 537bcba1d87..ac234c68285 100644 --- a/maps/groundbase/gb-z2.dmm +++ b/maps/groundbase/gb-z2.dmm @@ -312,11 +312,6 @@ /area/groundbase/level2/nw) "aH" = ( /obj/structure/table/glass, -/obj/item/antibody_scanner, -/obj/item/antibody_scanner{ - pixel_x = 2; - pixel_y = 2 - }, /turf/simulated/floor/tiled/white, /area/medical/virology) "aI" = ( @@ -3839,12 +3834,7 @@ }, /turf/simulated/floor/outdoors/sidewalk/slab, /area/groundbase/level2/nw) -"kb" = ( -/obj/machinery/disease2/diseaseanalyser, -/turf/simulated/floor/tiled/white, -/area/medical/virology) "kc" = ( -/obj/machinery/disease2/incubator, /obj/structure/reagent_dispensers/virusfood{ pixel_y = 27 }, @@ -4980,9 +4970,7 @@ /turf/simulated/floor/tiled, /area/groundbase/science/hall) "nx" = ( -/obj/machinery/computer/diseasesplicer{ - dir = 1 - }, +/obj/machinery/computer/pandemic, /turf/simulated/floor/tiled/white, /area/medical/virology) "ny" = ( @@ -7017,10 +7005,15 @@ /turf/simulated/floor/tiled/eris/cafe, /area/groundbase/civilian/kitchen) "tk" = ( -/obj/machinery/disease2/isolator, /obj/machinery/light{ dir = 1 }, +/obj/structure/closet/crate/medical, +/obj/item/reagent_containers/glass/bottle/culture/cold{ + pixel_x = -5; + pixel_y = 5 + }, +/obj/item/reagent_containers/glass/bottle/culture/flu, /turf/simulated/floor/tiled/white, /area/medical/virology) "tm" = ( @@ -9340,7 +9333,6 @@ "Ag" = ( /obj/structure/table/glass, /obj/item/book/manual/virology, -/obj/item/antibody_scanner, /obj/item/reagent_containers/glass/beaker, /obj/item/paper_bin, /obj/item/folder/white, @@ -18186,10 +18178,6 @@ /obj/structure/closet/secure_closet/personal/patient, /turf/simulated/floor/tiled/white, /area/medical/virology) -"Zd" = ( -/obj/machinery/computer/centrifuge, -/turf/simulated/floor/tiled/white, -/area/medical/virology) "Ze" = ( /obj/structure/cable/yellow{ icon_state = "1-2" @@ -36335,8 +36323,8 @@ QA pe lj RW -Zd -kb +cG +cG aZ mb pe @@ -36477,7 +36465,7 @@ pe pe tk OH -cG +nx Qr cG xf @@ -36622,7 +36610,7 @@ OH aH bC cG -nx +cG pe fk UH diff --git a/maps/stellar_delight/stellar_delight1.dmm b/maps/stellar_delight/stellar_delight1.dmm index 10c67153881..4a75431ddac 100644 --- a/maps/stellar_delight/stellar_delight1.dmm +++ b/maps/stellar_delight/stellar_delight1.dmm @@ -8914,7 +8914,6 @@ /turf/simulated/floor/tiled/techmaint, /area/stellardelight/deck1/starboard) "sf" = ( -/obj/machinery/disease2/isolator, /obj/machinery/light/floortube{ dir = 8; pixel_x = -6 @@ -8924,6 +8923,12 @@ dir = 8; pixel_x = -24 }, +/obj/structure/closet/crate/medical, +/obj/item/reagent_containers/glass/bottle/culture/cold{ + pixel_x = -5; + pixel_y = 5 + }, +/obj/item/reagent_containers/glass/bottle/culture/flu, /turf/simulated/floor/tiled/eris/white/bluecorner, /area/medical/virology) "sg" = ( @@ -11002,9 +11007,6 @@ /turf/simulated/floor, /area/maintenance/stellardelight/deck1/portaft) "wR" = ( -/obj/machinery/computer/diseasesplicer{ - dir = 1 - }, /turf/simulated/floor/tiled/eris/white/bluecorner, /area/medical/virology) "wS" = ( @@ -13403,7 +13405,6 @@ /turf/simulated/wall/bay/black, /area/chapel/main) "BV" = ( -/obj/machinery/disease2/incubator, /obj/structure/reagent_dispensers/virusfood{ pixel_y = 27 }, @@ -13734,7 +13735,6 @@ "CJ" = ( /obj/structure/table/glass, /obj/item/book/manual/virology, -/obj/item/antibody_scanner, /obj/item/reagent_containers/glass/beaker, /obj/item/paper_bin, /obj/item/folder/white, @@ -15325,11 +15325,11 @@ /turf/simulated/floor/tiled/steel_ridged, /area/prison/cell_block) "Gn" = ( -/obj/machinery/disease2/diseaseanalyser, /obj/machinery/light/floortube{ dir = 8; pixel_x = -6 }, +/obj/machinery/computer/pandemic, /turf/simulated/floor/tiled/eris/white/bluecorner, /area/medical/virology) "Go" = ( @@ -22433,7 +22433,6 @@ /turf/simulated/floor/wood, /area/library) "Vq" = ( -/obj/machinery/computer/centrifuge, /obj/machinery/embedded_controller/radio/airlock/access_controller{ dir = 4; id_tag = "virology_airlock_control"; diff --git a/maps/tether/tether-01-surface1.dmm b/maps/tether/tether-01-surface1.dmm index 413088b4ad2..2768b3e8c66 100644 --- a/maps/tether/tether-01-surface1.dmm +++ b/maps/tether/tether-01-surface1.dmm @@ -12580,10 +12580,6 @@ /obj/structure/catwalk, /turf/simulated/floor/plating, /area/maintenance/lower/solars) -"avQ" = ( -/obj/machinery/disease2/isolator, -/turf/simulated/floor/tiled/white, -/area/medical/virology) "avR" = ( /obj/machinery/atmospherics/pipe/simple/hidden/yellow, /obj/structure/disposalpipe/segment, @@ -14214,11 +14210,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/yellow, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/table/glass, -/obj/item/antibody_scanner, -/obj/item/antibody_scanner{ - pixel_x = 2; - pixel_y = 2 - }, /turf/simulated/floor/tiled/white, /area/medical/virology) "ayk" = ( @@ -30657,7 +30648,6 @@ /turf/simulated/floor/tiled, /area/tether/surfacebase/security/brig) "cdl" = ( -/obj/machinery/disease2/diseaseanalyser, /obj/item/radio/intercom{ dir = 1; name = "Station Intercom (General)"; @@ -30669,6 +30659,7 @@ /obj/effect/floor_decal/corner/lime/border{ dir = 9 }, +/obj/structure/table/standard, /turf/simulated/floor/tiled/white, /area/medical/virology) "cdO" = ( @@ -34892,10 +34883,11 @@ dir = 1 }, /obj/structure/closet/crate/freezer, -/obj/item/virusdish/random, -/obj/item/virusdish/random, -/obj/item/virusdish/random, -/obj/item/virusdish/random, +/obj/item/reagent_containers/glass/bottle/culture/cold{ + pixel_x = -5; + pixel_y = 5 + }, +/obj/item/reagent_containers/glass/bottle/culture/flu, /turf/simulated/floor/tiled/white, /area/medical/virology) "nMH" = ( @@ -36544,7 +36536,6 @@ /turf/simulated/floor/plating, /area/maintenance/lower/vacant_site) "sLf" = ( -/obj/machinery/computer/diseasesplicer, /obj/machinery/light{ dir = 1 }, @@ -36554,6 +36545,7 @@ /obj/effect/floor_decal/corner/lime/border{ dir = 1 }, +/obj/machinery/computer/pandemic, /turf/simulated/floor/tiled/white, /area/medical/virology) "sLi" = ( @@ -37426,7 +37418,7 @@ /obj/effect/floor_decal/corner/lime/border{ dir = 1 }, -/obj/machinery/computer/centrifuge, +/obj/structure/table/standard, /turf/simulated/floor/tiled/white, /area/medical/virology) "vBy" = ( @@ -37545,10 +37537,6 @@ /obj/machinery/computer/arcade/orion_trail, /turf/simulated/floor/tiled, /area/tether/surfacebase/security/brig) -"vXS" = ( -/obj/machinery/disease2/incubator, -/turf/simulated/floor/tiled/white, -/area/medical/virology) "waR" = ( /turf/simulated/floor/tiled/dark, /area/tether/surfacebase/security/weaponsrange) @@ -54128,7 +54116,7 @@ aeE vwM avl afB -avQ +avl axj ayk ayK @@ -54270,7 +54258,7 @@ aeE nLm avl afD -vXS +avl axF ayl avl diff --git a/tgui/packages/tgui/interfaces/PanDEMIC.tsx b/tgui/packages/tgui/interfaces/PanDEMIC.tsx new file mode 100644 index 00000000000..ff8c718529c --- /dev/null +++ b/tgui/packages/tgui/interfaces/PanDEMIC.tsx @@ -0,0 +1,315 @@ +import { useBackend } from '../backend'; +import { + Button, + Flex, + LabeledList, + NoticeBox, + Section, + Stack, + Table, + Tabs, +} from '../components'; +import { Window } from '../layouts'; + +type Data = { + beakerLoaded: boolean; + beakerContainsBlood: boolean; + beakerContainsVirus: boolean; + resistances: string[]; + selectedStrainIndex: number; + strains: Strain[]; + synthesisCooldown: boolean; +}; + +type Strain = { + commonName: string; + description: string; + diseaseAgent: string; + bloodDNA: string; + bloodType: string; + possibleTreatments: string; + transmissionRoute: string; + isAdvanced: boolean; + symptoms: Symptom[]; +}; + +type Symptom = { + name: string; + stealth: number; + resistance: number; + stageSpeed: number; + transmissibility: number; +}; + +export const PanDEMIC = () => { + const { data } = useBackend(); + const { + beakerLoaded, + beakerContainsBlood, + beakerContainsVirus, + resistances, + } = data; + + let emptyPlaceholder: JSX.Element | null = null; + if (!beakerLoaded) { + emptyPlaceholder = <>No container loaded.; + } else if (!beakerContainsBlood) { + emptyPlaceholder = <>No blood sample found in the loaded container.; + } else if (beakerContainsBlood && !beakerContainsVirus) { + emptyPlaceholder = <>No disease detected in provided blood sample.; + } + + return ( + + + + {emptyPlaceholder && !beakerContainsVirus ? ( +
} + > + {emptyPlaceholder} +
+ ) : ( + + )} + {resistances.length > 0 && } +
+
+
+ ); +}; + +const CommonCultureActions = () => { + const { act, data } = useBackend(); + const { beakerLoaded } = data; + return ( + <> + + act('destroy_eject_beaker')} + > + Destroy + + + ); +}; + +const CultureInformationSection = () => { + const { act, data } = useBackend(); + const { selectedStrainIndex, strains, synthesisCooldown } = data; + + if (strains.length === 0) { + return ( +
}> + No disease detected in provided blood sample. +
+ ); + } + + return ( + +
+ + + + } + > + + + +
+
+ ); +}; + +const StrainInformationSection = ({ + strains, + selectedStrainIndex, +}: { + strains: Strain[]; + selectedStrainIndex: number; +}) => { + const { act } = useBackend(); + const selectedStrain = strains[selectedStrainIndex - 1]; + + return ( + + + {strains.map((strain, index) => ( + act('switch_strain', { strain_index: index + 1 })} + > + {strain.commonName} + + ))} + + +
+ {selectedStrain ? ( + + ) : ( + No strain information available. + )} +
+ + {selectedStrain && selectedStrain.symptoms.length > 0 && ( + + )} +
+ ); +}; + +const StrainSymptomsSection = ({ strain }: { strain: Strain }) => { + const symptoms = strain.symptoms; + + return ( + +
+ + + Name + Stealth + Resistance + Stage Speed + Transmissibility + + {symptoms.map((symptom, index) => ( + + {symptom.name} + {symptom.stealth} + {symptom.resistance} + {symptom.stageSpeed} + {symptom.transmissibility} + + ))} +
+
+
+ ); +}; + +const StrainInformation = ({ + strain, + strainIndex, +}: { + strain: Strain; + strainIndex: number; +}) => { + const { act } = useBackend(); + const { + commonName, + description, + diseaseAgent, + bloodDNA, + bloodType, + possibleTreatments, + transmissionRoute, + isAdvanced, + } = strain; + + return ( + + + + {commonName ?? 'Unknown'} + {isAdvanced && ( + <> + + + + )} + + + {description && ( + {description} + )} + {diseaseAgent} + + {bloodDNA || 'Undetectable'} + + + {bloodType || 'Undetectable'} + + + {transmissionRoute || 'None'} + + + {possibleTreatments || 'None'} + + + ); +}; + +const ResistancesSection = () => { + const { act, data } = useBackend(); + const { resistances, synthesisCooldown } = data; + const vaccineIcons = ['flask', 'vial', 'eye-dropper']; + + return ( + +
+ + {resistances.map((resistance, index) => ( + +
+
+ ); +}; diff --git a/vorestation.dme b/vorestation.dme index cd766f12d6a..b16e5b01f8b 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -55,6 +55,7 @@ #include "code\__defines\cooldowns.dm" #include "code\__defines\crafting.dm" #include "code\__defines\damage_organs.dm" +#include "code\__defines\diseases.dm" #include "code\__defines\dna.dm" #include "code\__defines\economy_misc.dm" #include "code\__defines\equipment_vendor.dm" @@ -455,6 +456,49 @@ #include "code\datums\components\crafting\recipes\primitive.dm" #include "code\datums\components\crafting\recipes\survival.dm" #include "code\datums\components\crafting\recipes\weapons.dm" +#include "code\datums\diseases\_disease.dm" +#include "code\datums\diseases\_MobProcs.dm" +#include "code\datums\diseases\anxiety.dm" +#include "code\datums\diseases\beesease.dm" +#include "code\datums\diseases\brainrot.dm" +#include "code\datums\diseases\choreomania.dm" +#include "code\datums\diseases\cold.dm" +#include "code\datums\diseases\cold9.dm" +#include "code\datums\diseases\flu.dm" +#include "code\datums\diseases\food_poisoning.dm" +#include "code\datums\diseases\lycancoughy.dm" +#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\choking.dm" +#include "code\datums\diseases\advance\symptoms\confusion.dm" +#include "code\datums\diseases\advance\symptoms\cough.dm" +#include "code\datums\diseases\advance\symptoms\damage_converter.dm" +#include "code\datums\diseases\advance\symptoms\dizzy.dm" +#include "code\datums\diseases\advance\symptoms\fever.dm" +#include "code\datums\diseases\advance\symptoms\fire.dm" +#include "code\datums\diseases\advance\symptoms\flesh_eating.dm" +#include "code\datums\diseases\advance\symptoms\hallucigen.dm" +#include "code\datums\diseases\advance\symptoms\headache.dm" +#include "code\datums\diseases\advance\symptoms\heal.dm" +#include "code\datums\diseases\advance\symptoms\itching.dm" +#include "code\datums\diseases\advance\symptoms\language.dm" +#include "code\datums\diseases\advance\symptoms\macrophage.dm" +#include "code\datums\diseases\advance\symptoms\mlem.dm" +#include "code\datums\diseases\advance\symptoms\necrotic_agent.dm" +#include "code\datums\diseases\advance\symptoms\oxygen.dm" +#include "code\datums\diseases\advance\symptoms\sensory.dm" +#include "code\datums\diseases\advance\symptoms\shivering.dm" +#include "code\datums\diseases\advance\symptoms\sneeze.dm" +#include "code\datums\diseases\advance\symptoms\spin.dm" +#include "code\datums\diseases\advance\symptoms\symptoms.dm" +#include "code\datums\diseases\advance\symptoms\synthetic_infection.dm" +#include "code\datums\diseases\advance\symptoms\telepathy.dm" +#include "code\datums\diseases\advance\symptoms\viral.dm" +#include "code\datums\diseases\advance\symptoms\vision.dm" +#include "code\datums\diseases\advance\symptoms\vomit.dm" +#include "code\datums\diseases\advance\symptoms\weakness.dm" +#include "code\datums\diseases\advance\symptoms\weigh.dm" #include "code\datums\elements\_element.dm" #include "code\datums\elements\conflict_checking.dm" #include "code\datums\elements\light_blocking.dm" @@ -933,6 +977,7 @@ #include "code\game\machinery\overview.dm" #include "code\game\machinery\oxygen_pump.dm" #include "code\game\machinery\painter_vr.dm" +#include "code\game\machinery\pandemic.dm" #include "code\game\machinery\partslathe_vr.dm" #include "code\game\machinery\pda_multicaster.dm" #include "code\game\machinery\pointdefense.dm" @@ -2351,6 +2396,7 @@ #include "code\modules\events\carp_migration.dm" #include "code\modules\events\comms_blackout.dm" #include "code\modules\events\communications_blackout.dm" +#include "code\modules\events\disease_outbreak.dm" #include "code\modules\events\drone_pod_vr.dm" #include "code\modules\events\dust.dm" #include "code\modules\events\electrical_storm.dm" @@ -2512,7 +2558,6 @@ #include "code\modules\gamemaster\event2\events\everyone\sudden_weather_shift.dm" #include "code\modules\gamemaster\event2\events\legacy\legacy.dm" #include "code\modules\gamemaster\event2\events\medical\appendicitis.dm" -#include "code\modules\gamemaster\event2\events\medical\virus.dm" #include "code\modules\gamemaster\event2\events\security\carp_migration.dm" #include "code\modules\gamemaster\event2\events\security\drill_announcement.dm" #include "code\modules\gamemaster\event2\events\security\prison_break.dm" @@ -2933,7 +2978,6 @@ #include "code\modules\mob\living\carbon\resist.dm" #include "code\modules\mob\living\carbon\shock.dm" #include "code\modules\mob\living\carbon\taste.dm" -#include "code\modules\mob\living\carbon\viruses.dm" #include "code\modules\mob\living\carbon\alien\alien.dm" #include "code\modules\mob\living\carbon\alien\alien_attacks.dm" #include "code\modules\mob\living\carbon\alien\alien_damage.dm" @@ -3345,6 +3389,7 @@ #include "code\modules\mob\living\simple_mob\subtypes\vore\jelly.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\lamia.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\leopardmander.dm" +#include "code\modules\mob\living\simple_mob\subtypes\vore\macrophage.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\meowl.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\mimic.dm" #include "code\modules\mob\living\simple_mob\subtypes\vore\oregrub.dm" @@ -3689,7 +3734,6 @@ #include "code\modules\power\antimatter\control.dm" #include "code\modules\power\antimatter\shielding.dm" #include "code\modules\power\cells\device_cells.dm" -#include "code\modules\power\cells\device_cells_vr.dm" #include "code\modules\power\cells\esoteric_cells.dm" #include "code\modules\power\cells\power_cells.dm" #include "code\modules\power\fusion\_setup.dm" @@ -3885,6 +3929,7 @@ #include "code\modules\reagents\reactions\instant\food_vr.dm" #include "code\modules\reagents\reactions\instant\instant.dm" #include "code\modules\reagents\reactions\instant\instant_vr.dm" +#include "code\modules\reagents\reactions\instant\virology.dm" #include "code\modules\reagents\reagent_containers\_reagent_containers.dm" #include "code\modules\reagents\reagent_containers\blood_pack.dm" #include "code\modules\reagents\reagent_containers\blood_pack_vr.dm" @@ -3901,6 +3946,7 @@ #include "code\modules\reagents\reagent_containers\spray_vr.dm" #include "code\modules\reagents\reagent_containers\syringes.dm" #include "code\modules\reagents\reagent_containers\unidentified_hypospray.dm" +#include "code\modules\reagents\reagent_containers\virology.dm" #include "code\modules\reagents\reagents\_helpers.dm" #include "code\modules\reagents\reagents\_reagents.dm" #include "code\modules\reagents\reagents\core.dm" @@ -3914,6 +3960,7 @@ #include "code\modules\reagents\reagents\other.dm" #include "code\modules\reagents\reagents\other_vr.dm" #include "code\modules\reagents\reagents\toxins.dm" +#include "code\modules\reagents\reagents\virology.dm" #include "code\modules\reagents\reagents\vore_vr.dm" #include "code\modules\recycling\conveyor2.dm" #include "code\modules\recycling\disposal-construction.dm" @@ -4202,19 +4249,6 @@ #include "code\modules\ventcrawl\ventcrawl_atmospherics.dm" #include "code\modules\ventcrawl\ventcrawl_multiz.dm" #include "code\modules\ventcrawl\ventcrawl_verb.dm" -#include "code\modules\virus2\admin.dm" -#include "code\modules\virus2\analyser.dm" -#include "code\modules\virus2\antibodies.dm" -#include "code\modules\virus2\centrifuge.dm" -#include "code\modules\virus2\curer.dm" -#include "code\modules\virus2\disease2.dm" -#include "code\modules\virus2\diseasesplicer.dm" -#include "code\modules\virus2\dishincubator.dm" -#include "code\modules\virus2\effect.dm" -#include "code\modules\virus2\effect_vr.dm" -#include "code\modules\virus2\helpers.dm" -#include "code\modules\virus2\isolator.dm" -#include "code\modules\virus2\items_devices.dm" #include "code\modules\vore\chat_healthbars.dm" #include "code\modules\vore\hook-defs_vr.dm" #include "code\modules\vore\mouseray.dm"