Merge pull request #8029 from GinjaNinja32/viro

Virology rework
This commit is contained in:
Chinsky
2015-02-06 00:18:13 +03:00
22 changed files with 464 additions and 168 deletions

View File

@@ -1033,6 +1033,7 @@
#include "code\modules\mob\living\carbon\carbon_powers.dm" #include "code\modules\mob\living\carbon\carbon_powers.dm"
#include "code\modules\mob\living\carbon\give.dm" #include "code\modules\mob\living\carbon\give.dm"
#include "code\modules\mob\living\carbon\shock.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.dm"
#include "code\modules\mob\living\carbon\alien\alien_attacks.dm" #include "code\modules\mob\living\carbon\alien\alien_attacks.dm"
#include "code\modules\mob\living\carbon\alien\alien_damage.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\cargo_train.dm"
#include "code\modules\vehicles\train.dm" #include "code\modules\vehicles\train.dm"
#include "code\modules\vehicles\vehicle.dm" #include "code\modules\vehicles\vehicle.dm"
#include "code\modules\virus2\admin.dm"
#include "code\modules\virus2\analyser.dm" #include "code\modules\virus2\analyser.dm"
#include "code\modules\virus2\antibodies.dm" #include "code\modules\virus2\antibodies.dm"
#include "code\modules\virus2\centrifuge.dm" #include "code\modules\virus2\centrifuge.dm"

View File

@@ -108,7 +108,8 @@ var/list/admin_verbs_fun = list(
) )
var/list/admin_verbs_spawn = list( var/list/admin_verbs_spawn = list(
/datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ /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( var/list/admin_verbs_server = list(
/client/proc/Set_Holiday, /client/proc/Set_Holiday,

View File

@@ -1,6 +1,8 @@
/mob/living/carbon/Life() /mob/living/carbon/Life()
..() ..()
handle_viruses()
// Increase germ_level regularly // 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 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++ germ_level++

View File

@@ -3,7 +3,7 @@
var/datum/species/species //Contains icon generation and language information, set during New(). var/datum/species/species //Contains icon generation and language information, set during New().
var/list/stomach_contents = list() var/list/stomach_contents = list()
var/list/datum/disease2/disease/virus2 = 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/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. var/life_tick = 0 // The amount of life ticks that have processed on this mob.

View File

@@ -93,8 +93,6 @@
//Random events (vomiting etc) //Random events (vomiting etc)
handle_random_events() handle_random_events()
handle_virus_updates()
//stuff in the stomach //stuff in the stomach
handle_stomach() handle_stomach()
@@ -1460,47 +1458,6 @@
if(!currentTurf.lighting_lumcount) if(!currentTurf.lighting_lumcount)
playsound_local(src,pick(scarySounds),50, 1, -1) 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() proc/handle_stomach()
spawn(0) spawn(0)
for(var/mob/living/M in stomach_contents) for(var/mob/living/M in stomach_contents)

View File

@@ -44,9 +44,6 @@
//Disabilities //Disabilities
handle_disabilities() handle_disabilities()
//Virus updates, duh
handle_virus_updates()
//Apparently, the person who wrote this code designed it so that //Apparently, the person who wrote this code designed it so that
//blinded get reset each cycle and then get activated later in the //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 //code. Very ugly. I dont care. Moving this stuff here so its easy
@@ -155,47 +152,6 @@
domutcheck(src,null) domutcheck(src,null)
emote("gasp") 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() proc/breathe()
if(reagents) if(reagents)

View File

@@ -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

View File

@@ -31,7 +31,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
for(var/datum/reagent/blood/B in vessel.reagent_list) for(var/datum/reagent/blood/B in vessel.reagent_list)
if(B.id == "blood") 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, \ 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"] B.color = B.data["blood_colour"]
// Takes care blood loss and regeneration // Takes care blood loss and regeneration

View File

@@ -98,7 +98,7 @@ datum
blood 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" name = "Blood"
id = "blood" id = "blood"
reagent_state = LIQUID reagent_state = LIQUID
@@ -665,15 +665,13 @@ datum
for (var/ID in C.virus2) for (var/ID in C.virus2)
var/datum/disease2/disease/V = C.virus2[ID] var/datum/disease2/disease/V = C.virus2[ID]
if(prob(5)) if(prob(5))
M:antibodies |= V.antigen C.antibodies |= V.antigen
if(prob(50)) if(prob(50))
M.radiation += 50 // curing it that way may kill you instead M.radiation += 50 // curing it that way may kill you instead
var/absorbed var/absorbed
if(istype(C,/mob/living/carbon)) var/datum/organ/internal/diona/nutrients/rad_organ = locate() in C.internal_organs
var/mob/living/carbon/H = C if(rad_organ && !rad_organ.is_broken())
var/datum/organ/internal/diona/nutrients/rad_organ = locate() in H.internal_organs absorbed = 1
if(rad_organ && !rad_organ.is_broken())
absorbed = 1
if(!absorbed) if(!absorbed)
M.adjustToxLoss(100) M.adjustToxLoss(100)
..() ..()

View File

@@ -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 = {"
<center><h3>Virus2 Virus Editor</h3></center><br />
<b>Effects:</b><br />
"}
for(var/i = 1 to 4)
var/datum/disease2/effect/Eff = s[i]
H += {"
<a href='?src=\ref[src];what=effect;stage=[i];effect=1'>[initial(Eff.name)]</a>
Chance: <a href='?src=\ref[src];what=effect;stage=[i];chance=1'>[s_chance[i]]</a>
Multiplier: <a href='?src=\ref[src];what=effect;stage=[i];multiplier=1'>[s_multiplier[i]]</a>
<br />
"}
H += {"
<br />
<b>Infectable Species:</b><br />
"}
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 += "<a href='?src=\ref[src];what=species;toggle=[k]' style='color:[(k in species) ? "#006600" : "#ff0000"]'>[k]</a>"
H += {"
<a href="?src=\ref[src];what=species;reset=1" style="color:#0000aa">Reset</a>
<br />
<b>Infection Chance:</b> <a href="?src=\ref[src];what=ichance">[infectionchance]</a><br />
<b>Spread Type:</b> <a href="?src=\ref[src];what=stype">[spreadtype]</a><br />
<b>Speed:</b> <a href="?src=\ref[src];what=speed">[speed]</a><br />
<br />
"}
f = 1
for(var/k in ALL_ANTIGENS)
if(!f) H += " | "
else f = 0
H += "<a href='?src=\ref[src];what=antigen;toggle=[k]' style='color:[(k in antigens) ? "#006600" : "#ff0000"]'>[k]</a>"
H += {"
<a href="?src=\ref[src];what=antigen;reset=1" style="color:#0000aa">Reset</a>
<br />
<hr />
<b>Initial infectee:</b> <a href="?src=\ref[src];what=infectee">[infectee ? infectee : "(choose)"]</a>
<a href="?src=\ref[src];what=go" style="color:#ff0000">RELEASE</a>
"}
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("<span class='danger'>[key_name_admin(usr)] infected [key_name_admin(infectee)] with a virus (<a href='?src=\ref[D];info=1'>Info</a>)</span>")
log_admin("[key_name_admin(usr)] infected [key_name_admin(infectee)] with a virus!")
infect_virus2(infectee, D, forced=1)
show_ui(usr)

View File

@@ -1,5 +1,5 @@
/obj/machinery/disease2/diseaseanalyser /obj/machinery/disease2/diseaseanalyser
name = "Disease Analyser" name = "disease analyser"
icon = 'icons/obj/virology.dmi' icon = 'icons/obj/virology.dmi'
icon_state = "analyser" icon_state = "analyser"
anchored = 1 anchored = 1
@@ -43,7 +43,9 @@
<hr> <hr>
<u>Additional Notes:</u>&nbsp; <u>Additional Notes:</u>&nbsp;
"} "}
dish.basic_info = dish.virus2.get_basic_info()
dish.info = r dish.info = r
dish.name = "[initial(dish.name)] ([dish.virus2.name()])"
dish.analysed = 1 dish.analysed = 1
dish.loc = src.loc dish.loc = src.loc
dish = null dish = null

View File

@@ -1,37 +1,54 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
/*
// reserving some numbers for later special antigens // reserving some numbers for later special antigens
var/global/const/ANTIGEN_A = 1 var/global/const/ANTIGEN_A = 1
var/global/const/ANTIGEN_B = 2 var/global/const/ANTIGEN_B = 2
var/global/const/ANTIGEN_RH = 4 var/global/const/ANTIGEN_C = 4
var/global/const/ANTIGEN_Q = 8 var/global/const/ANTIGEN_D = 8
var/global/const/ANTIGEN_U = 16 var/global/const/ANTIGEN_E = 16
var/global/const/ANTIGEN_V = 32 var/global/const/ANTIGEN_M = 32
var/global/const/ANTIGEN_X = 64 var/global/const/ANTIGEN_N = 64
var/global/const/ANTIGEN_Y = 128 var/global/const/ANTIGEN_O = 128
var/global/const/ANTIGEN_Z = 256 var/global/const/ANTIGEN_P = 256
var/global/const/ANTIGEN_M = 512 var/global/const/ANTIGEN_Q = 512
var/global/const/ANTIGEN_N = 1024 var/global/const/ANTIGEN_U = 1024
var/global/const/ANTIGEN_P = 2048 var/global/const/ANTIGEN_V = 2048
var/global/const/ANTIGEN_O = 4096 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( var/global/list/ANTIGENS = list(
"[ANTIGEN_A]" = "A", "[ANTIGEN_A]" = "A",
"[ANTIGEN_B]" = "B", "[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_Q]" = "Q",
"[ANTIGEN_U]" = "U", "[ANTIGEN_U]" = "U",
"[ANTIGEN_V]" = "V", "[ANTIGEN_V]" = "V",
"[ANTIGEN_Z]" = "Z", "[ANTIGEN_W]" = "W",
"[ANTIGEN_M]" = "M", "[ANTIGEN_X]" = "X",
"[ANTIGEN_N]" = "N", "[ANTIGEN_Y]" = "Y",
"[ANTIGEN_P]" = "P", "[ANTIGEN_Z]" = "Z"
"[ANTIGEN_O]" = "O"
) )
*/
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 // pure concentrated antibodies
datum/reagent/antibodies datum/reagent/antibodies
data = list("antibodies"=0) data = list("antibodies"=list())
name = "Antibodies" name = "Antibodies"
id = "antibodies" id = "antibodies"
reagent_state = LIQUID reagent_state = LIQUID
@@ -39,14 +56,26 @@ datum/reagent/antibodies
reaction_mob(var/mob/M, var/method=TOUCH, var/volume) reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
if(istype(M,/mob/living/carbon)) if(istype(M,/mob/living/carbon))
var/mob/living/carbon/C = M
if(src.data && method == INGEST) if(src.data && method == INGEST)
if(M:virus2) if(src.data["antibodies"] & M:virus2.antigen) //if(C.virus2) if(src.data["antibodies"] & C.virus2.antigen)
M:virus2.dead = 1 // C.virus2.dead = 1
M:antibodies |= src.data["antibodies"] C.antibodies |= src.data["antibodies"]
return return
// iterate over the list of antigens and see what matches // 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 = "" 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 return code

View File

@@ -1,5 +1,5 @@
/obj/machinery/computer/centrifuge /obj/machinery/computer/centrifuge
name = "Isolation Centrifuge" name = "isolation centrifuge"
desc = "Used to separate things with different weight. Spin 'em round, round, right round." desc = "Used to separate things with different weight. Spin 'em round, round, right round."
icon = 'icons/obj/virology.dmi' icon = 'icons/obj/virology.dmi'
icon_state = "centrifuge" icon_state = "centrifuge"
@@ -54,7 +54,7 @@
if (sample) if (sample)
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list
if (B) 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/pathogens[0]
var/list/virus = B.data["virus2"] var/list/virus = B.data["virus2"]
@@ -67,7 +67,8 @@
else else
var/datum/reagent/antibodies/A = locate(/datum/reagent/antibodies) in sample.reagents.reagent_list 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 data["is_antibody_sample"] = 1
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) 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 var/datum/reagent/blood/B = locate(/datum/reagent/blood) in sample.reagents.reagent_list
if (B) if (B)
P.info += "<u>Antibodies:</u> " P.info += "<u>Antibodies:</u> "
P.info += B.data["antibodies"] ? antigens2string(B.data["antibodies"]) : "None" P.info += antigens2string(B.data["antibodies"])
P.info += "<br>" P.info += "<br>"
var/list/virus = B.data["virus2"] var/list/virus = B.data["virus2"]
@@ -202,7 +203,7 @@
var/datum/reagent/antibodies/A = locate(/datum/reagent/antibodies) in sample.reagents.reagent_list var/datum/reagent/antibodies/A = locate(/datum/reagent/antibodies) in sample.reagents.reagent_list
if (A) if (A)
P.info += "The following antibodies have been isolated from the blood sample: " 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 += "<br>" P.info += "<br>"
P.info += {" P.info += {"

View File

@@ -1,5 +1,5 @@
/obj/machinery/computer/curer /obj/machinery/computer/curer
name = "Cure Research Machine" name = "cure research machine"
icon = 'icons/obj/computer.dmi' icon = 'icons/obj/computer.dmi'
icon_state = "dna" icon_state = "dna"
circuit = /obj/item/weapon/circuitboard/curefab circuit = /obj/item/weapon/circuitboard/curefab
@@ -22,7 +22,7 @@
return return
var/obj/item/weapon/reagent_containers/glass/beaker/product = new(src.loc) 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 data["virus2"] |= I:virus2
product.reagents.add_reagent("blood",30,data) product.reagents.add_reagent("blood",30,data)
@@ -52,9 +52,7 @@
if(B) if(B)
dat = "Blood sample inserted." dat = "Blood sample inserted."
var/code = "" dat += "<BR>Antibodies: [antigens2string(B.data["antibodies"])]"
for(var/V in ANTIGENS) if(text2num(V) & B.data["antibodies"]) code += ANTIGENS[V]
dat += "<BR>Antibodies: [code]"
dat += "<BR><A href='?src=\ref[src];antibody=1'>Begin antibody production</a>" dat += "<BR><A href='?src=\ref[src];antibody=1'>Begin antibody production</a>"
else else
dat += "<BR>Please check container contents." dat += "<BR>Please check container contents."

View File

@@ -8,7 +8,7 @@
var/clicks = 0 var/clicks = 0
var/uniqueID = 0 var/uniqueID = 0
var/list/datum/disease2/effectholder/effects = list() 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/max_stage = 4
var/list/affected_species = list("Human","Unathi","Skrell","Tajara") var/list/affected_species = list("Human","Unathi","Skrell","Tajara")
@@ -17,10 +17,12 @@
..() ..()
/datum/disease2/disease/proc/makerandom(var/severity=1) /datum/disease2/disease/proc/makerandom(var/severity=1)
var/list/excludetypes = list()
for(var/i=1 ; i <= max_stage ; i++ ) for(var/i=1 ; i <= max_stage ; i++ )
var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder
holder.stage = i holder.stage = i
holder.getrandomeffect(severity) holder.getrandomeffect(severity, excludetypes)
excludetypes += holder.effect.type
effects += holder effects += holder
uniqueID = rand(0,10000) uniqueID = rand(0,10000)
switch(severity) switch(severity)
@@ -31,8 +33,8 @@
else else
infectionchance = rand(60,90) infectionchance = rand(60,90)
antigen |= text2num(pick(ANTIGENS)) antigen = list(pick(ALL_ANTIGENS))
antigen |= text2num(pick(ANTIGENS)) antigen |= pick(ALL_ANTIGENS)
spreadtype = prob(70) ? "Airborne" : "Contact" spreadtype = prob(70) ? "Airborne" : "Contact"
if(all_species.len) if(all_species.len)
@@ -79,13 +81,18 @@
mob.reagents.remove_reagent("virusfood",0.1) mob.reagents.remove_reagent("virusfood",0.1)
clicks += 10 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 //Moving to the next stage
if(clicks > max(stage*100, 200) && prob(10)) 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) src.cure(mob)
mob.antibodies |= src.antigen mob.antibodies |= src.antigen
stage++ stage++
clicks = 0 clicks = 0
//Do nasty effects //Do nasty effects
for(var/datum/disease2/effectholder/e in effects) for(var/datum/disease2/effectholder/e in effects)
if(prob(33)) if(prob(33))
@@ -98,7 +105,7 @@
infect_virus2(M,src) infect_virus2(M,src)
//fever //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 clicks+=speed
/datum/disease2/disease/proc/cure(var/mob/living/carbon/mob) /datum/disease2/disease/proc/cure(var/mob/living/carbon/mob)
@@ -116,10 +123,14 @@
/datum/disease2/disease/proc/majormutate() /datum/disease2/disease/proc/majormutate()
uniqueID = rand(0,10000) uniqueID = rand(0,10000)
var/datum/disease2/effectholder/holder = pick(effects) 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)) if (prob(5))
antigen = text2num(pick(ANTIGENS)) antigen = list(pick(ALL_ANTIGENS))
antigen |= text2num(pick(ANTIGENS)) antigen |= pick(ALL_ANTIGENS)
if (prob(5) && all_species.len) if (prob(5) && all_species.len)
affected_species = get_infectable_species() affected_species = get_infectable_species()
@@ -134,6 +145,7 @@
for(var/datum/disease2/effectholder/holder in effects) for(var/datum/disease2/effectholder/holder in effects)
var/datum/disease2/effectholder/newholder = new /datum/disease2/effectholder var/datum/disease2/effectholder/newholder = new /datum/disease2/effectholder
newholder.effect = new holder.effect.type newholder.effect = new holder.effect.type
newholder.effect.generate(holder.effect.data)
newholder.chance = holder.chance newholder.chance = holder.chance
newholder.cure = holder.cure newholder.cure = holder.cure
newholder.multiplier = holder.multiplier newholder.multiplier = holder.multiplier
@@ -176,6 +188,12 @@ var/global/list/virusDB = list()
var/datum/data/record/V = virusDB["[uniqueID]"] var/datum/data/record/V = virusDB["[uniqueID]"]
.= V.fields["name"] .= 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() /datum/disease2/disease/proc/get_info()
var/r = {" var/r = {"
<small>Analysis determined the existence of a GNAv2-based viral lifeform.</small><br> <small>Analysis determined the existence of a GNAv2-based viral lifeform.</small><br>
@@ -237,3 +255,10 @@ proc/virology_letterhead(var/report_name)
<center><small><i>[station_name()] Virology Lab</i></small></center> <center><small><i>[station_name()] Virology Lab</i></small></center>
<hr> <hr>
"} "}
/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

View File

@@ -1,5 +1,5 @@
/obj/machinery/computer/diseasesplicer /obj/machinery/computer/diseasesplicer
name = "Disease Splicer" name = "disease splicer"
icon = 'icons/obj/computer.dmi' icon = 'icons/obj/computer.dmi'
icon_state = "crew" icon_state = "crew"
@@ -49,7 +49,7 @@
data["affected_species"] = null data["affected_species"] = null
if (memorybank) 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) if (species_buffer)
data["species_buffer"] = analysed ? list2text(species_buffer, ", ") : "Unknown Species" data["species_buffer"] = analysed ? list2text(species_buffer, ", ") : "Unknown Species"
@@ -160,14 +160,26 @@
if(href_list["splice"]) if(href_list["splice"])
if(dish) if(dish)
if (memorybank) var/target = text2num(href_list["splice"]) // target = 1 to 4 for effects, 5 for species
for(var/datum/disease2/effectholder/e in dish.virus2.effects) if(memorybank && 0 < target && target <= 4)
if(e.stage == memorybank.stage) if(target < memorybank.effect.stage) return // too powerful, catching this for href exploit prevention
e.effect = memorybank.effect
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 dish.virus2.affected_species = species_buffer
else
return
splicing = 10 splicing = 10
dish.virus2.uniqueID = rand(0,10000) dish.virus2.uniqueID = rand(0,10000)
return 1 return 1

View File

@@ -1,5 +1,5 @@
/obj/machinery/disease2/incubator/ /obj/machinery/disease2/incubator/
name = "Pathogenic incubator" name = "pathogenic incubator"
density = 1 density = 1
anchored = 1 anchored = 1
icon = 'icons/obj/virology.dmi' icon = 'icons/obj/virology.dmi'
@@ -108,6 +108,7 @@
dish.virus2.majormutate() dish.virus2.majormutate()
if(dish.info) if(dish.info)
dish.info = "OUTDATED : [dish.info]" dish.info = "OUTDATED : [dish.info]"
dish.basic_info = "OUTDATED: [dish.basic_info]"
dish.analysed = 0 dish.analysed = 0
ping("\The [src] pings, \"Mutant viral strain detected.\"") ping("\The [src] pings, \"Mutant viral strain detected.\"")
else if(prob(5)) else if(prob(5))

View File

@@ -13,15 +13,19 @@
if(happensonce == 1) if(happensonce == 1)
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() var/list/datum/disease2/effect/list = list()
for(var/e in (typesof(/datum/disease2/effect) - /datum/disease2/effect)) for(var/e in (typesof(/datum/disease2/effect) - /datum/disease2/effect))
var/datum/disease2/effect/f = new e var/datum/disease2/effect/f = e
if (f.badness > badness) //we don't want such strong effects if(e in exclude_types)
continue 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 list += f
effect = pick(list) var/type = pick(list)
effect = new type()
effect.generate()
chance = rand(0,effect.chance_maxm) chance = rand(0,effect.chance_maxm)
multiplier = rand(1,effect.maxm) multiplier = rand(1,effect.maxm)
@@ -32,8 +36,8 @@
if(2) if(2)
multiplier = rand(1,effect.maxm) multiplier = rand(1,effect.maxm)
/datum/disease2/effectholder/proc/majormutate() /datum/disease2/effectholder/proc/majormutate(exclude_types=list())
getrandomeffect(3) getrandomeffect(3, exclude_types)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
////////////////////////EFFECTS///////////////////////////////// ////////////////////////EFFECTS/////////////////////////////////
@@ -45,8 +49,11 @@
var/stage = 4 var/stage = 4
var/maxm = 1 var/maxm = 1
var/badness = 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/activate(var/mob/living/carbon/mob,var/multiplier)
proc/deactivate(var/mob/living/carbon/mob) 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 /datum/disease2/effect/invisible
name = "Waiting Syndrome" name = "Waiting Syndrome"
@@ -67,7 +74,23 @@
stage = 4 stage = 4
badness = 3 badness = 3
activate(var/mob/living/carbon/mob,var/multiplier) 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 << "<span class='warning'>Your [O.display_name] feels as if it might fall off!</span>"
if(prob(10))
spawn(50)
if(O)
O.droplimb(1)
else
if(prob(75))
mob << "<span class='warning'>Your whole body feels like it might fall apart!</span>"
if(prob(10))
mob.adjustBruteLoss(25*multiplier)
/datum/disease2/effect/radian /datum/disease2/effect/radian
name = "Radian's Syndrome" name = "Radian's Syndrome"
@@ -257,6 +280,26 @@
chance_maxm = 25 chance_maxm = 25
activate(var/mob/living/carbon/mob,var/multiplier) activate(var/mob/living/carbon/mob,var/multiplier)
mob.say("*groan") 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///////////////////////////////// ////////////////////////STAGE 2/////////////////////////////////
/datum/disease2/effect/scream /datum/disease2/effect/scream

View File

@@ -76,14 +76,15 @@ proc/airborne_can_reach(turf/source, turf/target)
if ("[disease.uniqueID]" in M.virus2) if ("[disease.uniqueID]" in M.virus2)
return return
// if one of the antibodies in the mob's body matches one of the disease's antigens, don't infect // 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 return
if(M.reagents.has_reagent("spaceacillin")) if(M.reagents.has_reagent("spaceacillin"))
return return
if(!disease.affected_species.len) if(!disease.affected_species.len)
return return
if (!(M.species.name in disease.affected_species)) if (!(M.species.name in disease.affected_species))
if (forced) if (forced)
disease.affected_species[1] = M.species.name disease.affected_species[1] = M.species.name

View File

@@ -4,7 +4,7 @@
#define ENTRY "entry" #define ENTRY "entry"
/obj/machinery/disease2/isolator/ /obj/machinery/disease2/isolator/
name = "Pathogenic Isolator" name = "pathogenic isolator"
density = 1 density = 1
anchored = 1 anchored = 1
icon = 'icons/obj/virology.dmi' icon = 'icons/obj/virology.dmi'

View File

@@ -1,7 +1,7 @@
///////////////ANTIBODY SCANNER/////////////// ///////////////ANTIBODY SCANNER///////////////
/obj/item/device/antibody_scanner /obj/item/device/antibody_scanner
name = "\improper Antibody Scanner" name = "antibody scanner"
desc = "Scans living beings for antibodies in their blood." desc = "Scans living beings for antibodies in their blood."
icon_state = "health" icon_state = "health"
w_class = 2.0 w_class = 2.0
@@ -20,7 +20,7 @@
report("Scan aborted: The target does not have blood.", user) report("Scan aborted: The target does not have blood.", user)
return return
if(!C.antibodies) if(!C.antibodies.len)
report("Scan Complete: No antibodies detected.", user) report("Scan Complete: No antibodies detected.", user)
return return
@@ -36,11 +36,12 @@
///////////////VIRUS DISH/////////////// ///////////////VIRUS DISH///////////////
/obj/item/weapon/virusdish /obj/item/weapon/virusdish
name = "virus containment/growth dish" name = "virus dish"
icon = 'icons/obj/items.dmi' icon = 'icons/obj/items.dmi'
icon_state = "implantcase-b" icon_state = "implantcase-b"
var/datum/disease2/disease/virus2 = null var/datum/disease2/disease/virus2 = null
var/growth = 0 var/growth = 0
var/basic_info = null
var/info = 0 var/info = 0
var/analysed = 0 var/analysed = 0
@@ -66,10 +67,17 @@
del src del src
/obj/item/weapon/virusdish/examine(mob/user) /obj/item/weapon/virusdish/examine(mob/user)
user << "This is a virus containment dish." ..()
if(src.info) if(basic_info)
user << "It has the following information about its contents:" user << "[basic_info] : <a href='?src=\ref[src];info=1'>More Information</a>"
user << src.info
/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 /obj/item/weapon/ruinedvirusdish
name = "ruined virus sample" name = "ruined virus sample"

View File

@@ -104,5 +104,22 @@
</div> </div>
</div> </div>
{{:helper.link('Save To Disk', 'disk', { 'disk' : 1 }, (data.buffer || data.species_buffer) ? null : 'disabled')}} {{: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}} {{/if}}