ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/disease.C
Revision: 1.39
Committed: Fri Aug 24 01:41:02 2007 UTC (16 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.38: +3 -3 lines
Log Message:
consdierably reduce disease range modifier

File Contents

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