ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/disease.C
Revision: 1.15
Committed: Wed Jan 3 00:21:36 2007 UTC (17 years, 5 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.14: +4 -4 lines
Log Message:
initialised :)

File Contents

# User Rev Content
1 elmex 1.1 /*
2     CrossFire, A Multiplayer game for X-windows
3    
4     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5     Copyright (C) 1992 Frank Tore Johansen
6    
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 root 1.5 The authors can be reached via e-mail to <crossfire@schmorp.de>
22 elmex 1.1 */
23    
24     /* This file contains all the code implementing diseases,
25     except for odds and ends in attack.c and in
26 root 1.2 living.c*/
27 elmex 1.1
28    
29    
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     last_sp^ Lethargy Percentage of max speed--10 = 10% speed.
51    
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     /* check if victim is susceptible to disease. */
144 root 1.4 static int
145     is_susceptible_to_disease (object *victim, object *disease)
146 elmex 1.1 {
147 root 1.4 if (!QUERY_FLAG (victim, FLAG_ALIVE))
148     return 0;
149 elmex 1.1
150 root 1.4 if (strstr (disease->race, "*") && !QUERY_FLAG (victim, FLAG_UNDEAD))
151     return 1;
152 elmex 1.1
153 root 1.4 if ((disease->race == undead_name) && QUERY_FLAG (victim, FLAG_UNDEAD))
154     return 1;
155 elmex 1.1
156 root 1.4 if ((victim->race && strstr (disease->race, victim->race)) || strstr (disease->race, victim->name))
157     return 1;
158    
159     return 0;
160 elmex 1.1 }
161    
162 root 1.4 int
163     move_disease (object *disease)
164     {
165     /* first task is to determine if the disease is inside or outside of someone.
166     * If outside, we decrement 'value' until we're gone.
167     */
168    
169     if (disease->env == NULL)
170     { /* we're outside of someone */
171     if (disease->stats.maxhp > 0)
172     disease->value--;
173 root 1.9
174 root 1.4 if (disease->value == 0)
175     {
176 root 1.9 disease->destroy ();
177 root 1.4 return 1;
178 root 1.2 }
179 root 1.4 }
180     else
181     {
182     /* if we're inside a person, have the disease run its course */
183     /* negative foods denote "perpetual" diseases. */
184     if (disease->stats.food > 0)
185     {
186     disease->stats.food--;
187 root 1.9
188 root 1.4 if (disease->stats.food == 0)
189     {
190     remove_symptoms (disease); /* remove the symptoms of this disease */
191     grant_immunity (disease);
192 root 1.9 disease->destroy ();
193 root 1.4 return 1;
194 root 1.2 }
195     }
196 elmex 1.1 }
197 root 1.9
198 root 1.4 /* check to see if we infect others */
199     check_infection (disease);
200 elmex 1.1
201 root 1.4 /* impose or modify the symptoms of the disease */
202     if (disease->env && is_susceptible_to_disease (disease->env, disease))
203     do_symptoms (disease);
204 elmex 1.1
205 root 1.4 return 0;
206 elmex 1.1 }
207    
208     /* remove any symptoms of disease
209     * Modified by MSW 2003-03-28 do try to find all the symptom the
210     * player may have - I think through some odd interactoins with
211     * disease level and player level and whatnot, a player could get
212     * more than one symtpom to a disease.
213     */
214 root 1.4
215     int
216     remove_symptoms (object *disease)
217     {
218     object *symptom, *victim = NULL;
219    
220     while ((symptom = find_symptom (disease)) != NULL)
221     {
222     if (!victim)
223     victim = symptom->env;
224 root 1.9
225     symptom->destroy ();
226 root 1.4 }
227 root 1.9
228 root 1.4 if (victim)
229 root 1.13 victim->update_stats ();
230 root 1.4 return 0;
231 elmex 1.1 }
232    
233     /* argument is a disease */
234 root 1.4 object *
235     find_symptom (object *disease)
236     {
237 elmex 1.1 object *walk;
238    
239     /* check the inventory for symptoms */
240 root 1.4 for (walk = disease->env->inv; walk; walk = walk->below)
241     if (!strcmp (walk->name, disease->name) && walk->type == SYMPTOM)
242     return walk;
243 elmex 1.1 return NULL;
244     }
245 root 1.4
246 elmex 1.1 /* searches around for more victims to infect */
247 root 1.4 int
248     check_infection (object *disease)
249     {
250     int x, y, range, mflags;
251 root 1.6 maptile *map, *map2;
252 root 1.4 object *tmp;
253    
254     range = abs (disease->magic);
255 root 1.7
256 root 1.4 if (disease->env)
257     {
258 root 1.7 x = disease->env->x;
259     y = disease->env->y;
260 root 1.4 map = disease->env->map;
261     }
262     else
263     {
264 root 1.7 x = disease->x;
265     y = disease->y;
266 root 1.4 map = disease->map;
267     }
268    
269 root 1.7 if (!map)
270 root 1.4 return 0;
271 root 1.7
272     for (int i = x - range; i <= x + range; i++)
273     for (int j = y - range; j <= y + range; j++)
274     {
275     sint16 i2, j2;
276     mflags = get_map_flags (map, &map2, i, j, &i2, &j2);
277    
278     if (!(mflags & P_OUT_OF_MAP) && (mflags & P_IS_ALIVE))
279 root 1.12 for (tmp = GET_MAP_OB (map2, i2, j2); tmp; tmp = tmp->above)
280 root 1.7 infect_object (tmp, disease, 0);
281     }
282    
283 root 1.4 return 1;
284 elmex 1.1 }
285    
286    
287     /* check to see if an object is infectable:
288     * objects with immunity aren't infectable.
289     * objects already infected aren't infectable.
290     * dead objects aren't infectable.
291     * undead objects are infectible only if specifically named.
292     */
293 root 1.4 int
294     infect_object (object *victim, object *disease, int force)
295     {
296     object *tmp;
297     object *new_disease;
298 elmex 1.1
299 root 1.4 /* don't infect inanimate objects */
300     if (!QUERY_FLAG (victim, FLAG_MONSTER) && !(victim->type == PLAYER))
301     return 0;
302    
303     /* check and see if victim can catch disease: diseases
304     * are specific
305     */
306     if (!is_susceptible_to_disease (victim, disease))
307     return 0;
308    
309     /* roll the dice on infection before doing the inventory check! */
310     if (!force && (random_roll (0, 126, victim, PREFER_HIGH) >= disease->stats.wc))
311     return 0;
312 elmex 1.1
313 root 1.4 /* do an immunity check */
314     if (victim->head)
315     tmp = victim->head->inv;
316     else
317     tmp = victim->inv;
318    
319     /* There used to (IMO) be a flaw in the below - it used to be the case
320     * that if level check was done for both immunity and disease. This could
321     * result in a person with multiple afflictions of the same disease
322     * (eg, level 1 cold, level 2 cold, level 3 cold, etc), as long as
323     * they were cast in that same order. Instead, change it so that
324     * if you diseased, you can't get diseased more.
325     */
326    
327 pippijn 1.15 for ( /* tmp initialised in if, above */ ; tmp; tmp = tmp->below)
328 root 1.4 {
329     if (tmp->type == SIGN && !strcmp (tmp->name, disease->name) && tmp->level >= disease->level)
330 pippijn 1.15 return 0; /* Immune! */
331 root 1.4 else if (tmp->type == DISEASE && !strcmp (tmp->name, disease->name))
332     return 0; /* already diseased */
333     }
334    
335     /* If we've gotten this far, go ahead and infect the victim. */
336 root 1.10 new_disease = disease->clone ();
337 root 1.4 new_disease->stats.food = disease->stats.maxgrace;
338     new_disease->value = disease->stats.maxhp;
339     new_disease->stats.wc -= disease->last_grace; /* self-limiting factor */
340    
341     /* Unfortunately, set_owner does the wrong thing to the skills pointers
342     * resulting in exp going into the owners *current* chosen skill.
343     */
344    
345 root 1.11 if (disease->owner)
346 root 1.4 {
347 root 1.11 new_disease->set_owner (disease->owner);
348 root 1.4
349     /* Only need to update skill if different */
350     if (new_disease->skill != disease->skill)
351     new_disease->skill = disease->skill;
352     }
353     else
354     { /* for diseases which are passed by hitting, set owner and praying skill */
355     if (disease->env && disease->env->type == PLAYER)
356     {
357     object *player = disease->env;
358    
359 root 1.11 new_disease->set_owner (player);
360 root 1.4
361     /* the skill pointer for these diseases should already be set up -
362     * hardcoding in 'praying' is not the right approach.
363     */
364 root 1.2 }
365 elmex 1.1 }
366    
367 root 1.4 insert_ob_in_ob (new_disease, victim);
368     /* This appears to be a horrible case of overloading 'NO_PASS'
369     * for meaning in the diseases.
370     */
371     new_disease->move_block = 0;
372     if (new_disease->owner && new_disease->owner->type == PLAYER)
373     {
374     char buf[128];
375    
376     /* if the disease has a title, it has a special infection message
377     * This messages is printed in the form MESSAGE victim
378     */
379     if (new_disease->title)
380     sprintf (buf, "%s %s!!", &disease->title, &victim->name);
381     else
382     sprintf (buf, "You infect %s with your disease, %s!", &victim->name, &new_disease->name);
383    
384     if (victim->type == PLAYER)
385     new_draw_info (NDI_UNIQUE | NDI_RED, 0, new_disease->owner, buf);
386     else
387     new_draw_info (0, 4, new_disease->owner, buf);
388 elmex 1.1 }
389 root 1.4 if (victim->type == PLAYER)
390     new_draw_info (NDI_UNIQUE | NDI_RED, 0, victim, "You suddenly feel ill.");
391 elmex 1.1
392 root 1.4 return 1;
393 elmex 1.1
394     }
395    
396    
397    
398     /* this function monitors the symptoms caused by the disease (if any),
399     causes symptoms, and modifies existing symptoms in the case of
400     existing diseases. */
401    
402 root 1.4 int
403     do_symptoms (object *disease)
404     {
405     object *symptom;
406     object *victim;
407     object *tmp;
408    
409     victim = disease->env;
410    
411     /* This is a quick hack - for whatever reason, disease->env will point
412     * back to disease, causing endless loops. Why this happens really needs
413     * to be found, but this should at least prevent the infinite loops.
414     */
415    
416     if (victim == NULL || victim == disease)
417     return 0; /* no-one to inflict symptoms on */
418    
419     symptom = find_symptom (disease);
420     if (symptom == NULL)
421     {
422     /* no symptom? need to generate one! */
423     object *new_symptom;
424    
425     /* first check and see if the carrier of the disease is immune. If so, no symptoms! */
426     if (!is_susceptible_to_disease (victim, disease))
427     return 0;
428    
429     /* check for an actual immunity */
430     /* do an immunity check */
431     if (victim->head)
432     tmp = victim->head->inv;
433     else
434     tmp = victim->inv;
435    
436 pippijn 1.15 for ( /* tmp initialised in if, above */ ; tmp; tmp = tmp->below)
437 root 1.4 {
438     if (tmp->type == SIGN) /* possibly an immunity, or diseased */
439     if (!strcmp (tmp->name, disease->name) && tmp->level >= disease->level)
440     return 0; /*Immune! */
441 root 1.2 }
442    
443 root 1.4 new_symptom = get_archetype (ARCH_SYMPTOM);
444    
445     /* Something special done with dam. We want diseases to be more
446     * random in what they'll kill, so we'll make the damage they
447     * do random, note, this has a weird effect with progressive diseases.
448     */
449     if (disease->stats.dam != 0)
450     {
451     int dam = disease->stats.dam;
452    
453     /* reduce the damage, on average, 50%, and making things random. */
454    
455     dam = random_roll (1, FABS (dam), victim, PREFER_LOW);
456     if (disease->stats.dam < 0)
457     dam = -dam;
458     new_symptom->stats.dam = dam;
459 root 1.2 }
460 elmex 1.1
461 root 1.4
462     new_symptom->stats.maxsp = disease->stats.maxsp;
463     new_symptom->stats.food = new_symptom->stats.maxgrace;
464    
465     new_symptom->name = new_symptom->name_pl = disease->name;
466    
467     new_symptom->level = disease->level;
468     new_symptom->speed = disease->speed;
469     new_symptom->value = 0;
470     new_symptom->stats.Str = disease->stats.Str;
471     new_symptom->stats.Dex = disease->stats.Dex;
472     new_symptom->stats.Con = disease->stats.Con;
473     new_symptom->stats.Wis = disease->stats.Wis;
474     new_symptom->stats.Int = disease->stats.Int;
475     new_symptom->stats.Pow = disease->stats.Pow;
476     new_symptom->stats.Cha = disease->stats.Cha;
477     new_symptom->stats.sp = disease->stats.sp;
478     new_symptom->stats.food = disease->last_eat;
479     new_symptom->stats.maxsp = disease->stats.maxsp;
480     new_symptom->last_sp = disease->last_sp;
481     new_symptom->stats.exp = 0;
482     new_symptom->stats.hp = disease->stats.hp;
483     new_symptom->msg = disease->msg;
484     new_symptom->attacktype = disease->attacktype;
485     new_symptom->other_arch = disease->other_arch;
486    
487 root 1.11 new_symptom->set_owner (disease->owner);
488 root 1.4
489     if (new_symptom->skill != disease->skill)
490     new_symptom->skill = disease->skill;
491    
492     new_symptom->move_block = 0;
493     insert_ob_in_ob (new_symptom, victim);
494     return 1;
495     }
496    
497     /* now deal with progressing diseases: we increase the debility
498     * caused by the symptoms.
499     */
500    
501     if (disease->stats.ac != 0)
502     {
503     float scale;
504    
505     symptom->value += disease->stats.ac;
506     scale = 1.0 + symptom->value / 100.0;
507     /* now rescale all the debilities */
508     symptom->stats.Str = (int) (scale * disease->stats.Str);
509     symptom->stats.Dex = (int) (scale * disease->stats.Dex);
510     symptom->stats.Con = (int) (scale * disease->stats.Con);
511     symptom->stats.Wis = (int) (scale * disease->stats.Wis);
512     symptom->stats.Int = (int) (scale * disease->stats.Int);
513     symptom->stats.Pow = (int) (scale * disease->stats.Pow);
514     symptom->stats.Cha = (int) (scale * disease->stats.Cha);
515     symptom->stats.dam = (int) (scale * disease->stats.dam);
516     symptom->stats.sp = (int) (scale * disease->stats.sp);
517     symptom->stats.food = (int) (scale * disease->last_eat);
518     symptom->stats.maxsp = (int) (scale * disease->stats.maxsp);
519     symptom->last_sp = (int) (scale * disease->last_sp);
520     symptom->stats.exp = 0;
521     symptom->stats.hp = (int) (scale * disease->stats.hp);
522     symptom->msg = disease->msg;
523     symptom->attacktype = disease->attacktype;
524     symptom->other_arch = disease->other_arch;
525 elmex 1.1 }
526 root 1.4 SET_FLAG (symptom, FLAG_APPLIED);
527 root 1.13 victim->update_stats ();
528 root 1.4 return 1;
529 elmex 1.1 }
530    
531    
532     /* grants immunity to plagues we've seen before. */
533 root 1.4 int
534     grant_immunity (object *disease)
535     {
536     object *immunity;
537 elmex 1.1 object *walk;
538 root 1.4
539 elmex 1.1 /* Don't give immunity to this disease if last_heal is set. */
540 root 1.4 if (disease->last_heal)
541     return 0;
542 elmex 1.1 /* first, search for an immunity of the same name */
543 root 1.4 for (walk = disease->env->inv; walk; walk = walk->below)
544     {
545     if (walk->type == 98 && !strcmp (disease->name, walk->name))
546     {
547     walk->level = disease->level;
548     return 1; /* just update the existing immunity. */
549     }
550     }
551     immunity = get_archetype ("immunity");
552 root 1.3 immunity->name = disease->name;
553 elmex 1.1 immunity->level = disease->level;
554     immunity->move_block = 0;
555 root 1.4 insert_ob_in_ob (immunity, disease->env);
556 elmex 1.1 return 1;
557    
558     }
559    
560    
561     /* make the symptom do the nasty things it does */
562    
563 root 1.4 int
564     move_symptom (object *symptom)
565     {
566     object *victim = symptom->env;
567     object *new_ob;
568     int sp_reduce;
569    
570     if (victim == NULL || victim->map == NULL)
571     { /* outside a monster/player, die immediately */
572 root 1.9 symptom->destroy ();
573 root 1.4 return 0;
574     }
575    
576     if (symptom->stats.dam > 0)
577     hit_player (victim, symptom->stats.dam, symptom, symptom->attacktype, 1);
578     else
579     hit_player (victim, (int) MAX (1, -victim->stats.maxhp * symptom->stats.dam / 100.0), symptom, symptom->attacktype, 1);
580    
581     if (symptom->stats.maxsp > 0)
582     sp_reduce = symptom->stats.maxsp;
583     else
584     sp_reduce = (int) MAX (1, victim->stats.maxsp * symptom->stats.maxsp / 100.0);
585     victim->stats.sp = MAX (0, victim->stats.sp - sp_reduce);
586    
587     /* create the symptom "other arch" object and drop it here
588     * under every part of the monster
589     * The victim may well have died.
590     */
591 elmex 1.1
592 root 1.4 if (victim->map == NULL)
593     return 0;
594     if (symptom->other_arch)
595     {
596     object *tmp;
597    
598     tmp = victim;
599     if (tmp->head != NULL)
600     tmp = tmp->head;
601 pippijn 1.15 for ( /*tmp initialised above */ ; tmp != NULL; tmp = tmp->more)
602 root 1.4 {
603     new_ob = arch_to_object (symptom->other_arch);
604     new_ob->x = tmp->x;
605     new_ob->y = tmp->y;
606     new_ob->map = victim->map;
607     insert_ob_in_map (new_ob, victim->map, victim, 0);
608 root 1.2 }
609 elmex 1.1 }
610 root 1.4 new_draw_info (NDI_UNIQUE | NDI_RED, 0, victim, symptom->msg);
611    
612     return 1;
613 elmex 1.1 }
614    
615    
616     /* possibly infect due to direct physical contact
617     i.e., AT_PHYSICAL-- called from "hit_player_attacktype" */
618    
619 root 1.4 int
620     check_physically_infect (object *victim, object *hitter)
621     {
622 elmex 1.1 object *walk;
623 root 1.4
624 elmex 1.1 /* search for diseases, give every disease a chance to infect */
625 root 1.4 for (walk = hitter->inv; walk != NULL; walk = walk->below)
626     if (walk->type == DISEASE)
627     infect_object (victim, walk, 0);
628 elmex 1.1 return 1;
629     }
630    
631     /* find a disease in someone*/
632 root 1.4 object *
633     find_disease (object *victim)
634     {
635 elmex 1.1 object *walk;
636 root 1.4
637     for (walk = victim->inv; walk; walk = walk->below)
638     if (walk->type == DISEASE)
639     return walk;
640 elmex 1.1 return NULL;
641     }
642 root 1.4
643 elmex 1.1 /* do the cure disease stuff, from the spell "cure disease" */
644    
645 root 1.4 int
646     cure_disease (object *sufferer, object *caster)
647     {
648     object *disease, *next;
649     int casting_level;
650     int cure = 0;
651    
652     if (caster)
653     casting_level = caster->level;
654     else
655     casting_level = 1000; /* if null caster, CURE all. */
656    
657     for (disease = sufferer->inv; disease; disease = next)
658     {
659     next = disease->below;
660    
661     if (disease->type == DISEASE)
662     { /* attempt to cure this disease */
663     /* If caster lvel is higher than disease level, cure chance
664     * is automatic. If lower, then the chance is basically
665     * 1 in level_diff - if there is a 5 level difference, chance
666     * is 1 in 5.
667     */
668     if ((casting_level >= disease->level) || (!(random_roll (0, (disease->level - casting_level - 1), caster, PREFER_LOW))))
669     {
670    
671     remove_symptoms (disease);
672     cure = 1;
673 root 1.9
674 root 1.4 if (caster)
675     change_exp (caster, disease->stats.exp, caster->chosen_skill ? &caster->chosen_skill->skill : (const char *) 0, 0);
676 root 1.9
677     disease->destroy ();
678 root 1.2 }
679     }
680 elmex 1.1 }
681 root 1.4 if (cure)
682     {
683     /* Only draw these messages once */
684     if (caster)
685     new_draw_info_format (NDI_UNIQUE, 0, caster, "You cure a disease!");
686     new_draw_info (NDI_UNIQUE, 0, sufferer, "You no longer feel diseased.");
687 elmex 1.1 }
688     return 1;
689     }
690    
691     /* reduces disease progression: reduce_symptoms
692     * return true if we actually reduce a disease.
693     */
694    
695 root 1.4 int
696     reduce_symptoms (object *sufferer, int reduction)
697     {
698     object *walk;
699     int success = 0;
700    
701     for (walk = sufferer->inv; walk; walk = walk->below)
702     {
703     if (walk->type == SYMPTOM)
704     {
705     if (walk->value > 0)
706     {
707     success = 1;
708     walk->value = MAX (0, walk->value - 2 * reduction);
709     /* give the disease time to modify this symptom,
710     * and reduce its severity. */
711     walk->speed_left = 0;
712 root 1.2 }
713 root 1.4 }
714 elmex 1.1 }
715 root 1.4 if (success)
716     new_draw_info (NDI_UNIQUE, 0, sufferer, "Your illness seems less severe.");
717     return success;
718 elmex 1.1 }