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}}
+
+
+
+
+
+
+
+
+
+