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