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