mirror of
https://github.com/goonstation/goonstation-2020.git
synced 2026-07-16 17:42:19 +01:00
036a29b765
includes a lot of small things + fixes. big ones are Simple Lights, New Grab stuff, Disorient Eye/Ear protection armor values, access reprogrammer and deconstruction device also added flabo to the list of contributors, we missed her on the first go! check changelog for full list, i merged that too
581 lines
18 KiB
Plaintext
581 lines
18 KiB
Plaintext
/datum/ailment
|
|
// all the vars that don't change/are defaults go in here - these will be in a central list for referencing
|
|
var/name = "ailment"
|
|
var/scantype = "Ailment" // what type this shows up as on scanners
|
|
var/cure = "Unknown" // how do we get rid of it
|
|
var/spread = "Unknown" // how does it spread
|
|
var/info = null // info related to the thing to show on health scanners
|
|
var/print_name = null // printed name for health scanners
|
|
var/max_stages = 0 // how many stages the disease has overall
|
|
var/stage_prob = 5 // % chance per tick it'll advance a stage
|
|
var/list/affected_species = list() // what kind of mobs does this disease affect
|
|
var/tmp/DNA = null // no fuckin idea
|
|
var/list/reagentcure = list() // which reagents cure this disease...
|
|
// these can be: a list of reagent strings - ex: list("reag1", "reag2") - in which case recureprob is used for them
|
|
// or a list of strings with numbers associated with them - ex: list("reag1"=5, "reag2"=10) - which will use the associated number to determine % chance to cure
|
|
// or a list of strings with lists associated with them - ex: list("reag1"=list(1,10), "reag2"=list(1,1)) - which will use both numbers to determine chance to cure, in case 1% chance isn't low enough for you!
|
|
// or any combination of the above!
|
|
var/recureprob = 8 // ...and how likely % they are per tick to do so (unless a number or list is associated with the reagent as above)
|
|
var/temperature_cure = 406 // bodytemperature >= this will purge the infection
|
|
var/detectability = 0 // detectors must >= this to pick up the disease
|
|
var/resistance_prob = 0 // how likely this disease is to grant immunity once cured
|
|
var/max_stacks = 1 // how many times at once you can have this ailment
|
|
|
|
//MALADY STUFF ONLY
|
|
var/min_advance_ticks = 0//delay the evolution of stuff like shock if it rolls badly for us
|
|
var/tickcount = 0
|
|
//IM SORRY
|
|
|
|
proc/stage_act(var/mob/living/affected_mob,var/datum/ailment_data/D)
|
|
if (!affected_mob || !D)
|
|
return 1
|
|
return 0
|
|
|
|
proc/on_remove(var/mob/living/affected_mob,var/datum/ailment_data/D)
|
|
disposed = 1 // set to avoid bizarre interactions (such as surgerizing out a single disease multiple times)
|
|
return
|
|
|
|
proc/on_infection(var/mob/living/affected_mob,var/datum/ailment_data/D)
|
|
return
|
|
|
|
// This is still subject to serious change. For now it's mostly a mockup.
|
|
// Determines things that may happen during a surgery for different ailments
|
|
// requiring a surgeon's intervention. Currently used for the parasites.
|
|
// Returns a true value if the surgery was successful.
|
|
proc/surgery(var/mob/living/surgeon, var/mob/living/affected_mob, var/datum/ailment_data/D)
|
|
return 1
|
|
|
|
/datum/ailment/parasite
|
|
name = "Parasite"
|
|
scantype = "Parasite"
|
|
cure = "Surgery"
|
|
|
|
/datum/ailment/disability
|
|
name = "Disability"
|
|
scantype = "Disability"
|
|
cure = "Unknown"
|
|
|
|
/datum/ailment/disease
|
|
name = "Disease"
|
|
scantype = "Virus"
|
|
cure = "Unknown"
|
|
var/virulence = 100
|
|
var/develop_resist = 0
|
|
var/associated_reagent = null // associated reagent, duh
|
|
|
|
var/list/disease_data = list() // A list of things for people to research about the disease to make it
|
|
var/list/strain_data = list() // Used for Rhinovirus
|
|
|
|
// IMPLEMENT PROPER CURE PROC
|
|
|
|
/datum/ailment_data
|
|
// these will be the local thing on mobs that does all the effecting, and they store unique vars so we can still
|
|
// have unique strains of disease and whatnot
|
|
/////////////////////////////////////////////////////////////////////////
|
|
var/datum/ailment/master = null // we reference back to the ailment itself to get effects and static vars
|
|
var/tmp/mob/living/affected_mob = null // the poor sod suffering from the disease
|
|
var/name = null // an override - uses the base disease name if null - if not, it uses this
|
|
var/scantype = null // same as above but for scantype
|
|
var/detectability = 0 // scans must >= this to detect the disease
|
|
var/cure = "Unknown" // how do we get rid of it
|
|
var/spread = "Unknown" // how does this disease transmit itself around?
|
|
var/info = null // info related to the thing to show on health scanners
|
|
var/stage = 1 // what stage the disease is currently at
|
|
var/state = "Active" // what is this disease currently doing
|
|
var/stage_prob = 5 // how likely is this disease to advance to the next stage
|
|
var/list/reagentcure = list() // list of reagents that can cure this disease (see above for details on associations in this list)
|
|
var/recureprob = 8 // probability per tick that the reagent will cure the disease
|
|
var/temperature_cure = 406 // this temp or higher will cure the disease
|
|
var/resistance_prob = 0 // how likely this disease is to grant immunity once cured
|
|
|
|
disposing()
|
|
if (affected_mob)
|
|
if (affected_mob.ailments)
|
|
affected_mob.ailments -= src
|
|
affected_mob = null
|
|
|
|
master = null
|
|
reagentcure = null
|
|
|
|
..()
|
|
|
|
proc/stage_act()
|
|
if (!affected_mob || disposed)
|
|
return 1
|
|
|
|
if (!istype(master,/datum/ailment/))
|
|
affected_mob.cure_disease(src)
|
|
return 1
|
|
|
|
if (stage > master.max_stages)
|
|
stage = master.max_stages
|
|
|
|
if (prob(stage_prob) && stage < master.max_stages)
|
|
stage++
|
|
|
|
master.stage_act(affected_mob,src)
|
|
|
|
return 0
|
|
|
|
proc/scan_info()
|
|
var/text = "<span style='color:red'><b>"
|
|
if (istype(src.master,/datum/ailment/disease) || istype(src.master,/datum/ailment/malady))
|
|
text += "[src.state] "
|
|
text += "[src.scantype ? src.scantype : src.master.scantype]:"
|
|
|
|
text += " [src.name ? src.name : src.master.name]</b> <small>(Stage [src.stage]/[src.master.max_stages])<br>"
|
|
if (src.info)
|
|
text += "Info: [src.info]<br>"
|
|
if (istype(src.master,/datum/ailment/disease) && src.spread)
|
|
text += "Spread: [src.spread]<br>"
|
|
if (src.cure == "Incurable")
|
|
text += "Infection is incurable. Suggest quarantine measures."
|
|
else if (src.cure == "Unknown")
|
|
text += "No suggested remedies."
|
|
else
|
|
text += "Suggested Remedy: [src.cure]"
|
|
text += "</small></span>"
|
|
return text
|
|
|
|
proc/on_infection()
|
|
master.on_infection(affected_mob, src)
|
|
return
|
|
|
|
proc/surgery(var/mob/living/surgeon, var/mob/living/affected_mob)
|
|
if (master && istype(master, /datum/ailment))
|
|
return master.surgery(surgeon, affected_mob, src)
|
|
return 1
|
|
|
|
/datum/ailment_data/disease
|
|
var/virulence = 100 // how likely is this disease to spread
|
|
var/develop_resist = 0 // can you develop a resistance to this?
|
|
var/cycles = 0 // does this disease have a cyclical nature? if so, how many cycles have elapsed?
|
|
|
|
stage_act()
|
|
if (!affected_mob || disposed)
|
|
return 1
|
|
|
|
if (!istype(master,/datum/ailment/))
|
|
affected_mob.ailments -= src
|
|
qdel(src)
|
|
return 1
|
|
|
|
if (stage > master.max_stages)
|
|
stage = master.max_stages
|
|
|
|
if (stage < 1) // if it's less than one just get rid of it, goddamn
|
|
affected_mob.cure_disease(src)
|
|
return 1
|
|
|
|
var/advance_prob = stage_prob
|
|
if (state == "Acute")
|
|
advance_prob *= 2
|
|
advance_prob = max(0,min(advance_prob,100))
|
|
|
|
if (prob(advance_prob))
|
|
if (state == "Remissive")
|
|
stage--
|
|
if (stage < 1)
|
|
affected_mob.cure_disease(src)
|
|
return 1
|
|
else if (stage < master.max_stages)
|
|
stage++
|
|
|
|
// Common cures
|
|
if (cure != "Incurable")
|
|
if (cure == "Sleep" && affected_mob.sleeping && prob(33))
|
|
state = "Remissive"
|
|
return 1
|
|
|
|
else if (cure == "Self-Curing" && prob(5))
|
|
state = "Remissive"
|
|
return 1
|
|
|
|
else if (cure == "Beatings" && affected_mob.get_brute_damage() >= 40)
|
|
state = "Remissive"
|
|
return 1
|
|
|
|
else if (cure == "Burnings" && (affected_mob.get_burn_damage() >= 40 || affected_mob.getStatusDuration("burning")))
|
|
state = "Remissive"
|
|
return 1
|
|
|
|
else if (affected_mob.bodytemperature >= temperature_cure)
|
|
state = "Remissive"
|
|
return 1
|
|
|
|
if (reagentcure.len && affected_mob.reagents)
|
|
for (var/current_id in affected_mob.reagents.reagent_list)
|
|
if (reagentcure.Find(current_id))
|
|
var/we_are_cured = 0
|
|
var/reagcure_prob = reagentcure[current_id]
|
|
if (isnum(reagcure_prob))
|
|
if (prob(reagcure_prob))
|
|
we_are_cured = 1
|
|
else if (islist(reagcure_prob)) // we want to roll more than one prob() in order to succeed, aka we want a very low chance
|
|
var/list/cureprobs = reagcure_prob
|
|
var/success = 1
|
|
for (var/thing in cureprobs)
|
|
if (!isnum(thing))
|
|
continue
|
|
if (!prob(thing))
|
|
success = 0
|
|
if (success)
|
|
we_are_cured = 1
|
|
else if (prob(recureprob))
|
|
we_are_cured = 1
|
|
if (we_are_cured)
|
|
state = "Remissive"
|
|
return 1
|
|
|
|
if (state == "Asymptomatic" || state == "Dormant")
|
|
return 1
|
|
|
|
SPAWN_DBG(rand(1,5))
|
|
// vary it up a bit so the processing doesnt look quite as transparent
|
|
if (master)
|
|
master.stage_act(affected_mob,src)
|
|
|
|
return 0
|
|
|
|
/datum/ailment_data/addiction
|
|
var/associated_reagent = null
|
|
var/last_reagent_dose = 0
|
|
var/withdrawal_duration = 4800
|
|
var/max_severity = "HIGH"
|
|
|
|
New()
|
|
..()
|
|
master = get_disease_from_path(/datum/ailment/addiction)
|
|
|
|
/datum/ailment_data/parasite
|
|
var/was_setup = 0
|
|
var/surgery_prob = 50
|
|
|
|
var/source = null // for headspiders
|
|
var/stealth_asymptomatic = 0
|
|
proc/setup()
|
|
src.stage_prob = master.stage_prob
|
|
src.cure = master.cure
|
|
src.was_setup = 1
|
|
|
|
stage_act()
|
|
if (!affected_mob)
|
|
return
|
|
|
|
if (!istype(master, /datum/ailment/))
|
|
affected_mob.cure_disease(src)
|
|
return
|
|
|
|
if (!ismind(source))
|
|
affected_mob.cure_disease(src)
|
|
return
|
|
|
|
if (!was_setup)
|
|
src.setup()
|
|
|
|
if (stage > master.max_stages)
|
|
stage = master.max_stages
|
|
|
|
if (prob(stage_prob) && stage < master.max_stages)
|
|
stage++
|
|
|
|
|
|
if(!stealth_asymptomatic)
|
|
master.stage_act(affected_mob,src,source)
|
|
|
|
return
|
|
|
|
/mob/living/proc/disease_resistance_check(var/ailment_path, var/ailment_name)
|
|
if (!src)
|
|
return 0
|
|
|
|
var/resist_prob = 0
|
|
|
|
if (ishuman(src))
|
|
var/mob/living/carbon/human/H = src
|
|
resist_prob = H.get_disease_protection(ailment_path, ailment_name)
|
|
else
|
|
for(var/atom in src.get_equipped_items())
|
|
var/obj/item/C = atom
|
|
resist_prob += C.getProperty("viralprot")
|
|
|
|
if (ispath(ailment_path) || istext(ailment_name))
|
|
var/datum/ailment/A = null
|
|
if (ailment_name)
|
|
A = get_disease_from_name(ailment_name)
|
|
else
|
|
A = get_disease_from_path(ailment_path)
|
|
|
|
if (!istype(A,/datum/ailment/))
|
|
return 0
|
|
|
|
if (src.resistances.Find(A.type))
|
|
return 0
|
|
|
|
if (A.affected_species.len)
|
|
var/mob_type = null
|
|
if (ismonkey(src))
|
|
mob_type = "Monkey"
|
|
else if (ishuman(src))
|
|
var/mob/living/carbon/human/H = src
|
|
if (H.mutantrace && !H.mutantrace.human_compatible)
|
|
mob_type = capitalize(H.mutantrace.name)
|
|
else
|
|
mob_type = "Human"
|
|
if (!A.affected_species.Find(mob_type))
|
|
return 0
|
|
|
|
if (isdead(src) && !istype(A,/datum/ailment/parasite))
|
|
return 0
|
|
|
|
if (istype(A,/datum/ailment/disease/))
|
|
var/datum/ailment/disease/D = A
|
|
resist_prob -= D.virulence
|
|
|
|
if (prob(resist_prob))
|
|
return 0
|
|
else
|
|
return 1 // you caught the virus! do you want to give the captured virus a nickname? virus has been recorded in lurgydex
|
|
|
|
/mob/living/proc/contract_disease(var/ailment_path, var/ailment_name, var/datum/ailment_data/disease/strain, bypass_resistance = 0)
|
|
if (!src)
|
|
return null
|
|
if (!ailment_path && !ailment_name && !(istype(strain,/datum/ailment_data/disease) || istype(strain,/datum/ailment_data/malady))) // maladies use strain to transfer specific instances of their selves via organ transplant/etc
|
|
return null
|
|
|
|
var/datum/ailment/A = null
|
|
if (strain && istype(strain.master,/datum/ailment/))
|
|
A = strain.master
|
|
else if (ailment_name)
|
|
A = get_disease_from_name(ailment_name)
|
|
else
|
|
A = get_disease_from_path(ailment_path)
|
|
|
|
if (!istype(A,/datum/ailment/))
|
|
// can't find shit, captain!
|
|
return null
|
|
|
|
var/count = 0
|
|
for (var/datum/ailment_data/D in src.ailments)
|
|
if (D.master == A)
|
|
count++
|
|
|
|
if (count >= A.max_stacks)
|
|
return null
|
|
|
|
if (ischangeling(src) || isvampire(src) || src.nodamage)
|
|
//Vampires and changelings are immune to disease, as are the godmoded.
|
|
//This is here rather than in the resistance check proc because otherwise certain things could bypass the
|
|
//hard immunity these folks are supposed to have
|
|
return null
|
|
|
|
if (!bypass_resistance && !src.disease_resistance_check(null,A.name))
|
|
return null
|
|
|
|
if (istype(A, /datum/ailment/disease/))
|
|
var/datum/ailment/disease/D = A
|
|
var/datum/ailment_data/disease/AD = new /datum/ailment_data/disease
|
|
if (istype(strain,/datum/ailment_data/disease/))
|
|
if (strain.name)
|
|
AD.name = strain.name
|
|
else
|
|
AD.name = D.name
|
|
AD.stage_prob = strain.stage_prob
|
|
AD.reagentcure = strain.reagentcure
|
|
AD.recureprob = strain.recureprob
|
|
AD.virulence = strain.virulence
|
|
AD.detectability = strain.detectability
|
|
AD.develop_resist = strain.develop_resist
|
|
AD.cure = strain.cure
|
|
AD.info = strain.info
|
|
AD.resistance_prob = strain.resistance_prob
|
|
AD.temperature_cure = strain.temperature_cure
|
|
else
|
|
AD.name = D.name
|
|
AD.stage_prob = D.stage_prob
|
|
AD.reagentcure = D.reagentcure
|
|
AD.recureprob = D.recureprob
|
|
AD.virulence = D.virulence
|
|
AD.detectability = D.detectability
|
|
AD.develop_resist = D.develop_resist
|
|
AD.cure = D.cure
|
|
AD.info = D.info
|
|
AD.resistance_prob = D.resistance_prob
|
|
AD.temperature_cure = D.temperature_cure
|
|
|
|
src.ailments += AD
|
|
AD.master = A
|
|
AD.affected_mob = src
|
|
AD.on_infection()
|
|
|
|
if (prob(5))
|
|
AD.state = "Asymptomatic"
|
|
// carrier - will spread it but won't suffer from it
|
|
return AD
|
|
|
|
else if (istype(A, /datum/ailment/malady))
|
|
var/datum/ailment/malady/M = A
|
|
var/datum/ailment_data/malady/AD = new /datum/ailment_data/malady
|
|
if (istype(strain,/datum/ailment_data/malady))
|
|
if (strain.name)
|
|
AD.name = strain.name
|
|
else
|
|
AD.name = M.name
|
|
AD.stage_prob = strain.stage_prob
|
|
AD.reagentcure = strain.reagentcure
|
|
AD.recureprob = strain.recureprob
|
|
AD.detectability = strain.detectability
|
|
AD.cure = strain.cure
|
|
AD.spread = strain.spread
|
|
AD.info = strain.info
|
|
AD.resistance_prob = strain.resistance_prob
|
|
AD.temperature_cure = strain.temperature_cure
|
|
else
|
|
AD.name = M.name
|
|
AD.stage_prob = M.stage_prob
|
|
AD.reagentcure = M.reagentcure
|
|
AD.recureprob = M.recureprob
|
|
AD.detectability = M.detectability
|
|
AD.cure = M.cure
|
|
AD.spread = M.spread
|
|
AD.info = M.info
|
|
AD.resistance_prob = M.resistance_prob
|
|
AD.temperature_cure = M.temperature_cure
|
|
src.ailments += AD
|
|
AD.master = A
|
|
AD.affected_mob = src
|
|
AD.on_infection()
|
|
return AD
|
|
|
|
else
|
|
var/datum/ailment_data/AD = new /datum/ailment_data
|
|
AD.name = A.name
|
|
AD.stage_prob = A.stage_prob
|
|
AD.cure = A.cure
|
|
AD.reagentcure = A.reagentcure
|
|
AD.recureprob = A.recureprob
|
|
AD.master = A
|
|
|
|
AD.master = A
|
|
AD.affected_mob = src
|
|
src.ailments += AD
|
|
|
|
return AD
|
|
|
|
/mob/living/proc/viral_transmission(var/mob/living/target, var/spread_type, var/two_way = 0)
|
|
if (!src || !target || !istext(spread_type))
|
|
return
|
|
|
|
if (!src.ailments || !src.ailments.len)
|
|
return
|
|
|
|
for (var/datum/ailment_data/disease/AD in src.ailments)
|
|
if (AD.spread == spread_type)
|
|
target.contract_disease(null,null,AD,0)
|
|
|
|
if (two_way)
|
|
for (var/datum/ailment_data/disease/AD in target.ailments)
|
|
if (AD.spread == spread_type)
|
|
src.contract_disease(null,null,AD,0)
|
|
|
|
return
|
|
|
|
/mob/living/proc/cure_disease(var/datum/ailment_data/AD)
|
|
if (!istype(AD) || !AD.master)
|
|
return 0
|
|
|
|
if (prob(AD.resistance_prob))
|
|
src.resistances += AD.master.type
|
|
if (src.ailments) //ZeWaka: Fix for null.ailments
|
|
src.ailments -= AD
|
|
AD.master.on_remove(src,AD)
|
|
qdel(AD)
|
|
return 1
|
|
|
|
/mob/living/proc/cure_disease_by_path(var/ailment_path)
|
|
for (var/datum/ailment_data/AD in src.ailments)
|
|
if (!AD.master)
|
|
continue
|
|
if (AD.master.type == ailment_path)
|
|
if (prob(AD.resistance_prob))
|
|
src.resistances += AD.master.type
|
|
src.ailments -= AD
|
|
AD.master.on_remove(src,AD)
|
|
qdel(AD)
|
|
return 1
|
|
return 0
|
|
|
|
/mob/living/proc/find_ailment_by_type(var/ailment_path)
|
|
if (!ispath(ailment_path))
|
|
return null
|
|
|
|
for (var/datum/ailment_data/AD in src.ailments)
|
|
if (AD.master && AD.master.type == ailment_path)
|
|
return AD
|
|
|
|
return null
|
|
|
|
/mob/living/proc/find_ailment_by_name(var/ailment_name,var/base_ailments_only = 0)
|
|
if (!istext(ailment_name))
|
|
return null
|
|
|
|
for (var/datum/ailment_data/AD in src.ailments)
|
|
if (AD.name == ailment_name && !base_ailments_only)
|
|
return AD
|
|
if (AD.master && AD.master.name == ailment_name)
|
|
return AD
|
|
|
|
return null
|
|
|
|
/mob/living/proc/Virus_ShockCure(var/probcure = 50)
|
|
for (var/datum/ailment_data/V in src.ailments)
|
|
if (V.cure == "Electric Shock" && prob(probcure))
|
|
src.cure_disease(V)
|
|
|
|
/mob/living/proc/shock_cyberheart(var/shockInput)
|
|
return
|
|
|
|
/mob/living/carbon/human/shock_cyberheart(var/shockInput)
|
|
if (!src.organHolder)
|
|
return
|
|
var/numHigh = round((1 * shockInput) / 5)
|
|
var/numMid = round((1 * shockInput) / 10)
|
|
var/numLow = round((1 * shockInput) / 20)
|
|
if (src.organHolder.heart && src.organHolder.heart.robotic && src.organHolder.heart.emagged && !src.organHolder.heart.broken)
|
|
src.add_stam_mod_regen("heart_shock", 5)
|
|
src.add_stam_mod_max("heart_shock", 20)
|
|
SPAWN_DBG(9000)
|
|
src.remove_stam_mod_regen("heart_shock")
|
|
src.remove_stam_mod_max("heart_shock")
|
|
if (prob(numHigh))
|
|
boutput(src, "<span style='color:red'>Your cyberheart spasms violently!</span>")
|
|
random_brute_damage(src, numHigh)
|
|
if (prob(numHigh))
|
|
boutput(src, "<span style='color:red'>Your cyberheart shocks you painfully!</span>")
|
|
random_burn_damage(src, numHigh)
|
|
if (prob(numMid))
|
|
boutput(src, "<span style='color:red'>Your cyberheart lurches awkwardly!</span>")
|
|
src.contract_disease(/datum/ailment/malady/heartfailure, null, null, 1)
|
|
if (prob(numMid))
|
|
boutput(src, "<span style='color:red'><B>Your cyberheart stops beating!</B></span>")
|
|
src.contract_disease(/datum/ailment/malady/flatline, null, null, 1)
|
|
if (prob(numLow))
|
|
boutput(src, "<span style='color:red'><B>Your cyberheart shuts down!</B></span>")
|
|
src.organHolder.heart.broken = 1
|
|
src.contract_disease(/datum/ailment/malady/flatline, null, null, 1)
|
|
else if (src.organHolder.heart && src.organHolder.heart.robotic && !src.organHolder.heart.emagged && !src.organHolder.heart.broken)
|
|
src.add_stam_mod_regen("heart_shock", 1)
|
|
src.add_stam_mod_max("heart_shock", 10)
|
|
SPAWN_DBG(9000)
|
|
src.remove_stam_mod_regen("heart_shock")
|
|
src.remove_stam_mod_max("heart_shock")
|
|
if (prob(numMid))
|
|
boutput(src, "<span style='color:red'>Your cyberheart spasms violently!</span>")
|
|
random_brute_damage(src, numMid)
|
|
if (prob(numMid))
|
|
boutput(src, "<span style='color:red'>Your cyberheart shocks you painfully!</span>")
|
|
random_burn_damage(src, numMid)
|
|
if (prob(numLow))
|
|
boutput(src, "<span style='color:red'>Your cyberheart lurches awkwardly!</span>")
|
|
src.contract_disease(/datum/ailment/malady/heartfailure, null, null, 1)
|