ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/disease.C
Revision: 1.64
Committed: Fri Apr 9 02:45:17 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.63: +4 -4 lines
Log Message:
indent

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.43 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.17 *
4 root 1.63 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.62 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992 Frank Tore Johansen
7 pippijn 1.17 *
8 root 1.53 * Deliantra is free software: you can redistribute it and/or modify it under
9     * the terms of the Affero GNU General Public License as published by the
10     * Free Software Foundation, either version 3 of the License, or (at your
11     * option) any later version.
12 pippijn 1.17 *
13 root 1.27 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 root 1.25 *
18 root 1.53 * You should have received a copy of the Affero GNU General Public License
19     * and the GNU General Public License along with this program. If not, see
20     * <http://www.gnu.org/licenses/>.
21 pippijn 1.17 *
22 root 1.43 * The authors can be reached via e-mail to <support@deliantra.net>
23 pippijn 1.17 */
24 elmex 1.1
25 root 1.21 /* This file contains all the code implementing diseases,
26     * except for odds and ends in attack.c and in
27     * living.c
28     */
29 elmex 1.1
30     /*
31    
32     For DISEASES:
33     Stat Property Definition
34    
35     attacktype Attack effects Attacktype of the disease. usu. AT_GODPOWER.
36     other_arch Creation object created and dropped when symptom moved.
37     title Message When the "disease" "infects" something, it will
38     print "title victim!!!" to the player who owns
39 root 1.2 the "disease".
40 elmex 1.1 wc+ Infectiousness How well the plague spreads person-to-person
41     magic+ Range range of infection
42     Stats* Disability What stats are reduced by the disease (str con...)
43     maxhp+ Persistence How long the disease can last OUTSIDE the host.
44     value TimeLeft Counter for persistence
45     dam^ Damage How much damage it does (%?).
46     maxgrace+ Duration How long before the disease is naturally cured.
47     food DurCount Counter for Duration
48    
49     speed Speed How often the disease moves.
50 root 1.35 last_sp^ Lethargy Percentage of max speed. 10 = 10% speed.
51 elmex 1.1
52     maxsp^ Mana deplete Saps mana.
53     ac^ Progressiveness How the diseases increases in severity.
54     last_eat*^ Deplete food saps food if negative
55     last_heal GrantImmunity If nonzero, disease does NOT grant immunity
56     when it runs out
57    
58     exp experience experience awarded when plague cured
59     hp*^ ReduceRegen reduces regeneration of disease-bearer
60     sp*^ ReduceSpRegen reduces spellpoint regeneration
61    
62     name Name Name of the plague
63     msg message What the plague says when it strikes.
64     race those affected species/race the plague strikes (* = everything)
65     level Plague Level General description of the plague's deadliness
66     armour Attenuation reduction in wc per generation of disease.
67     This builds in a self-limiting factor.
68    
69    
70     Explanations:
71     * means this # should be negative to cause adverse effect.
72     + means that this effect is modulated in spells by ldur
73     ^ means that this effect is modulated in spells by ldam
74    
75     attacktype is the attacktype used by the disease to smite "dam" damage with.
76    
77     wc/127 is the chance of someone in range catching it.
78    
79     magic is the range at which infection may occur. If negative, the range is
80     NOT level dependent.
81    
82     Stats are stat modifications. These should typically be negative.
83    
84     maxhp is how long the disease will persist if the host dies and "drops" it,
85     in "disease moves", i.e., moves of the disease. If negative, permanent.
86    
87    
88     value is the counter for maxhp, it starts at maxhp and drops...
89    
90     dam if positive, it is straight damage. if negative, a %-age.
91    
92     maxgrace how long in "disease moves" the disease lasts in the host, if negative,
93     permanent until cured.
94    
95     food if negative, disease is permanent. otherwise, decreases at <speed>,
96     disease goes away at food=0, set to "maxgrace" on infection.
97    
98     speed is the speed of the disease, how fast "disease moves" occur.
99    
100     last_sp is the lethargy imposed on the player by the disease. A lethargy
101     of "1" reduces the players speed to 1% of its normal value.
102    
103     maxsp how much mana is sapped per "disease move". if negative, a %-age is
104     taken.
105    
106     ac every "disease move" the severity of the symptoms are increased by
107     ac/100. (severity = 1 + (accumlated_progression)/100)
108    
109     last_eat increases food usage if negative.
110    
111    
112    
113     For SYMPTOMS:
114    
115     Stats modify stats
116     hp modify regen
117     value progression counter (multiplier = value/100)
118     food modify food use (from last_eat in DISEASE)
119     maxsp suck mana ( as noted for DISEASE)
120     last_sp Lethargy
121     msg What to say
122     speed speed of movement, from DISEASE
123    
124    
125     */
126    
127    
128     #include <global.h>
129     #include <object.h>
130     #include <living.h>
131 root 1.14 #include <sproto.h>
132 elmex 1.1 #include <spells.h>
133     #include <sounds.h>
134     #include <skills.h>
135    
136     /* IMPLEMENTATION NOTES
137 root 1.2
138     Diseases may be contageous. They are objects which exist in a player's
139 elmex 1.1 inventory. They themselves do nothing, except modify Symptoms, or
140     spread to other live objects. Symptoms are what actually damage the player:
141     these are their own object. */
142    
143 root 1.49 /* grants immunity to plagues we've seen before. */
144 root 1.4 static int
145 root 1.49 grant_immunity (object *disease)
146 elmex 1.1 {
147 root 1.49 object *immunity;
148     object *walk;
149    
150     /* Don't give immunity to this disease if last_heal is set. */
151     if (disease->last_heal)
152 root 1.4 return 0;
153 elmex 1.1
154 root 1.49 /* first, search for an immunity of the same name */
155     for (walk = disease->env->inv; walk; walk = walk->below)
156 root 1.64 if (disease->name == walk->name && walk->is_immunity ())
157 root 1.49 {
158     walk->level = disease->level;
159     return 1; /* just update the existing immunity. */
160     }
161 root 1.40
162 root 1.57 immunity = get_archetype (shstr_immunity);
163 elmex 1.1
164 root 1.49 immunity->name = disease->name;
165     immunity->level = disease->level;
166     immunity->move_block = 0;
167 elmex 1.1
168 root 1.49 insert_ob_in_ob (immunity, disease->env);
169 root 1.4
170 root 1.49 return 1;
171 elmex 1.1 }
172    
173 root 1.49 /* argument is a disease */
174     static object *
175     find_symptom (object *disease)
176 root 1.4 {
177 root 1.49 /* check the inventory for symptoms */
178     for (object *walk = disease->env->inv; walk; walk = walk->below)
179     if (walk->name == disease->name && walk->type == SYMPTOM)
180     return walk;
181 root 1.4
182 root 1.49 return NULL;
183 elmex 1.1 }
184    
185     /* remove any symptoms of disease
186     * Modified by MSW 2003-03-28 do try to find all the symptom the
187     * player may have - I think through some odd interactoins with
188     * disease level and player level and whatnot, a player could get
189     * more than one symtpom to a disease.
190     */
191 root 1.49 static int
192 root 1.4 remove_symptoms (object *disease)
193     {
194     object *symptom, *victim = NULL;
195    
196     while ((symptom = find_symptom (disease)) != NULL)
197     {
198     if (!victim)
199     victim = symptom->env;
200 root 1.9
201 root 1.48 symptom->destroy ();
202 root 1.4 }
203 root 1.9
204 root 1.4 if (victim)
205 root 1.13 victim->update_stats ();
206 root 1.30
207 root 1.4 return 0;
208 elmex 1.1 }
209    
210     /* searches around for more victims to infect */
211 root 1.49 static int
212 root 1.4 check_infection (object *disease)
213     {
214 root 1.39 int range = abs (disease->magic);
215 root 1.7
216 root 1.52 object *op = disease->outer_env_or_self ();
217 root 1.4
218 root 1.49 if (!op->is_on_map ())
219 root 1.4 return 0;
220 root 1.7
221 root 1.61 dynbuf buf;
222     unordered_mapwalk (buf, op, -range, -range, range, range)
223 root 1.49 {
224     mapspace &ms = m->at (nx, ny);
225 root 1.7
226 root 1.49 if (ms.flags () & P_IS_ALIVE)
227     for (object *tmp = ms.bot; tmp; tmp = tmp->above)
228     infect_object (tmp, disease, 0);
229     }
230 root 1.7
231 root 1.4 return 1;
232 elmex 1.1 }
233    
234 root 1.49 /* check if victim is susceptible to disease. */
235     static int
236     is_susceptible_to_disease (object *victim, object *disease)
237 root 1.4 {
238 root 1.49 if (!QUERY_FLAG (victim, FLAG_ALIVE))
239 root 1.4 return 0;
240    
241 root 1.49 if (victim->flag [FLAG_WIZ])
242 root 1.4 return 0;
243    
244 root 1.51 if (disease->race.contains ("*") && !QUERY_FLAG (victim, FLAG_UNDEAD))
245 root 1.49 return 1;
246 elmex 1.1
247 root 1.49 if ((disease->race == shstr_undead) && QUERY_FLAG (victim, FLAG_UNDEAD))
248     return 1;
249 root 1.4
250 root 1.51 if ((victim->race && disease->race.contains (victim->race)) || disease->race.contains (victim->name))
251 root 1.49 return 1;
252 root 1.4
253 root 1.49 return 0;
254 elmex 1.1 }
255    
256     /* this function monitors the symptoms caused by the disease (if any),
257     causes symptoms, and modifies existing symptoms in the case of
258     existing diseases. */
259 root 1.49 static int
260 root 1.4 do_symptoms (object *disease)
261     {
262     object *symptom;
263     object *victim;
264     object *tmp;
265    
266     victim = disease->env;
267    
268 root 1.30 if (!victim)
269     return 0; /* no-one to inflict symptoms on */
270    
271 root 1.4 /* This is a quick hack - for whatever reason, disease->env will point
272     * back to disease, causing endless loops. Why this happens really needs
273     * to be found, but this should at least prevent the infinite loops.
274     */
275 root 1.30 //TODO: should no longer be the case, monitor, and remove
276     if (victim == disease)
277     {
278     LOG (llevError | logBacktrace, "%s: disease->env points to itself", disease->debug_desc ());
279     return 0;
280     }
281 root 1.4
282     symptom = find_symptom (disease);
283 root 1.30 if (!symptom)
284 root 1.4 {
285     /* no symptom? need to generate one! */
286    
287     /* first check and see if the carrier of the disease is immune. If so, no symptoms! */
288     if (!is_susceptible_to_disease (victim, disease))
289     return 0;
290    
291     /* check for an actual immunity */
292     /* do an immunity check */
293 root 1.35 for (tmp = victim->head_ ()->inv; tmp; tmp = tmp->below)
294 root 1.64 if (tmp->name == disease->name && tmp->is_immunity ()) /* possibly an immunity, or diseased */
295     if (tmp->level >= disease->level)
296 root 1.35 return 0; /* Immune! */
297 root 1.2
298 root 1.57 object *new_symptom = get_archetype (shstr_symptom);
299 root 1.4
300     /* Something special done with dam. We want diseases to be more
301     * random in what they'll kill, so we'll make the damage they
302     * do random, note, this has a weird effect with progressive diseases.
303     */
304 root 1.35 if (disease->stats.dam)
305 root 1.4 {
306     int dam = disease->stats.dam;
307    
308     /* reduce the damage, on average, 50%, and making things random. */
309    
310 root 1.18 dam = random_roll (1, abs (dam), victim, PREFER_LOW);
311 root 1.4 if (disease->stats.dam < 0)
312     dam = -dam;
313 root 1.30
314 root 1.4 new_symptom->stats.dam = dam;
315 root 1.2 }
316 elmex 1.1
317 root 1.4 new_symptom->stats.maxsp = disease->stats.maxsp;
318 root 1.29 new_symptom->stats.food = new_symptom->stats.maxgrace;
319 root 1.4
320     new_symptom->name = new_symptom->name_pl = disease->name;
321    
322     new_symptom->level = disease->level;
323     new_symptom->speed = disease->speed;
324     new_symptom->value = 0;
325 root 1.22
326     for (int i = 0; i < NUM_STATS; ++i)
327     new_symptom->stats.stat (i) = disease->stats.stat (i);
328    
329 root 1.29 new_symptom->stats.sp = disease->stats.sp;
330     new_symptom->stats.food = disease->last_eat;
331 root 1.4 new_symptom->stats.maxsp = disease->stats.maxsp;
332 root 1.29 new_symptom->last_sp = disease->last_sp;
333     new_symptom->stats.exp = 0;
334     new_symptom->stats.hp = disease->stats.hp;
335     new_symptom->msg = disease->msg;
336     new_symptom->attacktype = disease->attacktype;
337     new_symptom->other_arch = disease->other_arch;
338 root 1.35 new_symptom->skill = disease->skill;
339    
340     new_symptom->move_block = 0;
341    
342     victim->head_ ()->insert (new_symptom);
343 root 1.4
344 root 1.36 // set owner last, as insert clears owner
345 root 1.11 new_symptom->set_owner (disease->owner);
346 root 1.4
347     return 1;
348     }
349    
350 root 1.23 /* now deal with progressing diseases: we increase the debility
351 root 1.4 * caused by the symptoms.
352     */
353 root 1.29 if (disease->stats.ac)
354 root 1.4 {
355 root 1.29 symptom->value = clamp (symptom->value + disease->stats.ac, 0, 100*100);
356 root 1.4
357 root 1.23 float scale = 1.f + symptom->value / 100.f;
358 root 1.22
359 root 1.4 /* now rescale all the debilities */
360 root 1.22 for (int i = 0; i < NUM_STATS; ++i)
361 root 1.31 symptom->stats.stat (i) = clamp (int (scale * disease->stats.stat (i)), -128, 127);
362 root 1.22
363 root 1.29 symptom->stats.dam = clamp (scale * disease->stats.dam , -1024, 1024);
364     symptom->stats.food = clamp (scale * disease->last_eat , -1024, 1024);
365     symptom->stats.maxsp = clamp (scale * disease->stats.maxsp, -1024, 1024);
366     symptom->stats.sp = clamp (scale * disease->stats.sp , -1024, 1024);
367     symptom->stats.hp = clamp (scale * disease->stats.hp , -1024, 1024);
368 root 1.22 symptom->stats.exp = 0;
369 root 1.33 symptom->last_sp = disease->last_sp ? clamp (disease->last_sp / scale, 1, 1024) : 0;
370 root 1.29 symptom->msg = disease->msg;
371     symptom->attacktype = disease->attacktype;
372     symptom->other_arch = disease->other_arch;
373 elmex 1.1 }
374 root 1.23
375 root 1.4 SET_FLAG (symptom, FLAG_APPLIED);
376 root 1.13 victim->update_stats ();
377 root 1.23
378 root 1.4 return 1;
379 elmex 1.1 }
380    
381 root 1.4 int
382 root 1.49 move_disease (object *disease)
383     {
384     /* First task is to determine if the disease is inside or outside of someone.
385     * If outside, we decrement 'value' until we're gone.
386     */
387    
388     if (!disease->env)
389     { /* we're outside of someone */
390     if (disease->stats.maxhp > 0)
391     disease->value--;
392    
393     if (!disease->value)
394     {
395     disease->destroy ();
396     return 1;
397     }
398     }
399     else
400     {
401     /* if we're inside a person, have the disease run its course */
402     /* negative/zero food denotes "perpetual" diseases. */
403     if (disease->stats.food > 0)
404     {
405     disease->stats.food--;
406    
407     if (!disease->stats.food)
408     {
409     remove_symptoms (disease); /* remove the symptoms of this disease */
410     grant_immunity (disease);
411     disease->destroy ();
412     return 1;
413     }
414     }
415     }
416    
417     /* check to see if we infect others */
418     check_infection (disease);
419    
420     /* impose or modify the symptoms of the disease */
421     if (disease->env && is_susceptible_to_disease (disease->env, disease))
422     do_symptoms (disease);
423    
424     return 0;
425     }
426    
427     /* check to see if an object is infectable:
428     * objects with immunity aren't infectable.
429     * objects already infected aren't infectable.
430     * dead objects aren't infectable.
431     * undead objects are infectible only if specifically named.
432     */
433     int
434     infect_object (object *victim, object *disease, int force)
435 root 1.4 {
436 root 1.49 object *tmp;
437     object *new_disease;
438    
439     /* don't infect inanimate objects */
440     if (!QUERY_FLAG (victim, FLAG_MONSTER) && !(victim->type == PLAYER))
441     return 0;
442    
443     /* check and see if victim can catch disease: diseases
444     * are specific
445     */
446     if (!is_susceptible_to_disease (victim, disease))
447     return 0;
448 root 1.4
449 root 1.49 /* roll the dice on infection before doing the inventory check! */
450     if (!force && (random_roll (0, 126, victim, PREFER_HIGH) >= disease->stats.wc))
451 root 1.4 return 0;
452 root 1.35
453 root 1.49 /* do an immunity check */
454    
455     /* There used to (IMO) be a flaw in the below - it used to be the case
456     * that if level check was done for both immunity and disease. This could
457     * result in a person with multiple afflictions of the same disease
458     * (eg, level 1 cold, level 2 cold, level 3 cold, etc), as long as
459     * they were cast in that same order. Instead, change it so that
460     * if you diseased, you can't get diseased more.
461     */
462    
463     for (tmp = victim->head_ ()->inv; tmp; tmp = tmp->below)
464 root 1.64 if (tmp->name == disease->name && tmp->is_immunity () && tmp->level >= disease->level)
465 root 1.49 return 0; /* Immune! */
466     else if (tmp->type == DISEASE && tmp->name == disease->name)
467     return 0; /* already diseased */
468    
469     /* If we've gotten this far, go ahead and infect the victim. */
470    
471     new_disease = disease->clone ();
472    
473     new_disease->stats.food = disease->stats.maxgrace;
474     new_disease->value = disease->stats.maxhp;
475     new_disease->stats.wc -= disease->last_grace; /* self-limiting factor */
476    
477     /* This appears to be a horrible case of overloading 'NO_PASS'
478     * for meaning in the diseases.
479     */
480     new_disease->move_block = 0;
481    
482     // insert before setting the owner
483     victim->head_ ()->insert (new_disease);
484    
485     if (disease->owner)
486     new_disease->set_owner (disease->owner);
487     else if (object *pl = disease->in_player ())
488     /* for diseases which are passed by hitting, set owner and skill */
489     new_disease->set_owner (pl);
490    
491     if (new_disease->owner && new_disease->owner->type == PLAYER)
492     {
493     const char *buf;
494 root 1.35
495 root 1.49 /* if the disease has a title, it has a special infection message
496     * This messages is printed in the form MESSAGE victim
497     */
498     if (new_disease->title)
499     buf = format ("%s %s!!", &disease->title, &victim->name);
500     else
501     buf = format ("You infect %s with your disease, %s!", &victim->name, &new_disease->name);
502 root 1.35
503 root 1.49 if (victim->type == PLAYER)
504     new_draw_info (NDI_UNIQUE | NDI_RED, 0, new_disease->owner, buf);
505     else
506     new_draw_info (0, 4, new_disease->owner, buf);
507     }
508 root 1.35
509 root 1.49 if (victim->type == PLAYER)
510     new_draw_info (NDI_UNIQUE | NDI_RED, 0, victim, "You suddenly feel ill.");
511 root 1.35
512 elmex 1.1 return 1;
513     }
514    
515     /* make the symptom do the nasty things it does */
516 root 1.4 int
517     move_symptom (object *symptom)
518     {
519     object *victim = symptom->env;
520    
521 root 1.36 if (!victim || !victim->map)
522 root 1.4 { /* outside a monster/player, die immediately */
523 root 1.48 symptom->destroy ();
524 root 1.4 return 0;
525     }
526    
527     /* create the symptom "other arch" object and drop it here
528     * under every part of the monster
529     * The victim may well have died.
530     */
531 root 1.42 if (victim->map)
532     {
533     victim->play_sound (symptom->sound);
534    
535     if (symptom->other_arch)
536     for (object *tmp = victim->head_ (); tmp; tmp = tmp->more)
537     {
538 root 1.60 object *new_ob = symptom->other_arch->instance ();
539 root 1.42 new_ob->x = tmp->x;
540     new_ob->y = tmp->y;
541     new_ob->map = victim->map;
542     insert_ob_in_map (new_ob, victim->map, victim, 0);
543     }
544     }
545 root 1.4
546 root 1.59 int damage =
547     symptom->stats.dam > 0
548     ? symptom->stats.dam
549     : max (1, victim->stats.maxhp * -symptom->stats.dam / 100);
550    
551     hit_player (victim, damage, symptom, symptom->attacktype, 1);
552    
553     int sp_reduce =
554     symptom->stats.maxsp > 0
555     ? symptom->stats.maxsp
556     : max (1, victim->stats.maxsp * -symptom->stats.maxsp / 100);
557    
558     victim->stats.sp = max (0, victim->stats.sp - sp_reduce);
559    
560 root 1.4 new_draw_info (NDI_UNIQUE | NDI_RED, 0, victim, symptom->msg);
561    
562     return 1;
563 elmex 1.1 }
564    
565 root 1.20 /* possibly infect due to direct physical contact
566     * i.e., AT_PHYSICAL-- called from "hit_player_attacktype" */
567 root 1.4 int
568     check_physically_infect (object *victim, object *hitter)
569     {
570 root 1.20 /* search for diseases, give every disease a chance to infect */
571     for (object *disease = hitter->inv; disease; disease = disease->below)
572     if (disease->type == DISEASE)
573     infect_object (victim, disease, 0);
574 root 1.4
575 elmex 1.1 return 1;
576     }
577    
578     /* do the cure disease stuff, from the spell "cure disease" */
579 root 1.4 int
580 root 1.41 cure_disease (object *sufferer, object *caster, object *spell)
581 root 1.4 {
582     object *disease, *next;
583     int cure = 0;
584    
585 root 1.41 int casting_level = caster ? caster->level : 1000; /* if null caster, CURE all. */
586 root 1.4
587     for (disease = sufferer->inv; disease; disease = next)
588     {
589     next = disease->below;
590    
591     if (disease->type == DISEASE)
592     { /* attempt to cure this disease */
593 root 1.21 /* If caster level is higher than disease level, cure chance
594 root 1.4 * is automatic. If lower, then the chance is basically
595     * 1 in level_diff - if there is a 5 level difference, chance
596     * is 1 in 5.
597     */
598     if ((casting_level >= disease->level) || (!(random_roll (0, (disease->level - casting_level - 1), caster, PREFER_LOW))))
599     {
600     remove_symptoms (disease);
601     cure = 1;
602 root 1.9
603 root 1.41 if (caster && spell)
604     change_exp (caster, disease->stats.exp, spell->skill, SK_EXP_SKILL_ONLY);
605 root 1.9
606 root 1.48 disease->destroy ();
607 root 1.2 }
608     }
609 elmex 1.1 }
610 root 1.21
611 root 1.4 if (cure)
612     {
613     /* Only draw these messages once */
614     if (caster)
615     new_draw_info_format (NDI_UNIQUE, 0, caster, "You cure a disease!");
616 root 1.21
617 root 1.4 new_draw_info (NDI_UNIQUE, 0, sufferer, "You no longer feel diseased.");
618 elmex 1.1 }
619 root 1.21
620 elmex 1.1 return 1;
621     }
622    
623 root 1.56 #if 0 // unused, but seems interesting
624 elmex 1.1 /* reduces disease progression: reduce_symptoms
625     * return true if we actually reduce a disease.
626     */
627 root 1.55 static int
628 root 1.4 reduce_symptoms (object *sufferer, int reduction)
629     {
630     object *walk;
631     int success = 0;
632    
633     for (walk = sufferer->inv; walk; walk = walk->below)
634     {
635     if (walk->type == SYMPTOM)
636     {
637     if (walk->value > 0)
638     {
639     success = 1;
640 root 1.29 walk->value = max (0, walk->value - 2 * reduction);
641 root 1.4 /* give the disease time to modify this symptom,
642     * and reduce its severity. */
643     walk->speed_left = 0;
644 root 1.2 }
645 root 1.4 }
646 elmex 1.1 }
647 root 1.29
648 root 1.4 if (success)
649     new_draw_info (NDI_UNIQUE, 0, sufferer, "Your illness seems less severe.");
650 root 1.29
651 root 1.4 return success;
652 elmex 1.1 }
653 root 1.56 #endif