Crossfire Server, Trunk
spell_effect.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 
19 #define _GNU_SOURCE // strcasestr() is a GNU extension in string.h
20 
21 #include "global.h"
22 
23 #include <assert.h>
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "living.h"
29 #include "object.h"
30 #include "shop.h"
31 #include "sounds.h"
32 #include "spells.h"
33 #include "sproto.h"
34 #include "assets.h"
35 
46 void cast_magic_storm(object *op, object *tmp, int lvl) {
47  if (!tmp)
48  return; /* error */
49  tmp->level = op->level;
50  tmp->range += lvl/5; /* increase the area of destruction */
51  tmp->duration += lvl/5;
52 
53  /* Put a cap on duration for this - if the player fails in their
54  * apartment, don't want it to go on so long that it kills them
55  * multiple times. Also, damage already increases with level,
56  * so don't really need to increase the duration as much either.
57  */
58  if (tmp->duration >= 40)
59  tmp->duration = 40;
60  tmp->stats.dam = lvl; /* nasty recoils! */
61  tmp->stats.maxhp = tmp->count; /* tract single parent */
62  if (tmp->stats.maxhp == 0)
63  tmp->stats.maxhp = 1;
64  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
65 }
66 
81 int recharge(object *op, object *caster, object *spell_ob) {
82  object *wand, *tmp;
83  int ncharges;
84  char name[MAX_BUF];
85 
86  wand = find_marked_object(op);
87  if (wand == NULL || wand->type != WAND) {
89  "You need to mark the wand you want to recharge.");
90  return 0;
91  }
92  if (!(random_roll(0, 3, op, PREFER_HIGH))) {
93  query_name(wand, name, MAX_BUF);
95  "The %s vibrates violently, then explodes!",
96  name);
97  play_sound_map(SOUND_TYPE_ITEM, wand, 0, "explode");
98  object_remove(wand);
99  object_free(wand, 0);
100  tmp = create_archetype("fireball");
101  tmp->stats.dam = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob))/10;
102  if (!tmp->stats.dam)
103  tmp->stats.dam = 1;
104  tmp->stats.hp = tmp->stats.dam/2;
105  if (tmp->stats.hp < 2)
106  tmp->stats.hp = 2;
107  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
108  return 1;
109  }
110 
111  ncharges = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob));
112  if (wand->inv && wand->inv->level)
113  ncharges /= wand->inv->level;
114  else {
115  query_name(wand, name, MAX_BUF);
117  "Your %s is broken.",
118  name);
119  return 0;
120  }
121  if (!ncharges)
122  ncharges = 1;
123 
124  wand->stats.food += ncharges;
125  query_name(wand, name, MAX_BUF);
127  "The %s glows with power.",
128  name);
129 
130  if (wand->arch && QUERY_FLAG(&wand->arch->clone, FLAG_ANIMATE)) {
131  SET_FLAG(wand, FLAG_ANIMATE);
132  wand->speed = wand->arch->clone.speed;
133  object_update_speed(wand);
134  }
135  return 1;
136 }
137 
138 /******************************************************************************
139  * Start of polymorph related functions.
140  *
141  * Changed around for 0.94.3 - it will now look through and use all the
142  * possible choices for objects/monsters (before it was the first 80 -
143  * arbitrary hardcoded limit in this file.) Doing this will be a bit
144  * slower however - while before, it traversed the archetypes once and
145  * stored them into an array, it will now potentially traverse it
146  * an average of 1.5 times. This is probably more costly on the polymorph
147  * item function, since it is possible a couple lookups might be needed before
148  * an item of proper value is generated.
149  */
150 
159 static void polymorph_living(object *op, int level) {
160  archetype *at;
161  int x = op->x, y = op->y, numat = 0, choice, friendly, pos;
162  mapstruct *map = op->map;
163  object *owner, *replacing;
164 
165  op = HEAD(op);
166 
167  /* High level creatures are immune, as are creatures immune to magic. Otherwise,
168  * give the creature a saving throw.
169  */
170  if (op->level >= level*2
171  || did_make_save(op, op->level, op->resist[ATNR_MAGIC]/10)
172  || (op->resist[ATNR_MAGIC] == 100))
173  return;
174 
175  object_remove(op);
176 
177  /* First, count up the number of legal matches */
178  for (at = get_next_archetype(NULL); at != NULL; at = get_next_archetype(at))
179  if ((!at->head) && (QUERY_FLAG((&at->clone), FLAG_MONSTER) == QUERY_FLAG(op, FLAG_MONSTER))
180  && (object_find_first_free_spot(&at->clone, map, x, y) != -1)) {
181  numat++;
182  }
183 
184  if (!numat) {
185  object_insert_in_map_at(op, map, NULL, 0, x, y);
186  return; /* no valid matches? if so, return */
187  }
188 
189  /* Next make a choice, and loop through until we get to it */
190  choice = rndm(0, numat-1);
191  for (at = get_next_archetype(NULL); at != NULL; at = get_next_archetype(at))
192  if ((!at->head) && (QUERY_FLAG((&at->clone), FLAG_MONSTER) == QUERY_FLAG(op, FLAG_MONSTER)) && ((pos = object_find_first_free_spot(&at->clone, map, x, y)) != -1)) {
193  if (!choice)
194  break;
195  else
196  choice--;
197  }
198 
199  /* Look through the monster. Unapply anything they have applied,
200  * and remove any spells. Note that if this is extended
201  * to players, that would need to get fixed somehow.
202  */
205  apply_manual(op, tmp, 0);
206  if (tmp->type == SPELL) {
208  object_free(tmp, 0);
209  }
210  } FOR_INV_FINISH();
211 
212  /* Preserve some values for the new object */
213  owner = object_get_owner(op);
214  friendly = QUERY_FLAG(op, FLAG_FRIENDLY);
215  if (friendly)
217 
218  replacing = object_create_arch(at);
219  if (owner != NULL)
220  object_set_owner(replacing, owner);
221  if (friendly) {
222  SET_FLAG(replacing, FLAG_FRIENDLY);
223  replacing->attack_movement = PETMOVE;
224  add_friendly_object(replacing);
225  } else
226  CLEAR_FLAG(replacing, FLAG_FRIENDLY);
228 
229  /* Put the new creature on the map */
230  if ((replacing = object_insert_in_map_at(replacing, map, owner, 0, x + freearr_x[pos], y + freearr_y[pos])) == NULL)
231  return;
232 
233  if (HAS_RANDOM_ITEMS(replacing))
234  create_treasure(replacing->randomitems, replacing, GT_INVISIBLE, map->difficulty, 0);
235 
236  /* Apply any objects. */
237  monster_check_apply_all(replacing);
238 }
239 
240 
252 static void polymorph_melt(object *who, object *op) {
253  /* Not unique */
254  char name[MAX_BUF];
255 
257  if (op->nrof > 1)
259  "The %s glow red, melt and evaporate!",
260  name);
261  else
263  "The %s glows red, melts and evaporates!",
264  name);
265  play_sound_map(SOUND_TYPE_ITEM, op, 0, "evaporate");
266  object_remove(op);
267  object_free(op, 0);
268  return;
269 }
270 
280 static void polymorph_item(object *who, object *op, int level) {
281  archetype *at;
282  int max_value, difficulty, tries = 0, choice, charges = op->stats.food, numat = 0;
283  object *new_ob;
284  mapstruct *m;
285  int16_t x, y;
286 
287  /* We try and limit the maximum value of the changed object. */
288  max_value = op->value*2;
289  if (max_value > 2000*(level/10))
290  max_value = 2000*(level/10)+(max_value-2000*(level/10))/3;
291 
292  /* Look through and try to find matching items. Can't turn into something
293  * invisible. Also, if the value is too high now, it would almost
294  * certainly be too high below.
295  */
296  for (at = get_next_archetype(NULL); at != NULL; at = get_next_archetype(at)) {
297  if (at->clone.type == op->type
298  && !at->clone.invisible
299  && at->clone.value > 0
300  && at->clone.value < max_value
301  && !QUERY_FLAG(&at->clone, FLAG_NO_DROP)
302  && !QUERY_FLAG(&at->clone, FLAG_STARTEQUIP))
303  numat++;
304  }
305 
306  if (!numat)
307  return;
308 
309  difficulty = op->magic*5;
310  if (difficulty < 0)
311  difficulty = 0;
312  new_ob = object_new();
313  do {
314  choice = rndm(0, numat-1);
315  for (at = get_next_archetype(NULL); at != NULL; at = get_next_archetype(at)) {
316  if (at->clone.type == op->type
317  && !at->clone.invisible
318  && at->clone.value > 0
319  && at->clone.value < max_value
320  && !QUERY_FLAG(&at->clone, FLAG_NO_DROP)
321  && !QUERY_FLAG(&at->clone, FLAG_STARTEQUIP)) {
322  if (!choice)
323  break;
324  else
325  choice--;
326  }
327  }
328 
329  object_copy(&(at->clone), new_ob);
330  fix_generated_item(new_ob, op, difficulty, FABS(op->magic), GT_ENVIRONMENT);
331  ++tries;
332  } while (new_ob->value > max_value && tries < 10);
333  if (new_ob->invisible) {
334  LOG(llevError, "polymorph_item: fix_generated_object made %s invisible?!\n", new_ob->name);
336  return;
337  }
338 
339  /* Unable to generate an acceptable item? Melt it */
340  if (tries == 10) {
343  return;
344  }
345 
346  if (op->nrof && new_ob->nrof) {
347  new_ob->nrof = op->nrof;
348  /* decrease the number of items */
349  if (new_ob->nrof > 2)
350  new_ob->nrof -= rndm(0, op->nrof/2-1);
351  }
352 
353  /* We don't want rings to keep sustenance/hungry status. There are probably
354  * other cases too that should be checked.
355  */
356  if (charges && op->type != RING && op->type != FOOD)
357  op->stats.food = charges;
358 
359  x = op->x;
360  y = op->y;
361  m = op->map;
362  object_remove(op);
364  /*
365  * Don't want objects merged or re-arranged, as it then messes up the
366  * order
367  */
369 }
370 
381 void polymorph(object *op, object *who, int level) {
382  int tmp;
383 
384  /* Can't polymorph players right now */
385  /* polymorphing generators opens up all sorts of abuses */
386  if (op->type == PLAYER || QUERY_FLAG(op, FLAG_GENERATOR))
387  return;
388 
389  if (QUERY_FLAG(op, FLAG_MONSTER)) {
391  return;
392  }
393  /* If it is a living object of some other type, don't handle
394  * it now.
395  */
396  if (QUERY_FLAG(op, FLAG_ALIVE))
397  return;
398 
399  /* Don't want to morph flying arrows, etc... */
400  if (FABS(op->speed) > 0.001 && !QUERY_FLAG(op, FLAG_ANIMATE))
401  return;
402 
403  /* Do some sanity checking here. type=0 is unknown, objects
404  * without archetypes are not good. As are a few other
405  * cases.
406  */
407  if (op->type == 0
408  || op->arch == NULL
410  || op->move_block
411  || op->type == TREASURE)
412  return;
413 
414  tmp = rndm(0, 7);
415  if (tmp)
417  else
419 }
420 
421 
435 int cast_polymorph(object *op, object *caster, object *spell_ob, int dir) {
436  object *tmp;
437  int range, mflags, maxrange, level;
438  mapstruct *m;
439 
440  if (dir == 0)
441  return 0;
442 
443  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
444  level = caster_level(caster, spell_ob);
445  for (range = 1; range < maxrange; range++) {
446  int16_t x = op->x+freearr_x[dir]*range, y = op->y+freearr_y[dir]*range;
447  object *image;
448 
449  m = op->map;
450  mflags = get_map_flags(m, &m, x, y, &x, &y);
451 
452  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
453  break;
454 
456  break;
457 
458  /* Get the top most object */
459  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above)
460  ;
461 
462  /* Now start polymorphing the objects, top down */
464  /* Once we find the floor, no need to go further */
466  break;
467  polymorph(tmp, op, level);
469  image = arch_to_object(spell_ob->other_arch);
470  image->stats.food = 5;
471  image->speed_left = 0.1;
472  object_insert_in_map_at(image, m, op, 0, x, y);
473  }
474  return 1;
475 }
476 
503 int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg) {
504  int missile_plus = 0, bonus_plus = 0;
505  const char *missile_name;
506  object *tmp, *missile;
507  tag_t tag;
508 
510  missile_name = tmp != NULL ? tmp->race : "arrow";
511 
512  missile_plus = spell->stats.dam+SP_level_dam_adjust(caster, spell);
513 
514  if (!strcmp(missile_name, "arrows"))
515  missile_name = "arrow";
516  else if (!strcmp(missile_name, "crossbow bolts"))
517  missile_name = "bolt";
518 
519  /* Check if the type (bolt/arrow) was specified with the spell */
520  if ( stringarg && strncmp(stringarg,"of ",3)==0 ) stringarg +=3;
521  if ( stringarg && strncmp(stringarg,"bolt",4)==0 ) {
522  missile_name = "bolt";
523  stringarg += 4;
524  while ( isalpha(*stringarg) ) ++stringarg;
525  while ( *stringarg==' ' ) ++stringarg;
526  }
527  if ( stringarg && strncmp(stringarg,"arrow",5)==0 ) {
528  missile_name = "arrow";
529  stringarg += 5;
530  while ( isalpha(*stringarg) ) ++stringarg;
531  while ( *stringarg==' ' ) ++stringarg;
532  }
533 
534  if (try_find_archetype(missile_name) == NULL) {
535  LOG(llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
536  return 0;
537  }
538  missile = create_archetype(missile_name);
539 
540  if ( stringarg && strncmp(stringarg,"of ",3)==0 ) stringarg +=3;
541  if (stringarg) {
542  /* If it starts with a letter, presume it is a description */
543  if (isalpha(*stringarg)) {
544  artifact *al = find_artifactlist(missile->type)->items;
545 
546  for (; al != NULL; al = al->next)
547  if (!strcasecmp(al->item->name, stringarg))
548  break;
549 
550  if (!al) {
553  "No such object %ss of %s",
554  missile_name, stringarg);
555  return 0;
556  }
557  if (al->item->slaying) {
560  "You are not allowed to create %ss of %s",
561  missile_name, stringarg);
562  return 0;
563  }
564  give_artifact_abilities(missile, al->item);
565  /* These special arrows cost something extra. Don't have them also be
566  * magical - otherwise, in most cases, not enough will be created.
567  * I don't want to get into the parsing both plus and type.
568  */
569  bonus_plus = 1+(al->item->value/5);
570  missile_plus = 0;
571  } else if (atoi(stringarg) < missile_plus)
572  missile_plus = atoi(stringarg);
573  }
574  if (missile_plus > 4)
575  missile_plus = 4;
576  else if (missile_plus < -4)
577  missile_plus = -4;
578 
579  missile->nrof = spell->duration+SP_level_duration_adjust(caster, spell);
580  if (missile->nrof <= (uint32_t)3 * (missile_plus + bonus_plus)) {
583  "This item is too powerful for you to create!");
584  return 0;
585  }
586  missile->nrof -= 3*(missile_plus+bonus_plus);
587  if (missile->nrof < 1)
588  missile->nrof = 1;
589 
590  missile->magic = missile_plus;
591  /* Can't get any money for these objects */
592  missile->value = 0;
593 
594  SET_FLAG(missile, FLAG_IDENTIFIED);
595  tag = missile->count;
596 
597  if (!cast_create_obj(op, missile, dir)
598  && op->type == PLAYER
599  && !object_was_destroyed(missile, tag)) {
600  pick_up(op, missile);
601  }
602  return 1;
603 }
604 
607 static int food_value_choice;
608 static void food_each(archetype *arch) {
609  if (arch->clone.type == FOOD || arch->clone.type == DRINK) {
610  /* Basically, if the food value is something that is creatable
611  * under the limits of the spell and it is higher than
612  * the item we have now, take it instead.
613  */
614  if (arch->clone.stats.food <= food_value_choice
615  && (!food_choice || arch->clone.stats.food > food_choice->clone.stats.food))
616  food_choice = arch;
617  }
618 }
619 
640 int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg) {
641  int food_value;
642  archetype *at = NULL;
643  object *new_op;
644 
645  food_value = spell_ob->stats.food+50*SP_level_duration_adjust(caster, spell_ob);
646 
647  if (stringarg) {
648  at = find_archetype_by_object_type_name(FOOD, stringarg);
649  if (at == NULL)
650  at = find_archetype_by_object_type_name(DRINK, stringarg);
651  if (at == NULL || at->clone.stats.food > food_value)
652  stringarg = NULL;
653  }
654 
655  if (!stringarg) {
656  /* We try to find the archetype with the maximum food value.
657  * This removes the dependency of hard coded food values in this
658  * function, and addition of new food types is automatically added.
659  * We don't use flesh types because the weight values of those need
660  * to be altered from the donor.
661  */
662 
663  food_choice = at;
664  food_value_choice = food_value;
666  at = food_choice;
667  }
668  /* Pretty unlikely (there are some very low food items), but you never
669  * know
670  */
671  if (!at) {
673  "You don't have enough experience to create any food.");
674  return 0;
675  }
676 
677  food_value /= at->clone.stats.food;
678  new_op = object_new();
679  object_copy(&at->clone, new_op);
680  new_op->nrof = food_value;
681 
682  new_op->value = 0;
683  if (new_op->nrof < 1)
684  new_op->nrof = 1;
685 
686  cast_create_obj(op, new_op, dir);
687  return 1;
688 }
689 
708 int probe(object *op, object *caster, object *spell_ob, int dir, int level) {
709  int r, mflags, maxrange;
710  mapstruct *m;
711 
712  if (!dir) {
714  return 1;
715  }
716  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
717  for (r = 1; r < maxrange; r++) {
718  int16_t x = op->x+r*freearr_x[dir], y = op->y+r*freearr_y[dir];
719 
720  m = op->map;
721  mflags = get_map_flags(m, &m, x, y, &x, &y);
722 
723  if (mflags&P_OUT_OF_MAP)
724  break;
725 
726  if (!QUERY_FLAG(op, FLAG_WIZCAST) && (mflags&P_NO_MAGIC)) {
728  "Something blocks your magic.");
729  return 0;
730  }
731  if (mflags&P_IS_ALIVE) {
732  FOR_MAP_PREPARE(m, x, y, tmp)
733  if (CAN_PROBE(tmp)) {
735  "You detect something.");
737  return 1;
738  }
739  FOR_MAP_FINISH();
740  }
741  }
743  "You detect nothing.");
744  return 1;
745 }
746 
747 
765 int makes_invisible_to(object *pl, object *mon) {
766  if (!pl->invisible)
767  return 0;
768  if (pl->type == PLAYER) {
769  /* If race isn't set, then invisible unless it is undead */
770  if (!pl->contr->invis_race) {
771  if (QUERY_FLAG(mon, FLAG_UNDEAD))
772  return 0;
773  return 1;
774  }
775  /* invis_race is set if we get here */
776  if (!strcmp(pl->contr->invis_race, "undead") && is_true_undead(mon))
777  return 1;
778  /* No race, can't be invisible to it */
779  if (!mon->race)
780  return 0;
781  if (strstr(mon->race, pl->contr->invis_race))
782  return 1;
783  /* Nothing matched above, return 0 */
784  return 0;
785  } else {
786  /* monsters are invisible to everything */
787  return 1;
788  }
789 }
790 
812 int cast_invisible(object *op, object *caster, object *spell_ob) {
813  if (op->invisible > 1000) {
815  "You can not extend the duration of your invisibility any further");
816  return 0;
817  }
818 
819  /* Remove the switch with 90% duplicate code - just handle the differences with
820  * and if statement or two.
821  */
822  op->invisible += spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
823  /* max duration */
824  if (op->invisible > 1000)
825  op->invisible = 1000;
826 
827  if (op->type == PLAYER) {
828  if (op->contr->invis_race)
829  FREE_AND_CLEAR_STR(op->contr->invis_race);
830  if (spell_ob->race)
831  op->contr->invis_race = add_refcount(spell_ob->race);
832  if (QUERY_FLAG(spell_ob, FLAG_MAKE_INVIS))
833  op->contr->tmp_invis = 0;
834  else
835  op->contr->tmp_invis = 1;
836 
837  op->contr->hidden = 0;
838  }
839  if (makes_invisible_to(op, op))
841  "You can't see your hands!");
842  else
844  "You feel more transparent!");
845 
847  return 1;
848 }
849 
864 int cast_earth_to_dust(object *op, object *caster, object *spell_ob) {
865  int range, i, j, mflags;
866  int16_t sx, sy;
867  mapstruct *m;
868 
869  if (op->type != PLAYER)
870  return 0;
871 
872  range = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
873 
874  for (i = -range; i < range; i++)
875  for (j = -range; j < range; j++) {
876  sx = op->x+i;
877  sy = op->y+j;
878  m = op->map;
879  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
880 
881  if (mflags&P_OUT_OF_MAP)
882  continue;
883 
884  /* If the space doesn't block, no wall here to remove
885  * Don't care too much what it blocks - this allows for
886  * any sort of earthwall/airwall/waterwall, etc
887  * type effects.
888  */
889  if (GET_MAP_MOVE_BLOCK(m, sx, sy)) {
890  FOR_MAP_PREPARE(m, sx, sy, tmp)
891  if (tmp && QUERY_FLAG(tmp, FLAG_TEAR_DOWN))
892  hit_player(tmp, 9998, op, AT_PHYSICAL, 0);
893  FOR_MAP_FINISH();
894  }
895  }
896  return 1;
897 }
898 
915 int cast_word_of_recall(object *op, object *caster, object *spell_ob) {
916  object *dummy;
917  int time;
918 
919  if (op->type != PLAYER)
920  return 0;
921 
924  "You feel a force starting to build up inside you.");
925  return 1;
926  }
927 
928  dummy = create_archetype(FORCE_NAME);
929  if (dummy == NULL) {
931  "Oops, program error!");
932  LOG(llevError, "cast_word_of_recall: create_archetype(force) failed!\n");
933  return 0;
934  }
935  time = spell_ob->duration-SP_level_duration_adjust(caster, spell_ob);
936  if (time < 1)
937  time = 1;
938 
939  /* value of speed really doesn't make much difference, as long as it is
940  * positive. Lower value may be useful so that the problem doesn't
941  * do anything really odd if it say a -1000 or something.
942  */
943  dummy->speed = 0.002;
944  object_update_speed(dummy);
945  dummy->speed_left = -dummy->speed*time;
946  dummy->type = SPELL_EFFECT;
947  dummy->subtype = SP_WORD_OF_RECALL;
948 
949  /* If we could take advantage of enter_player_savebed() here, it would be
950  * nice, but until the map load fails, we can't.
951  */
952  EXIT_PATH(dummy) = add_string(op->contr->savebed_map);
953  EXIT_X(dummy) = op->contr->bed_x;
954  EXIT_Y(dummy) = op->contr->bed_y;
955 
956  (void)object_insert_in_ob(dummy, op);
958  "You feel a force starting to build up inside you.");
959  return 1;
960 }
961 
977 int cast_wonder(object *op, object *caster, int dir, object *spell_ob) {
978  object *newspell;
979 
980  if (!rndm(0, 3))
981  return cast_cone(op, caster, dir, spell_ob);
982 
983  if (spell_ob->randomitems) {
984  newspell = generate_treasure(spell_ob->randomitems, caster->level);
985  if (!newspell) {
986  LOG(llevError, "cast_wonder: Unable to get a spell!\n");
987  return 0;
988  }
989  if (newspell->type != SPELL) {
990  LOG(llevError, "cast_wonder: spell returned is not a spell (%d, %s)!\n", newspell->type, newspell->name);
991  return 0;
992  }
993  /* Prevent inifinite recursion */
994  if (newspell->subtype == SP_WONDER) {
995  LOG(llevError, "cast_wonder: spell returned is another wonder spell!\n");
996  return 0;
997  }
998  return cast_spell(op, caster, dir, newspell, NULL);
999  }
1000  return 1;
1001 }
1002 
1011 int perceive_self(object *op) {
1012  char *cp, buf[MAX_BUF];
1014  if (at == NULL) {
1015  return 1;
1016  }
1017  object *tmp;
1018  const object *god;
1019  int i;
1020  StringBuffer *immunity;
1021 
1022  god = find_god(determine_god(op));
1023  if (god)
1025  "You worship %s",
1026  god->name);
1027  else
1029  "You worship no god");
1030 
1031  tmp = arch_present_in_ob(at, op);
1032 
1033  cp = stringbuffer_finish(describe_item(op, op, 0, NULL));
1034 
1035  if (*cp == '\0' && tmp == NULL)
1037  "You feel very mundane");
1038  else {
1040  "You have:");
1042  cp);
1043  if (tmp != NULL) {
1044  for (i = 0; i < NUM_STATS; i++) {
1045  if (get_attr_value(&tmp->stats, i) < 0) {
1047  "Your %s is depleted by %d",
1048  statname[i], -(get_attr_value(&tmp->stats, i)));
1049  }
1050  }
1051  }
1052  }
1053  free(cp);
1054 
1055  if (op->glow_radius > 0)
1057  "You glow in the dark.");
1058 
1059  immunity = NULL;
1060  for (tmp = op->inv; tmp; tmp = tmp->below) {
1061  if (tmp->type == SIGN) {
1062  if (immunity == NULL) {
1063  immunity = stringbuffer_new();
1064  stringbuffer_append_string(immunity, "You have been exposed to: ");
1065  } else {
1066  stringbuffer_append_string(immunity, ", ");
1067  }
1068  stringbuffer_append_string(immunity, tmp->name);
1069  if (tmp->level > 100)
1070  stringbuffer_append_string(immunity, " (full immunity)");
1071  else if (tmp->level > 70)
1072  stringbuffer_append_string(immunity, " (high immunity)");
1073  else if (tmp->level > 20)
1074  stringbuffer_append_string(immunity, " (partial immunity)");
1075  }
1076  }
1077 
1078  if (immunity != NULL) {
1079  cp = stringbuffer_finish(immunity);
1081  free(cp);
1082  }
1083 
1084  if (is_dragon_pl(op)) {
1085  /* now grab the 'dragon_ability'-force from the player's inventory */
1086  tmp = object_find_by_type_and_arch_name(op, FORCE, "dragon_ability_force");
1087  if (tmp != NULL) {
1088  StringBuffer *levels = NULL;
1089  int i;
1090 
1091  if (tmp->stats.exp == 0) {
1092  snprintf(buf, sizeof(buf), "Your metabolism isn't focused on anything.");
1093  } else {
1094  snprintf(buf, sizeof(buf), "Your metabolism is focused on %s.", change_resist_msg[tmp->stats.exp]);
1095  }
1097  buf);
1098 
1099  for (i = 0; i < NROFATTACKS; i++) {
1100  if (atnr_is_dragon_enabled(i) && tmp->resist[i] > 0) {
1101  if (levels == NULL) {
1103  stringbuffer_append_string(levels, "Ability levels:\n");
1104  }
1105  stringbuffer_append_printf(levels, "- %s: %d\n", change_resist_msg[i], tmp->resist[i]);
1106  }
1107  }
1108 
1109  if (levels != NULL) {
1112  free(cp);
1113  }
1114  }
1115  }
1116  return 1;
1117 }
1118 
1119 static object* town_portal_find_force(object* op, object* spell) {
1120  object *dummy, *force;
1121 
1122  /* The first thing to do is to check if we have a marked destination
1123  * dummy is used to make a check inventory for the force
1124  */
1125  dummy = arch_to_object(spell->other_arch);
1126  if (dummy == NULL) {
1128  "Oops, program error!");
1129  LOG(llevError, "object_new failed (force in cast_create_town_portal for %s!\n", op->name);
1130  return NULL;
1131  }
1132 
1133  force = check_inv_recursive(op, dummy);
1134  if (force == NULL) {
1135  /* Here we know there is no destination marked up.
1136  * We have 2 things to do:
1137  * 1. Mark the destination in the player inventory.
1138  * 2. Let the player know it worked.
1139  */
1140  free_string(dummy->name);
1141  dummy->name = add_string(op->map->path);
1142  EXIT_X(dummy) = op->x;
1143  EXIT_Y(dummy) = op->y;
1144  dummy->weapontype = op->map->last_reset_time;
1145  object_insert_in_ob(dummy, op);
1147  "You fix this place in your mind and feel that you "
1148  "can come here from anywhere.");
1149  } else {
1151  }
1152  return force;
1153 }
1154 
1158 static int town_portal_destroy_existing(object* op, object* spell) {
1159  object* dummy = create_archetype(spell->race);
1160  object* old_force;
1161  if (dummy == NULL) {
1163  "Oops, program error!");
1164  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1165  return 0;
1166  }
1167  archetype *perm_portal;
1168  perm_portal = try_find_archetype(spell->slaying);
1169  if (perm_portal == NULL) {
1171  "Oops, program error!");
1172  return 0;
1173  }
1174 
1175  /* To kill a town portal, we go trough the player's inventory,
1176  * for each marked portal in player's inventory,
1177  * -We try load the associated map (if impossible, consider the portal destructed)
1178  * -We find any portal in the specified location.
1179  * If it has the good name, we destruct it.
1180  * -We destruct the force indicating that portal.
1181  */
1182  while ((old_force = check_inv_recursive(op, dummy))) {
1183  int16_t exitx = EXIT_X(old_force);
1184  int16_t exity = EXIT_Y(old_force);
1185  LOG(llevDebug, "Trying to kill a portal in %s (%d,%d)\n", old_force->race, exitx, exity);
1186 
1187  mapstruct *exitmap;
1188  if (!strncmp(old_force->race, settings.localdir, strlen(settings.localdir)))
1189  exitmap = ready_map_name(old_force->race, MAP_PLAYER_UNIQUE);
1190  else
1191  exitmap = ready_map_name(old_force->race, 0);
1192 
1193  if (exitmap) {
1194  object* tmp = map_find_by_archetype(exitmap, exitx, exity, perm_portal);
1196  if (tmp->name == old_force->name) {
1197  object_remove(tmp);
1198  object_free(tmp, 0);
1199  break;
1200  }
1202 
1203  /* kill any opening animation there is */
1204  archetype *arch = try_find_archetype("town_portal_open");
1205  if (arch != NULL) {
1206  tmp = map_find_by_archetype(exitmap, exitx, exity, arch);
1208  if (tmp->name == old_force->name) {
1209  object_remove(tmp);
1211  break;
1212  }
1214  }
1215  }
1216  object_remove(old_force);
1217  object_free(old_force, 0);
1218  }
1220  return 0;
1221 }
1222 
1250 int cast_create_town_portal(object *op, object *caster, object *spell) {
1251  object *dummy, *force, *tmp;
1252  char portal_name [1024], portal_message [1024];
1253  mapstruct *exitmap;
1254  int op_level, x, y;
1255 
1256  /* Check to see if the map the player is currently on is a per player unique
1257  * map. This can be determined in that per player unique maps have the
1258  * full pathname listed. Ignore if settings.create_home_portals is true.
1259  */
1261  if (!strncmp(op->map->path, settings.localdir, strlen(settings.localdir))) {
1263  "You can't cast that here.");
1264  return 0;
1265  }
1266  }
1267 
1268  /* Check to see if the player is on a transport */
1269  if (op->contr && op->contr->transport) {
1271  "You need to exit the transport to cast that.");
1272  return 0;
1273  }
1274 
1275  force = town_portal_find_force(op, spell);
1276  if (force == NULL) {
1277  return 1;
1278  }
1279 
1280  /* Here we know where the town portal should go to
1281  * We should kill any existing portal associated with the player.
1282  * Than we should create the 2 portals.
1283  * For each of them, we need:
1284  * - To create the portal with the name of the player+destination map
1285  * - set the owner of the town portal
1286  * - To mark the position of the portal in the player's inventory
1287  * for easier destruction.
1288  *
1289  * The mark works has follow:
1290  * slaying: Existing town portal
1291  * hp, sp : x & y of the associated portal
1292  * name : name of the portal
1293  * race : map the portal is in
1294  */
1295  if (town_portal_destroy_existing(op, spell) != 0) {
1296  return 1;
1297  }
1298 
1299  /* Creating the portals.
1300  * The very first thing to do is to ensure
1301  * access to the destination map.
1302  * If we can't, don't fizzle. Simply warn player.
1303  * This ensure player pays his mana for the spell
1304  * because HE is responsible for forgetting.
1305  * 'force' is the destination of the town portal, which we got
1306  * from the players inventory above.
1307  */
1308 
1309  /* Ensure exit map is loaded*/
1310  if (!strncmp(force->name, settings.localdir, strlen(settings.localdir)))
1311  exitmap = ready_map_name(force->name, MAP_PLAYER_UNIQUE);
1312  else
1313  exitmap = ready_map_name(force->name, 0);
1314 
1315  /* If we were unable to load (ex. random map deleted), warn player*/
1316  if (exitmap == NULL) {
1318  "Something strange happens. You can't remember where to go!?");
1320  object_free(force, 0);
1322  return 1;
1323  } else if (exitmap->last_reset_time != force->weapontype) {
1325  "The spell effect has expired.");
1327  object_free(force, 0);
1329  return 1;
1330  }
1331 
1332  op_level = caster_level(caster, spell);
1333  if (op_level < 15)
1334  snprintf(portal_message, 1024, "The air moves around you and a huge smell of ammonia surrounds you as you pass through %s's tiny portal. Pouah!", op->name);
1335  else if (op_level < 30)
1336  snprintf(portal_message, 1024, "%s's portal smells of ozone. You do a lot of movements and finally pass through the small hole in the air.", op->name);
1337  else if (op_level < 60)
1338  snprintf(portal_message, 1024, "A shining door opens in the air in front of you, showing you the path to another place.");
1339  else
1340  snprintf(portal_message, 1024, "As you walk through %s's portal, flowers come out from the ground around you. You feel awed.", op->name);
1341 
1342  /* Create a portal in front of player
1343  * dummy contain the portal and
1344  * force contain the track to kill it later
1345  */
1346 
1347  snprintf(portal_name, 1024, "%s's portal to %s", op->name, force->name);
1348  dummy = create_archetype(spell->slaying); /*The portal*/
1349  if (dummy == NULL) {
1351  "Oops, program error!");
1352  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1353  return 0;
1354  }
1355  EXIT_PATH(dummy) = add_string(force->name);
1356  EXIT_X(dummy) = EXIT_X(force);
1357  EXIT_Y(dummy) = EXIT_Y(force);
1358  FREE_AND_COPY(dummy->name, portal_name);
1359  FREE_AND_COPY(dummy->name_pl, portal_name);
1360  object_set_msg(dummy, portal_message);
1361  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1362 
1363  /* create a nice animation */
1364  tmp = create_archetype("town_portal_open");
1365  FREE_AND_COPY(tmp->name, portal_name);
1366  FREE_AND_COPY(tmp->name_pl, portal_name);
1367  object_insert_in_ob(dummy, tmp);
1368  /* and put it on the floor, when it ends the portal will be on the ground */
1369  cast_create_obj(op, tmp, 0);
1370  x = tmp->x;
1371  y = tmp->y;
1372 
1373  /* Now we need to to create a town portal marker inside the player
1374  * object, so on future castings, we can know that he has an active
1375  * town portal.
1376  */
1377  tmp = create_archetype(spell->race);
1378  if (tmp == NULL) {
1380  "Oops, program error!");
1381  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1382  return 0;
1383  }
1384  tmp->race = add_string(op->map->path);
1385  FREE_AND_COPY(tmp->name, portal_name);
1386  EXIT_X(tmp) = x;
1387  EXIT_Y(tmp) = y;
1389 
1390  /* Create a portal in the destination map
1391  * dummy contain the portal and
1392  * force the track to kill it later
1393  * the 'force' variable still contains the 'reminder' of
1394  * where this portal goes to.
1395  */
1396  snprintf(portal_name, 1024, "%s's portal to %s", op->name, op->map->path);
1397  dummy = create_archetype(spell->slaying); /*The portal*/
1398  if (dummy == NULL) {
1400  "Oops, program error!");
1401  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1402  return 0;
1403  }
1404  EXIT_PATH(dummy) = add_string(op->map->path);
1405  EXIT_X(dummy) = op->x;
1406  EXIT_Y(dummy) = op->y;
1407  FREE_AND_COPY(dummy->name, portal_name);
1408  FREE_AND_COPY(dummy->name_pl, portal_name);
1409  object_set_msg(dummy, portal_message);
1410  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1411 
1412  /* animation here too */
1413  tmp = create_archetype("town_portal_open");
1414  FREE_AND_COPY(tmp->name, portal_name);
1415  FREE_AND_COPY(tmp->name_pl, portal_name);
1416  object_insert_in_ob(dummy, tmp);
1417  /* and put it on the floor, when it ends the portal will be on the ground */
1419  x = tmp->x;
1420  y = tmp->y;
1421 
1422  /* Now we create another town portal marker that
1423  * points back to the one we just made
1424  */
1425  tmp = create_archetype(spell->race);
1426  if (tmp == NULL) {
1428  "Oops, program error!");
1429  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1430  return 0;
1431  }
1432  tmp->race = add_string(force->name);
1433  FREE_AND_COPY(tmp->name, portal_name);
1434  EXIT_X(tmp) = x;
1435  EXIT_Y(tmp) = y;
1437 
1438  /* Describe the player what happened
1439  */
1441  "You see air moving and showing you the way home.");
1442  object_remove(force); /* Delete the force inside the player*/
1443  object_free(force, 0);
1444  return 1;
1445 }
1446 
1447 
1465 int magic_wall(object *op, object *caster, int dir, object *spell_ob) {
1466  object *tmp, *tmp2;
1467  int i, posblocked, negblocked, maxrange;
1468  int16_t x, y;
1469  mapstruct *m;
1470  const char *name;
1471  archetype *at;
1472 
1473  if (!dir) {
1474  dir = op->facing;
1475  x = op->x;
1476  y = op->y;
1477  } else {
1478  x = op->x+freearr_x[dir];
1479  y = op->y+freearr_y[dir];
1480  }
1481  m = op->map;
1482 
1483  if ((spell_ob->move_block || x != op->x || y != op->y)
1484  && (get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE)
1485  || ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) == spell_ob->move_block))) {
1487  "Something is in the way.");
1488  return 0;
1489  }
1490  if (spell_ob->other_arch) {
1491  tmp = arch_to_object(spell_ob->other_arch);
1492  } else if (spell_ob->race) {
1493  char buf1[MAX_BUF];
1494 
1495  snprintf(buf1, sizeof(buf1), spell_ob->race, dir);
1496  at = try_find_archetype(buf1);
1497  if (!at) {
1498  LOG(llevError, "summon_wall: Unable to find archetype %s\n", buf1);
1500  "This spell is broken.");
1501  return 0;
1502  }
1503  tmp = arch_to_object(at);
1504  } else {
1505  LOG(llevError, "magic_wall: spell %s lacks other_arch\n", spell_ob->name);
1506  return 0;
1507  }
1508 
1509  if (tmp->type == SPELL_EFFECT) {
1510  tmp->attacktype = spell_ob->attacktype;
1511  tmp->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1512  tmp->stats.dam = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1513  tmp->range = 0;
1514  } else if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
1515  tmp->stats.hp = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1516  tmp->stats.maxhp = tmp->stats.hp;
1518  set_spell_skill(op, caster, spell_ob, tmp);
1519  }
1521  tmp->stats.food = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1523  }
1524  if (QUERY_FLAG(spell_ob, FLAG_TEAR_DOWN)) {
1525  tmp->stats.hp = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1526  tmp->stats.maxhp = tmp->stats.hp;
1529  }
1530 
1531  /* This can't really hurt - if the object doesn't kill anything,
1532  * these fields just won't be used.
1533  */
1535  set_spell_skill(op, caster, spell_ob, tmp);
1536  tmp->level = caster_level(caster, spell_ob)/2;
1537 
1538  name = tmp->name;
1539  if ((tmp = object_insert_in_map_at(tmp, m, op, 0, x, y)) == NULL) {
1541  "Something destroys your %s",
1542  name);
1543  return 0;
1544  }
1545  /* If this is a spellcasting wall, need to insert the spell object */
1546  if (tmp->other_arch && tmp->other_arch->clone.type == SPELL)
1547  object_insert_in_ob(arch_to_object(tmp->other_arch), tmp);
1548 
1549  /* This code causes the wall to extend some distance in
1550  * each direction, or until an obstruction is encountered.
1551  * posblocked and negblocked help determine how far the
1552  * created wall can extend, it won't go extend through
1553  * blocked spaces.
1554  */
1555  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
1556  posblocked = 0;
1557  negblocked = 0;
1558 
1559  for (i = 1; i <= maxrange; i++) {
1560  int dir2;
1561 
1562  dir2 = (dir < 4) ? (dir+2) : dir-2;
1563 
1564  x = tmp->x+i*freearr_x[dir2];
1565  y = tmp->y+i*freearr_y[dir2];
1566  m = tmp->map;
1567 
1568  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1569  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1570  && !posblocked) {
1571  tmp2 = object_new();
1572  object_copy(tmp, tmp2);
1573  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1574  /* If this is a spellcasting wall, need to insert the spell object */
1575  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1577  } else
1578  posblocked = 1;
1579 
1580  x = tmp->x-i*freearr_x[dir2];
1581  y = tmp->y-i*freearr_y[dir2];
1582  m = tmp->map;
1583 
1584  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1585  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1586  && !negblocked) {
1587  tmp2 = object_new();
1588  object_copy(tmp, tmp2);
1589  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1590  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1592  } else
1593  negblocked = 1;
1594  }
1595 
1597  update_all_los(op->map, op->x, op->y);
1598 
1599  return 1;
1600 }
1601 
1618 int dimension_door(object *op, object *caster, object *spob, int dir) {
1619  uint32_t dist, maxdist;
1620  int mflags;
1621  mapstruct *m;
1622  int16_t sx, sy;
1623 
1624  if (op->type != PLAYER)
1625  return 0;
1626 
1627  if (!dir) {
1629  "In what direction?");
1630  return 0;
1631  }
1632 
1633  /* Given the new outdoor maps, can't let players dimension door for
1634  * ever, so put limits in.
1635  */
1636  maxdist = spob->range+SP_level_range_adjust(caster, spob);
1637 
1638  if (op->contr->count) {
1639  if (op->contr->count > maxdist) {
1641  "You can't dimension door that far!");
1642  return 0;
1643  }
1644 
1645  for (dist = 0; dist < op->contr->count; dist++) {
1646  mflags = get_map_flags(op->map, &m,
1647  op->x+freearr_x[dir]*(dist+1),
1648  op->y+freearr_y[dir]*(dist+1),
1649  &sx, &sy);
1650 
1651  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1652  break;
1653 
1654  if ((mflags&P_BLOCKSVIEW)
1655  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1656  break;
1657  }
1658 
1659  if (dist < op->contr->count) {
1661  "Something blocks the magic of the spell.");
1662  op->contr->count = 0;
1663  return 0;
1664  }
1665  op->contr->count = 0;
1666 
1667  /* Remove code that puts player on random space on maps. IMO,
1668  * a lot of maps probably have areas the player should not get to,
1669  * but may not be marked as NO_MAGIC (as they may be bounded
1670  * by such squares). Also, there are probably treasure rooms and
1671  * lots of other maps that protect areas with no magic, but the
1672  * areas themselves don't contain no magic spaces.
1673  */
1674  /* This call here is really just to normalize the coordinates */
1675  mflags = get_map_flags(op->map, &m, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist,
1676  &sx, &sy);
1677  if (mflags&P_IS_ALIVE || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy))) {
1679  "You cast your spell, but nothing happens.");
1680  return 1; /* Maybe the penalty should be more severe... */
1681  }
1682  } else {
1683  /* Player didn't specify a distance, so lets see how far
1684  * we can move the player. Don't know why this stopped on
1685  * spaces that blocked the players view.
1686  */
1687 
1688  for (dist = 0; dist < maxdist; dist++) {
1689  mflags = get_map_flags(op->map, &m,
1690  op->x+freearr_x[dir]*(dist+1),
1691  op->y+freearr_y[dir]*(dist+1),
1692  &sx, &sy);
1693 
1694  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1695  break;
1696 
1697  if ((mflags&P_BLOCKSVIEW)
1698  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1699  break;
1700  }
1701 
1702  /* If the destination is blocked, keep backing up until we
1703  * find a place for the player.
1704  */
1705  for (; dist > 0; dist--) {
1706  if (get_map_flags(op->map, &m, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist, &sx, &sy)&(P_OUT_OF_MAP|P_IS_ALIVE))
1707  continue;
1708 
1709  if (!OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1710  break;
1711  }
1712  if (!dist) {
1714  "Your spell failed!");
1715  return 0;
1716  }
1717  }
1718 
1719  if (op->contr->transport && op->contr->transport->type == TRANSPORT) {
1720  ob_apply(op->contr->transport, op, 0);
1721  if (op->contr->transport) {
1723  "Your spell failed!");
1724  return 0;
1725  }
1726  }
1727 
1728  /* Actually move the player now */
1729  object_remove(op);
1730  if ((op = object_insert_in_map_at(op, op->map, op, 0, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist)) == NULL)
1731  return 1;
1732 
1733  if (op->type == PLAYER) {
1734  map_newmap_cmd(&op->contr->socket);
1736  }
1737  op->speed_left = -FABS(op->speed)*5; /* Freeze them for a short while */
1738  return 1;
1739 }
1740 
1741 
1754 int cast_heal(object *op, object *caster, object *spell, int dir) {
1755  object *target;
1756  archetype *at;
1757  object *poison;
1758  int heal = 0, success = 0;
1759 
1760  target = find_target_for_friendly_spell(op, dir);
1761 
1762  if (target == NULL)
1763  return 0;
1764 
1765  /* Figure out how many hp this spell might cure.
1766  * could be zero if this spell heals effects, not damage.
1767  */
1768  heal = spell->stats.dam;
1769  if (spell->stats.hp)
1770  heal += random_roll(spell->stats.hp, 6, op, PREFER_HIGH)+spell->stats.hp;
1771 
1772  if (heal) {
1773  if (target->stats.hp >= target->stats.maxhp) {
1775  "You are already fully healed.");
1776  } else {
1777  /* See how many points we actually heal. Instead of messages
1778  * based on type of spell, we instead do messages based
1779  * on amount of damage healed.
1780  */
1781  if (heal > (target->stats.maxhp-target->stats.hp))
1782  heal = target->stats.maxhp-target->stats.hp;
1783  target->stats.hp += heal;
1784 
1785  if (target->stats.hp >= target->stats.maxhp) {
1787  "You feel just fine!");
1788  } else if (heal > 50) {
1790  "Your wounds close!");
1791  } else if (heal > 25) {
1793  "Your wounds mostly close.");
1794  } else if (heal > 10) {
1796  "Your wounds start to fade.");
1797  } else {
1799  "Your wounds start to close.");
1800  }
1801  success = 1;
1802  }
1803  }
1804  if (spell->attacktype&AT_DISEASE)
1805  if (cure_disease(target, op, caster && caster->type != PLAYER ? caster->skill : spell->skill))
1806  success = 1;
1807 
1808  if (spell->attacktype&AT_POISON) {
1809  at = try_find_archetype("poisoning");
1810  if (at != NULL) {
1811  poison = arch_present_in_ob(at, target);
1812  if (poison) {
1813  success = 1;
1815  "Your body feels cleansed");
1816  poison->stats.food = 1;
1817  }
1818  }
1819  }
1820  if (spell->attacktype&AT_CONFUSION) {
1821  poison = object_present_in_ob_by_name(FORCE, "confusion", target);
1822  if (poison) {
1823  success = 1;
1825  "Your mind feels clearer");
1826  poison->duration = 1;
1827  }
1828  }
1829  if (spell->attacktype&AT_BLIND) {
1830  at = try_find_archetype("blindness");
1831  if (at != NULL) {
1832  poison = arch_present_in_ob(at, target);
1833  if (poison) {
1834  success = 1;
1836  "Your vision begins to return.");
1837  poison->stats.food = 1;
1838  }
1839  }
1840  }
1841  if (spell->last_sp && target->stats.sp < target->stats.maxsp) {
1842  target->stats.sp += spell->last_sp;
1843  if (target->stats.sp > target->stats.maxsp)
1844  target->stats.sp = target->stats.maxsp;
1845  success = 1;
1847  "Magical energies surge through your body!");
1848  }
1849  if (spell->last_grace && target->stats.grace < target->stats.maxgrace) {
1850  target->stats.grace += spell->last_grace;
1851  if (target->stats.grace > target->stats.maxgrace)
1852  target->stats.grace = target->stats.maxgrace;
1853  success = 1;
1855  "You feel redeemed with you god!");
1856  }
1857  if (spell->stats.food && target->stats.food < MAX_FOOD) {
1858  target->stats.food += spell->stats.food;
1859  if (target->stats.food > MAX_FOOD)
1860  target->stats.food = MAX_FOOD;
1861  success = 1;
1862  /* We could do something a bit better like the messages for healing above */
1864  "You feel your belly fill with food");
1865  }
1866 
1867  if (spell->other_arch != NULL && target->map != NULL) {
1868  object_insert_in_map_at(arch_to_object(spell->other_arch), target->map, NULL, INS_ON_TOP, target->x, target->y);
1869  }
1870 
1871  return success;
1872 }
1873 
1874 
1880 static const char *const no_gain_msgs[NUM_STATS] = {
1881  "You grow no stronger.",
1882  "You grow no more agile.",
1883  "You don't feel any healthier.",
1884  "no wis",
1885  "You are no easier to look at.",
1886  "no int",
1887  "no pow"
1888 };
1889 
1909 int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent) {
1910  object *tmp;
1911  object *force = NULL;
1912  int i;
1913 
1914  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1915  if (dir != 0) {
1917  } else {
1918  tmp = op;
1919  }
1920 
1921  if (tmp == NULL)
1922  return 0;
1923 
1924  /* If we've already got a force of this type, don't add a new one. */
1925  FOR_INV_PREPARE(tmp, tmp2)
1926  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
1927  if (tmp2->name == spell_ob->name) {
1928  force = tmp2; /* the old effect will be "refreshed" */
1929  break;
1930  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
1931  if (!silent)
1933  "You can not cast %s while %s is in effect",
1934  spell_ob->name, tmp2->name_pl);
1935  return 0;
1936  }
1937  }
1938  FOR_INV_FINISH();
1939  if (force == NULL) {
1941  force->subtype = FORCE_CHANGE_ABILITY;
1942  free_string(force->name);
1943  if (spell_ob->race)
1944  force->name = add_refcount(spell_ob->race);
1945  else
1946  force->name = add_refcount(spell_ob->name);
1947  free_string(force->name_pl);
1948  force->name_pl = add_refcount(spell_ob->name);
1949  } else {
1950  int duration;
1951 
1952  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1953  if (duration > force->duration) {
1954  force->duration = duration;
1956  "You recast the spell while in effect.");
1957 
1958  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
1959  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
1960  }
1961 
1962  } else {
1964  "Recasting the spell had no effect.");
1965  }
1966  return 1;
1967  }
1968  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1969  if (op->type == PLAYER)
1971  force->speed = 1.0;
1972  force->speed_left = -1.0;
1974 
1975  /* Now start processing the effects. First, protections */
1976  for (i = 0; i < NROFATTACKS; i++) {
1977  if (spell_ob->resist[i]) {
1978  force->resist[i] = spell_ob->resist[i]+SP_level_dam_adjust(caster, spell_ob);
1979  if (force->resist[i] > 100)
1980  force->resist[i] = 100;
1981  }
1982  }
1983  if (spell_ob->stats.hp)
1984  force->stats.hp = spell_ob->stats.hp+SP_level_dam_adjust(caster, spell_ob);
1985 
1986  if (tmp->type == PLAYER) {
1987  /* Stat adjustment spells */
1988  for (i = 0; i < NUM_STATS; i++) {
1989  int8_t stat = get_attr_value(&spell_ob->stats, i), k, sm;
1990 
1991  if (stat) {
1992  sm = 0;
1993  for (k = 0; k < stat; k++)
1994  sm += rndm(1, 3);
1995 
1996  if ((get_attr_value(&tmp->stats, i)+sm) > (15+5*stat)) {
1997  sm = (15+5*stat)-get_attr_value(&tmp->stats, i);
1998  if (sm < 0)
1999  sm = 0;
2000  }
2001  set_attr_value(&force->stats, i, sm);
2002  if (!sm)
2004  no_gain_msgs[i]);
2005  }
2006  }
2007  }
2008 
2009  force->move_type = spell_ob->move_type;
2010 
2011  if (QUERY_FLAG(spell_ob, FLAG_SEE_IN_DARK))
2013 
2014  if (QUERY_FLAG(spell_ob, FLAG_XRAYS))
2016 
2017  /* Haste/bonus speed */
2018  if (spell_ob->stats.exp) {
2019  if (op->speed > 0.5)
2020  force->stats.exp = (float)spell_ob->stats.exp/(op->speed+0.5);
2021  else
2022  force->stats.exp = spell_ob->stats.exp;
2023  }
2024 
2025  force->stats.wc = spell_ob->stats.wc;
2026  force->stats.ac = spell_ob->stats.ac;
2027  force->attacktype = spell_ob->attacktype;
2028 
2029  SET_FLAG(tmp, FLAG_NO_FIX_PLAYER); /* we don't want object_insert_in_ob() to call fix_object. */
2032  change_abil(tmp, force); /* Display any relevant messages, and call fix_object to update the player */
2033 
2034  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2035  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2036  }
2037 
2038  return 1;
2039 }
2040 
2057 int cast_bless(object *op, object *caster, object *spell_ob, int dir) {
2058  int i;
2059  const object *god = find_god(determine_god(op));
2060  object *force = NULL, *tmp;
2061 
2062  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
2063  if (dir != 0) {
2065  } else {
2066  tmp = op;
2067  }
2068 
2069  /* If we've already got a force of this type, don't add a new one. */
2070  FOR_INV_PREPARE(tmp, tmp2)
2071  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
2072  if (tmp2->name == spell_ob->name) {
2073  force = tmp2; /* the old effect will be "refreshed" */
2074  break;
2075  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
2077  "You can not cast %s while %s is in effect",
2078  spell_ob->name, tmp2->name_pl);
2079  return 0;
2080  }
2081  }
2082  FOR_INV_FINISH();
2083  if (force == NULL) {
2085  force->subtype = FORCE_CHANGE_ABILITY;
2086  free_string(force->name);
2087  if (spell_ob->race)
2088  force->name = add_refcount(spell_ob->race);
2089  else
2090  force->name = add_refcount(spell_ob->name);
2091  free_string(force->name_pl);
2092  force->name_pl = add_refcount(spell_ob->name);
2093  } else {
2094  int duration;
2095 
2096  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2097  if (duration > force->duration) {
2098  force->duration = duration;
2100  "You recast the spell while in effect.");
2101  } else {
2103  "Recasting the spell had no effect.");
2104  }
2105  return 0;
2106  }
2107  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2108  force->speed = 1.0;
2109  force->speed_left = -1.0;
2110 
2111  if (!god) {
2113  "Your blessing seems empty.");
2114  } else {
2115  /* Only give out good benefits, and put a max on it */
2116  const int16_t resist_max = spell_ob->resist[ATNR_GODPOWER];
2117  for (i = 0; i < NROFATTACKS; i++) {
2118  if (god->resist[i] > 0) {
2119  force->resist[i] = MIN(god->resist[i], resist_max);
2120  }
2121  }
2122  // Also grant appropriate amount of godpower resistance.
2123  force->resist[ATNR_GODPOWER] = spell_ob->resist[ATNR_GODPOWER];
2124 
2125  force->path_attuned |= god->path_attuned;
2126  if (spell_ob->attacktype) {
2127  force->attacktype |= god->attacktype|AT_PHYSICAL;
2128  if (god->slaying)
2129  force->slaying = add_string(god->slaying);
2130  }
2131  if (tmp != op) {
2133  "You bless %s.",
2134  tmp->name);
2136  "%s blessed you.",
2137  op->name);
2138  } else {
2140  "You are blessed by %s!",
2141  god->name);
2142  }
2143  }
2144  force->stats.wc = spell_ob->stats.wc;
2145  force->stats.ac = spell_ob->stats.ac;
2146 
2150  change_abil(tmp, force); /* To display any messages, will call fix_object() */
2151 
2152  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2153  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2154  }
2155  return 1;
2156 }
2157 
2158 
2159 
2160 /*
2161  * Alchemy code by Mark Wedel
2162  *
2163  * This code adds a new spell, called alchemy. Alchemy will turn
2164  * objects to gold nuggets, the value of the gold nuggets being
2165  * from 5% to 40% of that of the item itself depending on casting level.
2166  * It uses the value of the object before charisma adjustments, because
2167  * the nuggets themselves will be will be adjusted by charisma when sold.
2168  *
2169  * Large nuggets are worth 25 gp each (base). You will always get
2170  * the maximum number of large nuggets you could get.
2171  * Small nuggets are worth 1 gp each (base). You will get from 0
2172  * to the max amount of small nuggets as you could get.
2173  *
2174  * For example, if an item is worth 110 gold, you will get
2175  * 4 large nuggets, and from 0-10 small nuggets.
2176  *
2177  * There is also a chance (1:30) that you will get nothing at all
2178  * for the object. There is also a maximum weight that will be
2179  * alchemied.
2180  */
2181 
2182 #define SMALL_NUGGET "smallnugget"
2183 #define LARGE_NUGGET "largenugget"
2184 
2199 static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight) {
2200  uint64_t value = price_base(obj);
2201  uint64_t small_value, large_value;
2203  /* Multiply the value of the object by value_adj, which should range
2204  * from 0.05 to 0.40. Set value to 0 instead if unpaid.
2205  */
2206  if (QUERY_FLAG(obj, FLAG_UNPAID))
2207  value = 0;
2208  else
2209  value *= value_adj;
2210 
2211  archetype *small_nugget_arch = try_find_archetype(SMALL_NUGGET);
2212  if (small_nugget_arch == NULL) {
2213  return;
2214  }
2215  small_value = price_base(&small_nugget_arch->clone);
2216  archetype *large_nugget_arch = try_find_archetype(LARGE_NUGGET);
2217  if (large_nugget_arch == NULL) {
2218  return;
2219  }
2220  large_value = price_base(&large_nugget_arch->clone);
2221 
2222  /* Give half of what value_adj says when we alchemy money (This should
2223  * hopefully make it so that it isn't worth it to alchemy money, sell
2224  * the nuggets, alchemy the gold from that, etc.
2225  */
2226  if (value && (obj->type == MONEY || obj->type == GEM))
2227  value /= 2;
2228 
2229  if ((obj->value > 0) && rndm(0, 29)) {
2230  int count;
2231 
2232  assert(large_value != 0 && small_value != 0);
2233  count = value/large_value;
2234  *large_nuggets += count;
2235  value -= (uint64_t)count*large_value;
2236  count = value/small_value;
2237  *small_nuggets += count;
2238  }
2239 
2240  /* Turn 25 small nuggets into 1 large nugget. If the value
2241  * of large nuggets is not evenly divisable by the small nugget
2242  * value, take off an extra small_nugget (Assuming small_nuggets!=0)
2243  */
2244  if (*small_nuggets*small_value >= large_value) {
2245  assert(small_value != 0);
2246  (*large_nuggets)++;
2247  *small_nuggets -= large_value/small_value;
2248  if (*small_nuggets && large_value%small_value)
2249  (*small_nuggets)--;
2250  }
2251 
2252  if (weight != NULL) {
2253  *weight += obj->weight;
2254  }
2255 
2256  object_remove(obj);
2258 }
2259 
2273 static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y) {
2274  object *tmp;
2275  int flag = 0;
2276 
2277  /* Put any nuggets below the player, but we can only pass this
2278  * flag if we are on the same space as the player
2279  */
2280  if (x == op->x && y == op->y && op->map == m)
2281  flag = INS_BELOW_ORIGINATOR;
2282 
2283  if (small_nuggets) {
2285  tmp-> nrof = small_nuggets;
2286  object_insert_in_map_at(tmp, m, op, flag, x, y);
2287  }
2288  if (large_nuggets) {
2290  tmp-> nrof = large_nuggets;
2291  object_insert_in_map_at(tmp, m, op, flag, x, y);
2292  }
2293 }
2294 
2309 int alchemy(object *op, object *caster, object *spell_ob) {
2310  int x, y, weight = 0, weight_max, large_nuggets, small_nuggets, mflags;
2311  int16_t nx, ny;
2312  float value_adj;
2313  mapstruct *mp;
2314 
2315  if (op->type != PLAYER)
2316  return 0;
2317 
2318  /* Put a maximum weight of items that can be alchemied. Limits the power
2319  * some, and also prevents people from alcheming every table/chair/clock
2320  * in sight
2321  */
2322  weight_max = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
2323  weight_max *= 1000;
2324 
2325  /* Set value_adj to be a multiplier for how much of the original value
2326  * will be in the nuggets. Starts at 0.05, increasing by 0.01 per casting
2327  * level, maxing out at 0.40.
2328  */
2329  value_adj = (SP_level_dam_adjust(caster, spell_ob)/100.00)+0.05;
2330 
2331  if (value_adj > 0.40)
2332  value_adj = 0.40;
2333 
2334  for (y = op->y-1; y <= op->y+1; y++) {
2335  for (x = op->x-1; x <= op->x+1; x++) {
2336  nx = x;
2337  ny = y;
2338 
2339  mp = op->map;
2340 
2341  mflags = get_map_flags(mp, &mp, nx, ny, &nx, &ny);
2342 
2343  if (mflags&(P_OUT_OF_MAP|P_NO_MAGIC))
2344  continue;
2345 
2346  /* Treat alchemy a little differently - most spell effects
2347  * use fly as the movement type - for alchemy, consider it
2348  * ground level effect.
2349  */
2350  if (GET_MAP_MOVE_BLOCK(mp, nx, ny)&MOVE_WALK)
2351  continue;
2352 
2353  small_nuggets = 0;
2354  large_nuggets = 0;
2355 
2356  FOR_MAP_PREPARE(mp, nx, ny, tmp) {
2357  if (tmp->weight > 0 && !QUERY_FLAG(tmp, FLAG_NO_PICK)
2358  && !QUERY_FLAG(tmp, FLAG_ALIVE)
2359  // If a multitile monster has unalive pieces, then don't zap those.
2360  && (!tmp->head || !QUERY_FLAG(tmp->head, FLAG_ALIVE))
2362  if (tmp->inv) {
2363  FOR_INV_PREPARE(tmp, tmp1)
2364  if (tmp1->weight > 0 && !QUERY_FLAG(tmp1, FLAG_NO_PICK)
2365  && !QUERY_FLAG(tmp1, FLAG_ALIVE)
2366  && !QUERY_FLAG(tmp1, FLAG_IS_CAULDRON))
2367  alchemy_object(value_adj, tmp1, &small_nuggets, &large_nuggets, &weight);
2368  FOR_INV_FINISH();
2369  }
2370  alchemy_object(value_adj, tmp, &small_nuggets, &large_nuggets, &weight);
2371 
2372  if (weight > weight_max) {
2373  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2374  return 1;
2375  }
2376  } /* is alchemable object */
2377  } FOR_MAP_FINISH(); /* process all objects on this space */
2378 
2379  /* Insert all the nuggets at one time. This probably saves time, but
2380  * it also prevents us from alcheming nuggets that were just created
2381  * with this spell.
2382  */
2383  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2384  }
2385  }
2386 
2387  /* reset this so that if player standing on a big pile of stuff,
2388  * it is redrawn properly.
2389  */
2390  op->contr->socket.look_position = 0;
2391  return 1;
2392 }
2393 
2394 
2409 int remove_curse(object *op, object *caster, object *spell) {
2410  int success = 0, was_one = 0;
2411 
2414  && ((QUERY_FLAG(tmp, FLAG_CURSED) && QUERY_FLAG(spell, FLAG_CURSED))
2415  || (QUERY_FLAG(tmp, FLAG_DAMNED) && QUERY_FLAG(spell, FLAG_DAMNED)))) {
2416  was_one++;
2417  if (tmp->level <= caster_level(caster, spell)) {
2418  success++;
2419  if (QUERY_FLAG(spell, FLAG_DAMNED))
2421 
2424  tmp->value = 0; /* Still can't sell it */
2425  if (op->type == PLAYER)
2427  }
2428  }
2429  FOR_INV_FINISH();
2430 
2431  if (op->type == PLAYER) {
2432  if (success) {
2434  "You feel like some of your items are looser now.");
2435  } else {
2436  if (was_one)
2438  "You failed to remove the curse.");
2439  else
2441  "You are not using any cursed items.");
2442  }
2443  }
2444  return success;
2445 }
2446 
2457 int cast_item_curse_or_curse(object *op, object *spell_ob) {
2458  object *marked = find_marked_object(op);
2459  char name[HUGE_BUF];
2460 
2461  if (!marked) {
2463  "You need to mark an item first!");
2464  return 0;
2465  }
2466 
2467  if ((QUERY_FLAG(marked, FLAG_CURSED) && QUERY_FLAG(spell_ob, FLAG_CURSED))
2468  || (QUERY_FLAG(marked, FLAG_BLESSED) && QUERY_FLAG(spell_ob, FLAG_BLESSED))) {
2470  "The spell has no effect");
2471  return 0;
2472  }
2473 
2475  if (QUERY_FLAG(spell_ob, FLAG_CURSED)) {
2477  "Your %s emits a dark light for a few seconds.", name);
2482  return 1;
2483  }
2484 
2486  "Your %s glows blue for a few seconds.", name);
2491  return 1;
2492 }
2493 
2508 int cast_identify(object *op, object *caster, object *spell) {
2509  int success = 0, num_ident;
2510  char desc[MAX_BUF];
2511 
2512  num_ident = spell->stats.dam+SP_level_dam_adjust(caster, spell);
2513 
2514  if (num_ident < 1)
2515  num_ident = 1;
2516 
2518  if (!tmp->invisible && !is_identified(tmp)) {
2519  tmp = identify(tmp);
2520  if (op->type == PLAYER) {
2522  "You have %s.",
2523  ob_describe(tmp, op, 1, desc, sizeof(desc)));
2524  if (tmp->msg) {
2526  "The item has a story:\n%s",
2527  tmp->msg);
2528  }
2529  }
2530  num_ident--;
2531  success = 1;
2532  if (!num_ident)
2533  break;
2534  }
2535  FOR_INV_FINISH();
2536  /* If all the power of the spell has been used up, don't go and identify
2537  * stuff on the floor. Only identify stuff on the floor if the spell
2538  * was not fully used.
2539  */
2540  if (num_ident) {
2541  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2542  if (!tmp->invisible && !is_identified(tmp)) {
2543  tmp = identify(tmp);
2544  if (op->type == PLAYER) {
2546  "On the ground is %s.",
2547  ob_describe(tmp, op, 1, desc, sizeof(desc)));
2548  if (tmp->msg) {
2550  "The item has a story:\n%s",
2551  tmp->msg);
2552  }
2554  }
2555  num_ident--;
2556  success = 1;
2557  if (!num_ident)
2558  break;
2559  }
2560  FOR_MAP_FINISH();
2561  }
2562  if (!success)
2564  "You can't reach anything unidentified.");
2565  else {
2566  spell_effect(spell, op->x, op->y, op->map, op);
2567  }
2568  return success;
2569 }
2570 
2583 int cast_detection(object *op, object *caster, object *spell) {
2584  object *tmp, *last, *detect;
2585  const object *god;
2586  int done_one, range, mflags, floor, level;
2587  int16_t x, y, nx, ny;
2588  mapstruct *m;
2589 
2590  /* We precompute some values here so that we don't have to keep
2591  * doing it over and over again.
2592  */
2593  god = find_god(determine_god(op));
2594  level = caster_level(caster, spell);
2595  range = spell->range+SP_level_range_adjust(caster, spell);
2596 
2597  for (x = op->x-range; x <= op->x+range; x++)
2598  for (y = op->y-range; y <= op->y+range; y++) {
2599  m = op->map;
2600  mflags = get_map_flags(m, &m, x, y, &nx, &ny);
2601  if (mflags&P_OUT_OF_MAP)
2602  continue;
2603 
2604  /* For most of the detections, we only detect objects above the
2605  * floor. But this is not true for show invisible.
2606  * Basically, we just go and find the top object and work
2607  * down - that is easier than working up.
2608  */
2609 
2610  last = NULL;
2611  FOR_MAP_PREPARE(m, nx, ny, tmp)
2612  last = tmp;
2613  FOR_MAP_FINISH();
2614  /* Shouldn't happen, but if there are no objects on a space, this
2615  * would happen.
2616  */
2617  if (!last)
2618  continue;
2619 
2620  done_one = 0;
2621  floor = 0;
2622  detect = NULL;
2623  tmp = last;
2625  /* show invisible */
2626  if (QUERY_FLAG(spell, FLAG_MAKE_INVIS)
2627  /* Might there be other objects that we can make visibile? */
2628  && (tmp->invisible && (QUERY_FLAG(tmp, FLAG_MONSTER) ||
2629  (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)) ||
2630  tmp->type == CF_HANDLE ||
2631  tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
2632  tmp->type == BUTTON || tmp->type == TELEPORTER ||
2633  tmp->type == GATE || tmp->type == LOCKED_DOOR ||
2634  tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
2635  tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
2636  tmp->type == TREASURE || tmp->type == BOOK ||
2637  tmp->type == HOLY_ALTAR))) {
2638  if (random_roll(0, level-1, op, PREFER_HIGH) > tmp->level) {
2639  tmp->invisible = 0;
2640  done_one = 1;
2641  }
2642  }
2644  floor = 1;
2645 
2646  /* All detections below this point don't descend beneath the floor,
2647  * so just continue on. We could be clever and look at the type of
2648  * detection to completely break out if we don't care about objects beneath
2649  * the floor, but once we get to the floor, not likely a very big issue anyways.
2650  */
2651  if (floor)
2652  continue;
2653 
2654  /* I had thought about making detect magic and detect curse
2655  * show the flash the magic item like it does for detect monster.
2656  * however, if the object is within sight, this would then make it
2657  * difficult to see what object is magical/cursed, so the
2658  * effect wouldn't be as apparent.
2659  */
2660 
2661  /* detect magic */
2662  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2664  && is_magical(tmp)) {
2666  /* make runes more visible */
2667  if (tmp->type == RUNE && tmp->attacktype&AT_MAGIC)
2668  tmp->stats.Cha /= 4;
2669  done_one = 1;
2670  }
2671  /* detect monster */
2672  if (QUERY_FLAG(spell, FLAG_MONSTER)
2673  && (QUERY_FLAG(tmp, FLAG_MONSTER) || (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)))) {
2674  done_one = 2;
2675  if (!detect)
2676  detect = tmp;
2677  }
2678  /* Basically, if race is set in the spell, then the creatures race must
2679  * match that. if the spell race is set to GOD, then the gods opposing
2680  * race must match.
2681  */
2682  if (spell->race
2684  && tmp->race
2685  && ((!strcmp(spell->race, "GOD") && god && god->slaying && strstr(god->slaying, tmp->race)) || (strstr(spell->race, tmp->race)))) {
2686  done_one = 2;
2687  if (!detect)
2688  detect = tmp;
2689  }
2690  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2694  done_one = 1;
2695  }
2696  } FOR_OB_AND_BELOW_FINISH(); /* for stack of objects on this space */
2697 
2698  /* Code here puts an effect of the spell on the space, so you can see
2699  * where the magic is.
2700  */
2701  if (done_one) {
2702  object *detect_ob;
2703  int dx = nx, dy = ny;
2704 
2705  /* if this is set, we want to copy the face */
2706  if (done_one == 2 && detect) {
2707  /*
2708  * We can't simply copy the face to a single item, because
2709  * multipart objects need to have multipart glows.
2710  * So copy the initial item, erase some properties, and use that.
2711  */
2712 
2713  object *part;
2714  int flag;
2715 
2716  dx = HEAD(detect)->x;
2717  dy = HEAD(detect)->y;
2718 
2719  detect_ob = object_create_arch(HEAD(detect)->arch);
2720  for (part = detect_ob; part != NULL; part = part->more) {
2721  if (part->arch->reference_count > 0)
2722  part->arch->reference_count++;
2723  part->last_anim = 0;
2724  part->type = spell->other_arch->clone.type;
2725  for (flag = 0; flag < 4; flag++) {
2726  part->flags[flag] = spell->other_arch->clone.flags[flag];
2727  }
2728  part->stats.food = spell->other_arch->clone.stats.food;
2729  part->last_anim = 0;
2730  part->speed = spell->other_arch->clone.speed;
2731  part->speed_left = spell->other_arch->clone.speed_left;
2732  part->move_allow = spell->other_arch->clone.move_allow;
2733  part->move_block = spell->other_arch->clone.move_block;
2734  part->move_type = spell->other_arch->clone.move_type;
2735  part->glow_radius = spell->other_arch->clone.glow_radius;
2736  part->invisible = spell->other_arch->clone.invisible;
2737  part->weight = spell->other_arch->clone.weight;
2738  part->map_layer = spell->other_arch->clone.map_layer;
2739  FREE_AND_COPY(part->name, spell->other_arch->clone.name);
2740 
2741  /* by default, the detect_ob is already animated */
2742  if (!QUERY_FLAG(detect, FLAG_ANIMATE))
2743  CLEAR_FLAG(part, FLAG_ANIMATE);
2744  }
2745  object_update_speed(detect_ob);
2746  } else
2747  detect_ob = arch_to_object(spell->other_arch);
2748 
2749  object_insert_in_map_at(detect_ob, m, op, 0, dx, dy);
2750  }
2751  } /* for processing the surrounding spaces */
2752 
2753 
2754  /* Now process objects in the players inventory if detect curse or magic */
2755  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED) || QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)) {
2756  done_one = 0;
2757  FOR_INV_PREPARE(op, tmp) {
2758  if (!tmp->invisible) {
2759  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2760  && is_magical(tmp)
2763  if (op->type == PLAYER)
2764  esrv_send_item(op, tmp);
2765  }
2766  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2770  if (op->type == PLAYER)
2771  esrv_send_item(op, tmp);
2772  }
2773  } /* if item is not identified */
2774  } FOR_INV_FINISH(); /* for the players inventory */
2775  } /* if detect magic/curse and object is a player */
2776  return 1;
2777 }
2778 
2786 static void charge_mana_effect(object *victim, int caster_level) {
2787  /* Prevent explosions for objects without mana. Without this check, doors
2788  * will explode, too.
2789  */
2790  if (victim->stats.maxsp <= 0)
2791  return;
2792 
2794  "You feel energy course through you.");
2795 
2796  if (victim->stats.sp >= victim->stats.maxsp*2) {
2797  object *tmp;
2798 
2800  "Your head explodes!");
2801 
2802  /* Explodes a fireball centered at player */
2804  tmp->dam_modifier = random_roll(1, caster_level, victim, PREFER_LOW)/5+1;
2805  tmp->stats.maxhp = random_roll(1, caster_level, victim, PREFER_LOW)/10+2;
2806  object_insert_in_map_at(tmp, victim->map, NULL, 0, victim->x, victim->y);
2807  victim->stats.sp = 2*victim->stats.maxsp;
2808  } else if (victim->stats.sp >= victim->stats.maxsp*1.88) {
2810  "You feel like your head is going to explode.");
2811  } else if (victim->stats.sp >= victim->stats.maxsp*1.66) {
2813  "You get a splitting headache!");
2814  } else if (victim->stats.sp >= victim->stats.maxsp*1.5) {
2816  "Chaos fills your world.");
2818  } else if (victim->stats.sp >= victim->stats.maxsp*1.25) {
2820  "You start hearing voices.");
2821  }
2822 }
2823 
2841 int cast_transfer(object *op, object *caster, object *spell, int dir) {
2842  object *plyr = NULL;
2843  int16_t x, y;
2844  mapstruct *m;
2845  int mflags;
2846 
2847  m = op->map;
2848  x = op->x+freearr_x[dir];
2849  y = op->y+freearr_y[dir];
2850 
2851  mflags = get_map_flags(m, &m, x, y, &x, &y);
2852  if (!(mflags&P_OUT_OF_MAP) && mflags&P_IS_ALIVE) {
2853  FOR_MAP_PREPARE(m, x, y, tmp)
2854  plyr = tmp;
2855  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2856  break;
2857  FOR_MAP_FINISH();
2858  }
2859 
2860  /* If we did not find a player in the specified direction, transfer
2861  * to anyone on top of us. This is used for the rune of transference mostly.
2862  */
2863  if (plyr == NULL)
2864  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2865  plyr = tmp;
2866  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2867  break;
2868  FOR_MAP_FINISH();
2869 
2870  if (!plyr) {
2872  "There is no one there.");
2873  return 0;
2874  }
2875 
2876  /* give sp */
2877  if (spell->stats.dam > 0) {
2878  plyr->stats.sp += spell->stats.dam+SP_level_dam_adjust(caster, spell);
2879  charge_mana_effect(plyr, caster_level(caster, spell));
2880  return 1;
2881  /* suck sp away. Can't suck sp from yourself */
2882  } else if (op != plyr) {
2883  /* old dragin magic used floats. easier to just use ints and divide by 100 */
2884 
2885  int rate = -spell->stats.dam+SP_level_dam_adjust(caster, spell), sucked;
2886 
2887  if (rate > 95)
2888  rate = 95;
2889 
2890  sucked = (plyr->stats.sp*rate)/100;
2891  plyr->stats.sp -= sucked;
2892  if (QUERY_FLAG(op, FLAG_ALIVE)) {
2893  /* Player doesn't get full credit */
2894  sucked = (sucked*rate)/100;
2895  op->stats.sp += sucked;
2896  if (sucked > 0) {
2897  charge_mana_effect(op, caster_level(caster, spell));
2898  }
2899  }
2900  return 1;
2901  }
2902  return 0;
2903 }
2904 
2914 void counterspell(object *op, int dir) {
2915  object *head;
2916  int mflags;
2917  mapstruct *m;
2918  int16_t sx, sy;
2919 
2920  sx = op->x+freearr_x[dir];
2921  sy = op->y+freearr_y[dir];
2922  m = op->map;
2923  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2924  if (mflags&P_OUT_OF_MAP)
2925  return;
2926 
2927  FOR_MAP_PREPARE(m, sx, sy, tmp) {
2928  object *owner;
2929 
2930  /* Need to look at the head object - otherwise, if tmp
2931  * points to a monster, we don't have all the necessary
2932  * info for it.
2933  */
2934  head = HEAD(tmp);
2935 
2936  /* don't attack our own spells */
2937  owner = object_get_owner(tmp);
2938  if (owner != NULL && owner == object_get_owner(op))
2939  continue;
2940 
2941  /* Basically, if the object is magical and not counterspell,
2942  * we will more or less remove the object. Don't counterspell
2943  * monsters either.
2944  */
2945 
2946  if (head->attacktype&AT_MAGIC
2947  && !(head->attacktype&AT_COUNTERSPELL)
2948  && !QUERY_FLAG(head, FLAG_MONSTER)
2949  && (op->level > head->level)) {
2950  object_remove(head);
2951  object_free(head, 0);
2952  } else switch (head->type) {
2953  case SPELL_EFFECT:
2954  if ((op->level > head->level) && !op->stats.food && !op->speed_left) {
2955  object_remove(head);
2956  object_free(head, 0);
2957  }
2958  break;
2959 
2960  /* I really don't get this rune code that much - that
2961  * random chance seems really low.
2962  */
2963  case RUNE:
2964  if (rndm(0, 149) == 0) {
2965  head->stats.hp--; /* weaken the rune */
2966  if (!head->stats.hp) {
2967  object_remove(head);
2968  object_free(head, 0);
2969  }
2970  }
2971  break;
2972  }
2973  } FOR_MAP_FINISH();
2974 }
2975 
2990 int cast_consecrate(object *op, object *caster, object *spell) {
2991  char buf[MAX_BUF];
2992  const object *god = find_god(determine_god(op));
2993 
2994  if (!god) {
2996  "You can't consecrate anything if you don't worship a god!");
2997  return 0;
2998  }
2999 
3002  break;
3003  if (tmp->type == HOLY_ALTAR) {
3004  if (tmp->level > caster_level(caster, spell)) {
3006  "You are not powerful enough to reconsecrate the %s",
3007  tmp->name);
3008  return 0;
3009  } else {
3010  /* If we got here, we are consecrating an altar */
3011  object *new_altar;
3012  size_t letter;
3013  archetype *altar_arch;
3014 
3015  snprintf(buf, MAX_BUF, "altar_");
3016  letter = strlen(buf);
3017  strncpy(buf+letter, god->name, MAX_BUF-letter);
3018  for (; letter < strlen(buf); letter++)
3019  buf[letter] = tolower(buf[letter]);
3020  altar_arch = try_find_archetype(buf);
3021  if (!altar_arch) {
3023  "You fail to consecrate the altar.");
3024  LOG(llevError, "cast_consecrate: can't find altar %s for god %s\n", buf, god->name);
3025  return 0;
3026  }
3027  new_altar = arch_to_object(altar_arch);
3028  new_altar->level = tmp->level;
3030  SET_FLAG(new_altar, FLAG_IS_BUILDABLE);
3031  object_insert_in_map_at(new_altar, tmp->map, tmp, INS_BELOW_ORIGINATOR, tmp->x, tmp->y);
3032  object_remove(tmp);
3034  "You consecrated the altar to %s!",
3035  god->name);
3036  return 1;
3037  }
3038  }
3039  } FOR_BELOW_FINISH();
3041  "You are not standing over an altar!");
3042  return 0;
3043 }
3044 
3068 int animate_weapon(object *op, object *caster, object *spell, int dir) {
3069  object *weapon, *tmp;
3070  char buf[MAX_BUF];
3071  int a, i;
3072  int16_t x, y;
3073  mapstruct *m;
3074  materialtype_t *mt;
3075 
3076  if (!spell->other_arch) {
3078  "Oops, program error!");
3079  LOG(llevError, "animate_weapon failed: spell %s missing other_arch!\n", spell->name);
3080  return 0;
3081  }
3082 
3083  /* exit if it's not a player using this spell. */
3084  if (op->type != PLAYER)
3085  return 0;
3086 
3087  /* if player already has a golem, abort */
3088  if (op->contr->ranges[range_golem] != NULL && op->contr->golem_count == op->contr->ranges[range_golem]->count) {
3089  pets_control_golem(op->contr->ranges[range_golem], dir);
3090  return 0;
3091  }
3092 
3093  /* if no direction specified, pick one */
3094  if (!dir) {
3095  dir = object_find_free_spot(NULL, op->map, op->x, op->y, 1, 9);
3096  if ( dir == -1 ) {
3098  "There is something in the way.");
3099  return 0;
3100  }
3101  }
3102 
3103  m = op->map;
3104  x = op->x+freearr_x[dir];
3105  y = op->y+freearr_y[dir];
3106 
3107  /* if there's no place to put the golem, abort */
3108  if ((dir == -1)
3109  || (get_map_flags(m, &m, x, y, &x, &y)&P_OUT_OF_MAP)
3110  || ((spell->other_arch->clone.move_type&GET_MAP_MOVE_BLOCK(m, x, y)) == spell->other_arch->clone.move_type)) {
3112  "There is something in the way.");
3113  return 0;
3114  }
3115 
3116  /* Use the weapon marked by the player. */
3117  weapon = find_marked_object(op);
3118 
3119  if (!weapon) {
3121  "You must mark a weapon to use with this spell!");
3122  return 0;
3123  }
3124  if (spell->race && strcmp(weapon->arch->name, spell->race)) {
3126  "The spell fails to transform your weapon.");
3127  return 0;
3128  }
3129  if (weapon->type != WEAPON) {
3131  "You need to mark a weapon to animate it.");
3132  return 0;
3133  }
3134  if (QUERY_FLAG(weapon, FLAG_UNPAID)) {
3136  "You need to pay for the weapon to animate it.");
3137  return 0;
3138  }
3139  if (QUERY_FLAG(weapon, FLAG_APPLIED)) {
3140  char wn[MAX_BUF];
3141 
3142  query_name(weapon, wn, MAX_BUF);
3144  "You need to unequip %s before using it in this spell",
3145  wn);
3146  return 0;
3147  }
3148 
3149  if (weapon->nrof > 1) {
3150  tmp = object_split(weapon, 1, NULL, 0);
3151  esrv_update_item(UPD_NROF, op, weapon);
3152  weapon = tmp;
3153  }
3154 
3155  /* create the golem object */
3156  tmp = arch_to_object(spell->other_arch);
3157 
3158  /* if animated by a player, give the player control of the golem */
3161  tmp->stats.exp = 0;
3163  tmp->type = GOLEM;
3165  set_spell_skill(op, caster, spell, tmp);
3166  op->contr->ranges[range_golem] = tmp;
3167  op->contr->shoottype = range_golem;
3168  op->contr->golem_count = tmp->count;
3169 
3170  /* Give the weapon to the golem now. A bit of a hack to check the
3171  * removed flag - it should only be set if object_split() was
3172  * used above.
3173  */
3174  if (!QUERY_FLAG(weapon, FLAG_REMOVED))
3175  object_remove(weapon);
3176  object_insert_in_ob(weapon, tmp);
3177 
3178  /* To do everything necessary to let a golem use the weapon is a pain,
3179  * so instead, just set it as equipped (otherwise, we need to update
3180  * body_info, skills, etc)
3181  */
3183  SET_FLAG(weapon, FLAG_APPLIED);
3184  fix_object(tmp);
3185 
3186  /* There used to be 'odd' code that basically seemed to take the absolute
3187  * value of the weapon->magic an use that. IMO, that doesn't make sense -
3188  * if you're using a crappy weapon, it shouldn't be as good.
3189  */
3190 
3191  /* modify weapon's animated wc */
3192  tmp->stats.wc = tmp->stats.wc
3193  -SP_level_range_adjust(caster, spell)
3194  -5*weapon->stats.Dex
3195  -2*weapon->stats.Str
3196  -weapon->magic;
3197  if (tmp->stats.wc < -127)
3198  tmp->stats.wc = -127;
3199 
3200  /* Modify hit points for weapon */
3201  tmp->stats.maxhp = tmp->stats.maxhp
3202  +spell->duration
3203  +SP_level_duration_adjust(caster, spell)
3204  +8*weapon->magic
3205  +12*weapon->stats.Con;
3206  if (tmp->stats.maxhp < 0)
3207  tmp->stats.maxhp = 10;
3208  tmp->stats.hp = tmp->stats.maxhp;
3209 
3210  /* Modify weapon's damage */
3211  tmp->stats.dam = spell->stats.dam
3212  +SP_level_dam_adjust(caster, spell)
3213  +weapon->stats.dam
3214  +weapon->magic
3215  +5*weapon->stats.Str;
3216  if (tmp->stats.dam < 0)
3217  tmp->stats.dam = 127;
3218 
3219  /* attacktype */
3220  if (!tmp->attacktype)
3221  tmp->attacktype = AT_PHYSICAL;
3222 
3223  mt = NULL;
3224  if (op->materialname != NULL)
3225  mt = name_to_material(op->materialname);
3226  if (mt != NULL) {
3227  for (i = 0; i < NROFATTACKS; i++)
3228  tmp->resist[i] = 50-(mt->save[i]*5);
3229  a = mt->save[0];
3230  } else {
3231  for (i = 0; i < NROFATTACKS; i++)
3232  tmp->resist[i] = 5;
3233  a = 10;
3234  }
3235  /* Set weapon's immunity */
3236  tmp->resist[ATNR_CONFUSION] = 100;
3237  tmp->resist[ATNR_POISON] = 100;
3238  tmp->resist[ATNR_SLOW] = 100;
3239  tmp->resist[ATNR_PARALYZE] = 100;
3240  tmp->resist[ATNR_TURN_UNDEAD] = 100;
3241  tmp->resist[ATNR_FEAR] = 100;
3242  tmp->resist[ATNR_DEPLETE] = 100;
3243  tmp->resist[ATNR_DEATH] = 100;
3244  tmp->resist[ATNR_BLIND] = 100;
3245 
3246  /* Improve weapon's armour value according to best save vs. physical of its material */
3247 
3248  if (a > 14)
3249  a = 14;
3250  tmp->resist[ATNR_PHYSICAL] = 100-(int)((100.0-(float)tmp->resist[ATNR_PHYSICAL])/(30.0-2.0*a));
3251 
3252  /* Determine golem's speed */
3253  tmp->speed = 0.4+0.1*SP_level_range_adjust(caster, spell);
3254 
3255  if (tmp->speed > 3.33)
3256  tmp->speed = 3.33;
3257 
3258  if (!spell->race) {
3259  snprintf(buf, sizeof(buf), "animated %s", weapon->name);
3260  if (tmp->name)
3261  free_string(tmp->name);
3262  tmp->name = add_string(buf);
3263 
3264  tmp->face = weapon->face;
3265  tmp->animation = weapon->animation;
3266  tmp->anim_speed = weapon->anim_speed;
3267  tmp->last_anim = weapon->last_anim;
3268  tmp->state = weapon->state;
3269  if (QUERY_FLAG(weapon, FLAG_ANIMATE)) {
3271  } else {
3273  }
3275  }
3276 
3277  /* make experience increase in proportion to the strength of the summoned creature. */
3278  tmp->stats.exp *= 1+(MAX(spell->stats.maxgrace, spell->stats.sp)/caster_level(caster, spell));
3279 
3280  tmp->speed_left = -1;
3281  tmp->direction = dir;
3282  object_insert_in_map_at(tmp, m, op, 0, x, y);
3283  return 1;
3284 }
3285 
3298 int cast_change_map_lightlevel(object *op, object *spell) {
3299  int success;
3300 
3301  if (!op->map)
3302  return 0; /* shouldnt happen */
3303 
3304  success = change_map_light(op->map, spell->stats.dam);
3305  if (!success) {
3306  if (spell->stats.dam < 0)
3308  "It can be no brighter here.");
3309  else
3311  "It can be no darker here.");
3312  }
3313  return success;
3314 }
3315 
3330 int create_aura(object *op, object *caster, object *spell) {
3331  int refresh = 0, i;
3332  object *new_aura;
3333 
3334  new_aura = arch_present_in_ob(spell->other_arch, op);
3335  if (new_aura)
3336  refresh = 1;
3337  else
3338  new_aura = arch_to_object(spell->other_arch);
3339 
3340  new_aura->duration = spell->duration+10*SP_level_duration_adjust(caster, spell);
3341  if (op->type == PLAYER)
3342  store_spell_expiry(new_aura);
3343 
3344  new_aura->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
3345 
3346  // If the range is zero, it's not an aura. Plain and simple. Minimum is one.
3347  // Also provides backward compatability on existing auras to be range 1
3348  new_aura->range = MAX(1, spell->range+SP_level_range_adjust(caster, spell));
3349 
3350  object_set_owner(new_aura, op);
3351  set_spell_skill(op, caster, spell, new_aura);
3352  new_aura->attacktype = spell->attacktype;
3353 
3354  new_aura->level = caster_level(caster, spell);
3355 
3356  /* Code below is so that auras can also provide resistances. For
3357  * example, fire shield both does damage to nearby enemies and also
3358  * provides some protection to fire. We need to use a different
3359  * FORCE object for this, as putting it in with the aura object
3360  * just puts too many meanings into that one object. Because
3361  * the duration of this force object is the same, we don't need
3362  * to set up spell expiry on it - this second object is really
3363  * an internal mechanic that should be invisible to the player.
3364  */
3365  for (i = 0; i < NROFATTACKS; i++) {
3366  if (spell->resist[i]) {
3367  int refresh1=1;
3368  object *force;
3369 
3371  if (!force) {
3373  force->subtype = FORCE_CHANGE_ABILITY;
3374  free_string(force->name);
3375  force->name = add_refcount(spell->name);
3376  free_string(force->name_pl);
3377  force->name_pl = add_refcount(spell->name);
3378  refresh1=0;
3379  }
3380  force->duration = new_aura->duration;
3381  force->speed = new_aura->speed;
3382  memcpy(&force->resist, spell->resist, sizeof(spell->resist));
3384 
3385  if (!refresh1)
3387  change_abil(op, new_aura);
3388  fix_object(op);
3389  break;
3390  }
3391  }
3392 
3393  if (refresh)
3395  "You recast the spell while in effect.");
3396  else
3397  object_insert_in_ob(new_aura, op);
3398  return 1;
3399 }
3400 
3416 int write_mark(object *op, object *spell, const char *msg) {
3417  char rune[HUGE_BUF];
3418  object *tmp;
3419 
3420  if (!msg || msg[0] == 0) {
3422  "Write what?");
3423  return 0;
3424  }
3425 
3426  if (strcasestr_local(msg, "endmsg")) {
3428  "Trying to cheat are we?");
3429  LOG(llevInfo, "write_rune: player %s tried to write bogus rune %s\n", op->name, msg);
3430  return 0;
3431  }
3432 
3433  if (!spell->other_arch)
3434  return 0;
3435  tmp = arch_to_object(spell->other_arch);
3436  strncpy(rune, msg, HUGE_BUF-2);
3437  rune[HUGE_BUF-2] = 0;
3438  strcat(rune, "\n");
3439  tmp->race = add_string(op->name); /*Save the owner of the rune*/
3440  object_set_msg(tmp, rune);
3442  return 1;
3443 }
SP_level_range_adjust
int SP_level_range_adjust(const object *caster, const object *spob)
Definition: spell_util.c:337
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
MSG_TYPE_SPELL_PERCEIVE_SELF
#define MSG_TYPE_SPELL_PERCEIVE_SELF
Definition: newclient.h:637
obj::flags
ob_flags flags
Definition: object.h:420
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
perceive_self
int perceive_self(object *op)
Definition: spell_effect.c:1011
alchemy_object
static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight)
Definition: spell_effect.c:2199
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.c:3570
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.c:1785
FORCE_CHANGE_ABILITY
#define FORCE_CHANGE_ABILITY
Definition: spells.h:145
HAS_RANDOM_ITEMS
#define HAS_RANDOM_ITEMS(op)
Definition: define.h:184
UP_OBJ_FACE
#define UP_OBJ_FACE
Definition: object.h:519
PLAYER
@ PLAYER
Definition: object.h:107
obj::attack_movement
uint16_t attack_movement
Definition: object.h:396
ATNR_PARALYZE
#define ATNR_PARALYZE
Definition: attack.h:61
set_spell_skill
void set_spell_skill(object *op, object *caster, object *spob, object *dest)
Definition: spell_util.c:92
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:531
tolower
#define tolower(C)
Definition: c_new.c:30
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.c:210
CF_HANDLE
@ CF_HANDLE
Definition: object.h:208
SOUND_TYPE_ITEM
#define SOUND_TYPE_ITEM
Definition: newclient.h:335
liv::dam
int16_t dam
Definition: living.h:46
object_free
void object_free(object *ob, int flags)
Definition: object.c:1578
INS_NO_WALK_ON
#define INS_NO_WALK_ON
Definition: object.h:568
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
object_remove
void object_remove(object *op)
Definition: object.c:1819
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
remove_friendly_object
void remove_friendly_object(object *op)
Definition: friend.cpp:56
AT_POISON
#define AT_POISON
Definition: attack.h:86
obj::face
const Face * face
Definition: object.h:336
AT_MAGIC
#define AT_MAGIC
Definition: attack.h:77
obj::move_block
MoveType move_block
Definition: object.h:430
CAN_PROBE
static bool CAN_PROBE(const object *ob)
Definition: object.h:602
BOW
@ BOW
Definition: object.h:118
LARGE_NUGGET
#define LARGE_NUGGET
Definition: spell_effect.c:2183
archt::head
struct archt * head
Definition: object.h:471
llevError
@ llevError
Definition: logger.h:11
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.c:238
FABS
#define FABS(x)
Definition: define.h:22
create_aura
int create_aura(object *op, object *caster, object *spell)
Definition: spell_effect.c:3330
WAND
@ WAND
Definition: object.h:220
strcasestr_local
#define strcasestr_local
Definition: compat.h:28
FLAG_UNDEAD
#define FLAG_UNDEAD
Definition: define.h:270
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
find_archetype_by_object_type_name
archetype * find_archetype_by_object_type_name(int type, const char *name)
Definition: arch.cpp:68
FLAG_GENERATOR
#define FLAG_GENERATOR
Definition: define.h:248
object_find_by_type_and_arch_name
object * object_find_by_type_and_arch_name(const object *who, int type, const char *name)
Definition: object.c:4248
BUTTON
@ BUTTON
Definition: object.h:207
object_update
void object_update(object *op, int action)
Definition: object.c:1420
diamondslots.x
x
Definition: diamondslots.py:15
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
obj::count
tag_t count
Definition: object.h:302
obj::map
struct mapdef * map
Definition: object.h:300
cast_invisible
int cast_invisible(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:812
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
obj::race
sstring race
Definition: object.h:321
archetypes_for_each
void archetypes_for_each(arch_op op)
Definition: assets.cpp:331
get_next_archetype
archetype * get_next_archetype(archetype *current)
Definition: assets.cpp:280
liv::maxgrace
int16_t maxgrace
Definition: living.h:45
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:134
obj::value
int32_t value
Definition: object.h:355
ARCH_DEPLETION
#define ARCH_DEPLETION
Definition: object.h:576
liv::wc
int8_t wc
Definition: living.h:37
confuse_living
void confuse_living(object *op, object *hitter, int dam)
Definition: attack.c:2266
liv::Str
int8_t Str
Definition: living.h:36
FLAG_SEE_IN_DARK
#define FLAG_SEE_IN_DARK
Definition: define.h:337
food_choice
static archetype * food_choice
Definition: spell_effect.c:606
price_base
uint64_t price_base(const object *obj)
Definition: shop.c:75
object_new
object * object_new(void)
Definition: object.c:1255
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
cast_spell
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Definition: spell_util.c:1420
disinfect.a
a
Definition: disinfect.py:13
cast_transfer
int cast_transfer(object *op, object *caster, object *spell, int dir)
Definition: spell_effect.c:2841
obj::anim_speed
uint8_t anim_speed
Definition: object.h:422
obj::path_attuned
uint32_t path_attuned
Definition: object.h:348
liv::maxhp
int16_t maxhp
Definition: living.h:41
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Definition: define.h:704
GEM
@ GEM
Definition: object.h:167
pl
Definition: player.h:105
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:439
obj::last_anim
uint8_t last_anim
Definition: object.h:423
PREFER_LOW
#define PREFER_LOW
Definition: define.h:564
WEAPON
@ WEAPON
Definition: object.h:119
obj::invisible
int16_t invisible
Definition: object.h:365
arch_present_in_ob
object * arch_present_in_ob(const archetype *at, const object *op)
Definition: object.c:3193
liv::hp
int16_t hp
Definition: living.h:40
ATNR_SLOW
#define ATNR_SLOW
Definition: attack.h:60
MIN
#define MIN(x, y)
Definition: compat.h:21
mapdef::last_reset_time
long last_reset_time
Definition: map.h:359
ATNR_GODPOWER
#define ATNR_GODPOWER
Definition: attack.h:69
TREASURE
@ TREASURE
Definition: object.h:110
cast_polymorph
int cast_polymorph(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_effect.c:435
MSG_TYPE_VICTIM_SPELL
#define MSG_TYPE_VICTIM_SPELL
Definition: newclient.h:654
cast_consecrate
int cast_consecrate(object *op, object *caster, object *spell)
Definition: spell_effect.c:2990
SP_level_duration_adjust
int SP_level_duration_adjust(const object *caster, const object *spob)
Definition: spell_util.c:311
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Definition: object.c:4054
play_sound_map
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
Definition: sounds.c:113
remove_curse
int remove_curse(object *op, object *caster, object *spell)
Definition: spell_effect.c:2409
FLAG_WIZCAST
#define FLAG_WIZCAST
Definition: define.h:289
town_portal_find_force
static object * town_portal_find_force(object *op, object *spell)
Definition: spell_effect.c:1119
RUNE
@ RUNE
Definition: object.h:240
MAP_PLAYER_UNIQUE
#define MAP_PLAYER_UNIQUE
Definition: map.h:97
cast_wonder
int cast_wonder(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.c:977
artifactliststruct::items
struct artifactstruct * items
Definition: artifact.h:30
Ice.tmp
int tmp
Definition: Ice.py:207
FLAG_BLESSED
#define FLAG_BLESSED
Definition: define.h:369
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:244
P_NO_MAGIC
#define P_NO_MAGIC
Definition: map.h:228
TRANSPORT
@ TRANSPORT
Definition: object.h:108
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
UPD_NROF
#define UPD_NROF
Definition: newclient.h:321
SIGN
@ SIGN
Definition: object.h:211
levels
int64_t * levels
Definition: exp.c:26
cast_item_curse_or_curse
int cast_item_curse_or_curse(object *op, object *spell_ob)
Definition: spell_effect.c:2457
SMALL_NUGGET
#define SMALL_NUGGET
Definition: spell_effect.c:2182
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
food_value_choice
static int food_value_choice
Definition: spell_effect.c:607
FLAG_BLOCKSVIEW
#define FLAG_BLOCKSVIEW
Definition: define.h:269
ATNR_TURN_UNDEAD
#define ATNR_TURN_UNDEAD
Definition: attack.h:62
describe_item
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Definition: item.c:941
range_golem
@ range_golem
Definition: player.h:34
apply_manual
int apply_manual(object *op, object *tmp, int aflag)
Definition: apply.c:597
FOR_OB_AND_ABOVE_FINISH
#define FOR_OB_AND_ABOVE_FINISH()
Definition: define.h:743
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.c:241
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:238
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
statname
const char *const statname[NUM_STATS]
Definition: living.c:184
obj::randomitems
struct treasureliststruct * randomitems
Definition: object.h:390
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
MSG_TYPE_VICTIM
#define MSG_TYPE_VICTIM
Definition: newclient.h:415
MAX
#define MAX(x, y)
Definition: compat.h:24
cast_identify
int cast_identify(object *op, object *caster, object *spell)
Definition: spell_effect.c:2508
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.c:299
obj::nrof
uint32_t nrof
Definition: object.h:337
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.c:305
MSG_TYPE_SPELL_TARGET
#define MSG_TYPE_SPELL_TARGET
Definition: newclient.h:638
ATNR_CONFUSION
#define ATNR_CONFUSION
Definition: attack.h:54
ob_apply
method_ret ob_apply(object *op, object *applier, int aflags)
Definition: ob_methods.c:44
MSG_TYPE_SPELL_HEAL
#define MSG_TYPE_SPELL_HEAL
Definition: newclient.h:631
obj::duration
int16_t duration
Definition: object.h:408
find_god
const object * find_god(const char *name)
Definition: holy.cpp:321
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:246
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Definition: define.h:711
archt
Definition: object.h:469
obj
Definition: object.h:277
settings
struct Settings settings
Definition: init.c:39
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
esrv_send_item
void esrv_send_item(object *pl, object *op)
Definition: main.c:355
MSG_TYPE_SPELL_SUCCESS
#define MSG_TYPE_SPELL_SUCCESS
Definition: newclient.h:635
FOR_OB_AND_ABOVE_PREPARE
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Definition: define.h:739
store_spell_expiry
void store_spell_expiry(object *spell)
Definition: spell_util.c:1977
obj::slaying
sstring slaying
Definition: object.h:322
identify
object * identify(object *op)
Definition: item.c:1409
free_string
void free_string(sstring str)
Definition: shstr.c:280
cast_earth_to_dust
int cast_earth_to_dust(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:864
spell_effect
void spell_effect(object *spob, int x, int y, mapstruct *map, object *originator)
Definition: spell_util.c:143
ATNR_BLIND
#define ATNR_BLIND
Definition: attack.h:71
m
static event_registration m
Definition: citylife.cpp:427
liv::maxsp
int16_t maxsp
Definition: living.h:43
autojail.who
who
Definition: autojail.py:3
polymorph_living
static void polymorph_living(object *op, int level)
Definition: spell_effect.c:159
name_to_material
materialtype_t * name_to_material(const char *name)
Definition: utils.c:248
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.c:4272
liv::exp
int64_t exp
Definition: living.h:47
PREFER_HIGH
#define PREFER_HIGH
Definition: define.h:563
FLAG_TEAR_DOWN
#define FLAG_TEAR_DOWN
Definition: define.h:279
disinfect.map
map
Definition: disinfect.py:4
change_map_light
int change_map_light(mapstruct *m, int change)
Definition: map.c:2009
obj::name
sstring name
Definition: object.h:314
determine_god
const char * determine_god(object *op)
Definition: gods.c:55
find_artifactlist
artifactlist * find_artifactlist(int type)
Definition: artifact.c:575
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.c:1064
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:585
FLAG_KNOWN_BLESSED
#define FLAG_KNOWN_BLESSED
Definition: define.h:370
mon
object * mon
Definition: comet_perf.c:75
GT_INVISIBLE
@ GT_INVISIBLE
Definition: treasure.h:32
polymorph
void polymorph(object *op, object *who, int level)
Definition: spell_effect.c:381
MOVE_WALK
#define MOVE_WALK
Definition: define.h:392
FLAG_KNOWN_CURSED
#define FLAG_KNOWN_CURSED
Definition: define.h:320
EXPLODING_FIREBALL
#define EXPLODING_FIREBALL
Definition: spells.h:174
artifactstruct::next
struct artifactstruct * next
Definition: artifact.h:18
examine_monster
void examine_monster(object *op, object *tmp, int level)
Definition: c_object.c:1614
obj::name_pl
sstring name_pl
Definition: object.h:318
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:754
food_each
static void food_each(archetype *arch)
Definition: spell_effect.c:608
HEAD
#define HEAD(op)
Definition: object.h:593
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:95
_materialtype::save
int8_t save[NROFATTACKS]
Definition: material.h:36
obj::speed_left
float speed_left
Definition: object.h:333
cast_magic_storm
void cast_magic_storm(object *op, object *tmp, int lvl)
Definition: spell_effect.c:46
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:123
MSG_TYPE_ITEM
#define MSG_TYPE_ITEM
Definition: newclient.h:412
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.c:510
FLAG_MAKE_INVIS
#define FLAG_MAKE_INVIS
Definition: define.h:328
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:124
HOLE
@ HOLE
Definition: object.h:209
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Definition: global.h:201
obj::x
int16_t x
Definition: object.h:330
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:566
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
fix_object
void fix_object(object *op)
Definition: living.c:1126
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:315
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:301
CFweardisguise.tag
tag
Definition: CFweardisguise.py:25
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
_materialtype
Definition: material.h:32
is_magical
int is_magical(const object *op)
Definition: item.c:1215
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:193
obj::other_arch
struct archt * other_arch
Definition: object.h:418
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:570
GOLEM
@ GOLEM
Definition: object.h:145
caster_level
int caster_level(const object *caster, const object *spell)
Definition: spell_util.c:193
rndm
int rndm(int min, int max)
Definition: utils.c:162
disinfect.count
int count
Definition: disinfect.py:7
obj::speed
float speed
Definition: object.h:332
obj::weapontype
uint32_t weapontype
Definition: object.h:376
town_portal_destroy_existing
static int town_portal_destroy_existing(object *op, object *spell)
Definition: spell_effect.c:1158
tag_t
uint32_t tag_t
Definition: object.h:12
check_inv_recursive
object * check_inv_recursive(object *op, const object *trig)
Definition: button.c:782
liv::Con
int8_t Con
Definition: living.h:36
ATNR_POISON
#define ATNR_POISON
Definition: attack.h:59
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
Definition: define.h:296
sproto.h
liv::food
int32_t food
Definition: living.h:48
FLAG_NO_DROP
#define FLAG_NO_DROP
Definition: define.h:288
ATNR_DEATH
#define ATNR_DEATH
Definition: attack.h:66
polymorph_melt
static void polymorph_melt(object *who, object *op)
Definition: spell_effect.c:252
FOR_OB_AND_BELOW_PREPARE
#define FOR_OB_AND_BELOW_PREPARE(op_)
Definition: define.h:750
mapdef
Definition: map.h:317
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Definition: newclient.h:411
BOOK
@ BOOK
Definition: object.h:114
GT_ENVIRONMENT
@ GT_ENVIRONMENT
Definition: treasure.h:31
is_dragon_pl
int is_dragon_pl(const object *op)
Definition: player.c:122
write_mark
int write_mark(object *op, object *spell, const char *msg)
Definition: spell_effect.c:3416
RING
@ RING
Definition: object.h:185
obj::map_layer
uint8_t map_layer
Definition: object.h:427
cast_heal
int cast_heal(object *op, object *caster, object *spell, int dir)
Definition: spell_effect.c:1754
obj::animation
const Animations * animation
Definition: object.h:421
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:242
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
object_set_owner
void object_set_owner(object *op, object *owner)
Definition: object.c:844
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:250
EXIT_X
#define EXIT_X(xyz)
Definition: define.h:441
MAX_BUF
#define MAX_BUF
Definition: define.h:35
artifactstruct
Definition: artifact.h:14
INS_ON_TOP
#define INS_ON_TOP
Definition: object.h:569
fix_generated_item
void fix_generated_item(object *op, object *creator, int difficulty, int max_magic, int flags)
Definition: treasure.c:876
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:281
monster_check_apply_all
void monster_check_apply_all(object *monster)
Definition: monster.c:1991
probe
int probe(object *op, object *caster, object *spell_ob, int dir, int level)
Definition: spell_effect.c:708
cast_change_ability
int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent)
Definition: spell_effect.c:1909
StringBuffer
Definition: stringbuffer.c:25
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:195
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Definition: define.h:393
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:42
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
EXIT
@ EXIT
Definition: object.h:181
obj::y
int16_t y
Definition: object.h:330
FLAG_KNOWN_MAGICAL
#define FLAG_KNOWN_MAGICAL
Definition: define.h:319
obj::glow_radius
int8_t glow_radius
Definition: object.h:369
obj::arch
struct archt * arch
Definition: object.h:417
ob_describe
char * ob_describe(const object *op, const object *observer, int use_media_tags, char *buf, size_t size)
Definition: ob_methods.c:91
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.c:4781
sounds.h
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
llevInfo
@ llevInfo
Definition: logger.h:12
obj::type
uint8_t type
Definition: object.h:343
change_resist_msg
const EXTERN char *const change_resist_msg[NROFATTACKS]
Definition: attack.h:135
obj::last_grace
int16_t last_grace
Definition: object.h:364
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
AT_BLIND
#define AT_BLIND
Definition: attack.h:98
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
spells.h
no_gain_msgs
static const char *const no_gain_msgs[NUM_STATS]
Definition: spell_effect.c:1880
obj::stats
living stats
Definition: object.h:373
SP_level_dam_adjust
int SP_level_dam_adjust(const object *caster, const object *spob)
Definition: spell_util.c:286
archt::clone
object clone
Definition: object.h:473
obj::state
uint8_t state
Definition: object.h:354
MSG_TYPE_SPELL_FAILURE
#define MSG_TYPE_SPELL_FAILURE
Definition: newclient.h:633
add_friendly_object
void add_friendly_object(object *op)
Definition: friend.cpp:36
map_find_by_archetype
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
Definition: object.c:3089
obj::weight
int32_t weight
Definition: object.h:370
liv::Dex
int8_t Dex
Definition: living.h:36
ATNR_DEPLETE
#define ATNR_DEPLETE
Definition: attack.h:65
ARCH_PORTAL_FAILED
#define ARCH_PORTAL_FAILED
Definition: object.h:578
FLAG_IS_BUILDABLE
#define FLAG_IS_BUILDABLE
Definition: define.h:367
reputation.victim
victim
Definition: reputation.py:14
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
did_make_save
int did_make_save(const object *op, int level, int bonus)
Definition: living.c:2282
archt::reference_count
int reference_count
Definition: object.h:476
liv::grace
int16_t grace
Definition: living.h:44
give.op
op
Definition: give.py:33
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3530
autojail.value
value
Definition: autojail.py:6
MSG_TYPE_SPELL_ERROR
#define MSG_TYPE_SPELL_ERROR
Definition: newclient.h:636
shop.h
cast_create_food
int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
Definition: spell_effect.c:640
cast_create_obj
int cast_create_obj(object *op, object *new_op, int dir)
Definition: spell_util.c:493
cast_create_town_portal
int cast_create_town_portal(object *op, object *caster, object *spell)
Definition: spell_effect.c:1250
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.c:360
cast_create_missile
int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg)
Definition: spell_effect.c:503
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:215
ATNR_MAGIC
#define ATNR_MAGIC
Definition: attack.h:50
FLAG_NO_FIX_PLAYER
#define FLAG_NO_FIX_PLAYER
Definition: define.h:277
obj::last_sp
int32_t last_sp
Definition: object.h:363
hit_player
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Definition: attack.c:1860
EXIT_Y
#define EXIT_Y(xyz)
Definition: define.h:442
diamondslots.y
y
Definition: diamondslots.py:16
assets.h
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
counterspell
void counterspell(object *op, int dir)
Definition: spell_effect.c:2914
buf
StringBuffer * buf
Definition: readable.c:1610
set_attr_value
void set_attr_value(living *stats, int attr, int8_t value)
Definition: living.c:219
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:138
polymorph_item
static void polymorph_item(object *who, object *op, int level)
Definition: spell_effect.c:280
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2833
pl::invis_race
const char * invis_race
Definition: player.h:151
cast_bless
int cast_bless(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_effect.c:2057
update_all_los
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.c:536
object_update_speed
void object_update_speed(object *op)
Definition: object.c:1330
obj::subtype
uint8_t subtype
Definition: object.h:344
obj::more
struct obj * more
Definition: object.h:298
obj::move_type
MoveType move_type
Definition: object.h:429
map_newmap_cmd
void map_newmap_cmd(socket_struct *ns)
Definition: request.c:620
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:232
strcasecmp
int strcasecmp(const char *s1, const char *s2)
artifactstruct::item
object * item
Definition: artifact.h:15
make_face_from_files.int
int
Definition: make_face_from_files.py:26
FLAG_IS_USED_UP
#define FLAG_IS_USED_UP
Definition: define.h:260
object_present_in_ob_by_name
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.c:3174
recharge
int recharge(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:81
FLAG_ANIMATE
#define FLAG_ANIMATE
Definition: define.h:242
makes_invisible_to
int makes_invisible_to(object *pl, object *mon)
Definition: spell_effect.c:765
UPD_NAME
#define UPD_NAME
Definition: newclient.h:318
AT_COUNTERSPELL
#define AT_COUNTERSPELL
Definition: attack.h:95
liv::ac
int8_t ac
Definition: living.h:38
obj::skill
sstring skill
Definition: object.h:324
AT_DISEASE
#define AT_DISEASE
Definition: attack.h:102
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:2080
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:309
get_attr_value
int8_t get_attr_value(const living *stats, int attr)
Definition: living.c:314
FOOD
@ FOOD
Definition: object.h:112
dimension_door
int dimension_door(object *op, object *caster, object *spob, int dir)
Definition: spell_effect.c:1618
place_alchemy_objects
static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y)
Definition: spell_effect.c:2273
cure_disease
int cure_disease(object *sufferer, object *caster, sstring skill)
Definition: disease.c:685
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:288
ALTAR
@ ALTAR
Definition: object.h:122
positioning_system.marked
marked
Definition: positioning_system.py:21
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
AT_CONFUSION
#define AT_CONFUSION
Definition: attack.h:81
OB_TYPE_MOVE_BLOCK
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Definition: define.h:432
level
int level
Definition: readable.c:1608
generate_treasure
object * generate_treasure(treasurelist *t, int difficulty)
Definition: treasure.c:273
DRINK
@ DRINK
Definition: object.h:157
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:530
archt::name
sstring name
Definition: object.h:470
SP_WONDER
#define SP_WONDER
Definition: spells.h:83
FLAG_XRAYS
#define FLAG_XRAYS
Definition: define.h:300
PETMOVE
#define PETMOVE
Definition: define.h:501
atnr_is_dragon_enabled
int atnr_is_dragon_enabled(int attacknr)
Definition: player.c:103
alchemy
int alchemy(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:2309
obj::attacktype
uint32_t attacktype
Definition: object.h:347
cast_word_of_recall
int cast_word_of_recall(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:915
find_target_for_friendly_spell
object * find_target_for_friendly_spell(object *op, int dir)
Definition: spell_util.c:812
animate_weapon
int animate_weapon(object *op, object *caster, object *spell, int dir)
Definition: spell_effect.c:3068
FLAG_IS_CAULDRON
#define FLAG_IS_CAULDRON
Definition: define.h:338
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.c:301
pets_control_golem
void pets_control_golem(object *op, int dir)
Definition: pets.c:630
magic_wall
int magic_wall(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.c:1465
change_abil
int change_abil(object *op, object *tmp)
Definition: living.c:395
SPELL
@ SPELL
Definition: object.h:214
liv::sp
int16_t sp
Definition: living.h:42
Settings::create_home_portals
uint8_t create_home_portals
Definition: global.h:306
FLAG_CURSED
#define FLAG_CURSED
Definition: define.h:316
pick_up
void pick_up(object *op, object *alt)
Definition: c_object.c:519
TELEPORTER
@ TELEPORTER
Definition: object.h:141
cast_change_map_lightlevel
int cast_change_map_lightlevel(object *op, object *spell)
Definition: spell_effect.c:3298
living.h
obj::move_allow
MoveType move_allow
Definition: object.h:431
obj::magic
int8_t magic
Definition: object.h:353
obj::resist
int16_t resist[NROFATTACKS]
Definition: object.h:346
NDI_GREY
#define NDI_GREY
Definition: newclient.h:252
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.c:2613
NUM_STATS
@ NUM_STATS
Definition: living.h:18
MSG_TYPE_ITEM_INFO
#define MSG_TYPE_ITEM_INFO
Definition: newclient.h:645
find_marked_object
object * find_marked_object(object *op)
Definition: c_object.c:1520
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
MAX_FOOD
static const int32_t MAX_FOOD
Definition: define.h:461
FORCE
@ FORCE
Definition: object.h:224
HOLY_ALTAR
@ HOLY_ALTAR
Definition: object.h:161
TRAPDOOR
@ TRAPDOOR
Definition: object.h:210
cast_detection
int cast_detection(object *op, object *caster, object *spell)
Definition: spell_effect.c:2583
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
object.h
obj::level
int16_t level
Definition: object.h:356
llevDebug
@ llevDebug
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:137
obj::range
int8_t range
Definition: object.h:410
SP_WORD_OF_RECALL
#define SP_WORD_OF_RECALL
Definition: spells.h:92
charge_mana_effect
static void charge_mana_effect(object *victim, int caster_level)
Definition: spell_effect.c:2786
cast_cone
int cast_cone(object *op, object *caster, int dir, object *spell)
Definition: spell_attack.c:297
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Definition: define.h:302
is_true_undead
int is_true_undead(object *op)
Definition: player.c:3940
P_BLOCKSVIEW
#define P_BLOCKSVIEW
Definition: map.h:227
GATE
@ GATE
Definition: object.h:206
FORCE_NAME
#define FORCE_NAME
Definition: spells.h:169
obj::inv
struct obj * inv
Definition: object.h:293
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
give.name
name
Definition: give.py:27
player_update_bg_music
void player_update_bg_music(object *player)
ATNR_FEAR
#define ATNR_FEAR
Definition: attack.h:63
dragon_attune.force
force
Definition: dragon_attune.py:45
object_get_owner
object * object_get_owner(object *op)
Definition: object.c:808
is_identified
int is_identified(const object *op)
Definition: item.c:1336
level
Definition: level.py:1
Settings::localdir
const char * localdir
Definition: global.h:244