diff --git a/baystation12.dme b/baystation12.dme index c91304739e..82506f8bed 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1033,6 +1033,7 @@ #include "code\modules\mob\living\carbon\carbon_powers.dm" #include "code\modules\mob\living\carbon\give.dm" #include "code\modules\mob\living\carbon\shock.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" @@ -1500,6 +1501,7 @@ #include "code\modules\vehicles\cargo_train.dm" #include "code\modules\vehicles\train.dm" #include "code\modules\vehicles\vehicle.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" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 02ec9e9c5c..a67e42ca2b 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -108,7 +108,8 @@ var/list/admin_verbs_fun = list( ) var/list/admin_verbs_spawn = list( /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ - /client/proc/respawn_character + /client/proc/respawn_character, + /client/proc/virus2_editor ) var/list/admin_verbs_server = list( /client/proc/Set_Holiday, diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 4431ccdf80..a669e03d32 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1,6 +1,8 @@ /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++ diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index bf72360399..55b33324fb 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -3,7 +3,7 @@ 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/antibodies = 0 + var/list/antibodies = list() var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm var/life_tick = 0 // The amount of life ticks that have processed on this mob. diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 1f94c08e2c..05ea0a9714 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -93,8 +93,6 @@ //Random events (vomiting etc) handle_random_events() - handle_virus_updates() - //stuff in the stomach handle_stomach() @@ -1460,47 +1458,6 @@ if(!currentTurf.lighting_lumcount) playsound_local(src,pick(scarySounds),50, 1, -1) - proc/handle_virus_updates() - if(status_flags & GODMODE) return 0 //godmode - if(bodytemperature > 406) - for(var/datum/disease/D in viruses) - D.cure() - 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.getcopy()) - - 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.getcopy()) - - - 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 - if(V.antigen & src.antibodies) - V.dead = 1 - - return - proc/handle_stomach() spawn(0) for(var/mob/living/M in stomach_contents) diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 016f57f18f..dcf4caebb2 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -44,9 +44,6 @@ //Disabilities handle_disabilities() - //Virus updates, duh - handle_virus_updates() - //Apparently, the person who wrote this code designed it so that //blinded get reset each cycle and then get activated later in the //code. Very ugly. I dont care. Moving this stuff here so its easy @@ -155,47 +152,6 @@ domutcheck(src,null) emote("gasp") - proc/handle_virus_updates() - if(status_flags & GODMODE) return 0 //godmode - if(bodytemperature > 406) - for(var/datum/disease/D in viruses) - D.cure() - for (var/ID in virus2) - var/datum/disease2/disease/V = virus2[ID] - V.cure(src) - - 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) - - 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 - if(V.antigen & src.antibodies) - V.dead = 1 - - return - proc/breathe() if(reagents) diff --git a/code/modules/mob/living/carbon/viruses.dm b/code/modules/mob/living/carbon/viruses.dm new file mode 100644 index 0000000000..fed6d59e43 --- /dev/null +++ b/code/modules/mob/living/carbon/viruses.dm @@ -0,0 +1,43 @@ +/mob/living/carbon/proc/handle_viruses() + + if(status_flags & GODMODE) return 0 //godmode + + if(bodytemperature > 406) + for(var/datum/disease/D in viruses) + D.cure() + 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) + + 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/organs/blood.dm b/code/modules/organs/blood.dm index 067ef6a42e..ac9b3131cd 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -31,7 +31,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 for(var/datum/reagent/blood/B in vessel.reagent_list) if(B.id == "blood") B.data = list( "donor"=src,"viruses"=null,"species"=species.name,"blood_DNA"=dna.unique_enzymes,"blood_colour"= species.blood_color,"blood_type"=dna.b_type, \ - "resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = null) + "resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = list()) B.color = B.data["blood_colour"] // Takes care blood loss and regeneration diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index e523fab26c..eacbaf2a89 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -98,7 +98,7 @@ datum blood - data = new/list("donor"=null,"viruses"=null,"species"="Human","blood_DNA"=null,"blood_type"=null,"blood_colour"= "#A10808","resistances"=null,"trace_chem"=null, "antibodies" = null) + data = new/list("donor"=null,"viruses"=null,"species"="Human","blood_DNA"=null,"blood_type"=null,"blood_colour"= "#A10808","resistances"=null,"trace_chem"=null, "antibodies" = list()) name = "Blood" id = "blood" reagent_state = LIQUID @@ -665,15 +665,13 @@ datum for (var/ID in C.virus2) var/datum/disease2/disease/V = C.virus2[ID] if(prob(5)) - M:antibodies |= V.antigen + C.antibodies |= V.antigen if(prob(50)) M.radiation += 50 // curing it that way may kill you instead var/absorbed - if(istype(C,/mob/living/carbon)) - var/mob/living/carbon/H = C - var/datum/organ/internal/diona/nutrients/rad_organ = locate() in H.internal_organs - if(rad_organ && !rad_organ.is_broken()) - absorbed = 1 + var/datum/organ/internal/diona/nutrients/rad_organ = locate() in C.internal_organs + if(rad_organ && !rad_organ.is_broken()) + absorbed = 1 if(!absorbed) M.adjustToxLoss(100) ..() diff --git a/code/modules/virus2/admin.dm b/code/modules/virus2/admin.dm new file mode 100644 index 0000000000..88876da9ed --- /dev/null +++ b/code/modules/virus2/admin.dm @@ -0,0 +1,200 @@ +/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)) return + + usr << "Infection chance: [infectionchance]; Speed: [speed]; Spread type: [spreadtype]" + usr << "Affected species: [english_list(affected_species)]" + usr << "Effects:" + for(var/datum/disease2/effectholder/E in effects) + usr << "[E.stage]: [E.effect.name]; chance=[E.chance]; multiplier=[E.multiplier]" + usr << "Antigens: [antigens2string(antigen)]" + + return 1 + +/datum/admins/var/datum/virus2_editor/virus2_editor_datum = new +/client/proc/virus2_editor() + set name = "Virus Editor" + set category = "Admin" + 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/mob/living/carbon/infectee = null + + // this holds spawned viruses so that the "Info" links work after the proc exits + var/list/spawned_viruses = list() + + proc/select(mob/user, stage) + if(stage < 1 || stage > 4) return + + var/list/L = list() + + for(var/e in (typesof(/datum/disease2/effect) - /datum/disease2/effect)) + var/datum/disease2/effect/f = e + if(initial(f.stage) <= stage) + L[initial(f.name)] = e + + var/datum/disease2/effect/Eff = s[stage] + + var/C = input("Select effect for stage [stage]:", "Stage [stage]", initial(Eff.name)) as null|anything in L + if(!C) return + return L[C] + + 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 all_species) + var/datum/species/S = all_species[k] + if(!(S.flags & IS_SYNTHETIC)) + if(!f) H += " | " + else f = 0 + H += "[k]" + H += {" + Reset +
+ Infection Chance: [infectionchance]
+ Spread Type: [spreadtype]
+ Speed: [speed]
+
+ "} + 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") + + 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 = input("Chance, per tick, of this effect happening (min 0, max [initial(Eff.chance_maxm)])", "Effect Chance", s_chance[stage]) as null|num + 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 = input("Multiplier for this effect (min 1, max [initial(Eff.maxm)])", "Effect Multiplier", s_multiplier[stage]) as null|num + 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.name in species)) + infectee = null + if("ichance") + var/I = input("Input infection chance", "Infection Chance", infectionchance) as null|num + if(!I) return + infectionchance = I + if("stype") + var/S = alert("Which spread type?", "Spread Type", "Cancel", "Contact", "Airborne") + if(!S || S == "Cancel") return + spreadtype = S + if("speed") + var/S = input("Input speed", "Speed", speed) as null|num + 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("infectee") + var/list/candidates = list() + for(var/mob/living/carbon/G in living_mob_list) + if(G.stat != DEAD && G.species) + if(G.species.name in species) + candidates["[G.name][G.client ? "" : " (no client)"]"] = G + else + candidates["[G.name] ([G.species.name])[G.client ? "" : " (no client)"]"] = G + if(!candidates.len) usr << "No possible candidates found!" + + var/I = input("Choose initial infectee", "Infectee", infectee) as null|anything in candidates + if(!I || !candidates[I]) return + infectee = candidates[I] + species |= infectee.species.name + if("go") + if(!antigens.len) + var/a = alert("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", "Yes", "Yes", "No") + if(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 + 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("[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 index 8046c48af0..1bd3b3053c 100644 --- a/code/modules/virus2/analyser.dm +++ b/code/modules/virus2/analyser.dm @@ -1,5 +1,5 @@ /obj/machinery/disease2/diseaseanalyser - name = "Disease Analyser" + name = "disease analyser" icon = 'icons/obj/virology.dmi' icon_state = "analyser" anchored = 1 @@ -43,7 +43,9 @@
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 diff --git a/code/modules/virus2/antibodies.dm b/code/modules/virus2/antibodies.dm index 9d4c63ae2c..a209ef1c7f 100644 --- a/code/modules/virus2/antibodies.dm +++ b/code/modules/virus2/antibodies.dm @@ -1,37 +1,54 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 +/* // reserving some numbers for later special antigens var/global/const/ANTIGEN_A = 1 var/global/const/ANTIGEN_B = 2 -var/global/const/ANTIGEN_RH = 4 -var/global/const/ANTIGEN_Q = 8 -var/global/const/ANTIGEN_U = 16 -var/global/const/ANTIGEN_V = 32 -var/global/const/ANTIGEN_X = 64 -var/global/const/ANTIGEN_Y = 128 -var/global/const/ANTIGEN_Z = 256 -var/global/const/ANTIGEN_M = 512 -var/global/const/ANTIGEN_N = 1024 -var/global/const/ANTIGEN_P = 2048 -var/global/const/ANTIGEN_O = 4096 +var/global/const/ANTIGEN_C = 4 +var/global/const/ANTIGEN_D = 8 +var/global/const/ANTIGEN_E = 16 +var/global/const/ANTIGEN_M = 32 +var/global/const/ANTIGEN_N = 64 +var/global/const/ANTIGEN_O = 128 +var/global/const/ANTIGEN_P = 256 +var/global/const/ANTIGEN_Q = 512 +var/global/const/ANTIGEN_U = 1024 +var/global/const/ANTIGEN_V = 2048 +var/global/const/ANTIGEN_W = 4096 +var/global/const/ANTIGEN_X = 8192 +var/global/const/ANTIGEN_Y = 16384 +var/global/const/ANTIGEN_Z = 32768 var/global/list/ANTIGENS = list( "[ANTIGEN_A]" = "A", "[ANTIGEN_B]" = "B", -"[ANTIGEN_RH]" = "RH", +"[ANTIGEN_C]" = "C", +"[ANTIGEN_E]" = "E", +"[ANTIGEN_D]" = "D", +"[ANTIGEN_M]" = "M", +"[ANTIGEN_N]" = "N", +"[ANTIGEN_O]" = "O", +"[ANTIGEN_P]" = "P", "[ANTIGEN_Q]" = "Q", "[ANTIGEN_U]" = "U", "[ANTIGEN_V]" = "V", -"[ANTIGEN_Z]" = "Z", -"[ANTIGEN_M]" = "M", -"[ANTIGEN_N]" = "N", -"[ANTIGEN_P]" = "P", -"[ANTIGEN_O]" = "O" +"[ANTIGEN_W]" = "W", +"[ANTIGEN_X]" = "X", +"[ANTIGEN_Y]" = "Y", +"[ANTIGEN_Z]" = "Z" ) +*/ + +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) // pure concentrated antibodies datum/reagent/antibodies - data = list("antibodies"=0) + data = list("antibodies"=list()) name = "Antibodies" id = "antibodies" reagent_state = LIQUID @@ -39,14 +56,26 @@ datum/reagent/antibodies reaction_mob(var/mob/M, var/method=TOUCH, var/volume) if(istype(M,/mob/living/carbon)) + var/mob/living/carbon/C = M if(src.data && method == INGEST) - if(M:virus2) if(src.data["antibodies"] & M:virus2.antigen) - M:virus2.dead = 1 - M:antibodies |= src.data["antibodies"] + //if(C.virus2) if(src.data["antibodies"] & C.virus2.antigen) + // C.virus2.dead = 1 + C.antibodies |= src.data["antibodies"] return // iterate over the list of antigens and see what matches -/proc/antigens2string(var/antigens) +/proc/antigens2string(list/antigens, none="None") + if(!istype(antigens)) + CRASH("Illegal type!") + if(!antigens.len) + return none + var/code = "" - for(var/V in ANTIGENS) if(text2num(V) & antigens) code += ANTIGENS[V] + for(var/V in ALL_ANTIGENS) + if(V in antigens) + code += V + + if(!code) + return none + return code \ No newline at end of file diff --git a/code/modules/virus2/centrifuge.dm b/code/modules/virus2/centrifuge.dm index b36e63ff3a..a4c9187667 100644 --- a/code/modules/virus2/centrifuge.dm +++ b/code/modules/virus2/centrifuge.dm @@ -1,5 +1,5 @@ /obj/machinery/computer/centrifuge - name = "Isolation Centrifuge" + name = "isolation centrifuge" desc = "Used to separate things with different weight. Spin 'em round, round, right round." icon = 'icons/obj/virology.dmi' icon_state = "centrifuge" @@ -54,7 +54,7 @@ if (sample) var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list if (B) - data["antibodies"] = B.data["antibodies"] ? antigens2string(B.data["antibodies"]) : null + data["antibodies"] = antigens2string(B.data["antibodies"], none=null) var/list/pathogens[0] var/list/virus = B.data["virus2"] @@ -67,7 +67,8 @@ else var/datum/reagent/antibodies/A = locate(/datum/reagent/antibodies) in sample.reagents.reagent_list - data["antibodies"] = A && A.data["antibodies"] ? antigens2string(A.data["antibodies"]) : null + if(A) + data["antibodies"] = antigens2string(A.data["antibodies"], none=null) data["is_antibody_sample"] = 1 ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) @@ -186,7 +187,7 @@ var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list if (B) P.info += "Antibodies: " - P.info += B.data["antibodies"] ? antigens2string(B.data["antibodies"]) : "None" + P.info += antigens2string(B.data["antibodies"]) P.info += "
" var/list/virus = B.data["virus2"] @@ -202,7 +203,7 @@ 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 += A.data["antibodies"] ? antigens2string(A.data["antibodies"]) : "None" + P.info += antigens2string(A.data["antibodies"]) P.info += "
" P.info += {" diff --git a/code/modules/virus2/curer.dm b/code/modules/virus2/curer.dm index d87f579d31..367e336c43 100644 --- a/code/modules/virus2/curer.dm +++ b/code/modules/virus2/curer.dm @@ -1,5 +1,5 @@ /obj/machinery/computer/curer - name = "Cure Research Machine" + name = "cure research machine" icon = 'icons/obj/computer.dmi' icon_state = "dna" circuit = /obj/item/weapon/circuitboard/curefab @@ -22,7 +22,7 @@ return var/obj/item/weapon/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"=0) + 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) @@ -52,9 +52,7 @@ if(B) dat = "Blood sample inserted." - var/code = "" - for(var/V in ANTIGENS) if(text2num(V) & B.data["antibodies"]) code += ANTIGENS[V] - dat += "
Antibodies: [code]" + dat += "
Antibodies: [antigens2string(B.data["antibodies"])]" dat += "
Begin antibody production" else dat += "
Please check container contents." diff --git a/code/modules/virus2/disease2.dm b/code/modules/virus2/disease2.dm index 26ccd5475e..c1852a0cb9 100644 --- a/code/modules/virus2/disease2.dm +++ b/code/modules/virus2/disease2.dm @@ -8,7 +8,7 @@ var/clicks = 0 var/uniqueID = 0 var/list/datum/disease2/effectholder/effects = list() - var/antigen = 0 // 16 bits describing the antigens, when one bit is set, a cure with that bit can dock here + 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("Human","Unathi","Skrell","Tajara") @@ -17,10 +17,12 @@ ..() /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) + holder.getrandomeffect(severity, excludetypes) + excludetypes += holder.effect.type effects += holder uniqueID = rand(0,10000) switch(severity) @@ -31,8 +33,8 @@ else infectionchance = rand(60,90) - antigen |= text2num(pick(ANTIGENS)) - antigen |= text2num(pick(ANTIGENS)) + antigen = list(pick(ALL_ANTIGENS)) + antigen |= pick(ALL_ANTIGENS) spreadtype = prob(70) ? "Airborne" : "Contact" if(all_species.len) @@ -79,13 +81,18 @@ 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) + if((stage <= max_stage) && prob(20)) // ~60% 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)) @@ -98,7 +105,7 @@ infect_virus2(M,src) //fever - mob.bodytemperature = max(mob.bodytemperature, min(310+5*stage ,mob.bodytemperature+5*stage)) + 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) @@ -116,10 +123,14 @@ /datum/disease2/disease/proc/majormutate() uniqueID = rand(0,10000) var/datum/disease2/effectholder/holder = pick(effects) - holder.majormutate() + 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)) - antigen = text2num(pick(ANTIGENS)) - antigen |= text2num(pick(ANTIGENS)) + antigen = list(pick(ALL_ANTIGENS)) + antigen |= pick(ALL_ANTIGENS) if (prob(5) && all_species.len) affected_species = get_infectable_species() @@ -134,6 +145,7 @@ 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 @@ -176,6 +188,12 @@ var/global/list/virusDB = list() 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.
@@ -237,3 +255,10 @@ proc/virology_letterhead(var/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 \ No newline at end of file diff --git a/code/modules/virus2/diseasesplicer.dm b/code/modules/virus2/diseasesplicer.dm index cbab5f5f7d..81e4ed5e93 100644 --- a/code/modules/virus2/diseasesplicer.dm +++ b/code/modules/virus2/diseasesplicer.dm @@ -1,5 +1,5 @@ /obj/machinery/computer/diseasesplicer - name = "Disease Splicer" + name = "disease splicer" icon = 'icons/obj/computer.dmi' icon_state = "crew" @@ -49,7 +49,7 @@ data["affected_species"] = null if (memorybank) - data["buffer"] = list("name" = (analysed ? memorybank.effect.name : "Unknown Symptom"), "stage" = memorybank.stage) + data["buffer"] = list("name" = (analysed ? memorybank.effect.name : "Unknown Symptom"), "stage" = memorybank.effect.stage) if (species_buffer) data["species_buffer"] = analysed ? list2text(species_buffer, ", ") : "Unknown Species" @@ -160,14 +160,26 @@ if(href_list["splice"]) if(dish) - if (memorybank) - for(var/datum/disease2/effectholder/e in dish.virus2.effects) - if(e.stage == memorybank.stage) - e.effect = memorybank.effect + var/target = text2num(href_list["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 - if (species_buffer) + 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) return 1 diff --git a/code/modules/virus2/dishincubator.dm b/code/modules/virus2/dishincubator.dm index f3f339f895..b259c1eac7 100644 --- a/code/modules/virus2/dishincubator.dm +++ b/code/modules/virus2/dishincubator.dm @@ -1,5 +1,5 @@ /obj/machinery/disease2/incubator/ - name = "Pathogenic incubator" + name = "pathogenic incubator" density = 1 anchored = 1 icon = 'icons/obj/virology.dmi' @@ -108,6 +108,7 @@ 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)) diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm index 50d7bcb569..8b6d9f30e8 100644 --- a/code/modules/virus2/effect.dm +++ b/code/modules/virus2/effect.dm @@ -13,15 +13,19 @@ if(happensonce == 1) happensonce = -1 -/datum/disease2/effectholder/proc/getrandomeffect(var/badness = 1) +/datum/disease2/effectholder/proc/getrandomeffect(var/badness = 1, exclude_types=list()) var/list/datum/disease2/effect/list = list() for(var/e in (typesof(/datum/disease2/effect) - /datum/disease2/effect)) - var/datum/disease2/effect/f = new e - if (f.badness > badness) //we don't want such strong effects + var/datum/disease2/effect/f = e + if(e in exclude_types) continue - if(f.stage == src.stage) + if(initial(f.badness) > badness) //we don't want such strong effects + continue + if(initial(f.stage) <= src.stage) list += f - effect = pick(list) + var/type = pick(list) + effect = new type() + effect.generate() chance = rand(0,effect.chance_maxm) multiplier = rand(1,effect.maxm) @@ -32,8 +36,8 @@ if(2) multiplier = rand(1,effect.maxm) -/datum/disease2/effectholder/proc/majormutate() - getrandomeffect(3) +/datum/disease2/effectholder/proc/majormutate(exclude_types=list()) + getrandomeffect(3, exclude_types) //////////////////////////////////////////////////////////////// ////////////////////////EFFECTS///////////////////////////////// @@ -45,8 +49,11 @@ var/stage = 4 var/maxm = 1 var/badness = 1 + var/data = null // For semi-procedural effects; this should be generated in generate() if used + proc/activate(var/mob/living/carbon/mob,var/multiplier) proc/deactivate(var/mob/living/carbon/mob) + 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" @@ -67,7 +74,23 @@ stage = 4 badness = 3 activate(var/mob/living/carbon/mob,var/multiplier) - mob.gib() + // 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/datum/organ/external/O = pick(H.organs) + if(prob(25)) + mob << "Your [O.display_name] feels as if it might fall off!" + if(prob(10)) + spawn(50) + if(O) + O.droplimb(1) + else + if(prob(75)) + mob << "Your whole body feels like it might fall apart!" + if(prob(10)) + mob.adjustBruteLoss(25*multiplier) /datum/disease2/effect/radian name = "Radian's Syndrome" @@ -257,6 +280,26 @@ chance_maxm = 25 activate(var/mob/living/carbon/mob,var/multiplier) mob.say("*groan") + +/datum/disease2/effect/chem_synthesis + name = "Chemical Synthesis" + stage = 3 + chance_maxm = 25 + + generate(c_data) + if(c_data) + data = c_data + else + data = pick("bicaridine", "kelotane", "dylovene", "inaprovaline", "space_drugs", "sugar", + "tramadol", "dexalin", "cryptobiolin", "impedrezene", "hyperzine", "ethylredoxrazine", + "mindbreaker", "nutriment") + var/datum/reagent/R = chemical_reagents_list[data] + name = "[initial(name)] ([initial(R.name)])" + + activate(var/mob/living/carbon/mob,var/multiplier) + if (mob.reagents.get_reagent_amount(data) < 5) + mob.reagents.add_reagent(data, 2) + ////////////////////////STAGE 2///////////////////////////////// /datum/disease2/effect/scream diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm index 8c1a8250c0..a9ffedbca1 100644 --- a/code/modules/virus2/helpers.dm +++ b/code/modules/virus2/helpers.dm @@ -76,14 +76,15 @@ proc/airborne_can_reach(turf/source, turf/target) 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 - if((M.antibodies & disease.antigen) != 0) + var/list/antibodies_in_common = M.antibodies & disease.antigen + if(antibodies_in_common.len) return if(M.reagents.has_reagent("spaceacillin")) return - + if(!disease.affected_species.len) return - + if (!(M.species.name in disease.affected_species)) if (forced) disease.affected_species[1] = M.species.name diff --git a/code/modules/virus2/isolator.dm b/code/modules/virus2/isolator.dm index 09f07793c9..460181bc36 100644 --- a/code/modules/virus2/isolator.dm +++ b/code/modules/virus2/isolator.dm @@ -4,7 +4,7 @@ #define ENTRY "entry" /obj/machinery/disease2/isolator/ - name = "Pathogenic Isolator" + name = "pathogenic isolator" density = 1 anchored = 1 icon = 'icons/obj/virology.dmi' diff --git a/code/modules/virus2/items_devices.dm b/code/modules/virus2/items_devices.dm index a2a102611d..784c1c4249 100644 --- a/code/modules/virus2/items_devices.dm +++ b/code/modules/virus2/items_devices.dm @@ -1,7 +1,7 @@ ///////////////ANTIBODY SCANNER/////////////// /obj/item/device/antibody_scanner - name = "\improper Antibody Scanner" + name = "antibody scanner" desc = "Scans living beings for antibodies in their blood." icon_state = "health" w_class = 2.0 @@ -20,7 +20,7 @@ report("Scan aborted: The target does not have blood.", user) return - if(!C.antibodies) + if(!C.antibodies.len) report("Scan Complete: No antibodies detected.", user) return @@ -36,11 +36,12 @@ ///////////////VIRUS DISH/////////////// /obj/item/weapon/virusdish - name = "virus containment/growth dish" + name = "virus dish" icon = 'icons/obj/items.dmi' icon_state = "implantcase-b" var/datum/disease2/disease/virus2 = null var/growth = 0 + var/basic_info = null var/info = 0 var/analysed = 0 @@ -66,10 +67,17 @@ del src /obj/item/weapon/virusdish/examine(mob/user) - user << "This is a virus containment dish." - if(src.info) - user << "It has the following information about its contents:" - user << src.info + ..() + if(basic_info) + user << "[basic_info] : More Information" + +/obj/item/weapon/virusdish/Topic(href, href_list) + . = ..() + if(.) return + + if(href_list["info"]) + usr << browse(info, "window=info_\ref[src]") + return 1 /obj/item/weapon/ruinedvirusdish name = "ruined virus sample" diff --git a/nano/templates/disease_splicer.tmpl b/nano/templates/disease_splicer.tmpl index c0caafd09a..d2e874afe6 100644 --- a/nano/templates/disease_splicer.tmpl +++ b/nano/templates/disease_splicer.tmpl @@ -104,5 +104,22 @@ {{:helper.link('Save To Disk', 'disk', { 'disk' : 1 }, (data.buffer || data.species_buffer) ? null : 'disabled')}} - {{:helper.link('Splice Onto Dish', 'pencil', { 'splice' : 1 }, ((data.buffer || data.species_buffer) && !data.info) ? null : 'disabled')}} + {{if data.species_buffer}} + {{:helper.link('Splice Species', 'pencil', { 'splice' : 5 }, (data.species_buffer && !data.info) ? null : 'disabled')}} + {{else data.buffer}} + {{:helper.link('Splice #1', 'pencil', { 'splice' : 1 }, data.buffer.stage > 1 ? 'disabled' : null)}} + {{:helper.link('Splice #2', 'pencil', { 'splice' : 2 }, data.buffer.stage > 2 ? 'disabled' : null)}} + {{:helper.link('Splice #3', 'pencil', { 'splice' : 3 }, data.buffer.stage > 3 ? 'disabled' : null)}} + {{:helper.link('Splice #4', 'pencil', { 'splice' : 4 }, data.buffer.stage > 4 ? 'disabled' : null)}} + {{/if}} {{/if}} + + + + + + + + + +