forked from Sanerres/vgstation13
-
Notifications
You must be signed in to change notification settings - Fork 0
/
disease.dm
208 lines (172 loc) · 6.99 KB
/
disease.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#define SPECIAL -1
#define NON_CONTAGIOUS 0
#define BLOOD 1
#define CONTACT_FEET 2
#define CONTACT_HANDS 3
#define CONTACT_GENERAL 4
#define AIRBORNE 5
#define SCANNER 1
#define PANDEMIC 2
/*
IMPORTANT NOTE: Please delete the diseases by using cure() proc or del() instruction.
Diseases are referenced in a global list, so simply setting mob or obj vars
to null does not delete the object itself. Thank you.
*/
var/list/diseases = typesof(/datum/disease) - /datum/disease
/datum/disease
var/form = "Virus" //During medscans, what the disease is referred to as
var/name = "No disease"
var/stage = 1 //all diseases start at stage 1
var/max_stages = 0.0
var/cure = null
var/cure_id = null// reagent.id or list containing them
var/cure_list = null // allows for multiple possible cure combinations
var/cure_chance = 8//chance for the cure to do its job
var/spread = null //spread type description
var/initial_spread = null
var/spread_type = AIRBORNE
var/contagious_period = 0//the disease stage when it can be spread
var/list/affected_species = list()
var/mob/living/carbon/affected_mob = null //the mob which is affected by disease.
var/holder = null //the atom containing the disease (mob or obj)
var/carrier = 0.0 //there will be a small chance that the person will be a carrier
var/curable = 0 //can this disease be cured? (By itself...)
var/list/strain_data = list() //This is passed on to infectees
var/stage_prob = 4 // probability of advancing to next stage, default 4% per check
var/agent = "some microbes"//name of the disease agent
var/permeability_mod = 1//permeability modifier coefficient.
var/desc = null//description. Leave it null and this disease won't show in med records.
var/severity = null//severity descr
var/longevity = 150//time in "ticks" the virus stays in inanimate object (blood stains, corpses, etc). In syringes, bottles and beakers it stays infinitely.
var/list/hidden = list(0, 0)
var/can_carry = 1 // If the disease allows "carriers".
var/age = 0 // age of the disease in the current mob
var/stage_minimum_age = 0 // how old the disease must be to advance per stage
// if hidden[1] is true, then virus is hidden from medical scanners
// if hidden[2] is true, then virus is hidden from PANDEMIC machine
/datum/disease/proc/stage_act()
age++
var/cure_present = has_cure()
//world << "[cure_present]"
if(carrier&&!cure_present)
//world << "[affected_mob] is carrier"
return
spread = (cure_present?"Remissive":initial_spread)
if(stage > max_stages)
stage = max_stages
if(!cure_present && prob(stage_prob) && age > stage_minimum_age) //now the disease shouldn't get back up to stage 4 in no time
stage = min(stage + 1, max_stages)
age = 0
else if(cure_present && prob(cure_chance))
stage = max(stage - 1, 1)
if(stage <= 1 && ((prob(1) && curable) || (cure_present && prob(cure_chance))))
cure()
return
return
/datum/disease/proc/has_cure()//check if affected_mob has required reagents.
if(!cure_id) return 0
var/result = 1
if(cure_list == list(cure_id))
if(istype(cure_id, /list))
for(var/C_id in cure_id)
if(!affected_mob.reagents.has_reagent(C_id))
result = 0
else if(!affected_mob.reagents.has_reagent(cure_id))
result = 0
else
for(var/C_list in cure_list)
if(istype(C_list, /list))
for(var/C_id in cure_id)
if(affected_mob.reagents != null)
result = 0
else if(!affected_mob.reagents.has_reagent(C_id))
result = 0
else if(affected_mob.reagents != null)
if(!affected_mob.reagents.has_reagent(C_list))
result = 0
return result
/datum/disease/proc/spread_by_touch()
switch(spread_type)
if(CONTACT_FEET, CONTACT_HANDS, CONTACT_GENERAL)
return 1
return 0
/datum/disease/proc/spread(var/atom/source=null, var/airborne_range = 2, var/force_spread)
//world << "Disease [src] proc spread was called from holder [source]"
// If we're overriding how we spread, say so here
var/how_spread = spread_type
if(!istype(affected_mob))
return 0
if(force_spread)
how_spread = force_spread
if(how_spread == SPECIAL || how_spread == NON_CONTAGIOUS || how_spread == BLOOD)//does not spread
return
if(stage < contagious_period) //the disease is not contagious at this stage
return
if(!source)//no holder specified
if(affected_mob)//no mob affected holder
source = affected_mob
else //no source and no mob affected. Rogue disease. Break
return
if(affected_mob.reagents != null)
if(affected_mob)
if(affected_mob.reagents.has_reagent("spaceacillin"))
return // Don't spread if we have spaceacillin in our system.
var/check_range = airborne_range//defaults to airborne - range 2
if(how_spread != AIRBORNE && how_spread != SPECIAL)
check_range = 1 // everything else, like infect-on-contact things, only infect things on top of it
if(isturf(source.loc))
for(var/mob/living/carbon/M in oview(check_range, source))
if(isturf(M.loc))
if(AStar(source.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, check_range))
M.contract_disease(src, 0, 1, force_spread)
return
/datum/disease/proc/process()
if(!holder)
active_diseases -= src
return
if(prob(65))
spread(holder)
if(affected_mob)
for(var/datum/disease/D in affected_mob.viruses)
if(D != src)
if(IsSame(D))
//error("Deleting [D.name] because it's the same as [src.name].")
del(D) // if there are somehow two viruses of the same kind in the system, delete the other one
if(holder == affected_mob)
if(affected_mob.stat != DEAD) //he's alive
stage_act()
else //he's dead.
if(spread_type!=SPECIAL)
spread_type = CONTACT_GENERAL
affected_mob = null
if(!affected_mob) //the virus is in inanimate obj
// world << "[src] longevity = [longevity]"
if(prob(70))
if(--longevity<=0)
cure(0)
return
/datum/disease/proc/cure(var/resistance=1)//if resistance = 0, the mob won't develop resistance to disease
if(affected_mob)
if(resistance && !(type in affected_mob.resistances))
var/saved_type = "[type]"
affected_mob.resistances += text2path(saved_type)
/*if(istype(src, /datum/disease/alien_embryo)) //Get rid of the infection flag if it's a xeno embryo.
affected_mob.status_flags &= ~(XENO_HOST)*/
affected_mob.viruses -= src //remove the datum from the list
del(src) //delete the datum to stop it processing
return
/datum/disease/New(var/process=1, var/datum/disease/D)//process = 1 - adding the object to global list. List is processed by master controller.
cure_list = list(cure_id) // to add more cures, add more vars to this list in the actual disease's New()
if(process) // Viruses in list are considered active.
active_diseases += src
initial_spread = spread
/datum/disease/proc/IsSame(var/datum/disease/D)
if(istype(src, D.type))
return 1
return 0
/datum/disease/proc/Copy(var/process = 0)
return new type(process, src)
/*
/datum/disease/Destroy()
active_diseases.Remove(src)
*/