Crossfire Server, Trunk  R21670
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  // Make sure unaggressive monsters also go to attack
1023  if (QUERY_FLAG(head, FLAG_FRIENDLY))
1024  remove_friendly_object(head);
1025 
1026  done_one = 1;
1027  // Prevent three-player abuse w/ two casting aggravation at a distance and the last punishing the
1028  // monsters who can't decide who to attack.
1029  // Also prevents aggravation -> singing -> aggravation loops
1030  object_set_value(head, "no_mood_change", "1", 1);
1031  // They big mad
1032  object_set_enemy(head, op);
1033  }
1034 
1035  /* calm monsters */
1036  if (QUERY_FLAG(spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG(head, FLAG_UNAGGRESSIVE)) {
1037  SET_FLAG(head, FLAG_UNAGGRESSIVE);
1038  object_set_enemy(head, NULL);
1039  done_one = 1;
1040  }
1041 
1042  /* berserk monsters */
1043  if (QUERY_FLAG(spell, FLAG_BERSERK) && !QUERY_FLAG(head, FLAG_BERSERK)) {
1044  SET_FLAG(head, FLAG_BERSERK);
1045  done_one = 1;
1046  }
1047  /* charm */
1048  if (QUERY_FLAG(spell, FLAG_NO_ATTACK) && !QUERY_FLAG(head, FLAG_FRIENDLY)) {
1049  SET_FLAG(head, FLAG_FRIENDLY);
1050  /* Prevent uncontrolled outbreaks of self replicating monsters.
1051  Typical use case is charm, go somewhere, use aggravation to make hostile.
1052  This could lead to fun stuff like mice outbreak in bigworld and server crawl. */
1053  CLEAR_FLAG(head, FLAG_GENERATOR);
1054  object_set_owner(head, op);
1055  set_spell_skill(op, caster, spell, head);
1056  add_friendly_object(head);
1057  head->attack_movement = PETMOVE;
1058  done_one = 1;
1059  share_exp(op, head->stats.exp/2, head->skill, SK_EXP_ADD_SKILL);
1060  head->stats.exp = 0;
1061  }
1062 
1063  /* If a monster was affected, put an effect in */
1064  if (done_one && spell->other_arch) {
1065  tmp = arch_to_object(spell->other_arch);
1066  object_insert_in_map_at(tmp, m, op, 0, nx, ny);
1067  }
1068  } /* for y */
1069 
1070  return 1;
1071 }
1072 
1073 
1091 int fire_swarm(object *op, object *caster, object *spell, int dir) {
1092  object *tmp;
1093  int i;
1094 
1095  if (!spell->other_arch)
1096  return 0;
1097 
1099  object_set_owner(tmp, op); /* needed so that if swarm elements kill, caster gets xp.*/
1100  set_spell_skill(op, caster, spell, tmp);
1101 
1102  tmp->level = caster_level(caster, spell); /*needed later, to get level dep. right.*/
1103  tmp->spell = arch_to_object(spell->other_arch);
1104 
1105  tmp->attacktype = tmp->spell->attacktype;
1106 
1107  if (tmp->attacktype&AT_HOLYWORD || tmp->attacktype&AT_GODPOWER) {
1108  if (!tailor_god_spell(tmp, op))
1109  return 1;
1110  }
1111  tmp->duration = SP_level_duration_adjust(caster, spell);
1112  for (i = 0; i < spell->duration; i++)
1113  tmp->duration += die_roll(1, 3, op, PREFER_HIGH);
1114 
1115  tmp->direction = dir;
1116  tmp->invisible = 1;
1117  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1118  return 1;
1119 }
1120 
1139 int cast_light(object *op, object *caster, object *spell, int dir) {
1140  object *target = NULL, *tmp = NULL;
1141  int16_t x, y;
1142  int dam, mflags;
1143  mapstruct *m;
1144 
1145  dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
1146 
1147  if (!dir) {
1148  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "In what direction?");
1149  return 0;
1150  }
1151 
1152  x = op->x+freearr_x[dir];
1153  y = op->y+freearr_y[dir];
1154  m = op->map;
1155 
1156  mflags = get_map_flags(m, &m, x, y, &x, &y);
1157 
1158  if (mflags&P_OUT_OF_MAP) {
1159  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "Nothing is there.");
1160  return 0;
1161  }
1162 
1163  if (mflags&P_IS_ALIVE && spell->attacktype) {
1164  target = map_find_by_flag(m, x, y, FLAG_MONSTER);
1165  if (target != NULL) {
1166  /* oky doky. got a target monster. Lets make a blinding attack */
1167  (void)hit_player(target, dam, op, spell->attacktype, 1);
1168  return 1; /* one success only! */
1169  }
1170  }
1171 
1172  /* no live target, perhaps a wall is in the way? */
1173  if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y))) {
1174  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_ERROR, "Something is in the way.");
1175  return 0;
1176  }
1177 
1178  /* ok, looks groovy to just insert a new light on the map */
1179  tmp = arch_to_object(spell->other_arch);
1180  if (!tmp) {
1181  LOG(llevError, "Error: spell arch for cast_light() missing.\n");
1182  return 0;
1183  }
1184  tmp->stats.food = spell->duration+SP_level_duration_adjust(caster, spell);
1185  if (tmp->glow_radius) {
1186  tmp->glow_radius = spell->range+SP_level_range_adjust(caster, spell);
1187  if (tmp->glow_radius > MAX_LIGHT_RADII)
1188  tmp->glow_radius = MAX_LIGHT_RADII;
1189  }
1190  object_insert_in_map_at(tmp, m, op, 0, x, y);
1191  return 1;
1192 }
1193 
1210 int cast_cause_disease(object *op, object *caster, object *spell, int dir) {
1211  int16_t x, y;
1212  int i, mflags, range, dam_mod, dur_mod;
1213  object *target_head;
1214  mapstruct *m;
1215 
1216  x = op->x;
1217  y = op->y;
1218 
1219  /* If casting from a scroll, no direction will be available, so refer to the
1220  * direction the player is pointing.
1221  */
1222  if (!dir)
1223  dir = op->facing;
1224  if (!dir)
1225  return 0; /* won't find anything if casting on ourself, so just return */
1226 
1227  /* Calculate these once here */
1228  range = spell->range+SP_level_range_adjust(caster, spell);
1229  dam_mod = SP_level_dam_adjust(caster, spell);
1230  dur_mod = SP_level_duration_adjust(caster, spell);
1231 
1232  /* search in a line for a victim */
1233  for (i = 1; i < range; i++) {
1234  x = op->x+i*freearr_x[dir];
1235  y = op->y+i*freearr_y[dir];
1236  m = op->map;
1237 
1238  mflags = get_map_flags(m, &m, x, y, &x, &y);
1239 
1240  if (mflags&P_OUT_OF_MAP)
1241  return 0;
1242 
1243  /* don't go through walls - presume diseases are airborne */
1244  if (GET_MAP_MOVE_BLOCK(m, x, y)&MOVE_FLY_LOW)
1245  return 0;
1246 
1247  /* Only bother looking on this space if there is something living here */
1248  if (mflags&P_IS_ALIVE) {
1249  /* search this square for a victim */
1250  FOR_MAP_PREPARE(m, x, y, walk) {
1251  /* Flags for monster is set on head only, so get it now */
1252  target_head = HEAD(walk);
1253  if (QUERY_FLAG(target_head, FLAG_MONSTER) || (target_head->type == PLAYER)) { /* found a victim */
1254  object *disease = arch_to_object(spell->other_arch);
1255 
1256  object_set_owner(disease, op);
1257  set_spell_skill(op, caster, spell, disease);
1258  disease->stats.exp = 0;
1259  disease->level = caster_level(caster, spell);
1260 
1261  /* do level adjustments */
1262  if (disease->stats.wc)
1263  disease->stats.wc += dur_mod/2;
1264 
1265  if (disease->magic > 0)
1266  disease->magic += dur_mod/4;
1267 
1268  if (disease->stats.maxhp > 0)
1269  disease->stats.maxhp += dur_mod;
1270 
1271  if (disease->stats.maxgrace > 0)
1272  disease->stats.maxgrace += dur_mod;
1273 
1274  if (disease->stats.dam) {
1275  if (disease->stats.dam > 0)
1276  disease->stats.dam += dam_mod;
1277  else
1278  disease->stats.dam -= dam_mod;
1279  }
1280 
1281  if (disease->last_sp) {
1282  disease->last_sp -= 2*dam_mod;
1283  if (disease->last_sp < 1)
1284  disease->last_sp = 1;
1285  }
1286 
1287  if (disease->stats.maxsp) {
1288  if (disease->stats.maxsp > 0)
1289  disease->stats.maxsp += dam_mod;
1290  else
1291  disease->stats.maxsp -= dam_mod;
1292  }
1293 
1294  if (disease->stats.ac)
1295  disease->stats.ac += dam_mod;
1296 
1297  if (disease->last_eat)
1298  disease->last_eat -= dam_mod;
1299 
1300  if (disease->stats.hp)
1301  disease->stats.hp -= dam_mod;
1302 
1303  if (disease->stats.sp)
1304  disease->stats.sp -= dam_mod;
1305 
1306  if (infect_object(target_head, disease, 1)) {
1307  object *flash; /* visual effect for inflicting disease */
1308 
1309  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);
1310 
1311  object_free_drop_inventory(disease); /* don't need this one anymore */
1313  object_insert_in_map_at(flash, walk->map, op, 0, x, y);
1314  return 1;
1315  }
1316  object_free_drop_inventory(disease);
1317  } /* Found a victim */
1318  } FOR_MAP_FINISH(); /* Search squares for living creature */
1319  } /* if living creature on square */
1320  } /* for range of spaces */
1321  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, "No one caught anything!");
1322  return 1;
1323 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:316
#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:427
int change_skill(object *who, object *new_skill, int flag)
Definition: skill_util.c:340
uint8_t dam_modifier
Definition: object.h:410
MoveType move_on
Definition: object.h:430
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:394
#define MAX_LIGHT_RADII
Definition: define.h:465
#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:657
object * object_get_env_recursive(object *op)
Definition: object.c:360
#define ARCH_DETECT_MAGIC
Definition: object.h:578
#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:408
#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:4125
object clone
Definition: object.h:472
int16_t duration
Definition: object.h:406
int16_t invisible
Definition: object.h:362
short freearr_x[SIZEOFFREE]
Definition: object.c:65
#define PREFER_LOW
Definition: define.h:601
int cast_light(object *op, object *caster, object *spell, int dir)
Definition: object.h:240
#define DIRX(xyz)
Definition: define.h:478
const char * slaying
Definition: object.h:319
int32_t last_sp
Definition: object.h:360
uint8_t subtype
Definition: object.h:341
int SP_level_dam_adjust(const object *caster, const object *spob)
Definition: spell_util.c:326
int64_t exp
Definition: living.h:47
method_ret ob_process(object *op)
Definition: ob_methods.c:68
#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:518
uint32_t path_repelled
Definition: object.h:346
struct archt * other_arch
Definition: object.h:416
int absdir(int d)
Definition: object.c:3493
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:311
#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:479
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_IS_USED_UP
Definition: define.h:260
#define FLAG_UNDEAD
Definition: define.h:270
void object_set_owner(object *op, object *owner)
Definition: object.c:604
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4248
void object_free_drop_inventory(object *ob)
Definition: object.c:1316
int change_abil(object *op, object *tmp)
Definition: living.c:395
const char * title
Definition: object.h:317
int16_t y
Definition: object.h:327
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1838
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:1069
void cone_drop(object *op)
Definition: spell_attack.c:265
uint32_t path_denied
Definition: object.h:347
#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:2368
struct obj * spell
Definition: object.h:411
const char * name_pl
Definition: object.h:315
object * create_archetype(const char *name)
Definition: arch.c:620
int8_t direction
Definition: object.h:336
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2591
float speed_left
Definition: object.h:330
#define MSG_TYPE_SPELL_SUCCESS
Definition: newclient.h:630
#define INS_ON_TOP
Definition: object.h:571
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:351
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:2380
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:570
int16_t last_grace
Definition: object.h:361
int infect_object(object *victim, object *disease, int force)
Definition: disease.c:317
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:205
uint32_t tag_t
Definition: object.h:12
float speed
Definition: object.h:329
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Definition: object.h:594
int16_t x
Definition: object.h:327
#define FLAG_BERSERK
Definition: define.h:359
const char * skill
Definition: object.h:321
int32_t last_eat
Definition: object.h:358
int8_t wc
Definition: living.h:37
#define FOR_MAP_FINISH()
Definition: define.h:767
int16_t resist[NROFATTACKS]
Definition: object.h:343
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:1314
#define PREFER_HIGH
Definition: define.h:600
uint32_t attacktype
Definition: object.h:344
#define FLAG_GENERATOR
Definition: define.h:248
#define INS_NO_MERGE
Definition: object.h:568
int16_t grace
Definition: living.h:44
object * map_find_by_flag(mapstruct *map, int x, int y, int flag)
Definition: map.c:2674
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:377
tag_t count
Definition: object.h:299
living stats
Definition: object.h:370
#define SP_FAERY_FIRE
Definition: spells.h:118
int8_t Dex
Definition: living.h:36
struct archt * arch
Definition: object.h:415
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:340
void object_set_enemy(object *op, object *enemy)
Definition: object.c:679
#define SK_EXP_ADD_SKILL
Definition: skills.h:78
#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:366
#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:310
#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:2276
#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:583
#define SPELL_MANA
Definition: spells.h:58
void share_exp(object *op, int64_t exp, const char *skill, int flag)
Definition: living.c:2306
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:1867
int16_t level
Definition: object.h:353
int8_t facing
Definition: object.h:337
void fix_object(object *op)
Definition: living.c:1120
#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:192
object * arch_to_object(archetype *at)
Definition: arch.c:571
object * object_get_owner(object *op)
Definition: object.c:568
int8_t magic
Definition: object.h:350
const char * name
Definition: object.h:468
#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:1577
void check_bullet(object *op)
Definition: spell_attack.c:217
int32_t food
Definition: living.h:48
Definition: object.h:224