Crossfire Server, Trunk  R20513
disease.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
20 /*
21  * For DISEASES:
22  * Stat Property Definition
23  *
24  * attacktype Attack effects Attacktype of the disease. usu. AT_GODPOWER.
25  * other_arch Creation object created and dropped when symptom moved.
26  * title Message When the "disease" "infects" something, it will
27  * print "title victim!!!" to the player who owns
28  * the "disease".
29  * wc+ Infectiousness How well the plague spreads person-to-person
30  * magic+ Range range of infection
31  * Stats* Disability What stats are reduced by the disease (str con...)
32  * maxhp+ Persistence How long the disease can last OUTSIDE the host.
33  * * value TimeLeft Counter for persistence
34  * dam^ Damage How much damage it does (%?).
35  * maxgrace+ Duration How long before the disease is naturally cured.
36  * food DurCount Counter for Duration
37  *
38  * speed Speed How often the disease moves.
39  * last_sp^ Lethargy Percentage of max speed--10 = 10% speed.
40  *
41  * maxsp^ Mana deplete Saps mana.
42  * ac^ Progressiveness How the diseases increases in severity.
43  * last_eat*^ Deplete food saps food if negative
44  * last_heal GrantImmunity If nonzero, disease does NOT grant immunity
45  * when it runs out
46  *
47  * exp experience experience awarded when plague cured
48  * hp*^ ReduceRegen reduces regeneration of disease-bearer
49  * sp*^ ReduceSpRegen reduces spellpoint regeneration
50  *
51  * name Name Name of the plague
52  * msg message What the plague says when it strikes.
53  * race those affected species/race the plague strikes (* = everything)
54  * level Plague Level General description of the plague's deadliness
55  * armour Attenuation reduction in wc per generation of disease.
56  * This builds in a self-limiting factor.
57  *
58  *
59  * Explanations:
60  * * means this # should be negative to cause adverse effect.
61  * + means that this effect is modulated in spells by ldur
62  * ^ means that this effect is modulated in spells by ldam
63  *
64  * attacktype is the attacktype used by the disease to smite "dam" damage with.
65  *
66  * wc/127 is the chance of someone in range catching it.
67  *
68  * magic is the range at which infection may occur. If negative, the range is
69  * NOT level dependent.
70  *
71  * Stats are stat modifications. These should typically be negative.
72  *
73  * maxhp is how long the disease will persist if the host dies and "drops" it,
74  * in "disease moves", i.e., moves of the disease. If negative, permanent.
75  *
76  * value is the counter for maxhp, it starts at maxhp and drops...
77  *
78  * dam if positive, it is straight damage. if negative, a %-age.
79  *
80  * maxgrace how long in "disease moves" the disease lasts in the host, if negative,
81  * permanent until cured.
82  *
83  * food if negative, disease is permanent. otherwise, decreases at <speed>,
84  * disease goes away at food=0, set to "maxgrace" on infection.
85  *
86  * speed is the speed of the disease, how fast "disease moves" occur.
87  *
88  * last_sp is the lethargy imposed on the player by the disease. A lethargy
89  * of "1" reduces the players speed to 1% of its normal value.
90  *
91  * maxsp how much mana is sapped per "disease move". if negative, a %-age is
92  * taken.
93  *
94  * ac every "disease move" the severity of the symptoms are increased by
95  * ac/100. (severity = 1 + (accumlated_progression)/100)
96  *
97  * last_eat increases food usage if negative.
98  *
99  *
100  *
101  * For SYMPTOMS:
102  *
103  * Stats modify stats
104  * hp modify regen
105  * value progression counter (multiplier = value/100)
106  * food modify food use (from last_eat in DISEASE)
107  * maxsp suck mana ( as noted for DISEASE)
108  * last_sp Lethargy
109  * msg What to say
110  * speed speed of movement, from DISEASE
111  */
112 
113 #include "global.h"
114 
115 #include <assert.h>
116 #include <stdlib.h>
117 #include <string.h>
118 
119 #include "living.h"
120 #include "object.h"
121 #include "skills.h"
122 #include "sounds.h"
123 #include "spells.h"
124 #include "sproto.h"
125 
126 static void remove_symptoms(object *disease);
127 static object *find_symptom(object *disease);
128 static void check_infection(object *disease);
129 static void do_symptoms(object *disease);
130 static void grant_immunity(object *disease);
131 
132 
133 
134 /* IMPLEMENTATION NOTES
135 
136 Diseases may be contageous. They are objects which exist in a player's
137 inventory. They themselves do nothing, except modify Symptoms, or
138 spread to other live objects. Symptoms are what actually damage the player:
139 these are their own object. */
140 
153 static int is_susceptible_to_disease(object *victim, object *disease) {
154  /* Non living and DMs are immune. */
155  if (!QUERY_FLAG(victim, FLAG_ALIVE) || QUERY_FLAG(victim, FLAG_WIZ))
156  return 0;
157 
158  if (strstr(disease->race, "*") && !QUERY_FLAG(victim, FLAG_UNDEAD))
159  return 1;
160 
161  if ((disease->race == undead_name) && QUERY_FLAG(victim, FLAG_UNDEAD))
162  return 1;
163 
164  if ((victim->race && strstr(disease->race, victim->race))
165  || strstr(disease->race, victim->name))
166  return 1;
167 
168  return 0;
169 }
170 
180 int move_disease(object *disease) {
181  /* first task is to determine if the disease is inside or outside of someone.
182  * If outside, we decrement 'value' until we're gone.
183  */
184 
185  /* DMs don't infect, and don't suffer either. */
186  if (disease->env && QUERY_FLAG(disease->env, FLAG_WIZ))
187  return 0;
188 
189  if (disease->env == NULL) { /* we're outside of someone */
190  if (disease->stats.maxhp > 0)
191  disease->value--;
192  if (disease->value == 0) {
193  object_remove(disease);
195  return 1;
196  }
197  } else {
198  /* if we're inside a person, have the disease run its course */
199  /* negative foods denote "perpetual" diseases. */
200  if (disease->stats.food > 0) {
201  disease->stats.food--;
202  if (disease->stats.food == 0) {
203  remove_symptoms(disease); /* remove the symptoms of this disease */
204  grant_immunity(disease);
205  object_remove(disease);
207  return 1;
208  }
209  }
210  }
211  /* check to see if we infect others */
212  check_infection(disease);
213 
214  /* impose or modify the symptoms of the disease */
215  if (disease->env && is_susceptible_to_disease(disease->env, disease))
216  do_symptoms(disease);
217 
218  return 0;
219 }
220 
232 static void remove_symptoms(object *disease) {
233  object *symptom, *victim = NULL;
234 
235  assert(disease != NULL);
236 
237  while ((symptom = find_symptom(disease)) != NULL) {
238  if (!victim)
239  victim = symptom->env;
240  object_remove(symptom);
242  }
243  if (victim)
244  fix_object(victim);
245 }
246 
255 static object *find_symptom(object *disease) {
256  assert(disease->env != NULL);
257 
258  /* check the inventory for symptoms */
259  return object_find_by_type_and_name(disease->env, SYMPTOM, disease->name);
260 }
261 
268 static void check_infection(object *disease) {
269  int x, y, range, mflags;
270  mapstruct *map, *map2;
271  int16_t i, j, i2, j2;
272 
273  range = abs(disease->magic);
274  if (disease->env) {
275  x = disease->env->x;
276  y = disease->env->y;
277  map = disease->env->map;
278  } else {
279  x = disease->x;
280  y = disease->y;
281  map = disease->map;
282  }
283 
284  if (map == NULL)
285  return;
286  for (i = x-range; i <= x+range; i++) {
287  for (j = y-range; j <= y+range; j++) {
288  mflags = get_map_flags(map, &map2, i, j, &i2, &j2);
289  if (!(mflags&P_OUT_OF_MAP) && (mflags&P_IS_ALIVE)) {
290  FOR_MAP_PREPARE(map2, i2, j2, tmp)
291  infect_object(tmp, disease, 0);
292  FOR_MAP_FINISH();
293  }
294  }
295  }
296 }
297 
317 int infect_object(object *victim, object *disease, int force) {
318  object *tmp;
319  object *new_disease;
320  object *owner;
321 
322  victim = HEAD(victim);
323 
324  /* don't infect inanimate objects */
325  if (!QUERY_FLAG(victim, FLAG_MONSTER) && !(victim->type == PLAYER))
326  return 0;
327 
328  /* check and see if victim can catch disease: diseases
329  * are specific
330  */
331  if (!is_susceptible_to_disease(victim, disease))
332  return 0;
333 
334  /* If disease is on battleground, only infect other victims on battleground.
335  Not checking results in spectators being infected, which could lead to PK. */
336  if ((disease->map && op_on_battleground(disease, NULL, NULL, NULL))
337  || (disease->env && op_on_battleground(disease->env, NULL, NULL, NULL)))
338  if (!op_on_battleground(victim, NULL, NULL, NULL))
339  return 0;
340 
341  /* roll the dice on infection before doing the inventory check! */
342  if (!force && (random_roll(0, 126, victim, PREFER_HIGH) >= disease->stats.wc))
343  return 0;
344 
345  /* do an immunity check */
346 
347  /* There used to (IMO) be a flaw in the below - it used to be the case
348  * that if level check was done for both immunity and disease. This could
349  * result in a person with multiple afflictions of the same disease
350  * (eg, level 1 cold, level 2 cold, level 3 cold, etc), as long as
351  * they were cast in that same order. Instead, change it so that
352  * if you diseased, you can't get diseased more.
353  */
354  tmp = object_find_by_type_and_name(HEAD(victim), SIGN, disease->name);
355  if (tmp != NULL && tmp->level >= disease->level)
356  return 0; /*Immune! */
357  tmp = object_find_by_type_and_name(HEAD(victim), DISEASE, disease->name);
358  if (tmp != NULL)
359  return 0; /* already diseased; XXX: increase disease level? */
360 
361  /* If we've gotten this far, go ahead and infect the victim. */
362  new_disease = object_new();
363  object_copy(disease, new_disease);
364  new_disease->stats.food = disease->stats.maxgrace;
365  new_disease->value = disease->stats.maxhp;
366  new_disease->stats.wc -= disease->last_grace; /* self-limiting factor */
367 
368  /* Unfortunately, object_set_owner does the wrong thing to the skills pointers
369  * resulting in exp going into the owners *current *chosen skill.
370  */
371  owner = object_get_owner(disease);
372  if (owner) {
373  object_set_owner(new_disease, owner);
374 
375  /* Only need to update skill if different */
376  if (new_disease->skill != disease->skill) {
377  if (new_disease->skill)
378  free_string(new_disease->skill);
379  if (disease->skill)
380  new_disease->skill = add_refcount(disease->skill);
381  }
382  } else { /* for diseases which are passed by hitting, set owner and praying skill*/
383  if (disease->env && disease->env->type == PLAYER) {
384  object *player = disease->env;
385 
386  object_set_owner(new_disease, player);
387  /* the skill pointer for these diseases should already be set up -
388  * hardcoding in 'praying' is not the right approach.
389  */
390  }
391  }
392 
393  object_insert_in_ob(new_disease, victim);
394  /* This appears to be a horrible case of overloading 'NO_PASS'
395  * for meaning in the diseases.
396  */
397  new_disease->move_block = 0;
398  owner = object_get_owner(new_disease);
399  if (owner && owner->type == PLAYER) {
400  char buf[128];
401 
402  /* if the disease has a title, it has a special infection message
403  * This messages is printed in the form MESSAGE victim
404  */
405  if (new_disease->title)
406  snprintf(buf, sizeof(buf), "%s %s!!", disease->title, victim->name);
407  else
408  snprintf(buf, sizeof(buf), "You infect %s with your disease, %s!", victim->name, new_disease->name);
409 
410  if (victim->type == PLAYER)
412  buf);
413  else
415  buf);
416  }
417  if (victim->type == PLAYER)
419  "You suddenly feel ill.");
420 
421  return 1;
422 }
423 
432 static void do_symptoms(object *disease) {
433  object *symptom;
434  object *victim;
435  object *tmp;
436  victim = disease->env;
437 
438  /* This is a quick hack - for whatever reason, disease->env will point
439  * back to disease, causing endless loops. Why this happens really needs
440  * to be found, but this should at least prevent the infinite loops.
441  */
442 
443  if (victim == NULL || victim == disease)
444  return;/* no-one to inflict symptoms on */
445 
446  /* DMs don't suffer from diseases. */
447  if (QUERY_FLAG(victim, FLAG_WIZ))
448  return;
449 
450  symptom = find_symptom(disease);
451  if (symptom == NULL) {
452  /* no symptom? need to generate one! */
453  object *new_symptom;
454  int reduce_level = 0;
455 
456  /* first check and see if the carrier of the disease is immune. If so, no symptoms! */
457  if (!is_susceptible_to_disease(victim, disease))
458  return;
459 
460  /* check for an actual immunity */
461  /* do an immunity check */
462  tmp = object_find_by_type_and_name(HEAD(victim), SIGN, disease->name);
463  if (tmp != NULL) {
464  if (tmp->level >= disease->level)
465  return; /*Immune! */
466  /* partially immune */
467  reduce_level = tmp->level;
468  }
469 
470  new_symptom = create_archetype(ARCH_SYMPTOM);
471 
472  /* Something special done with dam. We want diseases to be more
473  * random in what they'll kill, so we'll make the damage they
474  * do random, note, this has a weird effect with progressive diseases.
475  */
476  if (disease->stats.dam != 0) {
477  int dam = disease->stats.dam;
478 
479  /* reduce the damage, on average, 50%, and making things random. */
480 
481  dam = random_roll(1, FABS(dam), victim, PREFER_LOW);
482  if (disease->stats.dam < 0)
483  dam = -dam;
484  new_symptom->stats.dam = dam;
485  }
486 
487  new_symptom->stats.maxsp = disease->stats.maxsp;
488  new_symptom->stats.food = new_symptom->stats.maxgrace;
489 
490  FREE_AND_COPY(new_symptom->name, disease->name);
491  FREE_AND_COPY(new_symptom->name_pl, disease->name);
492  new_symptom->level = disease->level - reduce_level;
493  new_symptom->speed = disease->speed;
494  new_symptom->value = 0;
495  new_symptom->stats.Str = disease->stats.Str;
496  new_symptom->stats.Dex = disease->stats.Dex;
497  new_symptom->stats.Con = disease->stats.Con;
498  new_symptom->stats.Wis = disease->stats.Wis;
499  new_symptom->stats.Int = disease->stats.Int;
500  new_symptom->stats.Pow = disease->stats.Pow;
501  new_symptom->stats.Cha = disease->stats.Cha;
502  new_symptom->stats.sp = disease->stats.sp;
503  new_symptom->stats.food = disease->last_eat;
504  new_symptom->stats.maxsp = disease->stats.maxsp;
505  new_symptom->last_sp = disease->last_sp;
506  new_symptom->stats.exp = 0;
507  new_symptom->stats.hp = disease->stats.hp;
508  object_set_msg(new_symptom, disease->msg);
509  new_symptom->attacktype = disease->attacktype;
510  new_symptom->other_arch = disease->other_arch;
511 
512  object_set_owner(new_symptom, object_get_owner(disease));
513  if (new_symptom->skill != disease->skill) {
514  if (new_symptom->skill)
515  free_string(new_symptom->skill);
516  if (disease->skill)
517  new_symptom->skill = add_refcount(disease->skill);
518  }
519  new_symptom->move_block = 0;
520  object_insert_in_ob(new_symptom, victim);
521  return;
522  }
523 
524  /* now deal with progressing diseases: we increase the debility
525  * caused by the symptoms.
526  */
527 
528  if (disease->stats.ac != 0) {
529  float scale;
530  int i;
531  int8_t cur_stat;
532 
533  symptom->value += disease->stats.ac;
534  scale = 1.0+symptom->value/100.0;
535  /* now rescale all the debilities */
536  for (i = 0; i<NUM_STATS; i++) {
537  cur_stat = get_attr_value(&disease->stats, i);
538  cur_stat = (int)(scale * cur_stat);
539  set_attr_value(&symptom->stats, i, cur_stat);
540  }
542 
543  symptom->stats.dam = (int)(scale*disease->stats.dam);
544  symptom->stats.sp = (int)(scale*disease->stats.sp);
545  symptom->stats.food = (int)(scale*disease->last_eat);
546  symptom->stats.maxsp = (int)(scale*disease->stats.maxsp);
547  symptom->last_sp = (int)(scale*disease->last_sp);
548  symptom->stats.exp = 0;
549  symptom->stats.hp = (int)(scale*disease->stats.hp);
550  object_set_msg(symptom, disease->msg);
551  symptom->attacktype = disease->attacktype;
552  symptom->other_arch = disease->other_arch;
553  }
554  SET_FLAG(symptom, FLAG_APPLIED);
555  fix_object(victim);
556 }
557 
564 static void grant_immunity(object *disease) {
565  object *immunity;
566 
567  /* Don't give immunity to this disease if last_heal is set. */
568  if (disease->last_heal)
569  return;
570 
571  assert(disease->env != NULL);
572 
573  /* first, search for an immunity of the same name */
574  immunity = object_find_by_type_and_name(disease->env, SIGN, disease->name);
575  if (immunity != NULL) {
576  immunity->level = disease->level;
577  return; /* just update the existing immunity. */
578  }
579  immunity = create_archetype("immunity");
580  immunity->name = add_string(disease->name);
581  immunity->level = disease->level;
582  immunity->move_block = 0;
583  object_insert_in_ob(immunity, disease->env);
584 }
585 
592 void move_symptom(object *symptom) {
593  object *victim = symptom->env;
594  object *new_ob;
595  int sp_reduce;
596  tag_t tag = symptom->count;
597 
598  if (victim == NULL || victim->map == NULL) { /* outside a monster/player, die immediately */
599  object_remove(symptom);
601  return;
602  }
603 
604  if (symptom->stats.dam > 0)
605  hit_player(victim, symptom->stats.dam, symptom, symptom->attacktype, 1);
606  else
607  hit_player(victim, MAX(1, -victim->stats.maxhp*symptom->stats.dam/100.0), symptom, symptom->attacktype, 1);
608 
609  /* In most cases, if the victim has been freed, the logic that
610  * does that will also free the symptom, so check for that.
611  */
612  if (QUERY_FLAG(victim, FLAG_FREED)) {
613  if (!object_was_destroyed(symptom, tag)) {
614  object_remove(symptom);
616  }
617  return;
618  }
619 
620  if (symptom->stats.maxsp > 0)
621  sp_reduce = symptom->stats.maxsp;
622  else
623  sp_reduce = MAX(1, victim->stats.maxsp*symptom->stats.maxsp/100.0);
624  victim->stats.sp = MAX(0, victim->stats.sp-sp_reduce);
625 
626  /* create the symptom "other arch" object and drop it here
627  * under every part of the monster
628  * The victim may well have died.
629  */
630 
631  if (symptom->other_arch) {
632  object *tmp;
633 
634  for (tmp = HEAD(victim); tmp != NULL; tmp = tmp->more) {
635  char name[MAX_BUF];
636 
637  new_ob = arch_to_object(symptom->other_arch);
638  snprintf(name, sizeof(name), "%s's %s", victim->name, new_ob->name);
639  FREE_AND_COPY(new_ob->name, name);
640  if (new_ob->name_pl != NULL) {
641  snprintf(name, sizeof(name), "%s's %s", victim->name, new_ob->name_pl);
642  FREE_AND_COPY(new_ob->name_pl, name);
643  }
644  object_insert_in_map_at(new_ob, tmp->map, victim, 0, tmp->x, tmp->y);
645  }
646  }
647  if (!symptom->msg) {
648  LOG(llevError, "BUG: move_symptom(): symptom %d (%s) without message!\n", symptom->count, symptom->name);
649  return;
650  }
652  symptom->msg);
653 }
654 
663 void check_physically_infect(object *victim, object *hitter) {
664  /* search for diseases, give every disease a chance to infect */
665  FOR_INV_PREPARE(hitter, walk)
666  if (walk->type == DISEASE)
667  infect_object(victim, walk, 0);
668  FOR_INV_FINISH();
669 }
670 
685 int cure_disease(object *sufferer, object *caster, sstring skill) {
686  int casting_level;
687  int cure = 0;
688 
689  if (caster)
690  casting_level = caster->level;
691  else
692  casting_level = 1000; /* if null caster, CURE all. */
693 
694  FOR_INV_PREPARE(sufferer, disease) {
695  if (disease->type == DISEASE && !QUERY_FLAG(disease, FLAG_STARTEQUIP)) {
696  /* attempt to cure this disease. God-given diseases are given by the god, so don't remove them */
697  /* If caster lvel is higher than disease level, cure chance
698  * is automatic. If lower, then the chance is basically
699  * 1 in level_diff - if there is a 5 level difference, chance
700  * is 1 in 5.
701  */
702  if ((casting_level >= disease->level)
703  || (!(random_roll(0, (disease->level-casting_level-1), caster, PREFER_LOW)))) {
704  remove_symptoms(disease);
705  object_remove(disease);
706  cure = 1;
707  if (caster)
708  change_exp(caster, disease->stats.exp, skill, 0);
710  }
711  }
712  } FOR_INV_FINISH();
713  if (cure) {
714  /* Only draw these messages once */
715  if (caster)
717  "You cure a disease!");
718 
720  "You no longer feel diseased.");
721  }
722  return cure;
723 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: main.c:315
Error, serious thing.
Definition: logger.h:11
object * object_find_by_type_and_name(const object *who, int type, const char *name)
Find object in inventory by type and name.
Definition: object.c:3999
void set_attr_value(living *stats, int attr, int8_t value)
Sets Str/Dex/con/Wis/Cha/Int/Pow in stats to value, depending on what attr is (STR to POW)...
Definition: living.c:218
int8_t Int
Definition: living.h:35
One player.
Definition: player.h:92
Sound-related defines.
int8_t ac
Armour Class, how hard to hit, the lower the better.
Definition: living.h:37
Spell-related defines: spellpath, subtypes, ...
uint8_t max_stat
Maximum stat value - 255 should be sufficient.
Definition: global.h:322
const char * race
Human, goblin, dragon, etc.
Definition: object.h:318
#define SET_FLAG(xyz, p)
Definition: define.h:223
sstring add_refcount(sstring str)
This will increase the refcount of the string str.
Definition: shstr.c:210
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
#define MSG_TYPE_SPELL
Spell related info.
Definition: newclient.h:387
int32_t last_heal
Last healed.
Definition: object.h:357
int16_t maxgrace
Maximum grace.
Definition: living.h:44
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
#define PREFER_LOW
Definition: define.h:600
#define ARCH_SYMPTOM
Archetype for disease symptom.
Definition: object.h:580
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:358
static void grant_immunity(object *disease)
Grants immunity to a disease.
Definition: disease.c:564
int64_t exp
Experience.
Definition: living.h:46
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
Definition: object.h:68
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.c:313
#define MAX(x, y)
Definition: compat.h:20
int16_t sp
Spell points.
Definition: living.h:41
Global type definitions and header inclusions.
static void check_infection(object *disease)
Searches around for more victims to infect.
Definition: disease.c:268
struct archt * other_arch
Pointer used for various things - mostly used for what this objects turns into or what this object cr...
Definition: object.h:413
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.c:310
int16_t maxsp
Max spell points.
Definition: living.h:42
int8_t Con
Definition: living.h:35
int16_t hp
Hit Points.
Definition: living.h:39
int cure_disease(object *sufferer, object *caster, sstring skill)
Do the cure disease stuff, from the spell "cure disease".
Definition: disease.c:685
#define FLAG_UNDEAD
Monster is undead.
Definition: define.h:270
void object_set_owner(object *op, object *owner)
Sets the owner and sets the skill and exp pointers to owner&#39;s current skill and experience objects...
Definition: object.c:601
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1368
const char * title
Of foo, etc.
Definition: object.h:317
int16_t y
Position in the map for this object.
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
#define NDI_RED
Definition: newclient.h:224
int16_t maxhp
Max hit points.
Definition: living.h:40
#define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_END
End of a bad effect.
Definition: newclient.h:561
See Sign & Magic Mouth.
Definition: object.h:211
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it...
Definition: object.c:1037
void move_symptom(object *symptom)
Make the symptom do the nasty things it does.
Definition: disease.c:592
const char * name_pl
The plural name of the object.
Definition: object.h:315
object * create_archetype(const char *name)
Finds which archetype matches the given name, and returns a new object containing a copy of the arche...
Definition: arch.c:620
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.c:2690
EXTERN const char * undead_name
Definition: global.h:163
#define MSG_TYPE_SPELL_HEAL
Healing related spells.
Definition: newclient.h:626
signed short int16_t
Definition: win32.h:160
int8_t Wis
Definition: living.h:35
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
#define snprintf
Definition: win32.h:46
#define MSG_TYPE_ATTRIBUTE
Changes to attributes (stats, resistances, etc)
Definition: newclient.h:380
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:712
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
const char * name
The name of the object, obviously...
Definition: object.h:311
struct obj * env
Pointer to the object which is the environment.
Definition: object.h:293
int16_t last_grace
As last_sp, except for grace.
Definition: object.h:359
int8_t Cha
Definition: living.h:35
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:251
Number of statistics.
Definition: living.h:18
int op_on_battleground(object *op, int *x, int *y, archetype **trophy)
Check if the given object (usually a player) is standing on a battleground tile.
Definition: player.c:4232
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:12
static int is_susceptible_to_disease(object *victim, object *disease)
Check if victim is susceptible to disease.
Definition: disease.c:153
float speed
The overall speed of this object.
Definition: object.h:328
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:594
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Changes experience to a player/monster.
Definition: living.c:2076
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
#define MSG_TYPE_ATTACK
Attack related messages.
Definition: newclient.h:385
#define MSG_TYPE_ATTACK_DID_HIT
Player hit something else.
Definition: newclient.h:607
int16_t x
Definition: object.h:326
const char * skill
Name of the skill this object uses/grants.
Definition: object.h:321
int32_t last_eat
How long since we last ate.
Definition: object.h:356
Skill-related defines, including subtypes.
int8_t wc
Weapon Class, how skilled, the lower the better.
Definition: living.h:36
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:765
int8_t Str
Definition: living.h:35
const char * sstring
Strings that should be manipulated through add_string() and free_string().
Definition: global.h:40
See Player.
Definition: object.h:107
Object structure, the core of Crossfire.
#define PREFER_HIGH
Definition: define.h:599
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:342
static object * find_symptom(object *disease)
Find a symptom for a disease in disease&#39;s env.
Definition: disease.c:255
#define FREE_AND_COPY(sv, nv)
Release the shared string if not NULL, and make it a reference to nv.
Definition: global.h:213
signed char int8_t
Type definitions for fixed-size integer types.
Definition: win32.h:158
void check_physically_infect(object *victim, object *hitter)
Possibly infect due to direct physical contact i.e., AT_PHYSICAL.
Definition: disease.c:663
tag_t count
Unique object number for this object.
Definition: object.h:299
living stats
Str, Con, Dex, etc.
Definition: object.h:368
int8_t Dex
Definition: living.h:35
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
const char * msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:322
#define FLAG_STARTEQUIP
Object was given to player at start.
Definition: define.h:268
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
static void remove_symptoms(object *disease)
Remove any symptoms of disease.
Definition: disease.c:232
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
void object_copy(const object *src_ob, object *dest_ob)
Copy object first frees everything allocated by the second object, and then copies the contents of th...
Definition: object.c:838
int8_t Pow
Definition: living.h:35
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_...
Definition: map.c:302
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
int move_disease(object *disease)
Ticks the clock for disease: infect, aggravate symptoms, ...
Definition: disease.c:180
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:758
MoveType move_block
What movement types this blocks.
Definition: object.h:425
Structure containing object statistics.
void object_set_msg(object *op, const char *msg)
Set the message field of an object.
Definition: object.c:4695
This is a game-map.
Definition: map.h:325
#define P_IS_ALIVE
Something alive is on this space.
Definition: map.h:237
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.c:42
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.c:1861
int infect_object(object *victim, object *disease, int force)
Try to infect something with a disease.
Definition: disease.c:317
int16_t level
Level of creature or object.
Definition: object.h:351
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.c:1120
See Disease.
Definition: object.h:244
struct obj * more
Pointer to the rest of a large body of objects.
Definition: object.h:295
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.c:571
int32_t value
How much money it is worth (or contains)
Definition: object.h:350
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.c:559
int8_t magic
Any magical bonuses to this item.
Definition: object.h:348
static void do_symptoms(object *disease)
This function monitors the symptoms caused by the disease (if any), causes symptoms, and modifies existing symptoms in the case of existing diseases.
Definition: disease.c:432
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:705
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
#define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_START
Start of a bad effect to the player.
Definition: newclient.h:558
int32_t food
How much food in stomach.
Definition: living.h:47
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:233
void check_stat_bounds(living *stats, int8_t min_stat, int8_t max_stat)
Ensures that all stats (str/dex/con/wis/cha/int) are within the passed in range of min_stat and max_s...
Definition: living.c:354