Initial Commit

This commit is contained in:
Tobba
2016-03-06 20:52:14 +01:00
commit b181d0b552
4325 changed files with 579453 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,25 @@
/proc/generate_cold_pathogen()
var/datum/pathogen/P = unpool(/datum/pathogen)
P.forced_microbody = /datum/microbody/virus
P.curable_by_suppression = 7
P.setup(2, null, 0)
P.add_symptom(pathogen_controller.path_to_symptom[/datum/pathogeneffects/malevolent/coughing])
P.add_symptom(pathogen_controller.path_to_symptom[/datum/pathogeneffects/malevolent/indigestion])
return P
/proc/generate_flu_pathogen()
var/datum/pathogen/P = unpool(/datum/pathogen)
P.forced_microbody = /datum/microbody/virus
P.curable_by_suppression = 4
P.setup(2, null, 0)
P.add_symptom(pathogen_controller.path_to_symptom[/datum/pathogeneffects/malevolent/coughing])
P.add_symptom(pathogen_controller.path_to_symptom[/datum/pathogeneffects/malevolent/sneezing])
P.add_symptom(pathogen_controller.path_to_symptom[/datum/pathogeneffects/malevolent/muscleache])
return P
/proc/generate_indigestion_pathogen()
var/datum/pathogen/P = unpool(/datum/pathogen)
P.curable_by_suppression = 18
P.setup(2, null, 0)
P.add_symptom(pathogen_controller.path_to_symptom[/datum/pathogeneffects/malevolent/indigestion])
return P
@@ -0,0 +1,181 @@
datum/pathogeneffects/benevolent
name = "Benevolent"
rarity = RARITY_ABSTRACT
datum/pathogeneffects/benevolent/mending
name = "Wound Mending"
desc = "Slow paced brute damage healing."
rarity = RARITY_UNCOMMON
disease_act(var/mob/M as mob, var/datum/pathogen/origin)
if (!origin.symptomatic)
return
if (prob(origin.stage * 5))
M.HealDamage("chest", origin.stage < 3 ? 1 : 2, 0)
M.updatehealth()
react_to(var/R, var/zoom)
if (R == "synthflesh")
if (zoom)
return "Microscopic damage on the synthetic flesh appears to be mended by the pathogen."
may_react_to()
return "The pathogen appears to have the ability to bond with organic tissue."
datum/pathogeneffects/benevolent/healing
name = "Burn Healing"
desc = "Slow paced burn damage healing."
rarity = RARITY_UNCOMMON
disease_act(var/mob/M as mob, var/datum/pathogen/origin)
if (!origin.symptomatic)
return
if (prob(origin.stage * 5))
M.HealDamage("chest", 0, origin.stage < 3 ? 1 : 2)
M.updatehealth()
react_to(var/R, var/zoom)
if (R == "synthflesh")
if (zoom)
return "The pathogen does not appear to mend the synthetic flesh. Perhaps something that might cause other types of injuries might help."
if (R == "infernite")
if (zoom)
return "The pathogen repels the scalding hot chemical and quickly repairs any damage caused by it to organic tissue."
may_react_to()
return "The pathogen appears to have the ability to bond with organic tissue."
datum/pathogeneffects/benevolent/detoxication
name = "Detoxication"
desc = "The pathogen aids the host body in metabolizing ethanol."
rarity = RARITY_COMMON
disease_act(var/mob/M as mob, var/datum/pathogen/origin)
if (!origin.symptomatic)
return
var/times = 1
if (origin.stage > 3)
times++
if (origin.stage > 4)
times++
var/met = 0
for (var/rid in M.reagents.reagent_list)
var/datum/reagent/R = M.reagents.reagent_list[rid]
if (rid == "ethanol" || istype(R, /datum/reagent/fooddrink/alcoholic))
met = 1
for (var/i = 1, i <= times, i++)
if (R) //Wire: Fix for Cannot execute null.on mob life().
R.on_mob_life()
if (!R || R.disposed)
break
if (R && !R.disposed)
M.reagents.remove_reagent(rid, R.depletion_rate * times)
if (met)
M.reagents.update_total()
react_to(var/R, var/zoom)
if (R == "ethanol")
return "The pathogen appears to have entirely metabolized the ethanol."
may_react_to()
return "The pathogen appears to react with a pure intoxicant."
datum/pathogeneffects/benevolent/metabolisis
name = "Accelerated Metabolisis"
desc = "The pathogen accelerates the metabolisis of all chemicals present in the host body."
rarity = RARITY_RARE
disease_act(var/mob/M as mob, var/datum/pathogen/origin)
if (!origin.symptomatic)
return
var/times = 1
if (origin.stage > 3)
times++
if (origin.stage > 4)
times++
var/met = 0
for (var/rid in M.reagents.reagent_list)
var/datum/reagent/R = M.reagents.reagent_list[rid]
met = 1
for (var/i = 1, i <= times, i++)
if (R) //Wire: Fix for Cannot execute null.on mob life().
R.on_mob_life()
if (!R || R.disposed)
break
if (R && !R.disposed)
M.reagents.remove_reagent(rid, R.depletion_rate * times)
if (met)
M.reagents.update_total()
react_to(var/R, var/zoom)
return "The pathogen appears to have entirely metabolized... all chemical agents in the dish."
may_react_to()
return null
datum/pathogeneffects/benevolent/cleansing
name = "Cleansing"
desc = "The pathogen cleans the body of damage caused by toxins."
rarity = RARITY_RARE
disease_act(var/mob/M as mob, var/datum/pathogen/origin)
if (!origin.symptomatic)
return
if (prob(origin.stage * 5) && M.get_toxin_damage())
M.take_toxin_damage(-1)
if (origin.stage > 3)
M.take_toxin_damage(-1)
if (origin.stage > 4)
M.take_toxin_damage(-1)
M.updatehealth()
if (prob(10))
M.show_message("<span style=\"color:blue\">You feel cleansed.</span>")
react_to(var/R, var/zoom)
return "The pathogen appears to have entirely metabolized... all chemical agents in the dish."
may_react_to()
return null
datum/pathogeneffects/benevolent/oxygenconversion
name = "Oxygen Conversion"
desc = "The pathogen converts organic tissue into oxygen."
rarity = RARITY_VERY_RARE
may_react_to()
return "The pathogen appears to radiate a bubble of oxygen."
react_to(var/R, var/zoom)
if (R == "synthflesh")
return "The pathogen consumes the synthflesh and converts it into oxygen."
disease_act(var/mob/M as mob, var/datum/pathogen/origin)
if (!origin.symptomatic)
return
if (M:losebreath > 0)
M.TakeDamage("chest", M:losebreath * 2, 0)
M:losebreath = 0
if (prob(25))
M.show_message("<span style=\"color:red\">You feel your body deteriorating as you breathe on.</span>")
if (M.get_oxygen_deprivation())
if (origin.stage != 0)
M.take_oxygen_deprivation(0 - (origin.stage / 2))
M.updatehealth()
datum/pathogeneffects/benevolent/oxygenproduction
name = "Oxygen Production"
desc = "The pathogen produces oxygen."
rarity = RARITY_VERY_RARE
may_react_to()
return "The pathogen appears to radiate a bubble of oxygen."
disease_act(var/mob/M as mob, var/datum/pathogen/origin)
if (!origin.symptomatic)
return
if (M:losebreath > 0)
M:losebreath = 0
if (M.get_oxygen_deprivation())
M.take_oxygen_deprivation(0 - origin.stage)
M.updatehealth()
@@ -0,0 +1,351 @@
/**
* Pathogen DNA
*
* The pathogen DNA sequence consists of two separately handled parts:
* - The "private" sequence is basically a sequence that contains
* - the unique identifier of the microbody of the pathogen, which must be defined in the /datum/microbody subclass.
* the pathogen controller contains a lookup table of the existing microbody IDs for fast lookup, reducing search times from O(n) to O(1).
* - the numeric values of the pathogen, sequentially, as two byte signed integers, which means each numeric value is encoded in the DNA sequence as four hexadecimal digits
* - a single digit signifying the amount of stages of a pathogen
* - a single digit signifying if the pathogen is symptomatic
* at the time of writing this documentation, the sequence of the numeric values is:
* mutativeness | mutation speed | advance speed | maliciousness | suppression threshold | stages
* EXAMPLE: A pathogen that is a virus, with a mutativeness of 19, a mutation speed of 6, an advance speed of 5, a maliciousness of 7
* and a suppression threshold of 5, 5 stages and symptomatic carries the following DNA sequence:
* 00010013000600050007000551
* DEVELOPER NOTE: The encoding is NOT two's complement as any coder would expect, due to the fact that I have no idea how
* BYOND numbers are represented. The encoding of the two bytes is 2 byte one's complement. (I think. Whatever.)
* NOTE: While any of these values are highly unlikely to ever pass 255, I'll leave it open for two bytes.
* This private sequence is only ever printed and cannot be directly spliced. Modifying the numeric values is done through seed mutation logic.
* Since this part of the DNA is never directly modified, this part is always calculated from the numeric values.
* - The "public" sequence is the sequence that contains
* - The suppressant of the pathogen. Each suppressant is given a round-randomized 3 quartet (1.5 byte) unique identifier by the pathogen controller upon round setup.
* A lookup table of available suppressants is available in the pathogen controller for fast processing.
* - A single separator to signal the end of suppressants and the beginning of carriers.
* - All carriers, sequentially. Carriers are assigned 3 quartets as well, and they have their own lookup table.
* - Anything I may have forgot to mention is also here.
* - A single separator to signal the beginning of the symptoms.
* - All symptoms of the pathogen sequentially. This might and will cause the DNA to inflate to a very large and complex sequence if a very mutative pathogen is introduced to the station.
* A symptom is composed of R * 3 quartets, where R represents rarity, followed by a 'DNA separator' marked by a | in the DNA.
* Rarity is a value from 1 to 5, where 1 is VERY COMMON and 5 is VERY RARE. All symptoms are assigned this value as their unique identifier and an unique identifier is generated for
* each symptom at round setup following this pattern:
* 1) All VERY_COMMON symptoms are assigned a symptom-unique round randomized 3 quartet (eg. 1F3 is now sweating and EE2 is now farting)
* 2) All symptoms of rarity R (where R is the next lowest rarity category not yet processed) are assigned a 3R quartet. First, a set of available identifiers is generated by taking
* each identifier for rarity R-1 symptoms, and prepending and appending the identifier of all VERY_COMMON symptoms. This will generate a moderate amount of collisions (for example
* prepeding 1F3 to EE20AB yields the same as appending 0AB to 1F3EE2), which are then eliminated. Then, rarity R symptoms are each assigned a randomly pick()-ed identifier from this
* list. If, due to an inbalance in the amount of symptoms available there is no ID that is left avaiable and the sequence will be a randomly generated 3R quartet. This, of course,
* means that the symptom cannot be synthesized via pathology science that round. Tough luck.
* At the time of writing this documentation, the numbers add up and all symptoms should be synthesizable. At current time, it is also hard to synthesize a VERY_RARE symptom. which
* is intended and a good thing.
* The DNA separators are a sort of 'resource' available to pathologists, although infinite of them is produceable through replicating DNA. If someone can come up with any reasonable way
* to limit DNA separators, I am open to implementing it.
* What is a DNA separator though? Well, as the above algorithm shows, the identifier sequence of each high tier symptom is composed of VALID sequences for lower tier symptoms. To be able
* to determine which symptom is supposed to be a higher tier one, symptoms must be separated by a ~magical nucleic acid~ we call the DNA separator. This means that a pathogen of K symptoms
* will contain K-1 DNA separators.
* The pathogen controller will contain a symptom lookup table and an inverse table for looking up the numeric identifier.
* Due to the nature of this, we are limited to 4096 (2^12, 3 quartets) VERY_COMMON symptoms. Oh the horror.
* This part of the DNA is modifiable through splicing. During a splicing session, you can scrap parts of the DNA and introduce new parts from already existing DNA. Once the splicing session
* is complete, the DNA is evaluated (compiled) and destroyed if it contains an invalid sequence (such as an attempt to create a tier three symptom, but no tier three symptom having that
* specific DNA sequence). I believe pathologists will be kept busy by making their ~fancy symptoms~ all round, and it's not as straightforward as chemistry or as boring as genetics.
* EXAMPLE: Suppose that sweating is 1F3, farting is EE2, coughing is sweating + farting (1F3EE2) and the heat weakness suppressant is 0C3.
* The DNA sequence for a pathogen with the above three symptoms, no carriers and heat weakness would be:
* 0C3||1F3|EE2|1F3EE2
* During splicing, moving could only be done by moving coherent parts. A coherent part is a 3 quartet beginning at a 3 quartet boundary or after a DNA separator. This means one could move
* 1F3 or EE2 out of 1F3EE2 but not 3EE or F3E. A single DNA separator is also a coherent part. A coherent part could only be moved to a boundary (ie. inserted between two existing coherent
* parts)
* EXAMPLE: Suppose that no symptom gained the unique identifier of farting + sweating (EE21F3). A pathologist splicing the above DNA sequence into
* 0C3||1F3|EE21F3
* would be in for a nasty surprise, as the DNA collapses, due to EE21F3 being an invalid sequence.
* Due to the nature of the rolling unique identifiers, of course it does not mean EE21F3AB0 couldn't be a valid sequence, as a symptom with the sequence 1F3AB0 could exist, and a higher
* tier symptom could have EE2 prepended to this. This means that only ELEMENTARY (3 quartet starting at boundary) subsets of a symptom's unique identifier is also guaranteed to be a
* valid unique identifier.
*/
/**
* Pathogen mutate-and-effect graph
*
* When numeric values of pathogens are mutated, other values are mutated in the other direction. This graph defines the mutation of which values effect which other values.
* (For every action, there is an equal and opposite reaction, except it's not equal because that would be annoying and I'm not trying to apply Newton's third law of motion)
*
* mutativeness ------------- advance_speed
* | /
* | maliciousness
* | \
* sthreshold --------------- mutation_speed
*
* ...sometimes I wish BYOND had pointers because it would be so much cleaner. I'm not going to use whatever twisted thing DM called refs.
*/
datum/pathogendna
var/seqnumeric = "00000000000000000000000000"
var/seqsplice = ""
var/valid = 0
var/datum/pathogen/reference = null
New(var/datum/pathogen/P)
if (P)
reference = unpool(/datum/pathogen)
reference.setup(0, P, 0, src)
recalculate()
reverse_engineer()
valid = 1
else
reference = unpool(/datum/pathogen)
valid = 0
proc/clone()
var/datum/pathogendna/D = new(reference)
return D
proc/manipulate(value, direction)
var/datum/pathogendna/this = src
src = null
if (prob(2))
del this
return 0
else if (prob(4))
this.reference.mutate()
this.recalculate()
this.reverse_engineer()
return -1
if (direction > 0)
direction = 1
else
direction = -1
if (!this)
return 0 // We somehow lost the DNA.
switch (value)
if ("mutativeness"):
this.reference.mutativeness += rand(1, 3) * direction
this.reference.advance_speed -= rand(0, 1) * direction
this.reference.suppression_threshold -= rand(0, 1) * direction
if ("suppression_threshold"):
this.reference.suppression_threshold += rand(1, 3) * direction
this.reference.mutation_speed -= rand(0, 1) * direction
this.reference.mutativeness -= rand(0, 1) * direction
if ("mutation_speed")
this.reference.mutation_speed += rand(1, 3) * direction
this.reference.suppression_threshold -= rand(0, 1) * direction
this.reference.maliciousness -= rand(0, 1) * direction
if ("maliciousness")
this.reference.maliciousness += rand(1, 3) * direction
this.reference.advance_speed -= rand(0, 1) * direction
this.reference.mutation_speed -= rand(0, 1) * direction
if ("advance_speed")
this.reference.advance_speed += rand(1, 3) * direction
this.reference.mutativeness -= rand(0, 1) * direction
this.reference.maliciousness -= rand(0, 1) * direction
if (this.reference.mutation_speed < 0)
this.reference.mutation_speed = 0
this.recalculate()
return 1
proc/explode()
var/list/ret = new/list()
var/pos = 1
while (pos < lentext(seqsplice))
if (copytext(seqsplice, pos, pos + 1) != "|")
ret += copytext(seqsplice, pos, pos + 3)
pos += 3
else
ret += "|"
pos += 1
return ret
proc/implode(var/list/parts)
var/newseq = ""
for (var/i = 1, i <= parts.len, i++)
newseq += parts[i]
seqsplice = newseq
valid = 0
return
proc/get_sequences()
var/list/seq = list()
var/list/parts = explode()
var/i = 1
var/s = 0
while (i < parts.len && s < 2)
if (parts[i] == "|")
s++
i++
if (s < 2)
return seq
var/act_seq = ""
while (i < parts.len)
if (parts[i] == "|")
if (act_seq != "")
seq += act_seq
else
return list() // error
act_seq = ""
else
act_seq += parts[i]
i++
if (act_seq == "")
return list()
seq += act_seq
return seq
// Pathogen numeric -> DNA/Private
proc/recalculate()
// BYOND number vars are unreliable. All numbers are rounded.
var/uid = num2hexoc(round(src.reference.body_type.uniqueid), 4)
var/mut = num2hexoc(round(src.reference.mutativeness), 4)
var/mts = num2hexoc(round(src.reference.mutation_speed), 4)
var/adv = num2hexoc(round(src.reference.advance_speed), 4)
var/mal = num2hexoc(round(src.reference.maliciousness), 4)
var/sup = num2hexoc(round(src.reference.suppression_threshold), 4)
src.seqnumeric = "[uid][mut][mts][adv][mal][sup][src.reference.stages][src.reference.symptomatic]"
// DNA/Private -> Pathogen numeric
proc/reevaluate_numeric()
var/uid = hex2numoc(copytext(seqnumeric, 1, 5))
var/mut = hex2numoc(copytext(seqnumeric, 5, 9))
var/mts = hex2numoc(copytext(seqnumeric, 9, 13))
var/adv = hex2numoc(copytext(seqnumeric, 13, 17))
var/mal = hex2numoc(copytext(seqnumeric, 17, 21))
var/sup = hex2numoc(copytext(seqnumeric, 21, 25))
var/stages = text2num(copytext(seqnumeric, 25, 26))
var/symptomatic = text2num(copytext(seqnumeric, 26, 27))
src.reference.mutativeness = mut
src.reference.mutation_speed = mts
src.reference.advance_speed = adv
src.reference.maliciousness = mal
src.reference.suppression_threshold = sup
src.reference.stages = stages
src.reference.symptomatic = symptomatic
for(var/T in pathogen_controller.path_to_microbody)
var/datum/microbody/B = pathogen_controller.path_to_microbody[T]
if (B.uniqueid == uid)
src.reference.body_type = B
src.reference.stages = B.stages
break
// Pathogen data -> DNA/Public
proc/reverse_engineer()
src.seqsplice = pathogen_controller.suppressant_to_UID[reference.suppressant.type]
src.seqsplice += "|"
//for (var/datum/pathogen_carrier/C in src.reference.carriers)
// src.seqsplice += pathogen_controller.carrier_to_UID[C.type]
src.seqsplice += "|"
var/first = 1
for (var/datum/pathogeneffects/E in src.reference.effects)
if (!first)
src.seqsplice += "|"
else
first = 0
src.seqsplice += pathogen_controller.symptom_to_UID[E.type]
// DNA/Public -> Pathogen data
proc/reevaluate()
// Move src reference so we can return false if evaluation fails (important for whatever is calling this)
var/datum/pathogendna/this = src
src = null
var/desc = this.reference.desc
var/name_base = this.reference.name_base
var/mutation = this.reference.mutation
var/uid = this.reference.pathogen_uid
this.reference.clear()
this.reference.desc = desc
this.reference.name_base = name_base
this.reference.base_mutation = mutation
this.reference.pathogen_uid = uid
this.reference.mutation = pathogen_controller.next_mutation[num2text(uid)]
this.reference.stage = 1
this.reference.name = "[name_base][mutation]"
pathogen_controller.next_mutation[num2text(uid)] += 1
this.reevaluate_numeric()
// Partition the DNA for traversal.
var/list/parts = this.explode()
if (!(parts[1] in pathogen_controller.UID_to_suppressant))
//log_game("[this.seqsplice] collapses: non-existent suppressant.")
qdel(this) // Bad DNA: Invalid suppressant.
return 0
else
if (this)
var/supp = pathogen_controller.UID_to_suppressant[parts[1]]
this.reference.suppressant = pathogen_controller.path_to_suppressant[supp]
else
return 0 // Somehow, we lost the DNA.
if (parts[2] != "|")
//log_game("[this.seqsplice] collapses: no separator after suppressant.")
qdel(this)
return 0 // Bad DNA: no separator after suppressant.
var/pos = 2
if (parts[3] == "|")
pos = 4 // No carriers.
else
pos = 3
while (pos <= parts.len && parts[pos] != "|")
if (!(parts[pos] in pathogen_controller.UID_to_carrier))
//log_game("[this.seqsplice] collapses: non-existent carrier.")
qdel(this) // Bad DNA: Invalid carrier
return 0
else
if (this)
this.reference.carriers += pathogen_controller.UID_to_carrier[parts[pos]]
else
return 0 // Somehow, we lost the DNA.
pos++
if (pos == parts.len)
//log_game("[this.seqsplice] collapses: no separator after carriers.")
qdel(this) // Bad DNA: No ending separator after carriers.
return 0
pos++
// Assemble the list of symptoms.
var/symptom = ""
while (pos <= parts.len)
if (parts[pos] == "|")
if (symptom != "")
// Validate symptom
if (!(symptom in pathogen_controller.UID_to_symptom))
//log_game("[this.seqsplice] collapses: non-existent symptom [symptom].")
qdel(this) // Bad DNA: DNA contains invalid symptom
return 0
else
if (this)
var/sym = pathogen_controller.UID_to_symptom[symptom]
this.reference.effects += pathogen_controller.path_to_symptom[sym]
symptom = ""
else
return 0 // Somehow, we lost the DNA.
else
//log_game("[this.seqsplice] collapses: two adjacent symptom separators.")
qdel(this) // Bad DNA: DNA contains two adjacent separators
return 0
else
symptom += parts[pos]
pos++
if (symptom != "")
if (!(symptom in pathogen_controller.UID_to_symptom))
//log_game("[this.seqsplice] collapses: non-existent symptom [symptom].")
qdel(this) // Bad DNA: DNA contains invalid symptom
return 0
else
if (this)
var/sym = pathogen_controller.UID_to_symptom[symptom]
this.reference.effects += pathogen_controller.path_to_symptom[sym]
else
return 0 // Somehow, we lost the DNA.
// DNA has been completely evaluated if we reach this point in execution and it is a valid pathogen DNA. Hooray!
// Build the available symptom list for the pathogen.
this.reference.dnasample = this
this.valid = 1
return 1 // Success.
proc/regenerate_uid()
src.reference.pathogen_uid = "[pathogen_controller.next_uid]"
src.reference.mutation = pick(pathogen_controller.lnums)
src.reference.name_base = pick(pathogen_controller.lalph) + pick(pathogen_controller.lnums) + pick(pathogen_controller.lalph)
src.reference.name = src.reference.name_base + "[src.reference.mutation]"
pathogen_controller.next_uid++
proc/move_mutation()
src.reference.mutation = pathogen_controller.next_mutation[src.reference.pathogen_uid]
pathogen_controller.next_mutation[src.reference.pathogen_uid] += 1
src.reference.name = src.reference.name_base + "[src.reference.mutation]"
@@ -0,0 +1,67 @@
/proc/shakespearify(var/string)
string = dd_replacetext(string, "your ", "[pick("thy", "thine")] ")
string = dd_replacetext(string, " your", " [pick("thy", "thine")]")
string = dd_replacetext(string, " is ", " be ")
string = dd_replacetext(string, "you ", "thou ")
string = dd_replacetext(string, " you", " thou")
string = dd_replacetext(string, "are ", "art ")
string = dd_replacetext(string, " are", " art")
string = dd_replacetext(string, "does ", "doth ")
string = dd_replacetext(string, " does", " doth")
string = dd_replacetext(string, "do ", "doth ")
string = dd_replacetext(string, " do", " doth")
string = dd_replacetext(string, "she ", "the lady ")
string = dd_replacetext(string, " she", " the lady")
string = dd_replacetext(string, "i think", "methinks")
return string
/mob/living/carbon/human/proc/become_ice_statue()
var/obj/overlay/iceman = new /obj/overlay(get_turf(src))
src.pixel_x = 0
src.pixel_y = 0
src.set_loc(iceman)
iceman.name = "ice statue of [src.name]"
iceman.desc = "We here at Space Station 13 believe in the transparency of our employees. It doesn't look like a functioning human can be retrieved from this."
iceman.anchored = 0
iceman.density = 1
iceman.layer = MOB_LAYER
iceman.dir = src.dir
iceman.alpha = 128
var/ist = "body_f"
if (src.gender == "male")
ist = "body_m"
var/icon/composite = icon('icons/mob/human.dmi', ist, null, 1)
for(var/O in src.overlays)
var/image/I = O
composite.Blend(icon(I.icon, I.icon_state, null, 1), ICON_OVERLAY)
composite.ColorTone( rgb(165,242,243) ) // ice
iceman.icon = composite
src.take_toxin_damage(INFINITY)
src.ghostize()
/proc/generate_random_pathogen()
var/datum/pathogen/P = unpool(/datum/pathogen)
P.setup(1, null, 0)
return P
/proc/wrap_pathogen(var/datum/reagents/reagents, var/datum/pathogen/P, var/units = 5)
reagents.add_reagent("pathogen", units)
var/datum/reagent/blood/pathogen/R = reagents.get_reagent("pathogen")
if (R)
R.pathogens[P.pathogen_uid] = P
/proc/ez_pathogen(var/stype)
var/datum/pathogen/P = unpool(/datum/pathogen)
var/datum/pathogen_cdc/cdc = P.generate_name()
cdc.mutations += P.name
cdc.mutations[P.name] = P
P.generate_components(cdc, 0)
P.generate_attributes(0)
P.mutativeness = 0
P.mutation_speed = 0
P.advance_speed = 6
P.suppression_threshold = max(1, P.suppression_threshold)
P.add_symptom(pathogen_controller.path_to_symptom[stype])
logTheThing("pathology", null, null, "Pathogen [P.name] created by quick-pathogen-proc with symptom [stype].")
return P
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,190 @@
/**
* Microbody notes
*
* A pathogen microbody identifies the cause of the disease.
* Most of the real life causes for diseases have been added already.
* Each microbody defines a specific characteristic for a pathogen:
* - How fast does the infection spiral out of control on the station (mutativeness)
* - How bad will the disease eventually evolve? (maliciousness multiplier)
* - How fast is the evolution of the disease? (mutation speed multiplier)
* - How powerful is a disease caused by the microbody (stages).
* - What is a fertile soil to cultivate this pathogen? (growth medium)
*
*
* We differentiate between two types of cures:
* - Serum. Every microbody has a serum; there is nothing that is currently incurable. Of course not adding a cure for a specific
* microbody will make all pathogens of that microbody incurable.
* - Vaccine. Currently, only virii have vaccines; injecting someone with a vaccine for a pathogen will make them immune to said
* pathogen and all its mutations. A traitor would use this for his very deadly airbourne pathogen to avoid getting infected
* by it.
*/
// A microscopic body, acting as a pathogen.
datum/microbody
var/name = "Microscopic body"
var/singular = "microscopic body"
var/plural = "microscopic bodies"
// The strength of the microbody. Used for randomization.
var/strength = 2
// An inverse of rarity. A value of 10 means a ten times relative chance to a value of 1.
var/commonness = 10
// Base mutativeness value for this microbody.
var/mutativeness = 6
// Multiplier for randomly generated maliciousness and mutation speed with this microbody.
var/maliciousness_multiplier = 1
var/mutation_speed_multiplier = 1
// The amount of stages a pathogen with this microbody has.
// Technically, this means there are less aggressive and more aggressive infections depending on the microbody.
// Keep this value between 3 and 5.
var/stages = 3
// Activity determines the probability of symptoms manifesting in each stage for a particular microbody.
var/activity = list(20, 20, 20, 20, 20)
// The growth medium is the reagent whose presence will make pathogens of this microbody grow in petri dishes.
// DO NOT set this to "blood" or "pathogen", only to a derivative.
var/growth_medium = "water"
// The base reagent for cures to this specific microbody type. Will be used by the synth-o-matic. Keep this null for an incurable microbody.
var/cure_base = "serum"
// Can you make a vaccine for this microbody? (Instant immunity)
var/vaccination = 0
// The unique ID for this microbody. Used in public DNA.
var/uniqueid = 0
// If specified, a special module is needed for the Synth-O-Matic to synthesize a cure for this microbody.
var/module_id = null
// A list of reagent IDs, each of which is required for the growth of a pathogen.
var/list/nutrients = list("water", "sugar", "sodium", "iron", "nitrogen")
// If 1, curing also immunizes to re-infection.
var/auto_immunize = 0
// The amount of nutrition of each type required per unit of pathogen to continue cultivation.
var/amount = 0.07
Del()
CRASH("ALERT MICROBODY IS BEING DELETED")
disposing()
CRASH("ALERT MICROBODY IS BEING DISPOSED")
datum/microbody/virus
name = "Virus"
singular = "virus"
plural = "viruses"
mutativeness = 15
maliciousness_multiplier = 2
mutation_speed_multiplier = 3
stages = 5
activity = list(1, 5, 20, 30, 40)
// Grows in eggs.
growth_medium = "egg"
cure_base = "antiviral"
vaccination = 1
auto_immunize = 1
uniqueid = 1
module_id = "virii"
datum/microbody/bacteria
name = "Bacteria"
singular = "bacterium"
plural = "bacteria"
mutativeness = 6
maliciousness_multiplier = 1
mutation_speed_multiplier = 1
activity = list(7, 15, 25, 30, 35)
stages = 3
growth_medium = "bacterialmedium"
cure_base = "spaceacillin"
auto_immunize = 1
uniqueid = 2
module_id = "bacteria"
datum/microbody/fungi
name = "Fungi"
singular = "fungus"
plural = "fungi"
mutativeness = 0
maliciousness_multiplier = 2
mutation_speed_multiplier = 1
stages = 4
activity = list(7, 8, 10, 14, 25)
growth_medium = "fungalmedium"
cure_base = "biocide"
uniqueid = 3
module_id = "fungi"
datum/microbody/parasite
name = "Parasites"
singular = "parasite"
plural = "parasites"
mutativeness = 3
maliciousness_multiplier = 4
mutation_speed_multiplier = 3
stages = 5
activity = list(30, 20, 10, 8, 8)
growth_medium = "parasiticmedium"
cure_base = "biocide"
uniqueid = 4
module_id = "parasite"
datum/microbody/gmcell
name = "Great Mutatis cell"
singular = "great mutatis cell"
plural = "great mutatis cells"
strength = 10
commonness = 2
activity = list(20, 20, 20, 20, 20)
mutativeness = 45
maliciousness_multiplier = 7
mutation_speed_multiplier = 5
stages = 5
// Grows in stable mutagen.
// INTEGRATION NOTES: stable mutagen reagent ID.
growth_medium = "dna_mutagen"
cure_base = "inhibitor"
uniqueid = 5
module_id = "gmcell"
nutrients = list("dna_mutagen")
amount = 0.35
@@ -0,0 +1,421 @@
#define MUTATION_MALICIOUS 1
#define MUTATION_BENEVOLENT -1
#define MUTATION_EVOLUTION 1
#define MUTATION_DEVOLUTION -1
/**
* Pathogen Mutations
*
* All possible mutation effects are a child of /datum/pathogen_mutation.
* These will be automatically chosen at random as candidates for mutation.
* There are a number of factors deciding whether or not a certain kind of mutation will occur. If a mutation's criteria are not satisfied,
* new mutations are chosen until one with satisfied criteria is found. The default mutations are defined so that no situation may arise
* where a mutation cannot be picked. Regardless, if all mutations defined are unsatisfied, a mutation will not occur.
*
* Each mutation may occur exactly session_maximum times per mutation session.
* This is in to prevent abusing the mutation system for gathering a large amount of symptoms quickly.
* Symptom gaining mutations are also purposefully made harder to gain very deadly symptoms.
*
* Mutation criteria for malicious mutations:
* - For a malicious mutation to occur on a pathogen, its maliciousness must be greater or equal to the mutation's maliciousness threshold.
* - For this mutation to occur, its maliciousness must be no greater than its maliciousness limit, unless the limit is lower than the
* threshold.
* - For this mutation to occur, the pathogen's mutativeness must be greater than the mutativeness threshold if it's an evolution, or
* lower than the mutativeness threshold if it's a devolution. It may also occur on equality.
* - If all the above criteria are satisfied, the chance of this mutation actually occurring is
* chance_base + maliciousness * chance_modifier
*
* Mutation criteria for benevolent mutations:
* - For a benevolent mutation to occur on a pathogen, its maliciousness must be less or equal to the mutation's maliciousness threshold.
* - For this mutation to occur, its maliciousness must be no less than its maliciousness limit, unless the limit is higher than the
* threshold.
* - For this mutation to occur, the pathogen's mutativeness must be greater than the mutativeness threshold if it's an evolution, or
* lower than the mutativeness threshold if it's a devolution. It may also occur on equality.
* - If all the above criteria are satisfied, the chance of this mutation actually occurring is
* chance_base - maliciousness * chance_modifier
*
* The mutation code must be in the mutate proc of the child type. It will be executed automatically if the mutation occurs.
*/
datum/pathogen_mutation
var/name = "Pathogen Mutation"
var/desc = "Generic mutation"
var/malicious_type = MUTATION_MALICIOUS
var/maliciousness_threshold = 0
var/maliciousness_limit = -1
var/session_maximum = 1
var/chance_base = 50
var/chance_modifier = 0
var/evolution_type = MUTATION_EVOLUTION
var/mutativeness_threshold = 0
proc/may_occur(var/datum/pathogen/P)
if (malicious_type * P.maliciousness >= malicious_type * maliciousness_threshold && (malicious_type * maliciousness_limit < malicious_type * maliciousness_threshold || malicious_type * P.maliciousness <= malicious_type * maliciousness_limit) && evolution_type * P.mutativeness >= evolution_type * mutativeness_threshold)
if (prob(chance_base + malicious_type * P.maliciousness * chance_modifier))
return 1
return 0
proc/mutate(var/datum/pathogen/P)
return
// This mutation is a general purpose mutation which acts as a "mutation sink" - it absorbs mutations from the pool by existing and
// occurring. This is mostly here for balance purposes.
datum/pathogen_mutation/scramble
name = "Attribute Scramble"
desc = "Modifies the five primary attributes of a pathogen by an amount."
malicious_type = MUTATION_MALICIOUS
session_maximum = 5
evolution_type = MUTATION_DEVOLUTION
may_occur(var/datum/pathogen/P)
return P.symptomatic && prob(20)
mutate(var/datum/pathogen/P)
var/factor = rand(1, 4)
P.mutativeness = P.mutativeness + factor * rand(-2, 2)
P.maliciousness = P.maliciousness + factor * rand(-2, 2)
P.suppression_threshold = P.suppression_threshold + factor * rand(-2, 2)
P.advance_speed = P.advance_speed + factor * rand(-2, 2)
P.mutation_speed = P.mutation_speed + factor * rand(-2, 2)
// This mutation exists to introduce a risk factor to getting mutations. Before this, mutations carried the pathogen in the desired
// direction.
datum/pathogen_mutation/lose_attributes
name = "Lose All Attributes"
desc = "Sets all five primary attributes of a pathogen to 0."
malicious_type = MUTATION_MALICIOUS
evolution_type = MUTATION_DEVOLUTION
may_occur(var/datum/pathogen/P)
return P.symptomatic && prob(8)
mutate(var/datum/pathogen/P)
P.mutativeness = 0
P.maliciousness = 0
P.suppression_threshold = 0
P.advance_speed = 0
P.mutation_speed = 0
datum/pathogen_mutation/increase_generation
name = "Increase Generation"
desc = "Advances a pathogen to the next generation. Higher generation pathogens may overtake a lower generation infection of the same strain."
malicious_type = MUTATION_BENEVOLENT
evolution_type = MUTATION_EVOLUTION
may_occur(var/datum/pathogen/P)
return 1
mutate(var/datum/pathogen/P)
P.generation++
datum/pathogen_mutation/become_asymptomatic
name = "Become Asymptomatic"
desc = "The mutated strain becomes asymptomatic."
malicious_type = MUTATION_BENEVOLENT
evolution_type = MUTATION_DEVOLUTION
may_occur(var/datum/pathogen/P)
return P.symptomatic && prob(35)
mutate(var/datum/pathogen/P)
P.symptomatic = 0
datum/pathogen_mutation/become_symptomatic
name = "Become Symptomatic"
desc = "The mutated strain becomes symptomatic."
malicious_type = MUTATION_MALICIOUS
evolution_type = MUTATION_EVOLUTION
may_occur(var/datum/pathogen/P)
return !P.symptomatic
mutate(var/datum/pathogen/P)
P.symptomatic = 1
datum/pathogen_mutation/maliciousness_boost
name = "Maliciousness Boost"
desc = "Increases the maliciousness primary attribute of a pathogen."
malicious_type = MUTATION_MALICIOUS
maliciousness_threshold = -25
maliciousness_limit = 5
chance_base = 75
chance_modifier = -5
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
if (P.symptomatic)
return ..()
return 0
mutate(var/datum/pathogen/P)
P.maliciousness += rand(1,3)
datum/pathogen_mutation/benevolence_boost
name = "Benevolence Boost"
desc = "Reduces the maliciousness primary attribute of a pathogen."
malicious_type = MUTATION_BENEVOLENT
maliciousness_threshold = 25
maliciousness_limit = -5
chance_base = 75
chance_modifier = -5
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
if (P.symptomatic)
return ..()
return 0
mutate(var/datum/pathogen/P)
P.maliciousness -= rand(1,3)
datum/pathogen_mutation/advance_boost
name = "Advance Speed Boost"
desc = "Increases the advance speed primary attribute of a pathogen."
malicious_type = MUTATION_MALICIOUS
maliciousness_threshold = 15
maliciousness_limit = 14
chance_base = 50
chance_modifier = 5
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
if (P.symptomatic)
return ..()
return 0
mutate(var/datum/pathogen/P)
P.advance_speed += rand(1,3)
datum/pathogen_mutation/advance_penalty
name = "Advance Speed Penalty"
desc = "Decreases the advance speed primary attribute of a pathogen."
malicious_type = MUTATION_BENEVOLENT
maliciousness_threshold = 20
maliciousness_limit = 21
chance_base = 50
chance_modifier = 5
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
if (P.symptomatic)
return ..()
return 0
mutate(var/datum/pathogen/P)
P.advance_speed -= rand(1,3)
datum/pathogen_mutation/mutation_boost
name = "Mutation Speed Boost"
desc = "Increases the mutation speed primary attribute of a pathogen."
malicious_type = MUTATION_MALICIOUS
maliciousness_threshold = -15
maliciousness_limit = -16
chance_base = 50
chance_modifier = 5
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
if (P.symptomatic)
return ..()
return 0
mutate(var/datum/pathogen/P)
P.mutation_speed += rand(1,3)
datum/pathogen_mutation/mutation_penalty
name = "Mutation Speed Penalty"
desc = "Decreases the mutation speed primary attribute of a pathogen."
malicious_type = MUTATION_BENEVOLENT
maliciousness_threshold = 15
maliciousness_limit = 16
chance_base = 50
chance_modifier = 5
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
return P.symptomatic && ..() && P.mutation_speed > 0
mutate(var/datum/pathogen/P)
P.mutation_speed -= rand(1,3)
if (P.mutation_speed < 0)
P.mutation_speed = 0
datum/pathogen_mutation/increase_stages
name = "More Stages"
desc = "Increases the stages cap of a pathogen, up to 5."
malicious_type = MUTATION_MALICIOUS
maliciousness_threshold = -25
maliciousness_limit = -26
chance_base = 75
chance_modifier = 0
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
return ..() && P.stages < 5
mutate(var/datum/pathogen/P)
P.stages++
datum/pathogen_mutation/decrease_stages
name = "Less Stages"
desc = "Decreases the stages cap of a pathogen, down to 3."
malicious_type = MUTATION_BENEVOLENT
maliciousness_threshold = 25
maliciousness_limit = 26
chance_base = 75
chance_modifier = 0
evolution_type = MUTATION_DEVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
return ..() && P.stages > 3
mutate(var/datum/pathogen/P)
P.stages--
P.stage = min(P.stage, P.stages)
datum/pathogen_mutation/gain_symptom
name = "Gain Symptom"
desc = "Adds a new symptom to the pathogen."
malicious_type = MUTATION_MALICIOUS
maliciousness_threshold = 15
maliciousness_limit = 30
chance_base = 40
chance_modifier = 8
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
return P.symptomatic && ..()
mutate(var/datum/pathogen/P)
var/retries = 10
while (!P.generate_effect() && retries)
retries--
datum/pathogen_mutation/gain_more_symptoms
name = "Gain More Symptoms"
desc = "Adds up to 3 new symptoms to the pathogen."
malicious_type = MUTATION_MALICIOUS
maliciousness_threshold = 25
maliciousness_limit = 70
chance_base = 40
chance_modifier = 8
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
return P.symptomatic && ..()
mutate(var/datum/pathogen/P)
var/retries = 10
for (var/i = 1, i <= rand(1,3), i++)
while (!P.generate_effect() && retries)
retries--
datum/pathogen_mutation/gain_strong_symptom
name = "Gain Strong Symptom"
desc = "Adds a new strong symptom to the pathogen."
malicious_type = MUTATION_MALICIOUS
maliciousness_threshold = 65
maliciousness_limit = 150
chance_base = 20
chance_modifier = 8
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
return P.symptomatic && ..()
mutate(var/datum/pathogen/P)
var/retries = 10
while (!P.generate_strong_effect() && retries)
retries--
datum/pathogen_mutation/gain_more_strong_symptoms
name = "Gain More Strong Symptoms"
desc = "Adds up to 3 new strong symptoms to the pathogen."
malicious_type = MUTATION_MALICIOUS
maliciousness_threshold = 125
maliciousness_limit = 100
chance_base = 10
chance_modifier = 1
evolution_type = MUTATION_EVOLUTION
mutativeness_threshold = 0
may_occur(var/datum/pathogen/P)
return P.symptomatic && ..()
mutate(var/datum/pathogen/P)
var/retries = 10
for (var/i = 1, i <= rand(1,3), i++)
while (!P.generate_strong_effect() && retries)
retries--
datum/pathogen_mutation/lose_symptom
name = "Lose Symptom"
desc = "Removes a symptom from the pathogen."
malicious_type = MUTATION_BENEVOLENT
maliciousness_threshold = 50
maliciousness_limit = 51
chance_base = 40
chance_modifier = 8
evolution_type = MUTATION_DEVOLUTION
mutativeness_threshold = 25
may_occur(var/datum/pathogen/P)
return P.symptomatic && ..() && P.effects.len
mutate(var/datum/pathogen/P)
P.remove_symptom(pick(P.effects))
/*datum/pathogen_mutation/become_alternative
name = "Become Alternative"
desc = "A symptom of the pathogen may interchange itself with a more serious, or a milder alternative."
malicious_type = MUTATION_MALICIOUS
session_maximum = 3
may_occur(var/datum/pathogen/P)
if (!P.symptomatic || P.maliciousness == 0 || P.mutativeness < 5)
return 0
else
for (var/datum/pathogeneffects/E in P.effects)
if (P.maliciousness > 0)
if (E.serious_alternatives.len)*/
@@ -0,0 +1,319 @@
/**
* Pathogen suppressants
*
* A well identifiable trait of each pathogen which inhibits its growth. The method of identification is through colour.
* Suppression cannot completely cure a pathogen, however, its destructive potential may be severely limited by suppression.
*
* Suppressants may react to events the same way symptoms can - as suppressants are instantiated per pathogen, they may have their
* own internal state without breaking anything.
*
* Suppressants also play a large role in the synthesis of cure for all default microbodies - each suppressant indicates a
* list of reagents which may be used for cure synthesis. Curing therefore requires at least some analysis of the pathogen.
*/
/datum/suppressant
var/name = "Suppressant"
var/color = "transparent"
var/desc = "The pathogen is not suppressed by any external effects."
var/therapy = "unknown"
// A list of reagent IDs which may be used for cure synthesis with this suppressant.
var/list/cure_synthesis = list()
// Override this to define when your suppression method should act.
// Returns the new value for suppressed which is ONLY considered if suppressed is 0.
// Is not called if suppressed is -1. A secondary resistance may overpower a primary weakness.
proc/suppress_act(var/datum/pathogen/P)
return
proc/ongrab(var/mob/target as mob, var/datum/pathogen/P)
return
proc/onpunched(var/mob/origin as mob, zone, var/datum/pathogen/P)
proc/onpunch(var/mob/target as mob, zone, var/datum/pathogen/P )
proc/ondisarm(var/mob/target as mob, isPushDown, var/datum/pathogen/P)
proc/onshocked(var/datum/shockparam/param, var/datum/pathogen/P)
proc/onsay(message, var/datum/pathogen/P)
proc/onadd(var/datum/pathogen/P)
proc/onemote(var/mob/target, message, var/datum/pathogen/P)
// While doing pathogen research, the suppression method may define how the pathogen reacts to certain reagents.
// Returns null if the pathogen does not react to the reagent.
// Returns a string describing what happened if it does react to the reagent.
// NOTE: Conforming with the new chemistry system, R is now a reagent ID, not a reagent instance.
proc/react_to(var/R)
return ""
proc/may_react_to()
return ""
/datum/suppressant/heat
color = "blue"
name = "Heat"
desc = "The pathogen is suppressed by a high body temperature."
therapy = "thermal"
cure_synthesis = list("napalm", "infernite")
suppress_act(var/datum/pathogen/P)
if (P.infected.bodytemperature > 310 + P.suppression_threshold)
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
may_react_to()
return "A peculiar gland on the pathogen suggests it may be <b style='font-size:20px;color:red'>suppressed</b> by affecting its temperature."
react_to(var/R)
if (R == "napalm" || R == "infernite")
return "The pathogens are attemping to escape from the area affected by the [R]."
else if (R in cure_synthesis)
return "The pathogens are moving towards the area affected by the [R]"
else return null
/datum/suppressant/cold
color = "red"
name = "Cold"
desc = "The pathogen is suppressed by a low body temperature."
therapy = "thermal"
cure_synthesis = list("cryostylane", "cryoxadone")
suppress_act(var/datum/pathogen/P)
if (P.infected.bodytemperature < 300 - P.suppression_threshold)
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
may_react_to()
return "A peculiar gland on the pathogen suggests it may be <b style='font-size:20px;color:red'>suppressed</b> by affecting its temperature."
react_to(var/R)
if (R == "napalm" || R == "infernite")
return "The pathogens are moving towards the area affected by the [R]"
else if (R in cure_synthesis)
return "The pathogens are attemping to escape from the area affected by the [R]."
else return null
/datum/suppressant/sleeping
color = "green"
name = "Sedative"
desc = "The pathogen is suppressed by sleeping."
therapy = "sedative"
suppress_act(var/datum/pathogen/P)
if (P.infected.sleeping)
P.symptom_data["suppressant"]++
var/slept = P.symptom_data["suppressant"]
if (slept > P.suppression_threshold)
if (P.stage > 3 && prob(P.advance_speed * 4))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
P.symptom_data["suppressant"] = 0
return 1
else
P.symptom_data["suppressant"] = 0
return 0
cure_synthesis = list("morphine", "sonambutril")
onadd(var/datum/pathogen/P)
P.symptom_data["suppressant"] = 0
may_react_to()
return "Membrane patterns of the pathogen indicate it might be <b style='font-size:20px;color:red'>suppressed</b> by a reagent affecting neural activity."
react_to(var/R)
if (R in cure_synthesis)
return "The pathogens near the sedative appear to be in stasis."
else return null
/datum/suppressant/brutemeds
color = "black"
name = "Brute Medicine"
desc = "The pathogen is suppressed by brute medicine."
therapy = "medical"
suppress_act(var/datum/pathogen/P)
if (P.infected.reagents.has_reagent("stypic_powder", P.suppression_threshold) || P.infected.reagents.has_reagent("synthflesh", P.suppression_threshold))
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
cure_synthesis = list("stypic_powder", "synthflesh")
may_react_to()
return "The DNA repair processes of the pathogen indicate that it might be <b style='font-size:20px;color:red'>suppressed</b> by certain kinds of medicine."
react_to(var/R)
if (R in cure_synthesis)
return "The pathogens near the [R] appear to be weakened by the brute medicine's presence."
else return null
/datum/suppressant/burnmeds
color = "cyan"
name = "Burn Medicine"
desc = "The pathogen is suppressed by burn medicine."
therapy = "medical"
suppress_act(var/datum/pathogen/P)
if (P.infected.reagents.has_reagent("silver_sulfadiazine", P.suppression_threshold))
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
cure_synthesis = list("silver_sulfadiazine")
may_react_to()
return "The DNA repair processes of the pathogen indicate that it might be <b style='font-size:20px;color:red'>suppressed</b> by certain kinds of medicine."
react_to(var/R)
if (R in cure_synthesis)
return "The pathogens near the [R] appear to be weakened by the burn medicine's presence."
else return null
/datum/suppressant/muscle
color = "white"
name = "Muscle"
desc = "The pathogen is suppressed by disrupting muscle function."
therapy = "sedative"
cure_synthesis = list("haloperidol", "neurotoxin")
suppress_act(var/datum/pathogen/P)
if (P.infected.reagents.has_reagent("haloperidol", P.suppression_threshold) || P.infected.reagents.has_reagent("neurotoxin", P.suppression_threshold))
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
onshocked(var/datum/shockparam/param, var/datum/pathogen/P)
if (param.skipsupp)
return
if (P.stage > 3)
var/better = 0
if (param.amt > 50)
P.stage = 3
else if (param.amt > 30)
if (prob(P.advance_speed * 2))
P.stage = 3
else
P.stage--
else if (param.amt > 15 && prob(P.advance_speed * 2))
P.stage--
better = 1
if (param.amt > 30 || better)
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
if (P.suppressed == 0)
P.suppressed = 1
may_react_to()
return "Membrane patterns of the pathogen indicate it might be <b style='font-size:20px;color:red'>suppressed</b> by a reagent affecting neural activity."
react_to(var/R)
if (R == "haloperidol")
return "The pathogens near the [R] appear to move at a slower pace."
if (R == "neurotoxin")
return "The pathogens near the [R] appear to be confused."
else return null
/datum/suppressant/fat
color = "orange"
name = "Fat"
desc = "The pathogen is suppressed by fats."
cure_synthesis = list("bad_grease", "grease", "porktonium")
therapy = "gastronomical"
suppress_act(var/datum/pathogen/P)
if (P.infected.reagents.has_reagent("bad_grease", P.suppression_threshold) || P.infected.reagents.has_reagent("grease", P.suppression_threshold) || P.infected.reagents.has_reagent("porktonium", P.suppression_threshold))
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
may_react_to()
return "An observation of the metabolizing processes of the pathogen shows that it might be <b style='font-size:20px;color:red'>suppressed</b> by certain kinds of foodstuffs."
react_to(var/datum/reagent/R)
if (R in cure_synthesis)
return "The pathogens near the fatty substance appear to be significantly heavier and slower than their unaffected counterparts."
else return null
/datum/suppressant/chickensoup
color = "pink"
name = "Chicken Soup"
desc = "The pathogen is suppressed by a nice bowl of old fashioned chicken soup."
therapy = "gastronomical"
cure_synthesis = list("chickensoup")
suppress_act(var/datum/pathogen/P)
if (P.infected.reagents.has_reagent("chickensoup", P.suppression_threshold))
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
may_react_to()
return "An observation of the metabolizing processes of the pathogen shows that it might be <b style='font-size:20px;color:red'>suppressed</b> by certain kinds of foodstuffs."
react_to(var/datum/reagent/R)
if (R == "chickensoup")
return "The pathogens near the chicken soup appear to be having a great meal and are ignorant of their surroundings."
/datum/suppressant/radiation
color = "viridian"
name = "Radiation"
desc = "The pathogen is suppressed by radiation."
therapy = "radioactive"
cure_synthesis = list("radium", "polonium", "uranium")
suppress_act(var/datum/pathogen/P)
if (P.infected.reagents.has_reagent("radium", P.suppression_threshold * 2) || P.infected.reagents.has_reagent("polonium", P.suppression_threshold) || P.infected.reagents.has_reagent("uranium", P.suppression_threshold * 10) || P.infected.get_radiation() > P.suppression_threshold * 0.1)
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
may_react_to()
return "The chemical structure of the pathogen's membrane indicates it may be <b style='font-size:20px;color:red'>suppressed</b> by either gamma rays or mutagenic substances."
react_to(var/datum/reagent/R)
if (R in cure_synthesis)
return "The radiation emitted by the [R] is severely damaging the inner elements of the pathogen."
/datum/suppressant/mutagen
color = "olive drab"
name = "Mutagen"
desc = "The pathogen is suppressed by mutagenic substances."
therapy = "radioactive"
cure_synthesis = list("mutagen", "dna_mutagen")
suppress_act(var/datum/pathogen/P)
if (P.infected.reagents.has_reagent("mutagen", P.suppression_threshold) || P.infected.reagents.has_reagent("dna_mutagen", P.suppression_threshold))
if (P.stage > 3 && prob(P.advance_speed * 2))
P.infected.show_message("<span style=\"color:blue\">You feel better.</span>")
P.stage--
return 1
return 0
may_react_to()
return "The chemical structure of the pathogen's membrane indicates it may be <b style='font-size:20px;color:red'>suppressed</b> by either gamma rays or mutagenic substances."
react_to(var/datum/reagent/R)
if (R in cure_synthesis)
return "The mutagenic substance is severely damaging the inner elements of the pathogen."
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,457 @@
// A blood slide, used by the centrifuge.
/obj/item/bloodslide
name = "Blood Slide"
icon = 'icons/obj/pathology.dmi'
icon_state = "slide0"
desc = "An item used by scientists and serial killers operating in the Miami area to store blood samples."
var/datum/reagent/blood/blood = null
flags = TABLEPASS | CONDUCT | FPRINT | NOSPLASH
New()
..()
var/datum/reagents/R = new /datum/reagents(5)
src.reagents = R
attackby(obj/item/I as obj, mob/user as mob)
return
on_reagent_change()
reagents.maximum_volume = reagents.total_volume // This should make the blood slide... permanent.
if (reagents.has_reagent("blood") || reagents.has_reagent("bloodc"))
icon_state = "slide1"
desc = "The blood slide contains a drop of blood."
if (reagents.has_reagent("blood"))
blood = reagents.get_reagent("blood")
else if (reagents.has_reagent("bloodc"))
blood = reagents.get_reagent("bloodc")
if (blood == null)
boutput(usr, "<span style=\"color:red\">Blood slides are not working. This is an error message, please page 1-800-555-MARQUESAS.</span>")
return
else
desc = "This blood slide is contaminated and useless."
/obj/item/reagent_containers/glass/petridish
name = "Petri Dish"
icon = 'icons/obj/pathology.dmi'
icon_state = "petri0"
desc = "A dish tailored hold pathogen cultures."
var/stage = 0
var/dirty = 0
var/dirty_reason = ""
var/datum/reagent/medium = null
var/list/nutrition = list()
var/ctime = 8
var/starving = 5
rc_flags = 0
New()
var/datum/reagents/R = new/datum/reagents(40)
reagents = R
R.my_atom = src
// Integration notes: stable mutagen ID.
for (var/nutrient in pathogen_controller.nutrients)
nutrition += nutrient
nutrition[nutrient] = 0
examine()
if (src.dirty || src.dirty_reason)
..()
boutput(usr, "<span style=\"color:red\">The petri dish appears to be incapable of growing any pathogen, and must be cleaned.</span>")
return
boutput(usr, "This is [src]")
if (src.reagents.reagent_list["pathogen"])
var/datum/reagent/blood/pathogen/P = src.reagents.reagent_list["pathogen"]
boutput(usr, "<span style=\"color:blue\">It contains [P.volume] units of harvestable pathogen.</span>")
if (src.medium)
boutput(usr, "<span style=\"color:blue\">The petri dish is coated with [src.medium.name].</span>")
boutput(usr, "Nutrients in the dish:")
var/count = 0
for (var/N in nutrition)
if (nutrition[N])
if (nutrition[N] != 1)
boutput(usr, "<span style=\"color:blue\">[nutrition[N]] units of [N]</span>")
else
boutput(usr, "<span style=\"color:blue\">[nutrition[N]] unit of [N]</span>")
count++
if (!count)
boutput(usr, "<span style=\"color:blue\">None.</span>")
afterattack(obj/target, mob/user , flag)
if (istype(target, /obj/machinery/microscope))
return
var/amount = src.reagents.total_volume
..(target, user, flag)
if (amount && !src.reagents.total_volume)
processing_items.Remove(src)
for (var/N in nutrition)
nutrition[N] = 0
reagents.clear_reagents()
if (src.medium)
del src.medium
src.medium = null
ctime = 8
starving = 5
process()
if (dirty && (src in processing_items))
processing_items -= src
ctime--
if (!src.reagents.reagent_list["pathogen"] )
set_dirty("All viable pathogen has been harvested from the petri dish.")
else
var/datum/reagent/blood/pathogen/P = src.reagents.reagent_list["pathogen"]
var/uid = P.pathogens[1]
var/datum/pathogen/PT = P.pathogens[uid]
if (medium.id != PT.body_type.growth_medium)
set_dirty("The pathogen is unable to cultivate on the growth medium.")
if (ctime <= 0)
ctime = 8
var/datum/reagent/blood/pathogen/P = src.reagents.reagent_list["pathogen"]
var/uid = P.pathogens[1]
var/datum/pathogen/PT = P.pathogens[uid]
// Integration notes etc. stablemutagen reagent ID
var/starvation = 0
for (var/N in PT.body_type.nutrients)
if (src.nutrition[N] < PT.body_type.amount * P.volume)
starvation = 1
src.nutrition[N] = 0
else
starving = 5
src.nutrition[N] -= PT.body_type.amount * P.volume
if (starvation && starving > 0)
starving--
if (starving == 5)
if (stage < 4)
stage++
update_dish_icon()
else
P.volume = min(P.volume + 5, 30)
src.reagents.update_total()
else if (starving == 0)
if (stage > 1)
stage--
update_dish_icon()
else
P.volume = max(P.volume - 5, 0)
if (P.volume == 0)
src.reagents.del_reagent("pathogen")
src.reagents.update_total()
set_dirty("The pathogen in the petri dish starved to death.")
on_reagent_change()
if (reagents.total_volume < 0.5)
return
if (dirty)
return
// Cultivation is already in progress in this dish. Depending on what reagent(s) were introduced, the process
// halts, or reverses entirely.
if (stage > 0)
// At this stage, only the pathogen should be in the reagents list.
for (var/R in src.reagents.reagent_list)
var/datum/reagent/RE = src.reagents.reagent_list[R]
// Sanity check the pathogen. Only a single type of pathogen can be cultivated in a petri dish.
// Multiple types of reagents will immediately make the dish dirty.
if (R == "pathogen")
var/datum/reagent/blood/pathogen/P = src.reagents.reagent_list["pathogen"]
if (P.pathogens.len > 1)
// Too many pathogens. This culture is dead.
set_dirty("The presence of multiple pathogens makes them unable to grow.")
else if (R in pathogen_controller.media)
if (R == medium.id)
if (RE.pathogen_nutrition)
for (var/N in RE.pathogen_nutrition)
if (N in nutrition)
nutrition[N] += RE.volume / RE.pathogen_nutrition.len
else
nutrition[N] = RE.volume / RE.pathogen_nutrition.len
src.reagents.reagent_list -= R
src.reagents.update_total()
else
// Malnutrition, a medium that normally rejects the grown pathogen type has been introduced.
set_dirty("A growth medium incompatible with the pathogen is killing the culture.")
else if (RE.pathogen_nutrition)
for (var/N in RE.pathogen_nutrition)
if (N in nutrition)
nutrition[N] += RE.volume / RE.pathogen_nutrition.len
else
nutrition[N] = RE.volume / RE.pathogen_nutrition.len
src.reagents.reagent_list -= R
src.reagents.update_total()
else
// Foreign chemical, murdering the culture.
set_dirty("The pathogen culture is unable to cultivate in the environment due to foreign chemicals.")
else
if (src.reagents.reagent_list.len == 1 && src.reagents.reagent_list[1] == "pathogen")
return
for (var/R in src.reagents.reagent_list)
var/datum/reagent/RE = src.reagents.reagent_list[R]
if (R == "pathogen")
if (src.medium)
if (!(src in processing_items))
processing_items.Add(src)
else if (R in pathogen_controller.media)
if (src.medium && src.medium.id != R)
set_dirty("There are multiple, incompatible growth media in the petri dish.")
else if (!src.medium)
src.medium = src.reagents.reagent_list[R]
if (RE.pathogen_nutrition)
for (var/N in RE.pathogen_nutrition)
if (N in nutrition)
nutrition[N] += RE.volume / RE.pathogen_nutrition.len
else
nutrition[N] = RE.volume / RE.pathogen_nutrition.len
src.reagents.reagent_list -= R
src.reagents.update_total()
if (src.reagents.has_reagent("pathogen"))
if (!(src in processing_items))
processing_items.Add(src)
else
if (RE.pathogen_nutrition)
for (var/N in RE.pathogen_nutrition)
if (N in nutrition)
nutrition[N] += RE.volume / RE.pathogen_nutrition.len
else
nutrition[N] = RE.volume / RE.pathogen_nutrition.len
src.reagents.reagent_list -= R
src.reagents.update_total()
else if (RE.pathogen_nutrition)
for (var/N in RE.pathogen_nutrition)
if (N in nutrition)
nutrition[N] += RE.volume / RE.pathogen_nutrition.len
else
nutrition[N] = RE.volume / RE.pathogen_nutrition.len
src.reagents.reagent_list -= R
src.reagents.update_total()
else
set_dirty("Foreign chemicals in the petri dish.")
proc/update_dish_icon()
if (stage == 0)
if (src.reagents.total_volume > 0)
icon_state = "petri1"
else
icon_state = "petri0"
else
icon_state = "petri[stage]"
proc/set_dirty(var/reason)
processing_items.Remove(src)
dirty = 1
stage = 0
ctime = 8
starving = 5
dirty_reason = reason
update_dish_icon()
flags = TABLEPASS | CONDUCT | FPRINT | OPENCONTAINER
/obj/item/reagent_containers/glass/vial
name = "vial"
desc = "A vial. Can hold up to 5 units."
icon = 'icons/obj/pathology.dmi'
icon_state = "vial0"
item_state = "vial"
rc_flags = RC_FULLNESS | RC_VISIBLE | RC_SPECTRO
on_reagent_change()
..()
if (reagents.total_volume < 0.05)
icon_state = "vial0"
else
icon_state = "vial1"
New()
var/datum/reagents/R = new /datum/reagents(5)
R.my_atom = src
src.reagents = R
..()
/obj/item/reagent_containers/glass/vial/prepared
name = "Totally Safe(tm) pathogen sample"
desc = "A vial. Can hold up to 5 units."
icon = 'icons/obj/pathology.dmi'
icon_state = "vial0"
item_state = "vial"
New()
..()
spawn(20)
var/datum/pathogen/P = unpool(/datum/pathogen)
P.create_weak()
var/datum/reagents/RE = src.reagents
RE.add_reagent("pathogen", 5)
var/datum/reagent/blood/pathogen/R = RE.get_reagent("pathogen")
R.pathogens[P.pathogen_uid] = P
/obj/item/reagent_containers/glass/beaker/parasiticmedium
name = "Beaker of Parasitic Medium"
desc = "A mix of blood and flesh; fertile ground for some microbes."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("parasiticmedium", 50)
/obj/item/reagent_containers/glass/beaker/egg
name = "Beaker of Eggs"
desc = "Eggs; fertile ground for some microbes."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("egg", 50)
/obj/item/reagent_containers/glass/beaker/stablemut
name = "Beaker of Stable Mutagen"
desc = "Stable Mutagen; fertile ground for some microbes."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("dna_mutagen", 50)
/obj/item/reagent_containers/glass/beaker/bacterial
name = "Beaker of Bacterial Growth Medium"
desc = "Bacterial Growth Medium; fertile ground for some microbes."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("bacterialmedium", 50)
/obj/item/reagent_containers/glass/beaker/fungal
name = "Beaker of Fungal Growth Medium"
desc = "Fungal Growth Medium; fertile ground for some microbes."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("fungalmedium", 50)
/obj/item/reagent_containers/glass/beaker/antiviral
name = "Beaker of Antiviral Agent"
desc = "A beaker of a weak anti-viral agent."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("antiviral", 50)
/obj/item/reagent_containers/glass/beaker/biocides
name = "Beaker of Biocides"
desc = "A beaker of biocides. The label says 'do not feed to worms or mushrooms'. Curious."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("biocide", 50)
/obj/item/reagent_containers/glass/beaker/spaceacillin
name = "Beaker of Spaceacillin"
desc = "It's penicillin in space."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("spaceacillin", 50)
/obj/item/reagent_containers/glass/beaker/inhibitor
name = "Beaker of Inhibition Agent"
desc = "It's green, that's for sure."
icon_state = "beaker1"
New()
..()
src.reagents.add_reagent("inhibitor", 50)
/obj/item/serum_injector
name = "Pathological Injector"
desc = "A specialized injector for injecting patients with serums and vaccines."
icon = 'icons/obj/pathology.dmi'
icon_state = "serum"
var/datum/pathogen/pathogen = null
var/used = 1
var/is_cure = 0
var/is_vaccine = 0
New(Location, var/datum/pathogen/P, cure, vaccine)
if (P && istype(P))
src.name = "[src.name] (strain [P.name_base])"
icon_state = "serum"
src.pathogen = P
src.is_cure = cure
src.is_vaccine = vaccine
used = 0
else
src.name = "empty [src.name]"
icon_state = "serum0"
used = 1
..()
attack_self()
return
proc/inject(var/mob/living/carbon/human/target, var/mob/user)
if (is_cure)
if (!is_vaccine)
logTheThing("pathology", user, target, "injects %target% with the cure for [src.pathogen.name].")
target.remission(src.pathogen)
else
logTheThing("pathology", user, target, "injects %target% with a vaccine for [src.pathogen.name].")
target.immunity(src.pathogen)
else
if (target.infected(src.pathogen))
logTheThing("pathology", user, target, "injects %target% with pathogen [src.pathogen.name] from a bad cure injector and infects them.")
else
logTheThing("pathology", user, target, "injects %target% with pathogen [src.pathogen.name] from a bad cure injector but they were unaffected.")
src.pathogen = null
used = 1
attack(mob/M as mob, mob/user as mob, def_zone)
if (used)
boutput(user, "<span style=\"color:red\">The [src.name] is empty.</span>")
return
if (istype(M, /mob/living/carbon/human))
if (M != user)
for (var/mob/V in viewers(M))
boutput(V, "<span style=\"color:red\"><b>[user] is trying to inject [M] with the [src.name]!</b></span>")
var/ML = M.loc
var/UL = user.loc
spawn (30)
if (used)
return
if (user.equipped() == src && M.loc == ML && user.loc == UL)
used = 1
for (var/mob/V in viewers(M))
boutput(V, "<span style=\"color:red\"><b>[user] is injects [M] with the [src.name]!</b></span>")
src.name = "empty [src.name]"
icon_state = "serum0"
inject(M, user)
else
used = 1
for (var/mob/V in viewers(M))
boutput(V, "<span style=\"color:red\"><b>[user] injects [M] with the [src.name]!</b></span>")
icon_state = "serum0"
src.name = "empty [src.name]"
inject(user, user)
/obj/item/reagent_containers/glass/beaker
afterattack(obj/target, mob/user , flag)
if (istype(target, /obj/machinery/synthomatic))
return
..()