Crossfire Server, Branches 1.12  R18729
spell_attack.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_spell_attack_c =
3  * "$Id: spell_attack.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 
7 /*
8  CrossFire, A Multiplayer game for X-windows
9 
10  Copyright (C) 2002-2006 Mark Wedel & Crossfire Development Team
11  Copyright (C) 1992 Frank Tore Johansen
12 
13  This program is free software; you can redistribute it and/or modify
14  it under the terms of the GNU General Public License as published by
15  the Free Software Foundation; either version 2 of the License, or
16  (at your option) any later version.
17 
18  This program is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with this program; if not, write to the Free Software
25  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 
27  The authors can be reached via e-mail at crossfire-devel@real-time.com
28 */
29 
40 #include <global.h>
41 #include <object.h>
42 #include <living.h>
43 #ifndef __CEXTRACT__
44 #include <sproto.h>
45 #endif
46 #include <spells.h>
47 #include <sounds.h>
48 
49 /***************************************************************************
50  *
51  * BOLT CODE
52  *
53  ***************************************************************************/
54 
78 int fire_bolt(object *op, object *caster, int dir, object *spob, object *skill) {
79  object *tmp = NULL;
80  int mflags;
81 
82  if (!spob->other_arch)
83  return 0;
84 
85  tmp = arch_to_object(spob->other_arch);
86  if (tmp == NULL)
87  return 0;
88 
89  /* peterm: level dependency for bolts */
90  tmp->stats.dam = spob->stats.dam+SP_level_dam_adjust(caster, spob);
91  tmp->attacktype = spob->attacktype;
92  if (spob->slaying)
93  tmp->slaying = add_refcount(spob->slaying);
94  tmp->range = spob->range+SP_level_range_adjust(caster, spob);
95  tmp->duration = spob->duration+SP_level_duration_adjust(caster, spob);
96  tmp->stats.Dex = spob->stats.Dex;
97  tmp->stats.Con = spob->stats.Con;
98 
99  tmp->direction = dir;
100  if (QUERY_FLAG(tmp, FLAG_IS_TURNABLE))
101  SET_ANIMATION(tmp, dir);
102 
103  set_owner(tmp, op);
104  set_spell_skill(op, caster, spob, tmp);
105 
106  tmp->x = op->x+DIRX(tmp);
107  tmp->y = op->y+DIRY(tmp);
108  tmp->map = op->map;
109 
110  mflags = get_map_flags(tmp->map, &tmp->map, tmp->x, tmp->y, &tmp->x, &tmp->y);
111  if (mflags&P_OUT_OF_MAP) {
112  free_object(tmp);
113  return 0;
114  }
115  if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(tmp->map, tmp->x, tmp->y))) {
116  if (!QUERY_FLAG(tmp, FLAG_REFLECTING)) {
117  free_object(tmp);
118  return 0;
119  }
120  tmp->x = op->x;
121  tmp->y = op->y;
122  tmp->direction = absdir(tmp->direction+4);
123  tmp->map = op->map;
124  }
125  if ((tmp = insert_ob_in_map(tmp, tmp->map, op, 0)) != NULL)
126  ob_process(tmp);
127  return 1;
128 }
129 
130 
131 
132 /***************************************************************************
133  *
134  * BULLET/BALL CODE
135  *
136  ***************************************************************************/
137 
144 void explode_bullet(object *op) {
145  tag_t op_tag = op->count;
146  object *tmp, *owner;
147 
148  if (op->other_arch == NULL) {
149  LOG(llevError, "BUG: explode_bullet(): op without other_arch\n");
150  remove_ob(op);
151  free_object(op);
152  return;
153  }
154 
155  if (op->env) {
156  object *env;
157 
158  env = object_get_env_recursive(op);
159  if (env->map == NULL || out_of_map(env->map, env->x, env->y)) {
160  LOG(llevError, "BUG: explode_bullet(): env out of map\n");
161  remove_ob(op);
162  free_object(op);
163  return;
164  }
165  remove_ob(op);
166  op->x = env->x;
167  op->y = env->y;
169  } else if (out_of_map(op->map, op->x, op->y)) {
170  LOG(llevError, "BUG: explode_bullet(): op out of map\n");
171  remove_ob(op);
172  free_object(op);
173  return;
174  }
175 
176  if (op->attacktype) {
177  hit_map(op, 0, op->attacktype, 1);
178  if (was_destroyed(op, op_tag))
179  return;
180  }
181 
182  /* other_arch contains what this explodes into */
183  tmp = arch_to_object(op->other_arch);
184 
185  copy_owner(tmp, op);
186  if (tmp->skill)
188  if (op->skill)
189  tmp->skill = add_refcount(op->skill);
190 
191  owner = get_owner(op);
192  if ((tmp->attacktype&AT_HOLYWORD || tmp->attacktype&AT_GODPOWER) && owner && !tailor_god_spell(tmp, owner)) {
193  remove_ob(op);
194  free_object(op);
195  return;
196  }
197  tmp->x = op->x;
198  tmp->y = op->y;
199 
200  /* special for bombs - it actually has sane values for these */
201  if (op->type == SPELL_EFFECT && op->subtype == SP_BOMB) {
202  tmp->attacktype = op->attacktype;
203  tmp->range = op->range;
204  tmp->stats.dam = op->stats.dam;
205  tmp->duration = op->duration;
206  } else {
207  if (op->attacktype&AT_MAGIC)
208  tmp->attacktype |= AT_MAGIC;
209  /* Spell doc describes what is going on here */
210  tmp->stats.dam = op->dam_modifier;
211  tmp->range = op->stats.maxhp;
212  tmp->duration = op->stats.hp;
213  }
214 
215  /* Used for spell tracking - just need a unique val for this spell -
216  * the count of the parent should work fine.
217  */
218  tmp->stats.maxhp = op->count;
219 
220  /* Set direction of cone explosion */
221  if (tmp->type == SPELL_EFFECT && tmp->subtype == SP_CONE)
222  tmp->stats.sp = op->direction;
223 
224  /* Prevent recursion */
225  op->move_on = 0;
226 
227  insert_ob_in_map(tmp, op->map, op, 0);
228  /* remove the firebullet */
229  if (!was_destroyed(op, op_tag)) {
230  remove_ob(op);
231  free_object(op);
232  }
233 }
234 
242 void check_bullet(object *op) {
243  tag_t op_tag = op->count, tmp_tag;
244  object *tmp;
245  int dam, mflags;
246  mapstruct *m;
247  sint16 sx, sy;
248 
249  mflags = get_map_flags(op->map, &m, op->x, op->y, &sx, &sy);
250 
251  if (!(mflags&P_IS_ALIVE) && !OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
252  return;
253 
254  if (op->other_arch) {
255  /* explode object will also remove op */
256  explode_bullet(op);
257  return;
258  }
259 
260  /* If nothing alive on this space, no reason to do anything further */
261  if (!(mflags&P_IS_ALIVE))
262  return;
263 
264  for (tmp = GET_MAP_OB(op->map, op->x, op->y); tmp != NULL; tmp = tmp->above) {
265  if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
266  tmp_tag = tmp->count;
267  dam = hit_player(tmp, op->stats.dam, op, op->attacktype, 1);
268  if (was_destroyed(op, op_tag) || !was_destroyed(tmp, tmp_tag) || (op->stats.dam -= dam) < 0) {
269  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
270  remove_ob(op);
271  free_object(op);
272  return;
273  }
274  }
275  }
276  }
277 }
278 
279 
301 int fire_bullet(object *op, object *caster, int dir, object *spob) {
302  object *tmp = NULL;
303  int mflags;
304 
305  if (!spob->other_arch)
306  return 0;
307 
308  tmp = arch_to_object(spob->other_arch);
309  if (tmp == NULL)
310  return 0;
311 
312  /* peterm: level dependency for bolts */
313  tmp->stats.dam = spob->stats.dam+SP_level_dam_adjust(caster, spob);
314  tmp->attacktype = spob->attacktype;
315  if (spob->slaying)
316  tmp->slaying = add_refcount(spob->slaying);
317 
318  tmp->range = 50;
319 
320  /* Need to store duration/range for the ball to use */
321  tmp->stats.hp = spob->duration+SP_level_duration_adjust(caster, spob);
322  tmp->stats.maxhp = spob->range+SP_level_range_adjust(caster, spob);
323  tmp->dam_modifier = spob->stats.food+SP_level_dam_adjust(caster, spob);
324 
325  tmp->direction = dir;
326  if (QUERY_FLAG(tmp, FLAG_IS_TURNABLE))
327  SET_ANIMATION(tmp, dir);
328 
329  set_owner(tmp, op);
330  set_spell_skill(op, caster, spob, tmp);
331 
332  tmp->x = op->x+freearr_x[dir];
333  tmp->y = op->y+freearr_y[dir];
334  tmp->map = op->map;
335 
336  mflags = get_map_flags(tmp->map, &tmp->map, tmp->x, tmp->y, &tmp->x, &tmp->y);
337  if (mflags&P_OUT_OF_MAP) {
338  free_object(tmp);
339  return 0;
340  }
341  if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(tmp->map, tmp->x, tmp->y))) {
342  if (!QUERY_FLAG(tmp, FLAG_REFLECTING)) {
343  free_object(tmp);
344  return 0;
345  }
346  tmp->x = op->x;
347  tmp->y = op->y;
348  tmp->direction = absdir(tmp->direction+4);
349  tmp->map = op->map;
350  }
351  if ((tmp = insert_ob_in_map(tmp, tmp->map, op, 0)) != NULL) {
352  check_bullet(tmp);
353  }
354  return 1;
355 }
356 
357 /*****************************************************************************
358  *
359  * CONE RELATED FUNCTIONS
360  *
361  *****************************************************************************/
362 
369 void cone_drop(object *op) {
370  object *new_ob = arch_to_object(op->other_arch);
371 
372  new_ob->x = op->x;
373  new_ob->y = op->y;
374  new_ob->level = op->level;
375  set_owner(new_ob, op->owner);
376 
377  /* preserve skill ownership */
378  if (op->skill && op->skill != new_ob->skill) {
379  if (new_ob->skill)
380  free_string(new_ob->skill);
381  new_ob->skill = add_refcount(op->skill);
382  }
383  insert_ob_in_map(new_ob, op->map, op, 0);
384 }
385 
403 int cast_cone(object *op, object *caster, int dir, object *spell) {
404  object *tmp;
405  int i, success = 0, range_min = -1, range_max = 1;
406  mapstruct *m;
407  sint16 sx, sy;
408  MoveType movetype;
409 
410  if (!spell->other_arch)
411  return 0;
412 
413  if (op->type == PLAYER && QUERY_FLAG(op, FLAG_UNDEAD) && op->attacktype&AT_TURN_UNDEAD) {
414  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "Your undead nature prevents you from turning undead!", NULL);
415  return 0;
416  }
417 
418  if (!dir) {
419  range_min = 0;
420  range_max = 8;
421  }
422 
423  /* Need to know what the movetype of the object we are about
424  * to create is, so we can know if the space we are about to
425  * insert it into is blocked.
426  */
427  movetype = spell->other_arch->clone.move_type;
428 
429  for (i = range_min; i <= range_max; i++) {
430  sint16 x, y, d;
431 
432  /* We can't use absdir here, because it never returns
433  * 0. If this is a rune, we want to hit the person on top
434  * of the trap (d==0). If it is not a rune, then we don't want
435  * to hit that person.
436  */
437  d = dir+i;
438  while (d < 0)
439  d += 8;
440  while (d > 8)
441  d -= 8;
442 
443  /* If it's not a rune, we don't want to blast the caster.
444  * In that case, we have to see - if dir is specified,
445  * turn this into direction 8. If dir is not specified (all
446  * direction) skip - otherwise, one line would do more damage
447  * becase 0 direction will go through 9 directions - necessary
448  * for the rune code.
449  */
450  if (caster->type != RUNE && d == 0) {
451  if (dir != 0)
452  d = 8;
453  else
454  continue;
455  }
456 
457  x = op->x+freearr_x[d];
458  y = op->y+freearr_y[d];
459 
460  if (get_map_flags(op->map, &m, x, y, &sx, &sy)&P_OUT_OF_MAP)
461  continue;
462 
463  if ((movetype&GET_MAP_MOVE_BLOCK(m, sx, sy)) == movetype)
464  continue;
465 
466  success = 1;
467  tmp = arch_to_object(spell->other_arch);
468  set_owner(tmp, op);
469  set_spell_skill(op, caster, spell, tmp);
470  tmp->level = caster_level(caster, spell);
471  tmp->x = sx;
472  tmp->y = sy;
473  tmp->attacktype = spell->attacktype;
474 
475  /* holy word stuff */
476  if ((tmp->attacktype&AT_HOLYWORD) || (tmp->attacktype&AT_GODPOWER)) {
477  if (!tailor_god_spell(tmp, op))
478  return 0;
479  }
480 
481  if (dir)
482  tmp->stats.sp = dir;
483  else
484  tmp->stats.sp = i;
485 
486  tmp->range = spell->range+SP_level_range_adjust(caster, spell);
487 
488  /* If casting it in all directions, it doesn't go as far */
489  if (dir == 0) {
490  tmp->range /= 4;
491  if (tmp->range < 2 && spell->range >= 2)
492  tmp->range = 2;
493  }
494  tmp->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
495  tmp->duration = spell->duration+SP_level_duration_adjust(caster, spell);
496 
497  /* Special bonus for fear attacks */
498  if (tmp->attacktype&AT_FEAR) {
499  if (caster->type == PLAYER)
500  tmp->duration += fear_bonus[caster->stats.Cha];
501  else
502  tmp->duration += caster->level/3;
503  }
505  if (caster->type == PLAYER)
506  tmp->duration += turn_bonus[caster->stats.Wis]/5;
507  else
508  tmp->duration += caster->level/3;
509  }
510 
511  if (!(tmp->move_type&MOVE_FLY_LOW))
512  LOG(llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", spell->other_arch->name);
513 
514  if (!tmp->move_on && tmp->stats.dam) {
515  LOG(llevDebug, "cast_cone(): arch %s doesn't have move_on set\n", spell->other_arch->name);
516  }
517  insert_ob_in_map(tmp, m, op, 0);
518 
519  /* This is used for tracking spells so that one effect doesn't hit
520  * a single space too many times.
521  */
522  tmp->stats.maxhp = tmp->count;
523 
524  if (tmp->other_arch)
525  cone_drop(tmp);
526  }
527  return success;
528 }
529 
530 /****************************************************************************
531  *
532  * BOMB related code
533  *
534  ****************************************************************************/
535 
552 int create_bomb(object *op, object *caster, int dir, object *spell) {
553  object *tmp;
554  int mflags;
555  sint16 dx = op->x+freearr_x[dir], dy = op->y+freearr_y[dir];
556  mapstruct *m;
557 
558  mflags = get_map_flags(op->map, &m, dx, dy, &dx, &dy);
559  if ((mflags&P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK(m, dx, dy)&MOVE_WALK)) {
560  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "There is something in the way.", NULL);
561  return 0;
562  }
563  tmp = arch_to_object(spell->other_arch);
564 
565  /* level dependencies for bomb */
566  tmp->range = spell->range+SP_level_range_adjust(caster, spell);
567  tmp->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
568  tmp->duration = spell->duration+SP_level_duration_adjust(caster, spell);
569  tmp->attacktype = spell->attacktype;
570 
571  set_owner(tmp, op);
572  set_spell_skill(op, caster, spell, tmp);
573  tmp->x = dx;
574  tmp->y = dy;
575  insert_ob_in_map(tmp, m, op, 0);
576  return 1;
577 }
578 
579 /****************************************************************************
580  *
581  * smite related spell code.
582  *
583  ****************************************************************************/
584 
603 static object *get_pointed_target(object *op, int dir, int range, int type) {
604  object *target;
605  sint16 x, y;
606  int dist, mflags;
607  mapstruct *mp;
608 
609  if (dir == 0)
610  return NULL;
611 
612  for (dist = 1; dist < range; dist++) {
613  x = op->x+freearr_x[dir]*dist;
614  y = op->y+freearr_y[dir]*dist;
615  mp = op->map;
616  mflags = get_map_flags(op->map, &mp, x, y, &x, &y);
617 
618  if (mflags&P_OUT_OF_MAP)
619  return NULL;
620  if ((type&SPELL_MANA) && (mflags&P_NO_MAGIC))
621  return NULL;
622  if ((type&SPELL_GRACE) && (mflags&P_NO_CLERIC))
623  return NULL;
624  if (GET_MAP_MOVE_BLOCK(mp, x, y)&MOVE_FLY_LOW)
625  return NULL;
626 
627  if (mflags&P_IS_ALIVE) {
628  for (target = GET_MAP_OB(mp, x, y); target; target = target->above) {
629  if (QUERY_FLAG(target->head ? target->head : target, FLAG_MONSTER)) {
630  return target;
631  }
632  }
633  }
634  }
635  return NULL;
636 }
637 
638 
655 int cast_smite_spell(object *op, object *caster, int dir, object *spell) {
656  object *effect, *target;
657  const object *god = find_god(determine_god(op));
658  int range;
659 
660  /* BUG? The value in range doesn't seem to be used. */
661  range = spell->range+SP_level_range_adjust(caster, spell);
662  target = get_pointed_target(op, dir, 50, spell->stats.grace ? SPELL_GRACE : SPELL_MANA);
663 
664  /* Bunch of conditions for casting this spell. Note that only
665  * require a god if this is a cleric spell (requires grace).
666  * This makes this spell much more general purpose - it can be used
667  * by wizards also, which is good, because I think this is a very
668  * interesting spell.
669  * if it is a cleric spell, you need a god, and the creature
670  * can't be friendly to your god.
671  */
672 
673  if (!target
674  || QUERY_FLAG(target, FLAG_REFL_SPELL)
675  || (!god && spell->stats.grace)
676  || (target->title && god && !strcmp(target->title, god->name))
677  || (target->race && god && strstr(target->race, god->race))) {
678  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Your request is unheeded.", NULL);
679  return 0;
680  }
681 
682  if (spell->other_arch)
683  effect = arch_to_object(spell->other_arch);
684  else
685  return 0;
686 
687  /* tailor the effect by priest level and worshipped God */
688  effect->level = caster_level(caster, spell);
689  effect->attacktype = spell->attacktype;
690  if (effect->attacktype&(AT_HOLYWORD|AT_GODPOWER)) {
691  if (tailor_god_spell(effect, op))
693  "%s answers your call!",
694  "%s answers your call!",
695  determine_god(op));
696  else {
697  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Your request is ignored.", NULL);
698  return 0;
699  }
700  }
701 
702  /* size of the area of destruction */
703  effect->range = spell->range+SP_level_range_adjust(caster, spell);
704  effect->duration = spell->duration+SP_level_range_adjust(caster, spell);
705 
706  if (effect->attacktype&AT_DEATH) {
707  effect->level = spell->stats.dam+SP_level_dam_adjust(caster, spell);
708 
709  /* casting death spells at undead isn't a good thing */
710  if QUERY_FLAG(target, FLAG_UNDEAD) {
711  if (random_roll(0, 2, op, PREFER_LOW)) {
712  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Idiot! Your spell boomerangs!", NULL);
713  effect->x = op->x;
714  effect->y = op->y;
715  } else {
716  char target_name[HUGE_BUF];
717 
718  query_name(target, target_name, HUGE_BUF);
721  "The %s looks stronger!",
722  "The %s looks stronger!",
723  target_name);
724  target->stats.hp = target->stats.maxhp*2;
725  free_object(effect);
726  return 0;
727  }
728  }
729  } else {
730  /* how much woe to inflict :) */
731  effect->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
732  }
733 
734  if (effect->type == SPELL_EFFECT && effect->subtype == SP_EXPLOSION) {
735  /* Used for spell tracking - just need a unique val for this spell -
736  * the count of the parent should work fine.
737  *
738  * Without this the server can easily get overloaded at high level
739  * spells.
740  */
741  effect->stats.maxhp = spell->count;
742  }
743 
744  set_owner(effect, op);
745  set_spell_skill(op, caster, spell, effect);
746 
747  /* ok, tell it where to be, and insert! */
748  effect->x = target->x;
749  effect->y = target->y;
750  insert_ob_in_map(effect, target->map, op, 0);
751 
752  return 1;
753 }
754 
755 /****************************************************************************
756  * Destruction
757  ****************************************************************************/
758 
777 static int make_object_glow(object *op, int radius, int time) {
778  object *tmp;
779 
780  /* some things are unaffected... */
781  if (op->path_denied&PATH_LIGHT)
782  return 0;
783 
785  tmp->speed = 0.01;
786  tmp->stats.food = time;
788  tmp->glow_radius = radius;
789  if (tmp->glow_radius > MAX_LIGHT_RADII)
791 
792  tmp->x = op->x;
793  tmp->y = op->y;
794  if (tmp->speed < MIN_ACTIVE_SPEED)
795  tmp->speed = MIN_ACTIVE_SPEED; /* safety */
796  tmp = insert_ob_in_ob(tmp, op);
797  if (tmp->glow_radius > op->glow_radius)
798  op->glow_radius = tmp->glow_radius;
799 
800  if (!tmp->env || op != tmp->env) {
801  LOG(llevError, "make_object_glow() failed to insert glowing force in %s\n", op->name);
802  return 0;
803  }
804  return 1;
805 }
806 
819 int cast_destruction(object *op, object *caster, object *spell_ob) {
820  int i, j, range, mflags, friendly = 0, dam, dur;
821  sint16 sx, sy;
822  mapstruct *m;
823  object *tmp;
824  const char *skill;
825 
826  range = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
827  dam = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
828  dur = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
829  if (QUERY_FLAG(op, FLAG_FRIENDLY) || op->type == PLAYER)
830  friendly = 1;
831 
832  /* destruction doesn't use another spell object, so we need
833  * update op's skill pointer so that exp is properly awarded.
834  * We do some shortcuts here - since this is just temporary
835  * and we'll reset the values back, we don't need to go through
836  * the full share string/free_string route.
837  */
838  skill = op->skill;
839  if (caster == op)
840  op->skill = spell_ob->skill;
841  else if (caster->skill)
842  op->skill = caster->skill;
843  else
844  op->skill = NULL;
845 
846  change_skill(op, find_skill_by_name(op, op->skill), 1);
847 
848  for (i = -range; i < range; i++) {
849  for (j = -range; j < range; j++) {
850  m = op->map;
851  sx = op->x+i;
852  sy = op->y+j;
853  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
854  if (mflags&P_OUT_OF_MAP)
855  continue;
856  if (mflags&P_IS_ALIVE) {
857  for (tmp = GET_MAP_OB(m, sx, sy); tmp; tmp = tmp->above) {
858  if (QUERY_FLAG(tmp, FLAG_ALIVE) || tmp->type == PLAYER)
859  break;
860  }
861  if (tmp) {
862  if (tmp->head)
863  tmp = tmp->head;
864 
865  if ((friendly && !QUERY_FLAG(tmp, FLAG_FRIENDLY) && tmp->type != PLAYER)
866  || (!friendly && (QUERY_FLAG(tmp, FLAG_FRIENDLY) || tmp->type == PLAYER))) {
867  if (spell_ob->subtype == SP_DESTRUCTION) {
868  hit_player(tmp, dam, op, spell_ob->attacktype, 0);
869  if (spell_ob->other_arch) {
870  tmp = arch_to_object(spell_ob->other_arch);
871  tmp->x = sx;
872  tmp->y = sy;
873  insert_ob_in_map(tmp, m, op, 0);
874  }
875  } else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100) {
876  if (make_object_glow(tmp, 1, dur) && spell_ob->other_arch) {
877  object *effect = arch_to_object(spell_ob->other_arch);
878  effect->x = sx;
879  effect->y = sy;
880  insert_ob_in_map(effect, m, op, 0);
881  }
882  }
883  }
884  }
885  }
886  }
887  }
888  op->skill = skill;
889  return 1;
890 }
891 
892 /***************************************************************************
893  *
894  * CURSE
895  *
896  ***************************************************************************/
897 
914 int cast_curse(object *op, object *caster, object *spell_ob, int dir) {
915  const object *god = find_god(determine_god(op));
916  object *tmp, *force;
917 
918  tmp = get_pointed_target(op, (dir == 0) ? op->direction : dir, spell_ob->range, SPELL_GRACE);
919  if (!tmp) {
920  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "There is no one in that direction to curse.", NULL);
921  return 0;
922  }
923 
924  /* If we've already got a force of this type, don't add a new one. */
925  for (force = tmp->inv; force != NULL; force = force->below) {
926  if (force->type == FORCE && force->subtype == FORCE_CHANGE_ABILITY) {
927  if (force->name == spell_ob->name) {
928  break;
929  } else if (spell_ob->race && spell_ob->race == force->name) {
932  "You can not cast %s while %s is in effect",
933  "You can not cast %s while %s is in effect",
934  spell_ob->name, force->name_pl);
935  return 0;
936  }
937  }
938  }
939 
940  if (force == NULL) {
941  force = create_archetype(FORCE_NAME);
942  force->subtype = FORCE_CHANGE_ABILITY;
943  free_string(force->name);
944  if (spell_ob->race)
945  force->name = add_refcount(spell_ob->race);
946  else
947  force->name = add_refcount(spell_ob->name);
948  free_string(force->name_pl);
949  force->name_pl = add_refcount(spell_ob->name);
950  } else {
951  int duration;
952 
953  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
954  if (duration > force->duration) {
955  force->duration = duration;
956  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_SUCCESS, "You recast the spell while in effect.", NULL);
957  } else {
958  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Recasting the spell had no effect.", NULL);
959  }
960  return 1;
961  }
962  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
963  force->speed = 1.0;
964  force->speed_left = -1.0;
965  SET_FLAG(force, FLAG_APPLIED);
966 
967  if (god) {
968  if (spell_ob->last_grace)
969  force->path_repelled = god->path_repelled;
970  if (spell_ob->last_grace)
971  force->path_denied = god->path_denied;
973  "You are a victim of %s's curse!",
974  "You are a victim of %s's curse!",
975  god->name);
976  } else
977  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Your curse seems empty.", NULL);
978 
979 
980  if (tmp != op && op->type == PLAYER)
982  "You curse %s!",
983  "You curse %s!",
984  tmp->name);
985 
986  force->stats.ac = spell_ob->stats.ac;
987  force->stats.wc = spell_ob->stats.wc;
988 
989  change_abil(tmp, force); /* Mostly to display any messages */
990  insert_ob_in_ob(force, tmp);
991  fix_object(tmp);
992  return 1;
993 }
994 
995 /**********************************************************************
996  * mood change
997  * Arguably, this may or may not be an attack spell. But since it
998  * effects monsters, it seems best to put it into this file
999  ***********************************************************************/
1000 
1014 int mood_change(object *op, object *caster, object *spell) {
1015  object *tmp, *head;
1016  const object *god;
1017  int done_one, range, mflags, level, at, best_at;
1018  sint16 x, y, nx, ny;
1019  mapstruct *m;
1020  const char *race;
1021 
1022  /* We precompute some values here so that we don't have to keep
1023  * doing it over and over again.
1024  */
1025  god = find_god(determine_god(op));
1026  level = caster_level(caster, spell);
1027  range = spell->range+SP_level_range_adjust(caster, spell);
1028 
1029  /* On the bright side, no monster should ever have a race of GOD_...
1030  * so even if the player doesn't worship a god, if race=GOD_.., it
1031  * won't ever match anything.
1032  */
1033  if (!spell->race)
1034  race = NULL;
1035  else if (god && !strcmp(spell->race, "GOD_SLAYING"))
1036  race = god->slaying;
1037  else if (god && !strcmp(spell->race, "GOD_FRIEND"))
1038  race = god->race;
1039  else
1040  race = spell->race;
1041 
1042  for (x = op->x-range; x <= op->x+range; x++)
1043  for (y = op->y-range; y <= op->y+range; y++) {
1044  done_one = 0;
1045  m = op->map;
1046  nx = x;
1047  ny = y;
1048  mflags = get_map_flags(m, &m, x, y, &nx, &ny);
1049  if (mflags&P_OUT_OF_MAP)
1050  continue;
1051 
1052  /* If there is nothing living on this space, no need to go further */
1053  if (!(mflags&P_IS_ALIVE))
1054  continue;
1055 
1056  for (tmp = GET_MAP_OB(m, nx, ny); tmp; tmp = tmp->above)
1057  if (QUERY_FLAG(tmp, FLAG_MONSTER))
1058  break;
1059 
1060  /* There can be living objects that are not monsters */
1061  if (!tmp || tmp->type == PLAYER)
1062  continue;
1063 
1064  /* Only the head has meaningful data, so resolve to that */
1065  if (tmp->head)
1066  head = tmp->head;
1067  else
1068  head = tmp;
1069 
1070  /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */
1071  if (race && head->race && !strstr(race, head->race))
1072  continue;
1073  if (QUERY_FLAG(head, FLAG_UNDEAD) && !QUERY_FLAG(spell, FLAG_UNDEAD))
1074  continue;
1075 
1076  /* Now do a bunch of stuff related to saving throws */
1077  best_at = -1;
1078  if (spell->attacktype) {
1079  for (at = 0; at < NROFATTACKS; at++)
1080  if (spell->attacktype&(1<<at))
1081  if (best_at == -1 || head->resist[at] > head->resist[best_at])
1082  best_at = at;
1083 
1084  if (best_at == -1)
1085  at = 0;
1086  else {
1087  if (head->resist[best_at] == 100)
1088  continue;
1089  else
1090  at = head->resist[best_at]/5;
1091  }
1092  at -= level/5;
1093  if (did_make_save(head, head->level, at))
1094  continue;
1095  } else { /* spell->attacktype */
1096  /*
1097  * Spell has no attacktype (charm&such), so we'll have a specific saving:
1098  * if spell level < monster level, no go
1099  * else, chance of effect = 20+min(50, 2*(spell level-monster level))
1100  *
1101  * The chance will then be in the range [20-70] percent, not too bad.
1102  *
1103  * This is required to fix the 'charm monster' abuse, where a player level 1 can
1104  * charm a level 125 monster...
1105  *
1106  * Ryo, august 14th
1107  */
1108  if (head->level > level)
1109  continue;
1110  if (random_roll(0, 100, caster, PREFER_LOW) >= (20+MIN(50, 2*(level-head->level))))
1111  /* Failed, no effect */
1112  continue;
1113  }
1114 
1115  /* Done with saving throw. Now start effecting the monster */
1116 
1117  /* aggravation */
1118  if (QUERY_FLAG(spell, FLAG_MONSTER)) {
1119  CLEAR_FLAG(head, FLAG_SLEEP);
1120  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1121  remove_friendly_object(head);
1122 
1123  done_one = 1;
1124  head->enemy = op;
1125  }
1126 
1127  /* calm monsters */
1128  if (QUERY_FLAG(spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG(head, FLAG_UNAGGRESSIVE)) {
1129  SET_FLAG(head, FLAG_UNAGGRESSIVE);
1130  head->enemy = NULL;
1131  done_one = 1;
1132  }
1133 
1134  /* berserk monsters */
1135  if (QUERY_FLAG(spell, FLAG_BERSERK) && !QUERY_FLAG(head, FLAG_BERSERK)) {
1136  SET_FLAG(head, FLAG_BERSERK);
1137  done_one = 1;
1138  }
1139  /* charm */
1140  if (QUERY_FLAG(spell, FLAG_NO_ATTACK) && !QUERY_FLAG(head, FLAG_FRIENDLY)) {
1141  SET_FLAG(head, FLAG_FRIENDLY);
1142  /* Prevent uncontolled outbreaks of self replicating monsters.
1143  Typical use case is charm, go somwhere, use aggravation to make hostile.
1144  This could lead to fun stuff like mice outbreak in bigworld and server crawl. */
1145  CLEAR_FLAG(head, FLAG_GENERATOR);
1146  set_owner(head, op);
1147  set_spell_skill(op, caster, spell, head);
1148  add_friendly_object(head);
1149  head->attack_movement = PETMOVE;
1150  done_one = 1;
1151  share_exp(op, head->stats.exp/2, head->skill, SK_EXP_ADD_SKILL);
1152  head->stats.exp = 0;
1153  }
1154 
1155  /* If a monster was effected, put an effect in */
1156  if (done_one && spell->other_arch) {
1157  tmp = arch_to_object(spell->other_arch);
1158  tmp->x = nx;
1159  tmp->y = ny;
1160  insert_ob_in_map(tmp, m, op, 0);
1161  }
1162  } /* for y */
1163 
1164  return 1;
1165 }
1166 
1167 
1185 int fire_swarm(object *op, object *caster, object *spell, int dir) {
1186  object *tmp;
1187  int i;
1188 
1189  if (!spell->other_arch)
1190  return 0;
1191 
1193  tmp->x = op->x;
1194  tmp->y = op->y;
1195  set_owner(tmp, op); /* needed so that if swarm elements kill, caster gets xp.*/
1196  set_spell_skill(op, caster, spell, tmp);
1197 
1198  tmp->level = caster_level(caster, spell); /*needed later, to get level dep. right.*/
1199  tmp->spell = arch_to_object(spell->other_arch);
1200 
1201  tmp->attacktype = tmp->spell->attacktype;
1202 
1203  if (tmp->attacktype&AT_HOLYWORD || tmp->attacktype&AT_GODPOWER) {
1204  if (!tailor_god_spell(tmp, op))
1205  return 1;
1206  }
1207  tmp->duration = SP_level_duration_adjust(caster, spell);
1208  for (i = 0; i < spell->duration; i++)
1209  tmp->duration += die_roll(1, 3, op, PREFER_HIGH);
1210 
1211  tmp->direction = dir;
1212  tmp->invisible = 1;
1213  insert_ob_in_map(tmp, op->map, op, 0);
1214  return 1;
1215 }
1216 
1235 int cast_light(object *op, object *caster, object *spell, int dir) {
1236  object *target = NULL, *tmp = NULL;
1237  sint16 x, y;
1238  int dam, mflags;
1239  mapstruct *m;
1240 
1241  dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
1242 
1243  if (!dir) {
1244  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "In what direction?", NULL);
1245  return 0;
1246  }
1247 
1248  x = op->x+freearr_x[dir];
1249  y = op->y+freearr_y[dir];
1250  m = op->map;
1251 
1252  mflags = get_map_flags(m, &m, x, y, &x, &y);
1253 
1254  if (mflags&P_OUT_OF_MAP) {
1255  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Nothing is there.", NULL);
1256  return 0;
1257  }
1258 
1259  if (mflags&P_IS_ALIVE && spell->attacktype) {
1260  for (target = GET_MAP_OB(m, x, y); target; target = target->above)
1261  if (QUERY_FLAG(target, FLAG_MONSTER)) {
1262  /* oky doky. got a target monster. Lets make a blinding attack */
1263  if (target->head)
1264  target = target->head;
1265  (void)hit_player(target, dam, op, spell->attacktype, 1);
1266  return 1; /* one success only! */
1267  }
1268  }
1269 
1270  /* no live target, perhaps a wall is in the way? */
1271  if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y))) {
1272  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "Something is in the way.", NULL);
1273  return 0;
1274  }
1275 
1276  /* ok, looks groovy to just insert a new light on the map */
1277  tmp = arch_to_object(spell->other_arch);
1278  if (!tmp) {
1279  LOG(llevError, "Error: spell arch for cast_light() missing.\n");
1280  return 0;
1281  }
1282  tmp->stats.food = spell->duration+SP_level_duration_adjust(caster, spell);
1283  if (tmp->glow_radius) {
1284  tmp->glow_radius = spell->range+SP_level_range_adjust(caster, spell);
1285  if (tmp->glow_radius > MAX_LIGHT_RADII)
1286  tmp->glow_radius = MAX_LIGHT_RADII;
1287  }
1288  tmp->x = x;
1289  tmp->y = y;
1290  insert_ob_in_map(tmp, m, op, 0);
1291  return 1;
1292 }
1293 
1310 int cast_cause_disease(object *op, object *caster, object *spell, int dir) {
1311  sint16 x, y;
1312  int i, mflags, range, dam_mod, dur_mod;
1313  object *walk, *target_head;
1314  mapstruct *m;
1315 
1316  x = op->x;
1317  y = op->y;
1318 
1319  /* If casting from a scroll, no direction will be available, so refer to the
1320  * direction the player is pointing.
1321  */
1322  if (!dir)
1323  dir = op->facing;
1324  if (!dir)
1325  return 0; /* won't find anything if casting on ourself, so just return */
1326 
1327  /* Calculate these once here */
1328  range = spell->range+SP_level_range_adjust(caster, spell);
1329  dam_mod = SP_level_dam_adjust(caster, spell);
1330  dur_mod = SP_level_duration_adjust(caster, spell);
1331 
1332  /* search in a line for a victim */
1333  for (i = 1; i < range; i++) {
1334  x = op->x+i*freearr_x[dir];
1335  y = op->y+i*freearr_y[dir];
1336  m = op->map;
1337 
1338  mflags = get_map_flags(m, &m, x, y, &x, &y);
1339 
1340  if (mflags&P_OUT_OF_MAP)
1341  return 0;
1342 
1343  /* don't go through walls - presume diseases are airborne */
1344  if (GET_MAP_MOVE_BLOCK(m, x, y)&MOVE_FLY_LOW)
1345  return 0;
1346 
1347  /* Only bother looking on this space if there is something living here */
1348  if (mflags&P_IS_ALIVE) {
1349  /* search this square for a victim */
1350  for (walk = GET_MAP_OB(m, x, y); walk; walk = walk->above) {
1351  /* Flags for monster is set on head only, so get it now */
1352  target_head = walk;
1353  while (target_head->head)
1354  target_head = target_head->head;
1355  if (QUERY_FLAG(target_head, FLAG_MONSTER) || (target_head->type == PLAYER)) { /* found a victim */
1356  object *disease = arch_to_object(spell->other_arch);
1357 
1358  set_owner(disease, op);
1359  set_spell_skill(op, caster, spell, disease);
1360  disease->stats.exp = 0;
1361  disease->level = caster_level(caster, spell);
1362 
1363  /* do level adjustments */
1364  if (disease->stats.wc)
1365  disease->stats.wc += dur_mod/2;
1366 
1367  if (disease->magic > 0)
1368  disease->magic += dur_mod/4;
1369 
1370  if (disease->stats.maxhp > 0)
1371  disease->stats.maxhp += dur_mod;
1372 
1373  if (disease->stats.maxgrace > 0)
1374  disease->stats.maxgrace += dur_mod;
1375 
1376  if (disease->stats.dam) {
1377  if (disease->stats.dam > 0)
1378  disease->stats.dam += dam_mod;
1379  else
1380  disease->stats.dam -= dam_mod;
1381  }
1382 
1383  if (disease->last_sp) {
1384  disease->last_sp -= 2*dam_mod;
1385  if (disease->last_sp < 1)
1386  disease->last_sp = 1;
1387  }
1388 
1389  if (disease->stats.maxsp) {
1390  if (disease->stats.maxsp > 0)
1391  disease->stats.maxsp += dam_mod;
1392  else
1393  disease->stats.maxsp -= dam_mod;
1394  }
1395 
1396  if (disease->stats.ac)
1397  disease->stats.ac += dam_mod;
1398 
1399  if (disease->last_eat)
1400  disease->last_eat -= dam_mod;
1401 
1402  if (disease->stats.hp)
1403  disease->stats.hp -= dam_mod;
1404 
1405  if (disease->stats.sp)
1406  disease->stats.sp -= dam_mod;
1407 
1408  if (infect_object(target_head, disease, 1)) {
1409  object *flash; /* visual effect for inflicting disease */
1410 
1411  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_SUCCESS, "You inflict %s on %s!", NULL, disease->name, target_head->name);
1412 
1413  free_object(disease); /* don't need this one anymore */
1415  flash->x = x;
1416  flash->y = y;
1417  flash->map = walk->map;
1418  insert_ob_in_map(flash, walk->map, op, 0);
1419  return 1;
1420  }
1421  free_object(disease);
1422  } /* Found a victim */
1423  } /* Search squares for living creature */
1424  } /* if living creature on square */
1425  } /* for range of spaces */
1426  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "No one caught anything!", NULL);
1427  return 1;
1428 }
#define AT_HOLYWORD
Definition: attack.h:125
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, sint16 x, sint16 y, sint16 *nx, sint16 *ny)
Definition: map.c:330
const int fear_bonus[MAX_STAT+1]
Definition: living.c:170
void explode_bullet(object *op)
Definition: spell_attack.c:144
int fire_bolt(object *op, object *caster, int dir, object *spob, object *skill)
Definition: spell_attack.c:78
const char * determine_god(object *op)
Definition: gods.c:118
sint8 ac
Definition: living.h:79
int mood_change(object *op, object *caster, object *spell)
#define MOVE_WALK
Definition: define.h:700
void share_exp(object *op, sint64 exp, const char *skill, int flag)
Definition: living.c:2150
int fire_swarm(object *op, object *caster, object *spell, int dir)
#define FORCE_CHANGE_ABILITY
Definition: spells.h:172
MoveType move_type
Definition: object.h:277
int change_skill(object *who, object *new_skill, int flag)
Definition: skill_util.c:301
MoveType move_on
Definition: object.h:280
signed short sint16
Definition: global.h:72
static object * get_pointed_target(object *op, int dir, int range, int type)
Definition: spell_attack.c:603
#define FLAG_SLEEP
Definition: define.h:604
const char * race
Definition: object.h:171
void set_owner(object *op, object *owner)
Definition: object.c:564
int caster_level(const object *caster, const object *spell)
Definition: spell_util.c:237
uint16 attack_movement
Definition: object.h:242
#define MAX_LIGHT_RADII
Definition: define.h:759
#define SET_FLAG(xyz, p)
Definition: define.h:510
sstring add_refcount(sstring str)
Definition: shstr.c:202
#define SP_CONE
Definition: spells.h:109
int cast_curse(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_attack.c:914
sint8 range
Definition: object.h:256
#define FLAG_IS_USED_UP
Definition: define.h:556
object * object_get_env_recursive(object *op)
Definition: object.c:339
#define ARCH_DETECT_MAGIC
Definition: object.h:404
#define PATH_LIGHT
Definition: spells.h:60
#define FLAG_FRIENDLY
Definition: define.h:542
#define P_NO_MAGIC
Definition: map.h:248
static int make_object_glow(object *op, int radius, int time)
Definition: spell_attack.c:777
#define SPELL_GRACE
Definition: spells.h:87
unsigned char MoveType
Definition: define.h:725
sint16 maxgrace
Definition: living.h:86
void free_string(sstring str)
Definition: shstr.c:272
#define MSG_TYPE_SPELL_FAILURE
Definition: newclient.h:548
#define HUGE_BUF
Definition: define.h:83
#define SET_ANIMATION(ob, newanim)
Definition: global.h:247
object clone
Definition: object.h:326
sint16 duration
Definition: object.h:254
sint16 invisible
Definition: object.h:211
short freearr_x[SIZEOFFREE]
Definition: object.c:75
#define PREFER_LOW
Definition: define.h:909
int cast_light(object *op, object *caster, object *spell, int dir)
#define DIRX(xyz)
Definition: define.h:785
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
const char * slaying
Definition: object.h:172
sint32 last_sp
Definition: object.h:209
#define MSG_TYPE_SPELL_ERROR
Definition: newclient.h:551
uint8 subtype
Definition: object.h:190
#define MSG_TYPE_SPELL
Definition: newclient.h:333
int SP_level_dam_adjust(const object *caster, const object *spob)
Definition: spell_util.c:332
sint64 exp
Definition: living.h:88
#define RUNE
Definition: define.h:325
struct obj * above
Definition: object.h:146
method_ret ob_process(object *op)
Definition: ob_methods.c:79
int fire_bullet(object *op, object *caster, int dir, object *spob)
Definition: spell_attack.c:301
#define FLAG_NO_ATTACK
Definition: define.h:659
int cast_cone(object *op, object *caster, int dir, object *spell)
Definition: spell_attack.c:403
sint16 x
Definition: object.h:179
void remove_friendly_object(object *op)
Definition: friend.c:69
sint16 sp
Definition: living.h:83
const object * find_god(const char *name)
Definition: gods.c:92
#define FLAG_REFLECTING
Definition: define.h:558
#define PETMOVE
Definition: define.h:826
uint32 path_repelled
Definition: object.h:195
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
struct obj * enemy
Definition: object.h:232
struct archt * other_arch
Definition: object.h:264
int absdir(int d)
Definition: object.c:3417
uint8 dam_modifier
Definition: object.h:258
#define PLAYER
Definition: define.h:113
sint16 maxsp
Definition: living.h:84
sint8 Con
Definition: living.h:78
#define FLAG_REMOVED
Definition: define.h:528
sint16 hp
Definition: living.h:81
#define DIRY(xyz)
Definition: define.h:786
short freearr_y[SIZEOFFREE]
Definition: object.c:81
#define AT_TURN_UNDEAD
Definition: attack.h:117
#define FLAG_UNDEAD
Definition: define.h:566
uint32 tag_t
Definition: object.h:40
int change_abil(object *op, object *tmp)
Definition: living.c:443
const char * title
Definition: object.h:170
void remove_ob(object *op)
Definition: object.c:1515
sint16 maxhp
Definition: living.h:82
#define AT_GODPOWER
Definition: attack.h:124
#define SWARM_SPELL
Definition: spells.h:193
void cone_drop(object *op)
Definition: spell_attack.c:369
uint32 path_denied
Definition: object.h:196
#define FLAG_ALIVE
Definition: define.h:526
#define FLAG_REFL_SPELL
Definition: define.h:571
struct obj * spell
Definition: object.h:259
const char * name_pl
Definition: object.h:168
object * create_archetype(const char *name)
Definition: arch.c:625
float speed_left
Definition: object.h:182
#define MSG_TYPE_VICTIM
Definition: newclient.h:336
#define MOVE_FLY_LOW
Definition: define.h:701
#define SP_BOMB
Definition: spells.h:110
sint8 Wis
Definition: living.h:78
#define FLAG_UNAGGRESSIVE
Definition: define.h:568
struct mapdef * map
Definition: object.h:155
int SP_level_duration_adjust(const object *caster, const object *spob)
Definition: spell_util.c:357
sint16 dam
Definition: living.h:87
int die_roll(int num, int size, const object *op, int goodbad)
Definition: utils.c:134
void add_friendly_object(object *op)
Definition: friend.c:43
const char * name
Definition: object.h:167
struct obj * env
Definition: object.h:151
int hit_map(object *op, int dir, uint32 type, int full_hit)
Definition: attack.c:292
object * get_owner(object *op)
Definition: object.c:524
struct obj * below
Definition: object.h:145
#define INS_NO_WALK_ON
Definition: object.h:396
sint16 last_grace
Definition: object.h:210
int infect_object(object *victim, object *disease, int force)
Definition: disease.c:336
sint8 Cha
Definition: living.h:78
#define ATNR_MAGIC
Definition: attack.h:78
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Definition: define.h:740
#define P_OUT_OF_MAP
Definition: map.h:272
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:213
sint8 facing
Definition: object.h:186
sint16 y
Definition: object.h:179
#define SP_DESTRUCTION
Definition: spells.h:118
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:283
float speed
Definition: object.h:181
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
#define FLAG_BERSERK
Definition: define.h:655
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
const char * skill
Definition: object.h:174
sint32 last_eat
Definition: object.h:207
sint8 wc
Definition: living.h:79
void copy_owner(object *op, object *clone)
Definition: object.c:614
#define MIN(x, y)
Definition: define.h:67
const int turn_bonus[MAX_STAT+1]
Definition: living.c:165
sint16 resist[NROFATTACKS]
Definition: object.h:192
int create_bomb(object *op, object *caster, int dir, object *spell)
Definition: spell_attack.c:552
int tailor_god_spell(object *spellop, object *caster)
Definition: gods.c:1394
#define FORCE
Definition: define.h:296
#define PREFER_HIGH
Definition: define.h:908
uint32 attacktype
Definition: object.h:193
#define FLAG_GENERATOR
Definition: define.h:544
#define INS_NO_MERGE
Definition: object.h:394
sint8 direction
Definition: object.h:185
struct obj * owner
Definition: object.h:228
sint16 grace
Definition: living.h:85
int cast_smite_spell(object *op, object *caster, int dir, object *spell)
Definition: spell_attack.c:655
int SP_level_range_adjust(const object *caster, const object *spob)
Definition: spell_util.c:383
tag_t count
Definition: object.h:157
living stats
Definition: object.h:219
#define SP_FAERY_FIRE
Definition: spells.h:146
sint8 Dex
Definition: living.h:78
void set_spell_skill(object *op, object *caster, object *spob, object *dest)
Definition: spell_util.c:105
#define AT_FEAR
Definition: attack.h:118
#define SK_EXP_ADD_SKILL
Definition: skills.h:103
#define SPELL_EFFECT
Definition: define.h:284
#define FLAG_APPLIED
Definition: define.h:531
#define NROFATTACKS
Definition: attack.h:45
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2300
#define FORCE_NAME
Definition: spells.h:196
#define AT_MAGIC
Definition: attack.h:105
#define MSG_TYPE_SPELL_SUCCESS
Definition: newclient.h:550
int cast_cause_disease(object *op, object *caster, object *spell, int dir)
#define MIN_ACTIVE_SPEED
Definition: define.h:1063
#define GET_MAP_OB(M, X, Y)
Definition: map.h:193
sint8 glow_radius
Definition: object.h:215
#define FLAG_MONSTER
Definition: define.h:541
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
struct obj * head
Definition: object.h:154
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
int did_make_save(const object *op, int level, int bonus)
Definition: living.c:2121
#define was_destroyed(op, old_tag)
Definition: object.h:94
int cast_destruction(object *op, object *caster, object *spell_ob)
Definition: spell_attack.c:819
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
#define SPELL_MANA
Definition: spells.h:86
#define MSG_TYPE_VICTIM_SPELL
Definition: newclient.h:569
void free_object(object *ob)
Definition: object.c:1238
Definition: map.h:346
#define P_IS_ALIVE
Definition: map.h:258
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:51
sint16 level
Definition: object.h:202
void fix_object(object *op)
Definition: living.c:900
#define SP_EXPLOSION
Definition: spells.h:108
#define AT_DEATH
Definition: attack.h:121
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.c:207
object * arch_to_object(archetype *at)
Definition: arch.c:576
sint8 magic
Definition: object.h:199
const char * name
Definition: object.h:322
int hit_player(object *op, int dam, object *hitter, uint32 type, int full_hit)
Definition: attack.c:1868
#define P_NO_CLERIC
Definition: map.h:259
uint8 type
Definition: object.h:189
void check_bullet(object *op)
Definition: spell_attack.c:242
sint32 food
Definition: living.h:89
#define FLAG_IS_TURNABLE
Definition: define.h:552