Crossfire Server, Trunk  R21024
spell_attack.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 
24 #include "global.h"
25 
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "object.h"
31 #include "living.h"
32 #include "sproto.h"
33 #include "spells.h"
34 #include "sounds.h"
35 
36 /***************************************************************************
37  * BOLT CODE
38  ***************************************************************************/
39 
61 int fire_bolt(object *op, object *caster, int dir, object *spob) {
62  object *tmp = NULL;
63  int mflags;
64 
65  if (!spob->other_arch)
66  return 0;
67 
68  tmp = arch_to_object(spob->other_arch);
69  if (tmp == NULL)
70  return 0;
71 
72  /* peterm: level dependency for bolts */
73  tmp->stats.dam = spob->stats.dam+SP_level_dam_adjust(caster, spob);
74  tmp->attacktype = spob->attacktype;
75  if (spob->slaying)
76  tmp->slaying = add_refcount(spob->slaying);
77  tmp->range = spob->range+SP_level_range_adjust(caster, spob);
78  tmp->duration = spob->duration+SP_level_duration_adjust(caster, spob);
79  tmp->stats.Dex = spob->stats.Dex;
80  tmp->stats.Con = spob->stats.Con;
81 
82  tmp->direction = dir;
84 
85  object_set_owner(tmp, op);
86  set_spell_skill(op, caster, spob, tmp);
87 
88  mflags = get_map_flags(op->map, &tmp->map, op->x+DIRX(tmp), op->y+DIRY(tmp), &tmp->x, &tmp->y);
89  if (mflags&P_OUT_OF_MAP) {
91  return 0;
92  }
93  if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(tmp->map, tmp->x, tmp->y))) {
94  if (!QUERY_FLAG(tmp, FLAG_REFLECTING)) {
96  return 0;
97  }
98  tmp->direction = absdir(tmp->direction+4);
99  tmp->map = op->map;
100  tmp->x = op->x;
101  tmp->y = op->y;
102  }
103  tmp = object_insert_in_map_at(tmp, op->map, op, 0, tmp->x, tmp->y);
104  if (tmp != NULL)
105  ob_process(tmp);
106  return 1;
107 }
108 
109 /***************************************************************************
110  *
111  * BULLET/BALL CODE
112  *
113  ***************************************************************************/
114 
121 void explode_bullet(object *op) {
122  tag_t op_tag = op->count;
123  object *tmp, *owner;
124 
125  if (op->other_arch == NULL) {
126  LOG(llevError, "BUG: explode_bullet(): op without other_arch\n");
127  object_remove(op);
129  return;
130  }
131 
132  if (op->env) {
133  object *env;
134 
135  env = object_get_env_recursive(op);
136  if (env->map == NULL || out_of_map(env->map, env->x, env->y)) {
137  LOG(llevError, "BUG: explode_bullet(): env out of map\n");
138  object_remove(op);
140  return;
141  }
142  object_remove(op);
143  object_insert_in_map_at(op, env->map, op, INS_NO_MERGE|INS_NO_WALK_ON, env->x, env->y);
144  } else if (out_of_map(op->map, op->x, op->y)) {
145  LOG(llevError, "BUG: explode_bullet(): op out of map\n");
146  object_remove(op);
148  return;
149  }
150 
151  if (op->attacktype) {
152  hit_map(op, 0, op->attacktype, 1);
153  if (object_was_destroyed(op, op_tag))
154  return;
155  }
156 
157  /* other_arch contains what this explodes into */
158  tmp = arch_to_object(op->other_arch);
159 
160  object_copy_owner(tmp, op);
161  if (tmp->skill)
163  if (op->skill)
164  tmp->skill = add_refcount(op->skill);
165 
166  owner = object_get_owner(op);
167  if ((tmp->attacktype&AT_HOLYWORD || tmp->attacktype&AT_GODPOWER) && owner && !tailor_god_spell(tmp, owner)) {
168  object_remove(op);
170  return;
171  }
172 
173  /* special for bombs - it actually has sane values for these */
174  if (op->type == SPELL_EFFECT && op->subtype == SP_BOMB) {
175  tmp->attacktype = op->attacktype;
176  tmp->range = op->range;
177  tmp->stats.dam = op->stats.dam;
178  tmp->duration = op->duration;
179  } else {
180  if (op->attacktype&AT_MAGIC)
181  tmp->attacktype |= AT_MAGIC;
182  /* Spell doc describes what is going on here */
183  tmp->stats.dam = op->dam_modifier;
184  tmp->range = op->stats.maxhp;
185  tmp->duration = op->stats.hp;
186  }
187 
188  /* Used for spell tracking - just need a unique val for this spell -
189  * the count of the parent should work fine.
190  */
191  tmp->stats.maxhp = op->count;
192  if (tmp->stats.maxhp == 0)
193  tmp->stats.maxhp = 1;
194 
195  /* Set direction of cone explosion */
196  if (tmp->type == SPELL_EFFECT && tmp->subtype == SP_CONE)
197  tmp->stats.sp = op->direction;
198 
199  /* Prevent recursion */
200  op->move_on = 0;
201 
202  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
203  /* remove the firebullet */
204  if (!object_was_destroyed(op, op_tag)) {
205  object_remove(op);
207  }
208 }
209 
217 void check_bullet(object *op) {
218  tag_t op_tag = op->count, tmp_tag;
219  int dam, mflags;
220  mapstruct *m;
221  int16_t sx, sy;
222 
223  mflags = get_map_flags(op->map, &m, op->x, op->y, &sx, &sy);
224 
225  if (!(mflags&P_IS_ALIVE) && !OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
226  return;
227 
228  if (op->other_arch) {
229  /* explode object will also remove op */
230  explode_bullet(op);
231  return;
232  }
233 
234  /* If nothing alive on this space, no reason to do anything further */
235  if (!(mflags&P_IS_ALIVE))
236  return;
237 
238  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp) {
239  if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
240  tmp_tag = tmp->count;
241  dam = hit_player(tmp, op->stats.dam, op, op->attacktype, 1);
242  if (object_was_destroyed(op, op_tag) || !object_was_destroyed(tmp, tmp_tag) || (op->stats.dam -= dam) < 0) {
243  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
244  object_remove(op);
246  return;
247  }
248  }
249  }
250  } FOR_MAP_FINISH();
251 }
252 
253 /*****************************************************************************
254  *
255  * CONE RELATED FUNCTIONS
256  *
257  *****************************************************************************/
258 
265 void cone_drop(object *op) {
266  object *new_ob = arch_to_object(op->other_arch);
267 
268  new_ob->level = op->level;
269  object_set_owner(new_ob, object_get_owner(op));
270 
271  /* preserve skill ownership */
272  if (op->skill && op->skill != new_ob->skill) {
273  if (new_ob->skill)
274  free_string(new_ob->skill);
275  new_ob->skill = add_refcount(op->skill);
276  }
277  object_insert_in_map_at(new_ob, op->map, op, 0, op->x, op->y);
278 }
279 
297 int cast_cone(object *op, object *caster, int dir, object *spell) {
298  object *tmp;
299  int i, success = 0, range_min = -1, range_max = 1;
300  mapstruct *m;
301  int16_t sx, sy;
302  MoveType movetype;
303 
304  if (!spell->other_arch)
305  return 0;
306 
307  if (op->type == PLAYER && QUERY_FLAG(op, FLAG_UNDEAD) && op->attacktype&AT_TURN_UNDEAD) {
308  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "Your undead nature prevents you from turning undead!");
309  return 0;
310  }
311 
312  if (!dir) {
313  range_min = 0;
314  range_max = 8;
315  }
316 
317  /* Need to know what the movetype of the object we are about
318  * to create is, so we can know if the space we are about to
319  * insert it into is blocked.
320  */
321  movetype = spell->other_arch->clone.move_type;
322 
323  for (i = range_min; i <= range_max; i++) {
324  int16_t x, y, d;
325 
326  /* We can't use absdir here, because it never returns
327  * 0. If this is a rune, we want to hit the person on top
328  * of the trap (d==0). If it is not a rune, then we don't want
329  * to hit that person.
330  */
331  d = dir+i;
332  while (d < 0)
333  d += 8;
334  while (d > 8)
335  d -= 8;
336 
337  /* If it's not a rune, we don't want to blast the caster.
338  * In that case, we have to see - if dir is specified,
339  * turn this into direction 8. If dir is not specified (all
340  * direction) skip - otherwise, one line would do more damage
341  * because 0 direction will go through 9 directions - necessary
342  * for the rune code.
343  */
344  if (caster->type != RUNE && d == 0) {
345  if (dir != 0)
346  d = 8;
347  else
348  continue;
349  }
350 
351  x = op->x+freearr_x[d];
352  y = op->y+freearr_y[d];
353 
354  if (get_map_flags(op->map, &m, x, y, &sx, &sy)&P_OUT_OF_MAP)
355  continue;
356 
357  if ((movetype&GET_MAP_MOVE_BLOCK(m, sx, sy)) == movetype)
358  continue;
359 
360  success = 1;
361  tmp = arch_to_object(spell->other_arch);
362  object_set_owner(tmp, op);
363  set_spell_skill(op, caster, spell, tmp);
364  tmp->level = caster_level(caster, spell);
365  tmp->attacktype = spell->attacktype;
366 
367  /* holy word stuff */
368  if ((tmp->attacktype&AT_HOLYWORD) || (tmp->attacktype&AT_GODPOWER)) {
369  if (!tailor_god_spell(tmp, op))
370  return 0;
371  }
372 
373  if (dir)
374  tmp->stats.sp = dir;
375  else
376  tmp->stats.sp = i;
377 
378  tmp->range = spell->range+SP_level_range_adjust(caster, spell);
379 
380  /* If casting it in all directions, it doesn't go as far */
381  if (dir == 0) {
382  tmp->range /= 4;
383  if (tmp->range < 2 && spell->range >= 2)
384  tmp->range = 2;
385  }
386  tmp->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
387  tmp->duration = spell->duration+SP_level_duration_adjust(caster, spell);
388 
389  /* Special bonus for fear attacks */
390  if (tmp->attacktype&AT_FEAR) {
391  if (caster->type == PLAYER)
392  tmp->duration += get_fear_bonus(caster->stats.Cha);
393  else
394  tmp->duration += caster->level/3;
395  }
397  if (caster->type == PLAYER)
398  tmp->duration += get_turn_bonus(caster->stats.Wis)/5;
399  else
400  tmp->duration += caster->level/3;
401  }
402 
403  if (!(tmp->move_type&MOVE_FLY_LOW))
404  LOG(llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", spell->other_arch->name);
405 
406  if (!tmp->move_on && tmp->stats.dam) {
407  LOG(llevDebug, "cast_cone(): arch %s doesn't have move_on set\n", spell->other_arch->name);
408  }
409 
410  /* This is used for tracking spells so that one effect doesn't hit
411  * a single space too many times.
412  */
413  tmp->stats.maxhp = tmp->count;
414  if (tmp->stats.maxhp == 0)
415  tmp->stats.maxhp = 1;
416 
417  object_insert_in_map_at(tmp, m, op, 0, sx, sy);
418 
419  if (tmp->other_arch)
420  cone_drop(tmp);
421  }
422  return success;
423 }
424 
425 /****************************************************************************
426  *
427  * BOMB related code
428  *
429  ****************************************************************************/
430 
447 int create_bomb(object *op, object *caster, int dir, object *spell) {
448  object *tmp;
449  int mflags;
450  int16_t dx = op->x+freearr_x[dir], dy = op->y+freearr_y[dir];
451  mapstruct *m;
452 
453  mflags = get_map_flags(op->map, &m, dx, dy, &dx, &dy);
454  if ((mflags&P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK(m, dx, dy)&MOVE_WALK)) {
455  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "There is something in the way.");
456  return 0;
457  }
458  tmp = arch_to_object(spell->other_arch);
459 
460  /* level dependencies for bomb */
461  tmp->range = spell->range+SP_level_range_adjust(caster, spell);
462  tmp->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
463  tmp->duration = spell->duration+SP_level_duration_adjust(caster, spell);
464  tmp->attacktype = spell->attacktype;
465 
466  object_set_owner(tmp, op);
467  set_spell_skill(op, caster, spell, tmp);
468  object_insert_in_map_at(tmp, m, op, 0, dx, dy);
469  return 1;
470 }
471 
472 /****************************************************************************
473  *
474  * smite related spell code.
475  *
476  ****************************************************************************/
477 
496 static object *get_pointed_target(object *op, int dir, int range, int type) {
497  object *target;
498  int16_t x, y;
499  int dist, mflags;
500  mapstruct *mp;
501 
502  if (dir == 0)
503  return NULL;
504 
505  for (dist = 1; dist < range; dist++) {
506  x = op->x+freearr_x[dir]*dist;
507  y = op->y+freearr_y[dir]*dist;
508  mp = op->map;
509  mflags = get_map_flags(op->map, &mp, x, y, &x, &y);
510 
511  if (mflags&P_OUT_OF_MAP)
512  return NULL;
513  if ((type&SPELL_MANA) && (mflags&P_NO_MAGIC))
514  return NULL;
515  if ((type&SPELL_GRACE) && (mflags&P_NO_CLERIC))
516  return NULL;
517  if (GET_MAP_MOVE_BLOCK(mp, x, y)&MOVE_FLY_LOW)
518  return NULL;
519 
520  if (mflags&P_IS_ALIVE) {
521  target = map_find_by_flag(mp, x, y, FLAG_MONSTER);
522  if (target != NULL) {
523  return target;
524  }
525  }
526  }
527  return NULL;
528 }
529 
546 int cast_smite_spell(object *op, object *caster, int dir, object *spell) {
547  object *effect, *target;
548  const object *god = find_god(determine_god(op));
549  int range;
550 
551  range = spell->range+SP_level_range_adjust(caster, spell);
552  target = get_pointed_target(op, dir, range, spell->stats.grace ? SPELL_GRACE : SPELL_MANA);
553 
554  /* Bunch of conditions for casting this spell. Note that only
555  * require a god if this is a cleric spell (requires grace).
556  * This makes this spell much more general purpose - it can be used
557  * by wizards also, which is good, because I think this is a very
558  * interesting spell.
559  * if it is a cleric spell, you need a god, and the creature
560  * can't be friendly to your god.
561  */
562 
563  if (!target
564  || QUERY_FLAG(target, FLAG_REFL_SPELL)
565  || (!god && spell->stats.grace)
566  || (target->title && god && !strcmp(target->title, god->name))
567  || (target->race && god && strstr(target->race, god->race))) {
568  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Your request is unheeded.");
569  return 0;
570  }
571 
572  if (spell->other_arch)
573  effect = arch_to_object(spell->other_arch);
574  else
575  return 0;
576 
577  /* tailor the effect by priest level and worshipped God */
578  effect->level = caster_level(caster, spell);
579  effect->attacktype = spell->attacktype;
580  if (effect->attacktype&(AT_HOLYWORD|AT_GODPOWER)) {
581  if (tailor_god_spell(effect, op))
583  "%s answers your call!",
584  determine_god(op));
585  else {
586  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Your request is ignored.");
587  return 0;
588  }
589  }
590 
591  /* size of the area of destruction */
592  effect->range = spell->range+SP_level_range_adjust(caster, spell);
593  effect->duration = spell->duration+SP_level_range_adjust(caster, spell);
594 
595  if (effect->attacktype&AT_DEATH) {
596  effect->level = spell->stats.dam+SP_level_dam_adjust(caster, spell);
597 
598  /* casting death spells at undead isn't a good thing */
599  if (QUERY_FLAG(target, FLAG_UNDEAD)) {
600  if (random_roll(0, 2, op, PREFER_LOW)) {
601  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Idiot! Your spell boomerangs!");
602  effect->x = op->x;
603  effect->y = op->y;
604  } else {
605  char target_name[HUGE_BUF];
606 
607  query_name(target, target_name, HUGE_BUF);
610  "The %s looks stronger!",
611  target_name);
612  target->stats.hp = target->stats.maxhp*2;
614  return 0;
615  }
616  }
617  } else {
618  /* how much woe to inflict :) */
619  effect->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
620  }
621 
622  if (effect->type == SPELL_EFFECT && effect->subtype == SP_EXPLOSION) {
623  /* Used for spell tracking - just need a unique val for this spell -
624  * the count of the parent should work fine.
625  *
626  * Without this the server can easily get overloaded at high level
627  * spells.
628  */
629  effect->stats.maxhp = spell->count;
630  if (effect->stats.maxhp == 0)
631  effect->stats.maxhp = 1;
632  }
633 
634  object_set_owner(effect, op);
635  set_spell_skill(op, caster, spell, effect);
636 
637  /* ok, tell it where to be, and insert! */
638  object_insert_in_map_at(effect, target->map, op, 0, target->x, target->y);
639 
640  return 1;
641 }
642 
643 /****************************************************************************
644  * Destruction
645  ****************************************************************************/
646 
665 static int make_object_glow(object *op, int radius, int time) {
666  object *tmp;
667 
668  /* some things are unaffected... */
669  if (op->path_denied&PATH_LIGHT)
670  return 0;
671 
673  tmp->speed = 0.01;
674  tmp->stats.food = time;
676  tmp->glow_radius = radius;
677  if (tmp->glow_radius > MAX_LIGHT_RADII)
679 
680  tmp->x = op->x;
681  tmp->y = op->y;
682  if (tmp->speed < MIN_ACTIVE_SPEED)
683  tmp->speed = MIN_ACTIVE_SPEED; /* safety */
684  tmp = object_insert_in_ob(tmp, op);
685  if (tmp->glow_radius > op->glow_radius)
686  op->glow_radius = tmp->glow_radius;
687 
688  if (!tmp->env || op != tmp->env) {
689  LOG(llevError, "make_object_glow() failed to insert glowing force in %s\n", op->name);
690  return 0;
691  }
692  return 1;
693 }
694 
707 int cast_destruction(object *op, object *caster, object *spell_ob) {
708  int i, j, range, mflags, friendly = 0, dam, dur;
709  int16_t sx, sy;
710  mapstruct *m;
711  object *tmp, *found_skill;
712  const char *skill;
713 
714  range = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
715  dam = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
716  dur = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
717  if (QUERY_FLAG(op, FLAG_FRIENDLY) || op->type == PLAYER)
718  friendly = 1;
719 
720  /* destruction doesn't use another spell object, so we need
721  * update op's skill pointer so that exp is properly awarded.
722  * We do some shortcuts here - since this is just temporary
723  * and we'll reset the values back, we don't need to go through
724  * the full share string/free_string route.
725  */
726  skill = op->skill;
727  if (caster == op)
728  op->skill = spell_ob->skill;
729  else if (caster->skill)
730  op->skill = caster->skill;
731  else
732  op->skill = NULL;
733 
734  /* The skill may be NULL (if op is not a player but eg a bulletwall), but that's ok because change_skill does what is right. */
735  found_skill = find_skill_by_name(op, op->skill);
736  change_skill(op, found_skill, 1);
737 
738  for (i = -range; i < range; i++) {
739  for (j = -range; j < range; j++) {
740  m = op->map;
741  sx = op->x+i;
742  sy = op->y+j;
743  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
744  if (mflags&P_OUT_OF_MAP)
745  continue;
746  if (mflags&P_IS_ALIVE) {
747  tmp = NULL;
748  FOR_MAP_PREPARE(m, sx, sy, inv) {
749  tmp = inv;
750  if (QUERY_FLAG(tmp, FLAG_ALIVE) || tmp->type == PLAYER)
751  break;
752  } FOR_MAP_FINISH();
753  if (tmp) {
754  tmp = HEAD(tmp);
755  if ((friendly && !QUERY_FLAG(tmp, FLAG_FRIENDLY) && tmp->type != PLAYER)
756  || (!friendly && (QUERY_FLAG(tmp, FLAG_FRIENDLY) || tmp->type == PLAYER))) {
757  if (spell_ob->subtype == SP_DESTRUCTION) {
758  hit_player(tmp, dam, op, spell_ob->attacktype, 0);
759  if (spell_ob->other_arch) {
760  tmp = arch_to_object(spell_ob->other_arch);
761  object_insert_in_map_at(tmp, m, op, 0, sx, sy);
762  }
763  } else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100) {
764  if (make_object_glow(tmp, 1, dur) && spell_ob->other_arch) {
765  object *effect = arch_to_object(spell_ob->other_arch);
766  object_insert_in_map_at(effect, m, op, 0, sx, sy);
767  }
768  }
769  }
770  }
771  }
772  }
773  }
774  op->skill = skill;
775  return 1;
776 }
777 
778 /***************************************************************************
779  *
780  * CURSE
781  *
782  ***************************************************************************/
783 
800 int cast_curse(object *op, object *caster, object *spell_ob, int dir) {
801  const object *god = find_god(determine_god(op));
802  object *tmp, *force;
803 
804  tmp = get_pointed_target(op, (dir == 0) ? op->direction : dir, spell_ob->range, SPELL_GRACE);
805  if (!tmp) {
806  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "There is no one in that direction to curse.");
807  return 0;
808  }
809 
810  /* If we've already got a force of this type, don't add a new one. */
811  force = NULL;
812  FOR_INV_PREPARE(tmp, inv) {
813  if (inv->type == FORCE && inv->subtype == FORCE_CHANGE_ABILITY) {
814  if (inv->name == spell_ob->name) {
815  force = inv;
816  break;
817  } else if (spell_ob->race && spell_ob->race == inv->name) {
820  "You can not cast %s while %s is in effect",
821  spell_ob->name, force->name_pl);
822  return 0;
823  }
824  }
825  } FOR_INV_FINISH();
826 
827  if (force == NULL) {
828  force = create_archetype(FORCE_NAME);
829  force->subtype = FORCE_CHANGE_ABILITY;
830  free_string(force->name);
831  if (spell_ob->race)
832  force->name = add_refcount(spell_ob->race);
833  else
834  force->name = add_refcount(spell_ob->name);
835  free_string(force->name_pl);
836  force->name_pl = add_refcount(spell_ob->name);
837  } else {
838  int duration;
839 
840  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
841  if (duration > force->duration) {
842  force->duration = duration;
843  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_SUCCESS, "You recast the spell while in effect.");
844  } else {
845  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Recasting the spell had no effect.");
846  }
847  return 1;
848  }
849  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
850  force->speed = 1.0;
851  force->speed_left = -1.0;
852  SET_FLAG(force, FLAG_APPLIED);
853 
854  if (god) {
855  if (spell_ob->last_grace)
856  force->path_repelled = god->path_repelled;
857  if (spell_ob->last_grace)
858  force->path_denied = god->path_denied;
860  "You are a victim of %s's curse!",
861  god->name);
862  } else
863  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Your curse seems empty.");
864 
865 
866  if (tmp != op && op->type == PLAYER)
868  "You curse %s!",
869  tmp->name);
870 
871  force->stats.ac = spell_ob->stats.ac;
872  force->stats.wc = spell_ob->stats.wc;
873 
874  change_abil(tmp, force); /* Mostly to display any messages */
875  object_insert_in_ob(force, tmp);
876  fix_object(tmp);
877 
878  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
879  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
880  }
881 
882  return 1;
883 }
884 
885 /**********************************************************************
886  * mood change
887  * Arguably, this may or may not be an attack spell. But since it
888  * effects monsters, it seems best to put it into this file
889  ***********************************************************************/
890 
904 int mood_change(object *op, object *caster, object *spell) {
905  object *tmp, *head;
906  const object *god;
907  int done_one, range, mflags, level, at, best_at, immunity_chance = 50;
908  int16_t x, y, nx, ny;
909  mapstruct *m;
910  const char *race;
911 
912  /* We pre-compute some values here so that we don't have to keep
913  * doing it over and over again.
914  */
915  god = find_god(determine_god(op));
916  level = caster_level(caster, spell);
917  range = spell->range+SP_level_range_adjust(caster, spell);
918  race = object_get_value(spell, "immunity_chance");
919  if (race != NULL) {
920  immunity_chance = atoi(race);
921  if (immunity_chance < 0 || immunity_chance > 100) {
922  LOG(llevError, "ignoring invalid immunity_chance %d for %s\n", immunity_chance, spell->arch->name);
923  immunity_chance = 50;
924  }
925  }
926 
927  /* On the bright side, no monster should ever have a race of GOD_...
928  * so even if the player doesn't worship a god, if race=GOD_.., it
929  * won't ever match anything.
930  */
931  if (!spell->race)
932  race = NULL;
933  else if (god && !strcmp(spell->race, "GOD_SLAYING"))
934  race = god->slaying;
935  else if (god && !strcmp(spell->race, "GOD_FRIEND"))
936  race = god->race;
937  else
938  race = spell->race;
939 
940  for (x = op->x-range; x <= op->x+range; x++)
941  for (y = op->y-range; y <= op->y+range; y++) {
942  done_one = 0;
943  m = op->map;
944  mflags = get_map_flags(m, &m, x, y, &nx, &ny);
945  if (mflags&P_OUT_OF_MAP)
946  continue;
947 
948  /* If there is nothing living on this space, no need to go further */
949  if (!(mflags&P_IS_ALIVE))
950  continue;
951 
952  head = map_find_by_flag(m, nx, ny, FLAG_MONSTER);
953  /* There can be living objects that are not monsters */
954  if (!head || head->type == PLAYER)
955  continue;
956 
957  /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */
958  if (race && head->race && !strstr(race, head->race))
959  continue;
960  if (QUERY_FLAG(head, FLAG_UNDEAD) && !QUERY_FLAG(spell, FLAG_UNDEAD))
961  continue;
962 
963  /* Now do a bunch of stuff related to saving throws */
964  best_at = -1;
965  if (spell->attacktype) {
966  for (at = 0; at < NROFATTACKS; at++)
967  if (spell->attacktype&(1<<at))
968  if (best_at == -1 || head->resist[at] > head->resist[best_at])
969  best_at = at;
970 
971  if (best_at == -1)
972  at = 0;
973  else {
974  if (head->resist[best_at] == 100)
975  continue;
976  else
977  at = head->resist[best_at]/5;
978  }
979  at -= level/5;
980  if (did_make_save(head, head->level, at))
981  continue;
982  } else { /* spell->attacktype */
983  const char *value;
984 
985  /*
986  * Spell has no attacktype (charm&such), so we'll have a specific saving:
987  * if spell level < monster level, no go
988  * else, chance of effect = 20+min(50, 2*(spell level-monster level))
989  *
990  * The chance will then be in the range [20-70] percent, not too bad.
991  *
992  * This is required to fix the 'charm monster' abuse, where a player level 1 can
993  * charm a level 125 monster...
994  *
995  * Ryo, august 14th
996  */
997  if (head->level > level)
998  continue;
999  if (random_roll(0, 100, caster, PREFER_LOW) >= (20+MIN(50, 2*(level-head->level)))) {
1000  /* Additionnally, randomly make the monster immune to that spell. */
1001  if (random_roll(0, 100, caster, PREFER_HIGH) <= immunity_chance) {
1002  object_set_value(head, "no_mood_change", "1", 1);
1003  }
1004  continue;
1005  }
1006 
1007  /*
1008  * There was no way to ensure immunity, so added a key/value for that.
1009  * Nicolas, september 2010.
1010  */
1011  value = object_get_value(head, "no_mood_change");
1012  if (value && strcmp(value, "1") == 0)
1013  continue;
1014  }
1015 
1016  /* Done with saving throw. Now start effecting the monster */
1017 
1018  /* aggravation */
1019  if (QUERY_FLAG(spell, FLAG_MONSTER)) {
1020  CLEAR_FLAG(head, FLAG_SLEEP);
1021  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1022  remove_friendly_object(head);
1023 
1024  done_one = 1;
1025  object_set_enemy(head, op);
1026  }
1027 
1028  /* calm monsters */
1029  if (QUERY_FLAG(spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG(head, FLAG_UNAGGRESSIVE)) {
1030  SET_FLAG(head, FLAG_UNAGGRESSIVE);
1031  object_set_enemy(head, NULL);
1032  done_one = 1;
1033  }
1034 
1035  /* berserk monsters */
1036  if (QUERY_FLAG(spell, FLAG_BERSERK) && !QUERY_FLAG(head, FLAG_BERSERK)) {
1037  SET_FLAG(head, FLAG_BERSERK);
1038  done_one = 1;
1039  }
1040  /* charm */
1041  if (QUERY_FLAG(spell, FLAG_NO_ATTACK) && !QUERY_FLAG(head, FLAG_FRIENDLY)) {
1042  SET_FLAG(head, FLAG_FRIENDLY);
1043  /* Prevent uncontrolled outbreaks of self replicating monsters.
1044  Typical use case is charm, go somewhere, use aggravation to make hostile.
1045  This could lead to fun stuff like mice outbreak in bigworld and server crawl. */
1046  CLEAR_FLAG(head, FLAG_GENERATOR);
1047  object_set_owner(head, op);
1048  set_spell_skill(op, caster, spell, head);
1049  add_friendly_object(head);
1050  head->attack_movement = PETMOVE;
1051  done_one = 1;
1052  share_exp(op, head->stats.exp/2, head->skill, SK_EXP_ADD_SKILL);
1053  head->stats.exp = 0;
1054  }
1055 
1056  /* If a monster was affected, put an effect in */
1057  if (done_one && spell->other_arch) {
1058  tmp = arch_to_object(spell->other_arch);
1059  object_insert_in_map_at(tmp, m, op, 0, nx, ny);
1060  }
1061  } /* for y */
1062 
1063  return 1;
1064 }
1065 
1066 
1084 int fire_swarm(object *op, object *caster, object *spell, int dir) {
1085  object *tmp;
1086  int i;
1087 
1088  if (!spell->other_arch)
1089  return 0;
1090 
1092  object_set_owner(tmp, op); /* needed so that if swarm elements kill, caster gets xp.*/
1093  set_spell_skill(op, caster, spell, tmp);
1094 
1095  tmp->level = caster_level(caster, spell); /*needed later, to get level dep. right.*/
1096  tmp->spell = arch_to_object(spell->other_arch);
1097 
1098  tmp->attacktype = tmp->spell->attacktype;
1099 
1100  if (tmp->attacktype&AT_HOLYWORD || tmp->attacktype&AT_GODPOWER) {
1101  if (!tailor_god_spell(tmp, op))
1102  return 1;
1103  }
1104  tmp->duration = SP_level_duration_adjust(caster, spell);
1105  for (i = 0; i < spell->duration; i++)
1106  tmp->duration += die_roll(1, 3, op, PREFER_HIGH);
1107 
1108  tmp->direction = dir;
1109  tmp->invisible = 1;
1110  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1111  return 1;
1112 }
1113 
1132 int cast_light(object *op, object *caster, object *spell, int dir) {
1133  object *target = NULL, *tmp = NULL;
1134  int16_t x, y;
1135  int dam, mflags;
1136  mapstruct *m;
1137 
1138  dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
1139 
1140  if (!dir) {
1141  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "In what direction?");
1142  return 0;
1143  }
1144 
1145  x = op->x+freearr_x[dir];
1146  y = op->y+freearr_y[dir];
1147  m = op->map;
1148 
1149  mflags = get_map_flags(m, &m, x, y, &x, &y);
1150 
1151  if (mflags&P_OUT_OF_MAP) {
1152  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Nothing is there.");
1153  return 0;
1154  }
1155 
1156  if (mflags&P_IS_ALIVE && spell->attacktype) {
1157  target = map_find_by_flag(m, x, y, FLAG_MONSTER);
1158  if (target != NULL) {
1159  /* oky doky. got a target monster. Lets make a blinding attack */
1160  (void)hit_player(target, dam, op, spell->attacktype, 1);
1161  return 1; /* one success only! */
1162  }
1163  }
1164 
1165  /* no live target, perhaps a wall is in the way? */
1166  if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y))) {
1167  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "Something is in the way.");
1168  return 0;
1169  }
1170 
1171  /* ok, looks groovy to just insert a new light on the map */
1172  tmp = arch_to_object(spell->other_arch);
1173  if (!tmp) {
1174  LOG(llevError, "Error: spell arch for cast_light() missing.\n");
1175  return 0;
1176  }
1177  tmp->stats.food = spell->duration+SP_level_duration_adjust(caster, spell);
1178  if (tmp->glow_radius) {
1179  tmp->glow_radius = spell->range+SP_level_range_adjust(caster, spell);
1180  if (tmp->glow_radius > MAX_LIGHT_RADII)
1181  tmp->glow_radius = MAX_LIGHT_RADII;
1182  }
1183  object_insert_in_map_at(tmp, m, op, 0, x, y);
1184  return 1;
1185 }
1186 
1203 int cast_cause_disease(object *op, object *caster, object *spell, int dir) {
1204  int16_t x, y;
1205  int i, mflags, range, dam_mod, dur_mod;
1206  object *target_head;
1207  mapstruct *m;
1208 
1209  x = op->x;
1210  y = op->y;
1211 
1212  /* If casting from a scroll, no direction will be available, so refer to the
1213  * direction the player is pointing.
1214  */
1215  if (!dir)
1216  dir = op->facing;
1217  if (!dir)
1218  return 0; /* won't find anything if casting on ourself, so just return */
1219 
1220  /* Calculate these once here */
1221  range = spell->range+SP_level_range_adjust(caster, spell);
1222  dam_mod = SP_level_dam_adjust(caster, spell);
1223  dur_mod = SP_level_duration_adjust(caster, spell);
1224 
1225  /* search in a line for a victim */
1226  for (i = 1; i < range; i++) {
1227  x = op->x+i*freearr_x[dir];
1228  y = op->y+i*freearr_y[dir];
1229  m = op->map;
1230 
1231  mflags = get_map_flags(m, &m, x, y, &x, &y);
1232 
1233  if (mflags&P_OUT_OF_MAP)
1234  return 0;
1235 
1236  /* don't go through walls - presume diseases are airborne */
1237  if (GET_MAP_MOVE_BLOCK(m, x, y)&MOVE_FLY_LOW)
1238  return 0;
1239 
1240  /* Only bother looking on this space if there is something living here */
1241  if (mflags&P_IS_ALIVE) {
1242  /* search this square for a victim */
1243  FOR_MAP_PREPARE(m, x, y, walk) {
1244  /* Flags for monster is set on head only, so get it now */
1245  target_head = HEAD(walk);
1246  if (QUERY_FLAG(target_head, FLAG_MONSTER) || (target_head->type == PLAYER)) { /* found a victim */
1247  object *disease = arch_to_object(spell->other_arch);
1248 
1249  object_set_owner(disease, op);
1250  set_spell_skill(op, caster, spell, disease);
1251  disease->stats.exp = 0;
1252  disease->level = caster_level(caster, spell);
1253 
1254  /* do level adjustments */
1255  if (disease->stats.wc)
1256  disease->stats.wc += dur_mod/2;
1257 
1258  if (disease->magic > 0)
1259  disease->magic += dur_mod/4;
1260 
1261  if (disease->stats.maxhp > 0)
1262  disease->stats.maxhp += dur_mod;
1263 
1264  if (disease->stats.maxgrace > 0)
1265  disease->stats.maxgrace += dur_mod;
1266 
1267  if (disease->stats.dam) {
1268  if (disease->stats.dam > 0)
1269  disease->stats.dam += dam_mod;
1270  else
1271  disease->stats.dam -= dam_mod;
1272  }
1273 
1274  if (disease->last_sp) {
1275  disease->last_sp -= 2*dam_mod;
1276  if (disease->last_sp < 1)
1277  disease->last_sp = 1;
1278  }
1279 
1280  if (disease->stats.maxsp) {
1281  if (disease->stats.maxsp > 0)
1282  disease->stats.maxsp += dam_mod;
1283  else
1284  disease->stats.maxsp -= dam_mod;
1285  }
1286 
1287  if (disease->stats.ac)
1288  disease->stats.ac += dam_mod;
1289 
1290  if (disease->last_eat)
1291  disease->last_eat -= dam_mod;
1292 
1293  if (disease->stats.hp)
1294  disease->stats.hp -= dam_mod;
1295 
1296  if (disease->stats.sp)
1297  disease->stats.sp -= dam_mod;
1298 
1299  if (infect_object(target_head, disease, 1)) {
1300  object *flash; /* visual effect for inflicting disease */
1301 
1302  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_SUCCESS, "You inflict %s on %s!", disease->name, target_head->name);
1303 
1304  object_free_drop_inventory(disease); /* don't need this one anymore */
1306  object_insert_in_map_at(flash, walk->map, op, 0, x, y);
1307  return 1;
1308  }
1309  object_free_drop_inventory(disease);
1310  } /* Found a victim */
1311  } FOR_MAP_FINISH(); /* Search squares for living creature */
1312  } /* if living creature on square */
1313  } /* for range of spaces */
1314  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "No one caught anything!");
1315  return 1;
1316 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:315
#define AT_HOLYWORD
Definition: attack.h:97
void explode_bullet(object *op)
Definition: spell_attack.c:121
const char * determine_god(object *op)
Definition: gods.c:106
int8_t ac
Definition: living.h:38
int mood_change(object *op, object *caster, object *spell)
Definition: spell_attack.c:904
#define MOVE_WALK
Definition: define.h:407
int fire_swarm(object *op, object *caster, object *spell, int dir)
#define FORCE_CHANGE_ABILITY
Definition: spells.h:145
MoveType move_type
Definition: object.h:424
int change_skill(object *who, object *new_skill, int flag)
Definition: skill_util.c:356
uint8_t dam_modifier
Definition: object.h:407
MoveType move_on
Definition: object.h:427
static object * get_pointed_target(object *op, int dir, int range, int type)
Definition: spell_attack.c:496
#define FLAG_SLEEP
Definition: define.h:308
const char * race
Definition: object.h:318
int caster_level(const object *caster, const object *spell)
Definition: spell_util.c:233
uint16_t attack_movement
Definition: object.h:391
#define MAX_LIGHT_RADII
Definition: define.h:466
#define SET_FLAG(xyz, p)
Definition: define.h:223
sstring add_refcount(sstring str)
Definition: shstr.c:210
#define SP_CONE
Definition: spells.h:81
int cast_curse(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_attack.c:800
void object_copy_owner(object *op, object *clone)
Definition: object.c:688
#define FLAG_IS_USED_UP
Definition: define.h:260
object * object_get_env_recursive(object *op)
Definition: object.c:364
#define ARCH_DETECT_MAGIC
Definition: object.h:576
#define PATH_LIGHT
Definition: spells.h:32
#define FLAG_FRIENDLY
Definition: define.h:246
#define P_NO_MAGIC
Definition: map.h:227
static int make_object_glow(object *op, int radius, int time)
Definition: spell_attack.c:665
int8_t range
Definition: object.h:405
#define MSG_TYPE_SPELL
Definition: newclient.h:387
#define SPELL_GRACE
Definition: spells.h:59
unsigned char MoveType
Definition: define.h:432
#define MSG_TYPE_SPELL_FAILURE
Definition: newclient.h:628
int16_t maxgrace
Definition: living.h:45
void free_string(sstring str)
Definition: shstr.c:280
#define HUGE_BUF
Definition: define.h:37
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4264
object clone
Definition: object.h:470
int16_t duration
Definition: object.h:403
int16_t invisible
Definition: object.h:360
short freearr_x[SIZEOFFREE]
Definition: object.c:65
#define PREFER_LOW
Definition: define.h:602
int cast_light(object *op, object *caster, object *spell, int dir)
Definition: object.h:240
#define DIRX(xyz)
Definition: define.h:479
const char * slaying
Definition: object.h:319
int32_t last_sp
Definition: object.h:358
uint8_t subtype
Definition: object.h:339
int SP_level_dam_adjust(const object *caster, const object *spob)
Definition: spell_util.c:328
int64_t exp
Definition: living.h:47
method_ret ob_process(object *op)
Definition: ob_methods.c:62
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
#define FLAG_NO_ATTACK
Definition: define.h:363
int cast_cone(object *op, object *caster, int dir, object *spell)
Definition: spell_attack.c:297
void remove_friendly_object(object *op)
Definition: friend.c:56
int16_t sp
Definition: living.h:42
const object * find_god(const char *name)
Definition: gods.c:80
#define FLAG_REFLECTING
Definition: define.h:262
#define PETMOVE
Definition: define.h:519
uint32_t path_repelled
Definition: object.h:344
struct archt * other_arch
Definition: object.h:413
int absdir(int d)
Definition: object.c:3652
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:310
#define MSG_TYPE_VICTIM_SPELL
Definition: newclient.h:651
int16_t maxsp
Definition: living.h:43
#define MIN(x, y)
Definition: compat.h:17
int8_t Con
Definition: living.h:36
#define FLAG_REMOVED
Definition: define.h:232
int16_t hp
Definition: living.h:40
#define DIRY(xyz)
Definition: define.h:480
short freearr_y[SIZEOFFREE]
Definition: object.c:71
int fire_bolt(object *op, object *caster, int dir, object *spob)
Definition: spell_attack.c:61
#define AT_TURN_UNDEAD
Definition: attack.h:89
#define FLAG_UNDEAD
Definition: define.h:270
void object_set_owner(object *op, object *owner)
Definition: object.c:632
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4393
void object_free_drop_inventory(object *ob)
Definition: object.c:1389
int change_abil(object *op, object *tmp)
Definition: living.c:394
const char * title
Definition: object.h:317
int16_t y
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1936
int16_t maxhp
Definition: living.h:41
#define AT_GODPOWER
Definition: attack.h:96
#define SWARM_SPELL
Definition: spells.h:166
void object_update_turn_face(object *op)
Definition: object.c:1130
void cone_drop(object *op)
Definition: spell_attack.c:265
uint32_t path_denied
Definition: object.h:345
#define FLAG_ALIVE
Definition: define.h:230
#define FLAG_REFL_SPELL
Definition: define.h:275
#define MSG_TYPE_VICTIM
Definition: newclient.h:392
int get_turn_bonus(int stat)
Definition: living.c:2293
struct obj * spell
Definition: object.h:408
const char * name_pl
Definition: object.h:315
object * create_archetype(const char *name)
Definition: arch.c:617
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2705
float speed_left
Definition: object.h:329
#define MSG_TYPE_SPELL_SUCCESS
Definition: newclient.h:630
#define INS_ON_TOP
Definition: object.h:569
signed short int16_t
Definition: win32.h:160
#define MOVE_FLY_LOW
Definition: define.h:408
#define SP_BOMB
Definition: spells.h:82
int8_t Wis
Definition: living.h:36
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
struct mapdef * map
Definition: object.h:297
#define FOR_INV_FINISH()
Definition: define.h:714
int SP_level_duration_adjust(const object *caster, const object *spob)
Definition: spell_util.c:353
int16_t dam
Definition: living.h:46
#define MSG_TYPE_SPELL_ERROR
Definition: newclient.h:631
int die_roll(int num, int size, const object *op, int goodbad)
Definition: utils.c:122
void add_friendly_object(object *op)
Definition: friend.c:30
const char * name
Definition: object.h:311
int get_fear_bonus(int stat)
Definition: living.c:2305
struct obj * env
Definition: object.h:293
int hit_map(object *op, int dir, uint32_t type, int full_hit)
Definition: attack.c:322
#define INS_NO_WALK_ON
Definition: object.h:568
int16_t last_grace
Definition: object.h:359
int infect_object(object *victim, object *disease, int force)
Definition: disease.c:317
int8_t direction
Definition: object.h:334
int8_t Cha
Definition: living.h:36
#define ATNR_MAGIC
Definition: attack.h:50
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Definition: define.h:447
#define P_OUT_OF_MAP
Definition: map.h:251
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:192
#define SP_DESTRUCTION
Definition: spells.h:90
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:206
uint32_t tag_t
Definition: object.h:12
float speed
Definition: object.h:328
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Definition: object.h:592
int16_t x
Definition: object.h:326
#define FLAG_BERSERK
Definition: define.h:359
const char * skill
Definition: object.h:321
int32_t last_eat
Definition: object.h:356
int8_t wc
Definition: living.h:37
#define FOR_MAP_FINISH()
Definition: define.h:767
int16_t resist[NROFATTACKS]
Definition: object.h:341
Definition: object.h:107
int create_bomb(object *op, object *caster, int dir, object *spell)
Definition: spell_attack.c:447
int tailor_god_spell(object *spellop, object *caster)
Definition: gods.c:1318
#define PREFER_HIGH
Definition: define.h:601
uint32_t attacktype
Definition: object.h:342
#define FLAG_GENERATOR
Definition: define.h:248
#define INS_NO_MERGE
Definition: object.h:566
int16_t grace
Definition: living.h:44
object * map_find_by_flag(mapstruct *map, int x, int y, int flag)
Definition: map.c:2673
int cast_smite_spell(object *op, object *caster, int dir, object *spell)
Definition: spell_attack.c:546
int SP_level_range_adjust(const object *caster, const object *spob)
Definition: spell_util.c:379
tag_t count
Definition: object.h:299
living stats
Definition: object.h:368
#define SP_FAERY_FIRE
Definition: spells.h:118
int8_t Dex
Definition: living.h:36
struct archt * arch
Definition: object.h:412
void set_spell_skill(object *op, object *caster, object *spob, object *dest)
Definition: spell_util.c:94
#define AT_FEAR
Definition: attack.h:90
uint8_t type
Definition: object.h:338
void object_set_enemy(object *op, object *enemy)
Definition: object.c:710
#define SK_EXP_ADD_SKILL
Definition: skills.h:79
#define FLAG_APPLIED
Definition: define.h:235
#define NROFATTACKS
Definition: attack.h:17
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2306
#define FORCE_NAME
Definition: spells.h:169
#define AT_MAGIC
Definition: attack.h:77
int cast_cause_disease(object *op, object *caster, object *spell, int dir)
#define MIN_ACTIVE_SPEED
Definition: define.h:676
int8_t glow_radius
Definition: object.h:364
#define FLAG_MONSTER
Definition: define.h:245
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.c:300
#define NDI_UNIQUE
Definition: newclient.h:245
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
int did_make_save(const object *op, int level, int bonus)
Definition: living.c:2201
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:760
int cast_destruction(object *op, object *caster, object *spell_ob)
Definition: spell_attack.c:707
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:626
#define SPELL_MANA
Definition: spells.h:58
void share_exp(object *op, int64_t exp, const char *skill, int flag)
Definition: living.c:2231
Definition: map.h:325
#define P_IS_ALIVE
Definition: map.h:237
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:42
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Definition: attack.c:1871
int16_t level
Definition: object.h:351
int8_t facing
Definition: object.h:335
void fix_object(object *op)
Definition: living.c:1119
#define SP_EXPLOSION
Definition: spells.h:80
#define AT_DEATH
Definition: attack.h:93
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.c:213
object * arch_to_object(archetype *at)
Definition: arch.c:569
object * object_get_owner(object *op)
Definition: object.c:590
int8_t magic
Definition: object.h:348
const char * name
Definition: object.h:466
#define P_NO_CLERIC
Definition: map.h:238
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:707
void object_remove(object *op)
Definition: object.c:1669
void check_bullet(object *op)
Definition: spell_attack.c:217
int32_t food
Definition: living.h:48
Definition: object.h:224