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 #include "AssetsManager.h"
38 
49 void cast_magic_storm(object *op, object *tmp, int lvl) {
50  if (!tmp)
51  return; /* error */
52  tmp->level = op->level;
53  tmp->range += lvl/5; /* increase the area of destruction */
54  tmp->duration += lvl/5;
55 
56  /* Put a cap on duration for this - if the player fails in their
57  * apartment, don't want it to go on so long that it kills them
58  * multiple times. Also, damage already increases with level,
59  * so don't really need to increase the duration as much either.
60  */
61  if (tmp->duration >= 40)
62  tmp->duration = 40;
63  tmp->stats.dam = lvl; /* nasty recoils! */
64  tmp->stats.maxhp = tmp->count; /* tract single parent */
65  if (tmp->stats.maxhp == 0)
66  tmp->stats.maxhp = 1;
67  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
68 }
69 
84 int recharge(object *op, object *caster, object *spell_ob) {
85  object *wand, *tmp;
86  int ncharges;
87  char name[MAX_BUF];
88 
89  wand = find_marked_object(op);
90  if (wand == NULL || wand->type != WAND) {
92  "You need to mark the wand you want to recharge.");
93  return 0;
94  }
95  if (!(random_roll(0, 3, op, PREFER_HIGH))) {
96  query_name(wand, name, MAX_BUF);
98  "The %s vibrates violently, then explodes!",
99  name);
100  play_sound_map(SOUND_TYPE_ITEM, wand, 0, "explode");
101  object_remove(wand);
102  object_free(wand, 0);
103  tmp = create_archetype("fireball");
104  tmp->stats.dam = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob))/10;
105  if (!tmp->stats.dam)
106  tmp->stats.dam = 1;
107  tmp->stats.hp = tmp->stats.dam/2;
108  if (tmp->stats.hp < 2)
109  tmp->stats.hp = 2;
110  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
111  return 1;
112  }
113 
114  ncharges = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob));
115  if (wand->inv && wand->inv->level)
116  ncharges /= wand->inv->level;
117  else {
118  query_name(wand, name, MAX_BUF);
120  "Your %s is broken.",
121  name);
122  return 0;
123  }
124  if (!ncharges)
125  ncharges = 1;
126 
127  wand->stats.food += ncharges;
128  query_name(wand, name, MAX_BUF);
130  "The %s glows with power.",
131  name);
132 
133  if (wand->arch && QUERY_FLAG(&wand->arch->clone, FLAG_ANIMATE)) {
134  SET_FLAG(wand, FLAG_ANIMATE);
135  wand->speed = wand->arch->clone.speed;
136  object_update_speed(wand);
137  }
138  return 1;
139 }
140 
141 /******************************************************************************
142  * Start of polymorph related functions.
143  *
144  * Changed around for 0.94.3 - it will now look through and use all the
145  * possible choices for objects/monsters (before it was the first 80 -
146  * arbitrary hardcoded limit in this file.) Doing this will be a bit
147  * slower however - while before, it traversed the archetypes once and
148  * stored them into an array, it will now potentially traverse it
149  * an average of 1.5 times. This is probably more costly on the polymorph
150  * item function, since it is possible a couple lookups might be needed before
151  * an item of proper value is generated.
152  */
153 
162 static void polymorph_living(object *op, int level) {
163  int x = op->x, y = op->y, choice, friendly;
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  std::vector<std::pair<archetype *, int>> candidates;
180 
181  getManager()->archetypes()->each([&] (auto at) {
182  int pos;
183  if ((!at->head) && (QUERY_FLAG((&at->clone), FLAG_MONSTER) == QUERY_FLAG(op, FLAG_MONSTER))
184  && ((pos = object_find_first_free_spot(&at->clone, map, x, y)) != -1)) {
185  candidates.push_back(std::make_pair(at, pos));
186  }
187  });
188 
189  if (candidates.empty()) {
190  object_insert_in_map_at(op, map, NULL, 0, x, y);
191  return; /* no valid matches? if so, return */
192  }
193 
194  /* Next make a choice, and loop through until we get to it */
195  choice = rndm(0, candidates.size() - 1);
196  auto at = candidates[choice].first;
197  int pos = candidates[choice].second;
198 
199  /* Look through the monster. Unapply anything they have applied,
200  * and remove any spells. Note that if this is extended
201  * to players, that would need to get fixed somehow.
202  */
205  apply_manual(op, tmp, 0);
206  if (tmp->type == SPELL) {
208  object_free(tmp, 0);
209  }
210  } FOR_INV_FINISH();
211 
212  /* Preserve some values for the new object */
213  owner = object_get_owner(op);
214  friendly = QUERY_FLAG(op, FLAG_FRIENDLY);
215  if (friendly)
217 
218  replacing = object_create_arch(at);
219  if (owner != NULL)
220  object_set_owner(replacing, owner);
221  if (friendly) {
222  SET_FLAG(replacing, FLAG_FRIENDLY);
223  replacing->attack_movement = PETMOVE;
224  add_friendly_object(replacing);
225  } else
226  CLEAR_FLAG(replacing, FLAG_FRIENDLY);
228 
229  /* Put the new creature on the map */
230  if ((replacing = object_insert_in_map_at(replacing, map, owner, 0, x + freearr_x[pos], y + freearr_y[pos])) == NULL)
231  return;
232 
233  if (HAS_RANDOM_ITEMS(replacing))
234  create_treasure(replacing->randomitems, replacing, GT_INVISIBLE, map->difficulty, 0);
235 
236  /* Apply any objects. */
237  monster_check_apply_all(replacing);
238 }
239 
240 
252 static void polymorph_melt(object *who, object *op) {
253  /* Not unique */
254  char name[MAX_BUF];
255 
257  if (op->nrof > 1)
259  "The %s glow red, melt and evaporate!",
260  name);
261  else
263  "The %s glows red, melts and evaporates!",
264  name);
265  play_sound_map(SOUND_TYPE_ITEM, op, 0, "evaporate");
266  object_remove(op);
267  object_free(op, 0);
268  return;
269 }
270 
280 static void polymorph_item(object *who, object *op, int level) {
281  archetype *at;
282  int max_value, difficulty, tries = 0, choice, charges = op->stats.food;
283  object *new_ob;
284  mapstruct *m;
285  int16_t x, y;
286 
287  /* We try and limit the maximum value of the changed object. */
288  max_value = op->value*2;
289  if (max_value > 2000*(level/10))
290  max_value = 2000*(level/10)+(max_value-2000*(level/10))/3;
291 
292  std::vector<archetype *> candidates;
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  getManager()->archetypes()->each([&] (auto 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  candidates.push_back(at);
306  });
307 
308  if (candidates.empty())
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, candidates.size() - 1);
317  at = candidates[choice];
318 
319  object_copy(&(at->clone), new_ob);
320  fix_generated_item(new_ob, op, difficulty, FABS(op->magic), GT_ENVIRONMENT);
321  ++tries;
322  } while (new_ob->value > max_value && tries < 10);
323  if (new_ob->invisible) {
324  LOG(llevError, "polymorph_item: fix_generated_object made %s invisible?!\n", new_ob->name);
326  return;
327  }
328 
329  /* Unable to generate an acceptable item? Melt it */
330  if (tries == 10) {
333  return;
334  }
335 
336  if (op->nrof && new_ob->nrof) {
337  new_ob->nrof = op->nrof;
338  /* decrease the number of items */
339  if (new_ob->nrof > 2)
340  new_ob->nrof -= rndm(0, op->nrof/2-1);
341  }
342 
343  /* We don't want rings to keep sustenance/hungry status. There are probably
344  * other cases too that should be checked.
345  */
346  if (charges && op->type != RING && op->type != FOOD)
347  op->stats.food = charges;
348 
349  x = op->x;
350  y = op->y;
351  m = op->map;
352  object_remove(op);
354  /*
355  * Don't want objects merged or re-arranged, as it then messes up the
356  * order
357  */
359 }
360 
371 void polymorph(object *op, object *who, int level) {
372  int tmp;
373 
374  /* Can't polymorph players right now */
375  /* polymorphing generators opens up all sorts of abuses */
376  if (op->type == PLAYER || QUERY_FLAG(op, FLAG_GENERATOR))
377  return;
378 
379  if (QUERY_FLAG(op, FLAG_MONSTER)) {
381  return;
382  }
383  /* If it is a living object of some other type, don't handle
384  * it now.
385  */
386  if (QUERY_FLAG(op, FLAG_ALIVE))
387  return;
388 
389  /* Don't want to morph flying arrows, etc... */
390  if (FABS(op->speed) > 0.001 && !QUERY_FLAG(op, FLAG_ANIMATE))
391  return;
392 
393  /* Do some sanity checking here. type=0 is unknown, objects
394  * without archetypes are not good. As are a few other
395  * cases.
396  */
397  if (op->type == 0
398  || op->arch == NULL
400  || op->move_block
401  || op->type == TREASURE)
402  return;
403 
404  tmp = rndm(0, 7);
405  if (tmp)
407  else
409 }
410 
411 
425 int cast_polymorph(object *op, object *caster, object *spell_ob, int dir) {
426  object *tmp;
427  int range, mflags, maxrange, level;
428  mapstruct *m;
429 
430  if (dir == 0)
431  return 0;
432 
433  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
434  level = caster_level(caster, spell_ob);
435  for (range = 1; range < maxrange; range++) {
436  int16_t x = op->x+freearr_x[dir]*range, y = op->y+freearr_y[dir]*range;
437  object *image;
438 
439  m = op->map;
440  mflags = get_map_flags(m, &m, x, y, &x, &y);
441 
442  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
443  break;
444 
446  break;
447 
448  /* Get the top most object */
449  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above)
450  ;
451 
452  /* Now start polymorphing the objects, top down */
454  /* Once we find the floor, no need to go further */
456  break;
457  polymorph(tmp, op, level);
459  image = arch_to_object(spell_ob->other_arch);
460  image->stats.food = 5;
461  image->speed_left = 0.1;
462  object_insert_in_map_at(image, m, op, 0, x, y);
463  }
464  return 1;
465 }
466 
493 int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg) {
494  int missile_plus = 0, bonus_plus = 0;
495  const char *missile_name;
496  object *tmp, *missile;
497  tag_t tag;
498 
500  missile_name = tmp != NULL ? tmp->race : "arrow";
501 
502  missile_plus = spell->stats.dam+SP_level_dam_adjust(caster, spell);
503 
504  if (!strcmp(missile_name, "arrows"))
505  missile_name = "arrow";
506  else if (!strcmp(missile_name, "crossbow bolts"))
507  missile_name = "bolt";
508 
509  /* Check if the type (bolt/arrow) was specified with the spell */
510  if ( stringarg && strncmp(stringarg,"of ",3)==0 ) stringarg +=3;
511  if ( stringarg && strncmp(stringarg,"bolt",4)==0 ) {
512  missile_name = "bolt";
513  stringarg += 4;
514  while ( isalpha(*stringarg) ) ++stringarg;
515  while ( *stringarg==' ' ) ++stringarg;
516  }
517  if ( stringarg && strncmp(stringarg,"arrow",5)==0 ) {
518  missile_name = "arrow";
519  stringarg += 5;
520  while ( isalpha(*stringarg) ) ++stringarg;
521  while ( *stringarg==' ' ) ++stringarg;
522  }
523 
524  if (try_find_archetype(missile_name) == NULL) {
525  LOG(llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
526  return 0;
527  }
528  missile = create_archetype(missile_name);
529 
530  if ( stringarg && strncmp(stringarg,"of ",3)==0 ) stringarg +=3;
531  if (stringarg) {
532  /* If it starts with a letter, presume it is a description */
533  if (isalpha(*stringarg)) {
534  auto items = find_artifactlist(missile->type)->items;
535  auto ial = std::find_if(items.cbegin(), items.cend(), [&] (const auto al) { return !strcasecmp(al->item->name, stringarg); });
536  if (ial == items.cend()) {
539  "No such object %ss of %s",
540  missile_name, stringarg);
541  return 0;
542  }
543  artifact *al = *ial;
544  if (al->item->slaying) {
547  "You are not allowed to create %ss of %s",
548  missile_name, stringarg);
549  return 0;
550  }
551  give_artifact_abilities(missile, al->item);
552  /* These special arrows cost something extra. Don't have them also be
553  * magical - otherwise, in most cases, not enough will be created.
554  * I don't want to get into the parsing both plus and type.
555  */
556  bonus_plus = 1+(al->item->value/5);
557  missile_plus = 0;
558  } else if (atoi(stringarg) < missile_plus)
559  missile_plus = atoi(stringarg);
560  }
561  if (missile_plus > 4)
562  missile_plus = 4;
563  else if (missile_plus < -4)
564  missile_plus = -4;
565 
566  missile->nrof = spell->duration+SP_level_duration_adjust(caster, spell);
567  if (missile->nrof <= (uint32_t)3 * (missile_plus + bonus_plus)) {
570  "This item is too powerful for you to create!");
571  return 0;
572  }
573  missile->nrof -= 3*(missile_plus+bonus_plus);
574  if (missile->nrof < 1)
575  missile->nrof = 1;
576 
577  missile->magic = missile_plus;
578  /* Can't get any money for these objects */
579  missile->value = 0;
580 
581  SET_FLAG(missile, FLAG_IDENTIFIED);
582  tag = missile->count;
583 
584  if (!cast_create_obj(op, missile, dir)
585  && op->type == PLAYER
586  && !object_was_destroyed(missile, tag)) {
587  pick_up(op, missile);
588  }
589  return 1;
590 }
591 
594 static int food_value_choice;
595 static void food_each(archetype *arch) {
596  if (arch->clone.type == FOOD || arch->clone.type == DRINK) {
597  /* Basically, if the food value is something that is creatable
598  * under the limits of the spell and it is higher than
599  * the item we have now, take it instead.
600  */
601  if (arch->clone.stats.food <= food_value_choice
602  && (!food_choice || arch->clone.stats.food > food_choice->clone.stats.food))
603  food_choice = arch;
604  }
605 }
606 
627 int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg) {
628  int food_value;
629  archetype *at = NULL;
630  object *new_op;
631 
632  food_value = spell_ob->stats.food+50*SP_level_duration_adjust(caster, spell_ob);
633 
634  if (stringarg) {
635  at = find_archetype_by_object_type_name(FOOD, stringarg);
636  if (at == NULL)
637  at = find_archetype_by_object_type_name(DRINK, stringarg);
638  if (at == NULL || at->clone.stats.food > food_value)
639  stringarg = NULL;
640  }
641 
642  if (!stringarg) {
643  /* We try to find the archetype with the maximum food value.
644  * This removes the dependency of hard coded food values in this
645  * function, and addition of new food types is automatically added.
646  * We don't use flesh types because the weight values of those need
647  * to be altered from the donor.
648  */
649 
650  food_choice = at;
651  food_value_choice = food_value;
653  at = food_choice;
654  }
655  /* Pretty unlikely (there are some very low food items), but you never
656  * know
657  */
658  if (!at) {
660  "You don't have enough experience to create any food.");
661  return 0;
662  }
663 
664  food_value /= at->clone.stats.food;
665  new_op = object_new();
666  object_copy(&at->clone, new_op);
667  new_op->nrof = food_value;
668 
669  new_op->value = 0;
670  if (new_op->nrof < 1)
671  new_op->nrof = 1;
672  // Drinks are unidentified by default. Identify those.
673  if (!is_identified(new_op)) {
674  identify(new_op);
675  }
676 
677  cast_create_obj(op, new_op, dir);
678  return 1;
679 }
680 
699 int probe(object *op, object *caster, object *spell_ob, int dir, int level) {
700  int r, mflags, maxrange;
701  mapstruct *m;
702 
703  if (!dir) {
705  return 1;
706  }
707  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
708  for (r = 1; r < maxrange; r++) {
709  int16_t x = op->x+r*freearr_x[dir], y = op->y+r*freearr_y[dir];
710 
711  m = op->map;
712  mflags = get_map_flags(m, &m, x, y, &x, &y);
713 
714  if (mflags&P_OUT_OF_MAP)
715  break;
716 
717  if (!QUERY_FLAG(op, FLAG_WIZCAST) && (mflags&P_NO_MAGIC)) {
719  "Something blocks your magic.");
720  return 0;
721  }
722  if (mflags&P_IS_ALIVE) {
723  FOR_MAP_PREPARE(m, x, y, tmp)
724  if (CAN_PROBE(tmp)) {
726  "You detect something.");
728  return 1;
729  }
730  FOR_MAP_FINISH();
731  }
732  }
734  "You detect nothing.");
735  return 1;
736 }
737 
738 
756 int makes_invisible_to(object *pl, object *mon) {
757  if (!pl->invisible)
758  return 0;
759  if (pl->type == PLAYER) {
760  /* If race isn't set, then invisible unless it is undead */
761  if (!pl->contr->invis_race) {
762  if (QUERY_FLAG(mon, FLAG_UNDEAD))
763  return 0;
764  return 1;
765  }
766  /* invis_race is set if we get here */
767  if (!strcmp(pl->contr->invis_race, "undead") && is_true_undead(mon))
768  return 1;
769  /* No race, can't be invisible to it */
770  if (!mon->race)
771  return 0;
772  if (strstr(mon->race, pl->contr->invis_race))
773  return 1;
774  /* Nothing matched above, return 0 */
775  return 0;
776  } else {
777  /* monsters are invisible to everything */
778  return 1;
779  }
780 }
781 
803 int cast_invisible(object *op, object *caster, object *spell_ob) {
804  if (op->invisible > 1000) {
806  "You can not extend the duration of your invisibility any further");
807  return 0;
808  }
809 
810  /* Remove the switch with 90% duplicate code - just handle the differences with
811  * and if statement or two.
812  */
813  op->invisible += spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
814  /* max duration */
815  if (op->invisible > 1000)
816  op->invisible = 1000;
817 
818  if (op->type == PLAYER) {
819  if (op->contr->invis_race)
820  FREE_AND_CLEAR_STR(op->contr->invis_race);
821  if (spell_ob->race)
822  op->contr->invis_race = add_refcount(spell_ob->race);
823  if (QUERY_FLAG(spell_ob, FLAG_MAKE_INVIS))
824  op->contr->tmp_invis = 0;
825  else
826  op->contr->tmp_invis = 1;
827 
828  op->contr->hidden = 0;
829  }
830  if (makes_invisible_to(op, op))
832  "You can't see your hands!");
833  else
835  "You feel more transparent!");
836 
838  return 1;
839 }
840 
855 int cast_earth_to_dust(object *op, object *caster, object *spell_ob) {
856  int range, i, j, mflags;
857  int16_t sx, sy;
858  mapstruct *m;
859 
860  if (op->type != PLAYER)
861  return 0;
862 
863  range = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
864 
865  for (i = -range; i < range; i++)
866  for (j = -range; j < range; j++) {
867  sx = op->x+i;
868  sy = op->y+j;
869  m = op->map;
870  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
871 
872  if (mflags&P_OUT_OF_MAP)
873  continue;
874 
875  /* If the space doesn't block, no wall here to remove
876  * Don't care too much what it blocks - this allows for
877  * any sort of earthwall/airwall/waterwall, etc
878  * type effects.
879  */
880  if (GET_MAP_MOVE_BLOCK(m, sx, sy)) {
881  FOR_MAP_PREPARE(m, sx, sy, tmp)
882  if (tmp && QUERY_FLAG(tmp, FLAG_TEAR_DOWN))
883  hit_player(tmp, 9998, op, AT_PHYSICAL, 0);
884  FOR_MAP_FINISH();
885  }
886  }
887  return 1;
888 }
889 
906 int cast_word_of_recall(object *op, object *caster, object *spell_ob) {
907  object *dummy;
908  int time;
909 
910  if (op->type != PLAYER)
911  return 0;
912 
915  "You feel a force starting to build up inside you.");
916  return 1;
917  }
918 
919  dummy = create_archetype(FORCE_NAME);
920  if (dummy == NULL) {
922  "Oops, program error!");
923  LOG(llevError, "cast_word_of_recall: create_archetype(force) failed!\n");
924  return 0;
925  }
926  time = spell_ob->duration-SP_level_duration_adjust(caster, spell_ob);
927  if (time < 1)
928  time = 1;
929 
930  /* value of speed really doesn't make much difference, as long as it is
931  * positive. Lower value may be useful so that the problem doesn't
932  * do anything really odd if it say a -1000 or something.
933  */
934  dummy->speed = 0.002;
935  object_update_speed(dummy);
936  dummy->speed_left = -dummy->speed*time;
937  dummy->type = SPELL_EFFECT;
938  dummy->subtype = SP_WORD_OF_RECALL;
939 
940  /* If we could take advantage of enter_player_savebed() here, it would be
941  * nice, but until the map load fails, we can't.
942  */
943  EXIT_PATH(dummy) = add_string(op->contr->savebed_map);
944  EXIT_X(dummy) = op->contr->bed_x;
945  EXIT_Y(dummy) = op->contr->bed_y;
946 
947  (void)object_insert_in_ob(dummy, op);
949  "You feel a force starting to build up inside you.");
950  return 1;
951 }
952 
968 int cast_wonder(object *op, object *caster, int dir, object *spell_ob) {
969  object *newspell;
970 
971  if (!rndm(0, 3))
972  return cast_cone(op, caster, dir, spell_ob);
973 
974  if (spell_ob->randomitems) {
975  newspell = generate_treasure(spell_ob->randomitems, caster->level);
976  if (!newspell) {
977  LOG(llevError, "cast_wonder: Unable to get a spell!\n");
978  return 0;
979  }
980  if (newspell->type != SPELL) {
981  LOG(llevError, "cast_wonder: spell returned is not a spell (%d, %s)!\n", newspell->type, newspell->name);
982  return 0;
983  }
984  /* Prevent inifinite recursion */
985  if (newspell->subtype == SP_WONDER) {
986  LOG(llevError, "cast_wonder: spell returned is another wonder spell!\n");
987  return 0;
988  }
989  return cast_spell(op, caster, dir, newspell, NULL);
990  }
991  return 1;
992 }
993 
1002 int perceive_self(object *op) {
1003  char *cp, buf[MAX_BUF];
1005  if (at == NULL) {
1006  return 1;
1007  }
1008  object *tmp;
1009  const object *god;
1010  int i;
1011  StringBuffer *immunity;
1012 
1013  god = find_god(determine_god(op));
1014  if (god)
1016  "You worship %s",
1017  god->name);
1018  else
1020  "You worship no god");
1021 
1022  tmp = arch_present_in_ob(at, op);
1023 
1024  cp = stringbuffer_finish(describe_item(op, op, 0, NULL));
1025 
1026  if (*cp == '\0' && tmp == NULL)
1028  "You feel very mundane");
1029  else {
1031  "You have:");
1033  cp);
1034  if (tmp != NULL) {
1035  for (i = 0; i < NUM_STATS; i++) {
1036  if (get_attr_value(&tmp->stats, i) < 0) {
1038  "Your %s is depleted by %d",
1039  statname[i], -(get_attr_value(&tmp->stats, i)));
1040  }
1041  }
1042  }
1043  }
1044  free(cp);
1045 
1046  if (op->glow_radius > 0)
1048  "You glow in the dark.");
1049 
1050  immunity = NULL;
1051  for (tmp = op->inv; tmp; tmp = tmp->below) {
1052  if (tmp->type == SIGN) {
1053  if (immunity == NULL) {
1054  immunity = stringbuffer_new();
1055  stringbuffer_append_string(immunity, "You have been exposed to: ");
1056  } else {
1057  stringbuffer_append_string(immunity, ", ");
1058  }
1059  stringbuffer_append_string(immunity, tmp->name);
1060  if (tmp->level > 100)
1061  stringbuffer_append_string(immunity, " (full immunity)");
1062  else if (tmp->level > 70)
1063  stringbuffer_append_string(immunity, " (high immunity)");
1064  else if (tmp->level > 20)
1065  stringbuffer_append_string(immunity, " (partial immunity)");
1066  }
1067  }
1068 
1069  if (immunity != NULL) {
1070  cp = stringbuffer_finish(immunity);
1072  free(cp);
1073  }
1074 
1075  if (is_dragon_pl(op)) {
1076  /* now grab the 'dragon_ability'-force from the player's inventory */
1077  tmp = object_find_by_type_and_arch_name(op, FORCE, "dragon_ability_force");
1078  if (tmp != NULL) {
1079  StringBuffer *levels = NULL;
1080  int i;
1081 
1082  if (tmp->stats.exp == 0) {
1083  snprintf(buf, sizeof(buf), "Your metabolism isn't focused on anything.");
1084  } else {
1085  snprintf(buf, sizeof(buf), "Your metabolism is focused on %s.", change_resist_msg[tmp->stats.exp]);
1086  }
1088  buf);
1089 
1090  for (i = 0; i < NROFATTACKS; i++) {
1091  if (atnr_is_dragon_enabled(i) && tmp->resist[i] > 0) {
1092  if (levels == NULL) {
1094  stringbuffer_append_string(levels, "Ability levels:\n");
1095  }
1096  stringbuffer_append_printf(levels, "- %s: %d\n", change_resist_msg[i], tmp->resist[i]);
1097  }
1098  }
1099 
1100  if (levels != NULL) {
1103  free(cp);
1104  }
1105  }
1106  }
1107  return 1;
1108 }
1109 
1110 static object* town_portal_find_force(object* op, object* spell) {
1111  object *dummy, *force;
1112 
1113  /* The first thing to do is to check if we have a marked destination
1114  * dummy is used to make a check inventory for the force
1115  */
1116  dummy = arch_to_object(spell->other_arch);
1117  if (dummy == NULL) {
1119  "Oops, program error!");
1120  LOG(llevError, "object_new failed (force in cast_create_town_portal for %s!\n", op->name);
1121  return NULL;
1122  }
1123 
1124  force = check_inv_recursive(op, dummy);
1125  if (force == NULL) {
1126  /* Here we know there is no destination marked up.
1127  * We have 2 things to do:
1128  * 1. Mark the destination in the player inventory.
1129  * 2. Let the player know it worked.
1130  */
1131  free_string(dummy->name);
1132  dummy->name = add_string(op->map->path);
1133  EXIT_X(dummy) = op->x;
1134  EXIT_Y(dummy) = op->y;
1135  dummy->weapontype = op->map->last_reset_time;
1136  object_insert_in_ob(dummy, op);
1138  "You fix this place in your mind and feel that you "
1139  "can come here from anywhere.");
1140  } else {
1142  }
1143  return force;
1144 }
1145 
1149 static int town_portal_destroy_existing(object* op, object* spell) {
1150  object* dummy = create_archetype(spell->race);
1151  object* old_force;
1152  if (dummy == NULL) {
1154  "Oops, program error!");
1155  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1156  return 0;
1157  }
1158  archetype *perm_portal;
1159  perm_portal = try_find_archetype(spell->slaying);
1160  if (perm_portal == NULL) {
1162  "Oops, program error!");
1163  return 0;
1164  }
1165 
1166  /* To kill a town portal, we go trough the player's inventory,
1167  * for each marked portal in player's inventory,
1168  * -We try load the associated map (if impossible, consider the portal destructed)
1169  * -We find any portal in the specified location.
1170  * If it has the good name, we destruct it.
1171  * -We destruct the force indicating that portal.
1172  */
1173  while ((old_force = check_inv_recursive(op, dummy))) {
1174  int16_t exitx = EXIT_X(old_force);
1175  int16_t exity = EXIT_Y(old_force);
1176  LOG(llevDebug, "Trying to kill a portal in %s (%d,%d)\n", old_force->race, exitx, exity);
1177 
1178  mapstruct *exitmap;
1179  if (map_path_unique(old_force->race))
1180  exitmap = ready_map_name(old_force->race, MAP_PLAYER_UNIQUE);
1181  else
1182  exitmap = ready_map_name(old_force->race, 0);
1183 
1184  if (exitmap) {
1185  object* tmp = map_find_by_archetype(exitmap, exitx, exity, perm_portal);
1187  if (tmp->name == old_force->name) {
1188  object_remove(tmp);
1189  object_free(tmp, 0);
1190  break;
1191  }
1193 
1194  /* kill any opening animation there is */
1195  archetype *arch = try_find_archetype("town_portal_open");
1196  if (arch != NULL) {
1197  tmp = map_find_by_archetype(exitmap, exitx, exity, arch);
1199  if (tmp->name == old_force->name) {
1200  object_remove(tmp);
1202  break;
1203  }
1205  }
1206  }
1207  object_remove(old_force);
1208  object_free(old_force, 0);
1209  }
1211  return 0;
1212 }
1213 
1241 int cast_create_town_portal(object *op, object *caster, object *spell) {
1242  object *dummy, *force, *tmp;
1243  char portal_name [2 * HUGE_BUF], portal_message [1024];
1244  mapstruct *exitmap;
1245  int op_level, x, y;
1246 
1247  /* Check to see if the map the player is currently on is a per player unique
1248  * map. This can be determined in that per player unique maps have the
1249  * full pathname listed. Ignore if settings.create_home_portals is true.
1250  */
1252  if (op->map->unique) {
1254  "You can't cast that here.");
1255  return 0;
1256  }
1257  }
1258 
1259  /* Check to see if the player is on a transport */
1260  if (op->contr && op->contr->transport) {
1262  "You need to exit the transport to cast that.");
1263  return 0;
1264  }
1265 
1266  force = town_portal_find_force(op, spell);
1267  if (force == NULL) {
1268  return 1;
1269  }
1270 
1271  /* Here we know where the town portal should go to
1272  * We should kill any existing portal associated with the player.
1273  * Than we should create the 2 portals.
1274  * For each of them, we need:
1275  * - To create the portal with the name of the player+destination map
1276  * - set the owner of the town portal
1277  * - To mark the position of the portal in the player's inventory
1278  * for easier destruction.
1279  *
1280  * The mark works has follow:
1281  * slaying: Existing town portal
1282  * hp, sp : x & y of the associated portal
1283  * name : name of the portal
1284  * race : map the portal is in
1285  */
1286  if (town_portal_destroy_existing(op, spell) != 0) {
1287  return 1;
1288  }
1289 
1290  /* Creating the portals.
1291  * The very first thing to do is to ensure
1292  * access to the destination map.
1293  * If we can't, don't fizzle. Simply warn player.
1294  * This ensure player pays his mana for the spell
1295  * because HE is responsible for forgetting.
1296  * 'force' is the destination of the town portal, which we got
1297  * from the players inventory above.
1298  */
1299 
1300  /* Ensure exit map is loaded*/
1301  if (map_path_unique(force->name))
1302  exitmap = ready_map_name(force->name, MAP_PLAYER_UNIQUE);
1303  else
1304  exitmap = ready_map_name(force->name, 0);
1305 
1306  /* If we were unable to load (ex. random map deleted), warn player*/
1307  if (exitmap == NULL) {
1309  "Something strange happens. You can't remember where to go!?");
1311  object_free(force, 0);
1313  return 1;
1314  } else if (exitmap->last_reset_time != force->weapontype) {
1316  "The spell effect has expired.");
1318  object_free(force, 0);
1320  return 1;
1321  }
1322 
1323  op_level = caster_level(caster, spell);
1324  if (op_level < 15)
1325  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);
1326  else if (op_level < 30)
1327  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);
1328  else if (op_level < 60)
1329  snprintf(portal_message, 1024, "A shining door opens in the air in front of you, showing you the path to another place.");
1330  else
1331  snprintf(portal_message, 1024, "As you walk through %s's portal, flowers come out from the ground around you. You feel awed.", op->name);
1332 
1333  /* Create a portal in front of player
1334  * dummy contain the portal and
1335  * force contain the track to kill it later
1336  */
1337 
1338  snprintf(portal_name, sizeof(portal_name), "%s's portal to %s", op->name, force->name);
1339  dummy = create_archetype(spell->slaying); /*The portal*/
1340  if (dummy == NULL) {
1342  "Oops, program error!");
1343  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1344  return 0;
1345  }
1346  EXIT_PATH(dummy) = add_string(force->name);
1347  EXIT_X(dummy) = EXIT_X(force);
1348  EXIT_Y(dummy) = EXIT_Y(force);
1349  FREE_AND_COPY(dummy->name, portal_name);
1350  FREE_AND_COPY(dummy->name_pl, portal_name);
1351  object_set_msg(dummy, portal_message);
1352  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1353 
1354  /* create a nice animation */
1355  tmp = create_archetype("town_portal_open");
1356  FREE_AND_COPY(tmp->name, portal_name);
1357  FREE_AND_COPY(tmp->name_pl, portal_name);
1358  object_insert_in_ob(dummy, tmp);
1359  /* and put it on the floor, when it ends the portal will be on the ground */
1360  cast_create_obj(op, tmp, 0);
1361  x = tmp->x;
1362  y = tmp->y;
1363 
1364  /* Now we need to to create a town portal marker inside the player
1365  * object, so on future castings, we can know that he has an active
1366  * town portal.
1367  */
1368  tmp = create_archetype(spell->race);
1369  if (tmp == NULL) {
1371  "Oops, program error!");
1372  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1373  return 0;
1374  }
1375  tmp->race = add_string(op->map->path);
1376  FREE_AND_COPY(tmp->name, portal_name);
1377  EXIT_X(tmp) = x;
1378  EXIT_Y(tmp) = y;
1380 
1381  /* Create a portal in the destination map
1382  * dummy contain the portal and
1383  * force the track to kill it later
1384  * the 'force' variable still contains the 'reminder' of
1385  * where this portal goes to.
1386  */
1387  snprintf(portal_name, sizeof(portal_name), "%s's portal to %s", op->name, op->map->path);
1388  dummy = create_archetype(spell->slaying); /*The portal*/
1389  if (dummy == NULL) {
1391  "Oops, program error!");
1392  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1393  return 0;
1394  }
1395  EXIT_PATH(dummy) = add_string(op->map->path);
1396  EXIT_X(dummy) = op->x;
1397  EXIT_Y(dummy) = op->y;
1398  FREE_AND_COPY(dummy->name, portal_name);
1399  FREE_AND_COPY(dummy->name_pl, portal_name);
1400  object_set_msg(dummy, portal_message);
1401  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1402 
1403  /* animation here too */
1404  tmp = create_archetype("town_portal_open");
1405  FREE_AND_COPY(tmp->name, portal_name);
1406  FREE_AND_COPY(tmp->name_pl, portal_name);
1407  object_insert_in_ob(dummy, tmp);
1408  /* and put it on the floor, when it ends the portal will be on the ground */
1410  x = tmp->x;
1411  y = tmp->y;
1412 
1413  /* Now we create another town portal marker that
1414  * points back to the one we just made
1415  */
1416  tmp = create_archetype(spell->race);
1417  if (tmp == NULL) {
1419  "Oops, program error!");
1420  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1421  return 0;
1422  }
1423  tmp->race = add_string(force->name);
1424  FREE_AND_COPY(tmp->name, portal_name);
1425  EXIT_X(tmp) = x;
1426  EXIT_Y(tmp) = y;
1428 
1429  /* Describe the player what happened
1430  */
1432  "You see air moving and showing you the way home.");
1433  object_remove(force); /* Delete the force inside the player*/
1434  object_free(force, 0);
1435  return 1;
1436 }
1437 
1438 
1456 int magic_wall(object *op, object *caster, int dir, object *spell_ob) {
1457  object *tmp, *tmp2;
1458  int i, posblocked, negblocked, maxrange;
1459  int16_t x, y;
1460  mapstruct *m;
1461  const char *name;
1462  archetype *at;
1463 
1464  if (!dir) {
1465  dir = op->facing;
1466  x = op->x;
1467  y = op->y;
1468  } else {
1469  x = op->x+freearr_x[dir];
1470  y = op->y+freearr_y[dir];
1471  }
1472  m = op->map;
1473 
1474  if ((spell_ob->move_block || x != op->x || y != op->y)
1475  && (get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE)
1476  || ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) == spell_ob->move_block))) {
1478  "Something is in the way.");
1479  return 0;
1480  }
1481  if (spell_ob->other_arch) {
1482  tmp = arch_to_object(spell_ob->other_arch);
1483  } else if (spell_ob->race) {
1484  char buf1[MAX_BUF];
1485 
1486  snprintf(buf1, sizeof(buf1), spell_ob->race, dir);
1487  at = try_find_archetype(buf1);
1488  if (!at) {
1489  LOG(llevError, "summon_wall: Unable to find archetype %s\n", buf1);
1491  "This spell is broken.");
1492  return 0;
1493  }
1494  tmp = arch_to_object(at);
1495  } else {
1496  LOG(llevError, "magic_wall: spell %s lacks other_arch\n", spell_ob->name);
1497  return 0;
1498  }
1499 
1500  if (tmp->type == SPELL_EFFECT) {
1501  tmp->attacktype = spell_ob->attacktype;
1502  tmp->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1503  tmp->stats.dam = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1504  tmp->range = 0;
1505  } else if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
1506  tmp->stats.hp = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1507  tmp->stats.maxhp = tmp->stats.hp;
1509  set_spell_skill(op, caster, spell_ob, tmp);
1510  }
1512  tmp->stats.food = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1514  }
1515  if (QUERY_FLAG(spell_ob, FLAG_TEAR_DOWN)) {
1516  tmp->stats.hp = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1517  tmp->stats.maxhp = tmp->stats.hp;
1520  }
1521 
1522  /* This can't really hurt - if the object doesn't kill anything,
1523  * these fields just won't be used.
1524  */
1526  set_spell_skill(op, caster, spell_ob, tmp);
1527  tmp->level = caster_level(caster, spell_ob)/2;
1528 
1529  name = tmp->name;
1530  if ((tmp = object_insert_in_map_at(tmp, m, op, 0, x, y)) == NULL) {
1532  "Something destroys your %s",
1533  name);
1534  return 0;
1535  }
1536  /* If this is a spellcasting wall, need to insert the spell object */
1537  if (tmp->other_arch && tmp->other_arch->clone.type == SPELL)
1538  object_insert_in_ob(arch_to_object(tmp->other_arch), tmp);
1539 
1540  /* This code causes the wall to extend some distance in
1541  * each direction, or until an obstruction is encountered.
1542  * posblocked and negblocked help determine how far the
1543  * created wall can extend, it won't go extend through
1544  * blocked spaces.
1545  */
1546  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
1547  posblocked = 0;
1548  negblocked = 0;
1549 
1550  for (i = 1; i <= maxrange; i++) {
1551  int dir2;
1552 
1553  dir2 = (dir < 4) ? (dir+2) : dir-2;
1554 
1555  x = tmp->x+i*freearr_x[dir2];
1556  y = tmp->y+i*freearr_y[dir2];
1557  m = tmp->map;
1558 
1559  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1560  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1561  && !posblocked) {
1562  tmp2 = object_new();
1563  object_copy(tmp, tmp2);
1564  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1565  /* If this is a spellcasting wall, need to insert the spell object */
1566  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1568  } else
1569  posblocked = 1;
1570 
1571  x = tmp->x-i*freearr_x[dir2];
1572  y = tmp->y-i*freearr_y[dir2];
1573  m = tmp->map;
1574 
1575  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1576  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1577  && !negblocked) {
1578  tmp2 = object_new();
1579  object_copy(tmp, tmp2);
1580  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1581  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1583  } else
1584  negblocked = 1;
1585  }
1586 
1588  update_all_los(op->map, op->x, op->y);
1589 
1590  return 1;
1591 }
1592 
1609 int dimension_door(object *op, object *caster, object *spob, int dir) {
1610  uint32_t dist, maxdist;
1611  int mflags;
1612  mapstruct *m;
1613  int16_t sx, sy;
1614 
1615  if (op->type != PLAYER)
1616  return 0;
1617 
1618  if (!dir) {
1620  "In what direction?");
1621  return 0;
1622  }
1623 
1624  /* Given the new outdoor maps, can't let players dimension door for
1625  * ever, so put limits in.
1626  */
1627  maxdist = spob->range+SP_level_range_adjust(caster, spob);
1628 
1629  if (op->contr->count) {
1630  if (op->contr->count > maxdist) {
1632  "You can't dimension door that far!");
1633  return 0;
1634  }
1635 
1636  for (dist = 0; dist < op->contr->count; dist++) {
1637  mflags = get_map_flags(op->map, &m,
1638  op->x+freearr_x[dir]*(dist+1),
1639  op->y+freearr_y[dir]*(dist+1),
1640  &sx, &sy);
1641 
1642  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1643  break;
1644 
1645  if ((mflags&P_BLOCKSVIEW)
1646  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1647  break;
1648  }
1649 
1650  if (dist < op->contr->count) {
1652  "Something blocks the magic of the spell.");
1653  op->contr->count = 0;
1654  return 0;
1655  }
1656  op->contr->count = 0;
1657 
1658  /* Remove code that puts player on random space on maps. IMO,
1659  * a lot of maps probably have areas the player should not get to,
1660  * but may not be marked as NO_MAGIC (as they may be bounded
1661  * by such squares). Also, there are probably treasure rooms and
1662  * lots of other maps that protect areas with no magic, but the
1663  * areas themselves don't contain no magic spaces.
1664  */
1665  /* This call here is really just to normalize the coordinates */
1666  mflags = get_map_flags(op->map, &m, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist,
1667  &sx, &sy);
1668  if (mflags&P_IS_ALIVE || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy))) {
1670  "You cast your spell, but nothing happens.");
1671  return 1; /* Maybe the penalty should be more severe... */
1672  }
1673  } else {
1674  /* Player didn't specify a distance, so lets see how far
1675  * we can move the player. Don't know why this stopped on
1676  * spaces that blocked the players view.
1677  */
1678 
1679  for (dist = 0; dist < maxdist; dist++) {
1680  mflags = get_map_flags(op->map, &m,
1681  op->x+freearr_x[dir]*(dist+1),
1682  op->y+freearr_y[dir]*(dist+1),
1683  &sx, &sy);
1684 
1685  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1686  break;
1687 
1688  if ((mflags&P_BLOCKSVIEW)
1689  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1690  break;
1691  }
1692 
1693  /* If the destination is blocked, keep backing up until we
1694  * find a place for the player.
1695  */
1696  for (; dist > 0; dist--) {
1697  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))
1698  continue;
1699 
1700  if (!OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1701  break;
1702  }
1703  if (!dist) {
1705  "Your spell failed!");
1706  return 0;
1707  }
1708  }
1709 
1710  if (op->contr->transport && op->contr->transport->type == TRANSPORT) {
1711  ob_apply(op->contr->transport, op, 0);
1712  if (op->contr->transport) {
1714  "Your spell failed!");
1715  return 0;
1716  }
1717  }
1718 
1719  /* Actually move the player now */
1720  object_remove(op);
1721  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)
1722  return 1;
1723 
1724  if (op->type == PLAYER) {
1725  map_newmap_cmd(op->contr->socket);
1727  }
1728  op->speed_left = -FABS(op->speed)*5; /* Freeze them for a short while */
1729  return 1;
1730 }
1731 
1732 
1745 int cast_heal(object *op, object *caster, object *spell, int dir) {
1746  object *target;
1747  archetype *at;
1748  object *poison;
1749  int heal = 0, success = 0;
1750 
1751  target = find_target_for_friendly_spell(op, dir);
1752 
1753  if (target == NULL)
1754  return 0;
1755 
1756  /* Figure out how many hp this spell might cure.
1757  * could be zero if this spell heals effects, not damage.
1758  */
1759  heal = spell->stats.dam;
1760  if (spell->stats.hp)
1761  heal += random_roll(spell->stats.hp, 6, op, PREFER_HIGH)+spell->stats.hp;
1762 
1763  if (heal) {
1764  if (target->stats.hp >= target->stats.maxhp) {
1766  "You are already fully healed.");
1767  } else {
1768  /* See how many points we actually heal. Instead of messages
1769  * based on type of spell, we instead do messages based
1770  * on amount of damage healed.
1771  */
1772  if (heal > (target->stats.maxhp-target->stats.hp))
1773  heal = target->stats.maxhp-target->stats.hp;
1774  target->stats.hp += heal;
1775 
1776  if (target->stats.hp >= target->stats.maxhp) {
1778  "You feel just fine!");
1779  } else if (heal > 50) {
1781  "Your wounds close!");
1782  } else if (heal > 25) {
1784  "Your wounds mostly close.");
1785  } else if (heal > 10) {
1787  "Your wounds start to fade.");
1788  } else {
1790  "Your wounds start to close.");
1791  }
1792  success = 1;
1793  }
1794  }
1795  if (spell->attacktype&AT_DISEASE)
1796  if (cure_disease(target, op, caster && caster->type != PLAYER ? caster->skill : spell->skill))
1797  success = 1;
1798 
1799  if (spell->attacktype&AT_POISON) {
1800  at = try_find_archetype("poisoning");
1801  if (at != NULL) {
1802  poison = arch_present_in_ob(at, target);
1803  if (poison) {
1804  success = 1;
1806  "Your body feels cleansed");
1807  poison->stats.food = 1;
1808  }
1809  }
1810  }
1811  if (spell->attacktype&AT_CONFUSION) {
1812  poison = object_present_in_ob_by_name(FORCE, "confusion", target);
1813  if (poison) {
1814  success = 1;
1816  "Your mind feels clearer");
1817  poison->duration = 1;
1818  }
1819  }
1820  if (spell->attacktype&AT_BLIND) {
1821  at = try_find_archetype("blindness");
1822  if (at != NULL) {
1823  poison = arch_present_in_ob(at, target);
1824  if (poison) {
1825  success = 1;
1827  "Your vision begins to return.");
1828  poison->stats.food = 1;
1829  }
1830  }
1831  }
1832  if (spell->last_sp && target->stats.sp < target->stats.maxsp) {
1833  target->stats.sp += spell->last_sp;
1834  if (target->stats.sp > target->stats.maxsp)
1835  target->stats.sp = target->stats.maxsp;
1836  success = 1;
1838  "Magical energies surge through your body!");
1839  }
1840  if (spell->last_grace && target->stats.grace < target->stats.maxgrace) {
1841  target->stats.grace += spell->last_grace;
1842  if (target->stats.grace > target->stats.maxgrace)
1843  target->stats.grace = target->stats.maxgrace;
1844  success = 1;
1846  "You feel redeemed with you god!");
1847  }
1848  if (spell->stats.food && target->stats.food < MAX_FOOD) {
1849  target->stats.food += spell->stats.food;
1850  if (target->stats.food > MAX_FOOD)
1851  target->stats.food = MAX_FOOD;
1852  success = 1;
1853  /* We could do something a bit better like the messages for healing above */
1855  "You feel your belly fill with food");
1856  }
1857 
1858  if (spell->other_arch != NULL && target->map != NULL) {
1859  object_insert_in_map_at(arch_to_object(spell->other_arch), target->map, NULL, INS_ON_TOP, target->x, target->y);
1860  }
1861 
1862  return success;
1863 }
1864 
1865 
1871 static const char *const no_gain_msgs[NUM_STATS] = {
1872  "You grow no stronger.",
1873  "You grow no more agile.",
1874  "You don't feel any healthier.",
1875  "no wis",
1876  "You are no easier to look at.",
1877  "no int",
1878  "no pow"
1879 };
1880 
1900 int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent) {
1901  object *tmp;
1902  object *force = NULL;
1903  int i;
1904 
1905  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1906  if (dir != 0) {
1908  } else {
1909  tmp = op;
1910  }
1911 
1912  if (tmp == NULL)
1913  return 0;
1914 
1915  /* If we've already got a force of this type, don't add a new one. */
1916  FOR_INV_PREPARE(tmp, tmp2)
1917  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
1918  if (tmp2->name == spell_ob->name) {
1919  force = tmp2; /* the old effect will be "refreshed" */
1920  break;
1921  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
1922  if (!silent)
1924  "You can not cast %s while %s is in effect",
1925  spell_ob->name, tmp2->name_pl);
1926  return 0;
1927  }
1928  }
1929  FOR_INV_FINISH();
1930  if (force == NULL) {
1932  force->subtype = FORCE_CHANGE_ABILITY;
1933  free_string(force->name);
1934  if (spell_ob->race)
1935  force->name = add_refcount(spell_ob->race);
1936  else
1937  force->name = add_refcount(spell_ob->name);
1938  free_string(force->name_pl);
1939  force->name_pl = add_refcount(spell_ob->name);
1940  } else {
1941  int duration;
1942 
1943  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1944  if (duration > force->duration) {
1945  force->duration = duration;
1947  "You recast the spell while in effect.");
1948 
1949  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
1950  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
1951  }
1952 
1953  } else {
1955  "Recasting the spell had no effect.");
1956  }
1957  return 1;
1958  }
1959  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1960  if (op->type == PLAYER)
1962  force->speed = 1.0;
1963  force->speed_left = -1.0;
1965 
1966  /* Now start processing the effects. First, protections */
1967  for (i = 0; i < NROFATTACKS; i++) {
1968  if (spell_ob->resist[i]) {
1969  force->resist[i] = spell_ob->resist[i]+SP_level_dam_adjust(caster, spell_ob);
1970  if (force->resist[i] > 100)
1971  force->resist[i] = 100;
1972  }
1973  }
1974  if (spell_ob->stats.hp)
1975  force->stats.hp = spell_ob->stats.hp+SP_level_dam_adjust(caster, spell_ob);
1976 
1977  if (tmp->type == PLAYER) {
1978  /* Stat adjustment spells */
1979  for (i = 0; i < NUM_STATS; i++) {
1980  int8_t stat = get_attr_value(&spell_ob->stats, i), k, sm;
1981 
1982  if (stat) {
1983  sm = 0;
1984  for (k = 0; k < stat; k++)
1985  sm += rndm(1, 3);
1986 
1987  if ((get_attr_value(&tmp->stats, i)+sm) > (15+5*stat)) {
1988  sm = (15+5*stat)-get_attr_value(&tmp->stats, i);
1989  if (sm < 0)
1990  sm = 0;
1991  }
1992  set_attr_value(&force->stats, i, sm);
1993  if (!sm)
1995  no_gain_msgs[i]);
1996  }
1997  }
1998  }
1999 
2000  force->move_type = spell_ob->move_type;
2001 
2002  if (QUERY_FLAG(spell_ob, FLAG_SEE_IN_DARK))
2004 
2005  if (QUERY_FLAG(spell_ob, FLAG_XRAYS))
2007 
2008  /* Haste/bonus speed */
2009  if (spell_ob->stats.exp) {
2010  if (op->speed > 0.5)
2011  force->stats.exp = (float)spell_ob->stats.exp/(op->speed+0.5);
2012  else
2013  force->stats.exp = spell_ob->stats.exp;
2014  }
2015 
2016  force->stats.wc = spell_ob->stats.wc;
2017  force->stats.ac = spell_ob->stats.ac;
2018  force->attacktype = spell_ob->attacktype;
2019 
2020  SET_FLAG(tmp, FLAG_NO_FIX_PLAYER); /* we don't want object_insert_in_ob() to call fix_object. */
2023  change_abil(tmp, force); /* Display any relevant messages, and call fix_object to update the player */
2024 
2025  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2026  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2027  }
2028 
2029  return 1;
2030 }
2031 
2048 int cast_bless(object *op, object *caster, object *spell_ob, int dir) {
2049  int i;
2050  const object *god = find_god(determine_god(op));
2051  object *force = NULL, *tmp;
2052 
2053  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
2054  if (dir != 0) {
2056  } else {
2057  tmp = op;
2058  }
2059 
2060  /* If we've already got a force of this type, don't add a new one. */
2061  FOR_INV_PREPARE(tmp, tmp2)
2062  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
2063  if (tmp2->name == spell_ob->name) {
2064  force = tmp2; /* the old effect will be "refreshed" */
2065  break;
2066  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
2068  "You can not cast %s while %s is in effect",
2069  spell_ob->name, tmp2->name_pl);
2070  return 0;
2071  }
2072  }
2073  FOR_INV_FINISH();
2074  if (force == NULL) {
2076  force->subtype = FORCE_CHANGE_ABILITY;
2077  free_string(force->name);
2078  if (spell_ob->race)
2079  force->name = add_refcount(spell_ob->race);
2080  else
2081  force->name = add_refcount(spell_ob->name);
2082  free_string(force->name_pl);
2083  force->name_pl = add_refcount(spell_ob->name);
2084  } else {
2085  int duration;
2086 
2087  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2088  if (duration > force->duration) {
2089  force->duration = duration;
2091  "You recast the spell while in effect.");
2092  } else {
2094  "Recasting the spell had no effect.");
2095  }
2096  return 0;
2097  }
2098  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2099  force->speed = 1.0;
2100  force->speed_left = -1.0;
2101 
2102  if (!god) {
2104  "Your blessing seems empty.");
2105  } else {
2106  /* Only give out good benefits, and put a max on it */
2107  const int16_t resist_max = spell_ob->resist[ATNR_GODPOWER];
2108  for (i = 0; i < NROFATTACKS; i++) {
2109  if (god->resist[i] > 0) {
2110  force->resist[i] = MIN(god->resist[i], resist_max);
2111  }
2112  }
2113  // Also grant appropriate amount of godpower resistance.
2114  force->resist[ATNR_GODPOWER] = spell_ob->resist[ATNR_GODPOWER];
2115 
2116  force->path_attuned |= god->path_attuned;
2117  if (spell_ob->attacktype) {
2118  force->attacktype |= god->attacktype|AT_PHYSICAL;
2119  if (god->slaying)
2120  force->slaying = add_string(god->slaying);
2121  }
2122  if (tmp != op) {
2124  "You bless %s.",
2125  tmp->name);
2127  "%s blessed you.",
2128  op->name);
2129  } else {
2131  "You are blessed by %s!",
2132  god->name);
2133  }
2134  }
2135  force->stats.wc = spell_ob->stats.wc;
2136  force->stats.ac = spell_ob->stats.ac;
2137 
2141  change_abil(tmp, force); /* To display any messages, will call fix_object() */
2142 
2143  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2144  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2145  }
2146  return 1;
2147 }
2148 
2149 
2150 
2151 /*
2152  * Alchemy code by Mark Wedel
2153  *
2154  * This code adds a new spell, called alchemy. Alchemy will turn
2155  * objects to gold nuggets, the value of the gold nuggets being
2156  * from 5% to 40% of that of the item itself depending on casting level.
2157  * It uses the value of the object before charisma adjustments, because
2158  * the nuggets themselves will be will be adjusted by charisma when sold.
2159  *
2160  * Large nuggets are worth 25 gp each (base). You will always get
2161  * the maximum number of large nuggets you could get.
2162  * Small nuggets are worth 1 gp each (base). You will get from 0
2163  * to the max amount of small nuggets as you could get.
2164  *
2165  * For example, if an item is worth 110 gold, you will get
2166  * 4 large nuggets, and from 0-10 small nuggets.
2167  *
2168  * There is also a chance (1:30) that you will get nothing at all
2169  * for the object. There is also a maximum weight that will be
2170  * alchemied.
2171  */
2172 
2173 #define SMALL_NUGGET "smallnugget"
2174 #define LARGE_NUGGET "largenugget"
2175 
2190 static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight) {
2191  uint64_t value = price_base(obj);
2192  // Don't reduce gems or money, since they don't get the x4 multiplier in price_base()
2193  // FIXME: If the x4 multiplier in price_base() gets changed, this should as well.
2194  if (obj->type != GEM && obj->type != MONEY)
2195  value /= 4;
2196  uint64_t small_value, large_value;
2198  /* Multiply the value of the object by value_adj, which should range
2199  * from 0.05 to 0.40. Set value to 0 instead if unpaid.
2200  */
2201  if (QUERY_FLAG(obj, FLAG_UNPAID))
2202  value = 0;
2203  else
2204  value *= value_adj;
2205 
2206  archetype *small_nugget_arch = try_find_archetype(SMALL_NUGGET);
2207  if (small_nugget_arch == NULL) {
2208  return;
2209  }
2210  small_value = price_base(&small_nugget_arch->clone);
2211  archetype *large_nugget_arch = try_find_archetype(LARGE_NUGGET);
2212  if (large_nugget_arch == NULL) {
2213  return;
2214  }
2215  large_value = price_base(&large_nugget_arch->clone);
2216 
2217  /* Give half of what value_adj says when we alchemy money (This should
2218  * hopefully make it so that it isn't worth it to alchemy money, sell
2219  * the nuggets, alchemy the gold from that, etc.
2220  */
2221  if (value && (obj->type == MONEY || obj->type == GEM))
2222  value /= 2;
2223 
2224  if ((obj->value > 0) && rndm(0, 29)) {
2225  int count;
2226 
2227  assert(large_value != 0 && small_value != 0);
2228  count = value/large_value;
2229  *large_nuggets += count;
2230  value -= (uint64_t)count*large_value;
2231  count = value/small_value;
2232  *small_nuggets += count;
2233  }
2234 
2235  /* Turn 25 small nuggets into 1 large nugget. If the value
2236  * of large nuggets is not evenly divisable by the small nugget
2237  * value, take off an extra small_nugget (Assuming small_nuggets!=0)
2238  */
2239  if (*small_nuggets*small_value >= large_value) {
2240  assert(small_value != 0);
2241  (*large_nuggets)++;
2242  *small_nuggets -= large_value/small_value;
2243  if (*small_nuggets && large_value%small_value)
2244  (*small_nuggets)--;
2245  }
2246 
2247  if (weight != NULL) {
2248  *weight += obj->weight;
2249  }
2250 
2251  object_remove(obj);
2253 }
2254 
2268 static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y) {
2269  object *tmp;
2270  int flag = 0;
2271 
2272  /* Put any nuggets below the player, but we can only pass this
2273  * flag if we are on the same space as the player
2274  */
2275  if (x == op->x && y == op->y && op->map == m)
2276  flag = INS_BELOW_ORIGINATOR;
2277 
2278  if (small_nuggets) {
2280  tmp-> nrof = small_nuggets;
2281  object_insert_in_map_at(tmp, m, op, flag, x, y);
2282  }
2283  if (large_nuggets) {
2285  tmp-> nrof = large_nuggets;
2286  object_insert_in_map_at(tmp, m, op, flag, x, y);
2287  }
2288 }
2289 
2304 int alchemy(object *op, object *caster, object *spell_ob) {
2305  int x, y, weight = 0, weight_max, large_nuggets, small_nuggets, mflags;
2306  int16_t nx, ny;
2307  float value_adj;
2308  mapstruct *mp;
2309 
2310  if (op->type != PLAYER)
2311  return 0;
2312 
2313  /* Put a maximum weight of items that can be alchemied. Limits the power
2314  * some, and also prevents people from alcheming every table/chair/clock
2315  * in sight
2316  */
2317  weight_max = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
2318  weight_max *= 1000;
2319 
2320  /* Set value_adj to be a multiplier for how much of the original value
2321  * will be in the nuggets. Starts at 0.05, increasing by 0.01 per casting
2322  * level, maxing out at 0.40.
2323  */
2324  value_adj = (SP_level_dam_adjust(caster, spell_ob)/100.00)+0.05;
2325 
2326  if (value_adj > 0.40)
2327  value_adj = 0.40;
2328 
2329  for (y = op->y-1; y <= op->y+1; y++) {
2330  for (x = op->x-1; x <= op->x+1; x++) {
2331  nx = x;
2332  ny = y;
2333 
2334  mp = op->map;
2335 
2336  mflags = get_map_flags(mp, &mp, nx, ny, &nx, &ny);
2337 
2338  if (mflags&(P_OUT_OF_MAP|P_NO_MAGIC))
2339  continue;
2340 
2341  /* Treat alchemy a little differently - most spell effects
2342  * use fly as the movement type - for alchemy, consider it
2343  * ground level effect.
2344  */
2345  if (GET_MAP_MOVE_BLOCK(mp, nx, ny)&MOVE_WALK)
2346  continue;
2347 
2348  small_nuggets = 0;
2349  large_nuggets = 0;
2350 
2351  FOR_MAP_PREPARE(mp, nx, ny, tmp) {
2352  if (tmp->weight > 0 && !QUERY_FLAG(tmp, FLAG_NO_PICK)
2353  && !QUERY_FLAG(tmp, FLAG_ALIVE)
2354  // If a multitile monster has unalive pieces, then don't zap those.
2355  && (!tmp->head || !QUERY_FLAG(tmp->head, FLAG_ALIVE))
2357  if (tmp->inv) {
2358  FOR_INV_PREPARE(tmp, tmp1)
2359  if (tmp1->weight > 0 && !QUERY_FLAG(tmp1, FLAG_NO_PICK)
2360  && !QUERY_FLAG(tmp1, FLAG_ALIVE)
2361  && !QUERY_FLAG(tmp1, FLAG_IS_CAULDRON))
2362  alchemy_object(value_adj, tmp1, &small_nuggets, &large_nuggets, &weight);
2363  FOR_INV_FINISH();
2364  }
2365  alchemy_object(value_adj, tmp, &small_nuggets, &large_nuggets, &weight);
2366 
2367  if (weight > weight_max) {
2368  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2369  return 1;
2370  }
2371  } /* is alchemable object */
2372  } FOR_MAP_FINISH(); /* process all objects on this space */
2373 
2374  /* Insert all the nuggets at one time. This probably saves time, but
2375  * it also prevents us from alcheming nuggets that were just created
2376  * with this spell.
2377  */
2378  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2379  }
2380  }
2381 
2382  /* reset this so that if player standing on a big pile of stuff,
2383  * it is redrawn properly.
2384  */
2385  op->contr->socket->look_position = 0;
2386  return 1;
2387 }
2388 
2389 
2404 int remove_curse(object *op, object *caster, object *spell) {
2405  int success = 0, was_one = 0;
2406 
2409  && ((QUERY_FLAG(tmp, FLAG_CURSED) && QUERY_FLAG(spell, FLAG_CURSED))
2410  || (QUERY_FLAG(tmp, FLAG_DAMNED) && QUERY_FLAG(spell, FLAG_DAMNED)))) {
2411  was_one++;
2412  if (tmp->level <= caster_level(caster, spell)) {
2413  success++;
2414  if (QUERY_FLAG(spell, FLAG_DAMNED))
2416 
2419  tmp->value = 0; /* Still can't sell it */
2420  if (op->type == PLAYER)
2422  }
2423  }
2424  FOR_INV_FINISH();
2425 
2426  if (op->type == PLAYER) {
2427  if (success) {
2429  "You feel like some of your items are looser now.");
2430  } else {
2431  if (was_one)
2433  "You failed to remove the curse.");
2434  else
2436  "You are not using any cursed items.");
2437  }
2438  }
2439  return success;
2440 }
2441 
2452 int cast_item_curse_or_bless(object *op, object *spell_ob) {
2453  object *marked = find_marked_object(op);
2454  char name[HUGE_BUF];
2455 
2456  if (!marked) {
2458  "You need to mark an item first!");
2459  return 0;
2460  }
2461 
2462  if ((QUERY_FLAG(marked, FLAG_CURSED) && QUERY_FLAG(spell_ob, FLAG_CURSED))
2463  || (QUERY_FLAG(marked, FLAG_BLESSED) && QUERY_FLAG(spell_ob, FLAG_BLESSED))) {
2465  "The spell has no effect");
2466  return 0;
2467  }
2468 
2470  if (QUERY_FLAG(spell_ob, FLAG_CURSED)) {
2472  "Your %s emits a dark light for a few seconds.", name);
2477  return 1;
2478  }
2479 
2481  "Your %s glows blue for a few seconds.", name);
2486  return 1;
2487 }
2488 
2503 int cast_identify(object *op, object *caster, object *spell) {
2504  int success = 0, num_ident;
2505  char desc[MAX_BUF];
2506 
2507  num_ident = spell->stats.dam+SP_level_dam_adjust(caster, spell);
2508 
2509  if (num_ident < 1)
2510  num_ident = 1;
2511 
2513  if (!tmp->invisible && !is_identified(tmp)) {
2514  tmp = identify(tmp);
2515  if (op->type == PLAYER) {
2517  "You have %s.",
2518  ob_describe(tmp, op, 1, desc, sizeof(desc)));
2519  if (tmp->msg) {
2521  "The item has a story:\n%s",
2522  tmp->msg);
2523  }
2524  }
2525  num_ident--;
2526  success = 1;
2527  if (!num_ident)
2528  break;
2529  }
2530  FOR_INV_FINISH();
2531  /* If all the power of the spell has been used up, don't go and identify
2532  * stuff on the floor. Only identify stuff on the floor if the spell
2533  * was not fully used.
2534  */
2535  if (num_ident) {
2536  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2537  if (!tmp->invisible && !is_identified(tmp)) {
2538  tmp = identify(tmp);
2539  if (op->type == PLAYER) {
2541  "On the ground is %s.",
2542  ob_describe(tmp, op, 1, desc, sizeof(desc)));
2543  if (tmp->msg) {
2545  "The item has a story:\n%s",
2546  tmp->msg);
2547  }
2549  }
2550  num_ident--;
2551  success = 1;
2552  if (!num_ident)
2553  break;
2554  }
2555  FOR_MAP_FINISH();
2556  }
2557  if (!success)
2559  "You can't reach anything unidentified.");
2560  else {
2561  spell_effect(spell, op->x, op->y, op->map, op);
2562  }
2563  return success;
2564 }
2565 
2578 int cast_detection(object *op, object *caster, object *spell) {
2579  object *tmp, *last, *detect;
2580  const object *god;
2581  int done_one, range, mflags, floor, level;
2582  int16_t x, y, nx, ny;
2583  mapstruct *m;
2584 
2585  /* We precompute some values here so that we don't have to keep
2586  * doing it over and over again.
2587  */
2588  god = find_god(determine_god(op));
2589  level = caster_level(caster, spell);
2590  range = spell->range+SP_level_range_adjust(caster, spell);
2591 
2592  for (x = op->x-range; x <= op->x+range; x++)
2593  for (y = op->y-range; y <= op->y+range; y++) {
2594  m = op->map;
2595  mflags = get_map_flags(m, &m, x, y, &nx, &ny);
2596  if (mflags&P_OUT_OF_MAP)
2597  continue;
2598 
2599  /* For most of the detections, we only detect objects above the
2600  * floor. But this is not true for show invisible.
2601  * Basically, we just go and find the top object and work
2602  * down - that is easier than working up.
2603  */
2604 
2605  last = NULL;
2606  FOR_MAP_PREPARE(m, nx, ny, tmp)
2607  last = tmp;
2608  FOR_MAP_FINISH();
2609  /* Shouldn't happen, but if there are no objects on a space, this
2610  * would happen.
2611  */
2612  if (!last)
2613  continue;
2614 
2615  done_one = 0;
2616  floor = 0;
2617  detect = NULL;
2618  tmp = last;
2620  /* show invisible */
2621  if (QUERY_FLAG(spell, FLAG_MAKE_INVIS)
2622  /* Might there be other objects that we can make visibile? */
2623  && (tmp->invisible && (QUERY_FLAG(tmp, FLAG_MONSTER) ||
2624  (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)) ||
2625  tmp->type == CF_HANDLE ||
2626  tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
2627  tmp->type == BUTTON || tmp->type == TELEPORTER ||
2628  tmp->type == GATE || tmp->type == LOCKED_DOOR ||
2629  tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
2630  tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
2631  tmp->type == TREASURE || tmp->type == BOOK ||
2632  tmp->type == HOLY_ALTAR))) {
2633  if (random_roll(0, level-1, op, PREFER_HIGH) > tmp->level) {
2634  tmp->invisible = 0;
2635  done_one = 1;
2636  }
2637  }
2639  floor = 1;
2640 
2641  /* All detections below this point don't descend beneath the floor,
2642  * so just continue on. We could be clever and look at the type of
2643  * detection to completely break out if we don't care about objects beneath
2644  * the floor, but once we get to the floor, not likely a very big issue anyways.
2645  */
2646  if (floor)
2647  continue;
2648 
2649  /* I had thought about making detect magic and detect curse
2650  * show the flash the magic item like it does for detect monster.
2651  * however, if the object is within sight, this would then make it
2652  * difficult to see what object is magical/cursed, so the
2653  * effect wouldn't be as apparent.
2654  */
2655 
2656  /* detect magic */
2657  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2659  && is_magical(tmp)) {
2661  /* make runes more visible */
2662  if (tmp->type == RUNE && tmp->attacktype&AT_MAGIC)
2663  tmp->stats.Cha /= 4;
2664  done_one = 1;
2665  }
2666  /* detect monster */
2667  if (QUERY_FLAG(spell, FLAG_MONSTER)
2668  && (QUERY_FLAG(tmp, FLAG_MONSTER) || (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)))) {
2669  done_one = 2;
2670  if (!detect)
2671  detect = tmp;
2672  }
2673  /* Basically, if race is set in the spell, then the creatures race must
2674  * match that. if the spell race is set to GOD, then the gods opposing
2675  * race must match.
2676  */
2677  if (spell->race
2679  && tmp->race
2680  && ((!strcmp(spell->race, "GOD") && god && god->slaying && strstr(god->slaying, tmp->race)) || (strstr(spell->race, tmp->race)))) {
2681  done_one = 2;
2682  if (!detect)
2683  detect = tmp;
2684  }
2685  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2689  done_one = 1;
2690  }
2691  } FOR_OB_AND_BELOW_FINISH(); /* for stack of objects on this space */
2692 
2693  /* Code here puts an effect of the spell on the space, so you can see
2694  * where the magic is.
2695  */
2696  if (done_one) {
2697  object *detect_ob;
2698  int dx = nx, dy = ny;
2699 
2700  /* if this is set, we want to copy the face */
2701  if (done_one == 2 && detect) {
2702  /*
2703  * We can't simply copy the face to a single item, because
2704  * multipart objects need to have multipart glows.
2705  * So copy the initial item, erase some properties, and use that.
2706  */
2707 
2708  object *part;
2709  int flag;
2710 
2711  dx = HEAD(detect)->x;
2712  dy = HEAD(detect)->y;
2713 
2714  detect_ob = object_create_arch(HEAD(detect)->arch);
2715  for (part = detect_ob; part != NULL; part = part->more) {
2716  if (part->arch->reference_count > 0)
2717  part->arch->reference_count++;
2718  part->last_anim = 0;
2719  part->type = spell->other_arch->clone.type;
2720  for (flag = 0; flag < 4; flag++) {
2721  part->flags[flag] = spell->other_arch->clone.flags[flag];
2722  }
2723  part->stats.food = spell->other_arch->clone.stats.food;
2724  part->last_anim = 0;
2725  part->speed = spell->other_arch->clone.speed;
2726  part->speed_left = spell->other_arch->clone.speed_left;
2727  part->move_allow = spell->other_arch->clone.move_allow;
2728  part->move_block = spell->other_arch->clone.move_block;
2729  part->move_type = spell->other_arch->clone.move_type;
2730  part->glow_radius = spell->other_arch->clone.glow_radius;
2731  part->invisible = spell->other_arch->clone.invisible;
2732  part->weight = spell->other_arch->clone.weight;
2733  part->map_layer = spell->other_arch->clone.map_layer;
2734  FREE_AND_COPY(part->name, spell->other_arch->clone.name);
2735 
2736  /* by default, the detect_ob is already animated */
2737  if (!QUERY_FLAG(detect, FLAG_ANIMATE))
2738  CLEAR_FLAG(part, FLAG_ANIMATE);
2739  }
2740  object_update_speed(detect_ob);
2741  } else
2742  detect_ob = arch_to_object(spell->other_arch);
2743 
2744  object_insert_in_map_at(detect_ob, m, op, 0, dx, dy);
2745  }
2746  } /* for processing the surrounding spaces */
2747 
2748 
2749  /* Now process objects in the players inventory if detect curse or magic */
2750  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED) || QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)) {
2751  done_one = 0;
2752  FOR_INV_PREPARE(op, tmp) {
2753  if (!tmp->invisible) {
2754  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2755  && is_magical(tmp)
2758  if (op->type == PLAYER)
2759  esrv_send_item(op, tmp);
2760  }
2761  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2765  if (op->type == PLAYER)
2766  esrv_send_item(op, tmp);
2767  }
2768  } /* if item is not identified */
2769  } FOR_INV_FINISH(); /* for the players inventory */
2770  } /* if detect magic/curse and object is a player */
2771  return 1;
2772 }
2773 
2781 static void charge_mana_effect(object *victim, int caster_level) {
2782  /* Prevent explosions for objects without mana. Without this check, doors
2783  * will explode, too.
2784  */
2785  if (victim->stats.maxsp <= 0)
2786  return;
2787 
2789  "You feel energy course through you.");
2790 
2791  if (victim->stats.sp >= victim->stats.maxsp*2) {
2792  object *tmp;
2793 
2795  "Your head explodes!");
2796 
2797  /* Explodes a fireball centered at player */
2799  tmp->dam_modifier = random_roll(1, caster_level, victim, PREFER_LOW)/5+1;
2800  tmp->stats.maxhp = random_roll(1, caster_level, victim, PREFER_LOW)/10+2;
2801  object_insert_in_map_at(tmp, victim->map, NULL, 0, victim->x, victim->y);
2802  victim->stats.sp = 2*victim->stats.maxsp;
2803  } else if (victim->stats.sp >= victim->stats.maxsp*1.88) {
2805  "You feel like your head is going to explode.");
2806  } else if (victim->stats.sp >= victim->stats.maxsp*1.66) {
2808  "You get a splitting headache!");
2809  } else if (victim->stats.sp >= victim->stats.maxsp*1.5) {
2811  "Chaos fills your world.");
2813  } else if (victim->stats.sp >= victim->stats.maxsp*1.25) {
2815  "You start hearing voices.");
2816  }
2817 }
2818 
2836 int cast_transfer(object *op, object *caster, object *spell, int dir) {
2837  object *plyr = NULL;
2838  int16_t x, y;
2839  mapstruct *m;
2840  int mflags;
2841 
2842  m = op->map;
2843  x = op->x+freearr_x[dir];
2844  y = op->y+freearr_y[dir];
2845 
2846  mflags = get_map_flags(m, &m, x, y, &x, &y);
2847  if (!(mflags&P_OUT_OF_MAP) && mflags&P_IS_ALIVE) {
2848  FOR_MAP_PREPARE(m, x, y, tmp)
2849  plyr = tmp;
2850  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2851  break;
2852  FOR_MAP_FINISH();
2853  }
2854 
2855  /* If we did not find a player in the specified direction, transfer
2856  * to anyone on top of us. This is used for the rune of transference mostly.
2857  */
2858  if (plyr == NULL)
2859  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2860  plyr = tmp;
2861  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2862  break;
2863  FOR_MAP_FINISH();
2864 
2865  if (!plyr) {
2867  "There is no one there.");
2868  return 0;
2869  }
2870 
2871  /* give sp */
2872  if (spell->stats.dam > 0) {
2873  plyr->stats.sp += spell->stats.dam+SP_level_dam_adjust(caster, spell);
2874  charge_mana_effect(plyr, caster_level(caster, spell));
2875  return 1;
2876  /* suck sp away. Can't suck sp from yourself */
2877  } else if (op != plyr) {
2878  /* old dragin magic used floats. easier to just use ints and divide by 100 */
2879 
2880  int rate = -spell->stats.dam+SP_level_dam_adjust(caster, spell), sucked;
2881 
2882  if (rate > 95)
2883  rate = 95;
2884 
2885  sucked = (plyr->stats.sp*rate)/100;
2886  plyr->stats.sp -= sucked;
2887  if (QUERY_FLAG(op, FLAG_ALIVE)) {
2888  /* Player doesn't get full credit */
2889  sucked = (sucked*rate)/100;
2890  op->stats.sp += sucked;
2891  if (sucked > 0) {
2892  charge_mana_effect(op, caster_level(caster, spell));
2893  }
2894  }
2895  return 1;
2896  }
2897  return 0;
2898 }
2899 
2909 void counterspell(object *op, int dir) {
2910  object *head;
2911  int mflags;
2912  mapstruct *m;
2913  int16_t sx, sy;
2914 
2915  sx = op->x+freearr_x[dir];
2916  sy = op->y+freearr_y[dir];
2917  m = op->map;
2918  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2919  if (mflags&P_OUT_OF_MAP)
2920  return;
2921 
2922  FOR_MAP_PREPARE(m, sx, sy, tmp) {
2923  object *owner;
2924 
2925  /* Need to look at the head object - otherwise, if tmp
2926  * points to a monster, we don't have all the necessary
2927  * info for it.
2928  */
2929  head = HEAD(tmp);
2930 
2931  /* don't attack our own spells */
2932  owner = object_get_owner(tmp);
2933  if (owner != NULL && owner == object_get_owner(op))
2934  continue;
2935 
2936  /* Basically, if the object is magical and not counterspell,
2937  * we will more or less remove the object. Don't counterspell
2938  * monsters either.
2939  */
2940 
2941  if (head->attacktype&AT_MAGIC
2942  && !(head->attacktype&AT_COUNTERSPELL)
2943  && !QUERY_FLAG(head, FLAG_MONSTER)
2944  && (op->level > head->level)) {
2945  object_remove(head);
2946  object_free(head, 0);
2947  } else switch (head->type) {
2948  case SPELL_EFFECT:
2949  if ((op->level > head->level) && !op->stats.food && !op->speed_left) {
2950  object_remove(head);
2951  object_free(head, 0);
2952  }
2953  break;
2954 
2955  /* I really don't get this rune code that much - that
2956  * random chance seems really low.
2957  */
2958  case RUNE:
2959  if (rndm(0, 149) == 0) {
2960  head->stats.hp--; /* weaken the rune */
2961  if (!head->stats.hp) {
2962  object_remove(head);
2963  object_free(head, 0);
2964  }
2965  }
2966  break;
2967  }
2968  } FOR_MAP_FINISH();
2969 }
2970 
2985 int cast_consecrate(object *op, object *caster, object *spell) {
2986  char buf[MAX_BUF];
2987  const object *god = find_god(determine_god(op));
2988 
2989  if (!god) {
2991  "You can't consecrate anything if you don't worship a god!");
2992  return 0;
2993  }
2994 
2997  break;
2998  if (tmp->type == HOLY_ALTAR) {
2999  if (tmp->level > caster_level(caster, spell)) {
3001  "You are not powerful enough to reconsecrate the %s",
3002  tmp->name);
3003  return 0;
3004  } else {
3005  /* If we got here, we are consecrating an altar */
3006  object *new_altar;
3007  size_t letter;
3008  archetype *altar_arch;
3009 
3010  snprintf(buf, MAX_BUF, "altar_");
3011  letter = strlen(buf);
3012  strncpy(buf+letter, god->name, MAX_BUF-letter);
3013  for (; letter < strlen(buf); letter++)
3014  buf[letter] = tolower(buf[letter]);
3015  altar_arch = try_find_archetype(buf);
3016  if (!altar_arch) {
3018  "You fail to consecrate the altar.");
3019  LOG(llevError, "cast_consecrate: can't find altar %s for god %s\n", buf, god->name);
3020  return 0;
3021  }
3022  new_altar = arch_to_object(altar_arch);
3023  new_altar->level = tmp->level;
3025  SET_FLAG(new_altar, FLAG_IS_BUILDABLE);
3026  object_insert_in_map_at(new_altar, tmp->map, tmp, INS_BELOW_ORIGINATOR, tmp->x, tmp->y);
3027  object_remove(tmp);
3029  "You consecrated the altar to %s!",
3030  god->name);
3031  return 1;
3032  }
3033  }
3034  } FOR_BELOW_FINISH();
3036  "You are not standing over an altar!");
3037  return 0;
3038 }
3039 
3063 int animate_weapon(object *op, object *caster, object *spell, int dir) {
3064  object *weapon, *tmp;
3065  char buf[MAX_BUF];
3066  int a, i;
3067  int16_t x, y;
3068  mapstruct *m;
3069  materialtype_t *mt;
3070 
3071  if (!spell->other_arch) {
3073  "Oops, program error!");
3074  LOG(llevError, "animate_weapon failed: spell %s missing other_arch!\n", spell->name);
3075  return 0;
3076  }
3077 
3078  /* exit if it's not a player using this spell. */
3079  if (op->type != PLAYER)
3080  return 0;
3081 
3082  /* if player already has a golem, abort */
3083  if (op->contr->ranges[range_golem] != NULL && op->contr->golem_count == op->contr->ranges[range_golem]->count) {
3084  pets_control_golem(op->contr->ranges[range_golem], dir);
3085  return 0;
3086  }
3087 
3088  /* if no direction specified, pick one */
3089  if (!dir) {
3090  dir = object_find_free_spot(NULL, op->map, op->x, op->y, 1, 9);
3091  if ( dir == -1 ) {
3093  "There is something in the way.");
3094  return 0;
3095  }
3096  }
3097 
3098  m = op->map;
3099  x = op->x+freearr_x[dir];
3100  y = op->y+freearr_y[dir];
3101 
3102  /* if there's no place to put the golem, abort */
3103  if ((dir == -1)
3104  || (get_map_flags(m, &m, x, y, &x, &y)&P_OUT_OF_MAP)
3105  || ((spell->other_arch->clone.move_type&GET_MAP_MOVE_BLOCK(m, x, y)) == spell->other_arch->clone.move_type)) {
3107  "There is something in the way.");
3108  return 0;
3109  }
3110 
3111  /* Use the weapon marked by the player. */
3112  weapon = find_marked_object(op);
3113 
3114  if (!weapon) {
3116  "You must mark a weapon to use with this spell!");
3117  return 0;
3118  }
3119  if (spell->race && strcmp(weapon->arch->name, spell->race)) {
3121  "The spell fails to transform your weapon.");
3122  return 0;
3123  }
3124  if (weapon->type != WEAPON) {
3126  "You need to mark a weapon to animate it.");
3127  return 0;
3128  }
3129  if (QUERY_FLAG(weapon, FLAG_UNPAID)) {
3131  "You need to pay for the weapon to animate it.");
3132  return 0;
3133  }
3134  if (QUERY_FLAG(weapon, FLAG_APPLIED)) {
3135  char wn[MAX_BUF];
3136 
3137  query_name(weapon, wn, MAX_BUF);
3139  "You need to unequip %s before using it in this spell",
3140  wn);
3141  return 0;
3142  }
3143 
3144  if (weapon->nrof > 1) {
3145  tmp = object_split(weapon, 1, NULL, 0);
3146  esrv_update_item(UPD_NROF, op, weapon);
3147  weapon = tmp;
3148  }
3149 
3150  /* create the golem object */
3151  tmp = arch_to_object(spell->other_arch);
3152 
3153  /* if animated by a player, give the player control of the golem */
3156  tmp->stats.exp = 0;
3158  tmp->type = GOLEM;
3160  set_spell_skill(op, caster, spell, tmp);
3161  op->contr->ranges[range_golem] = tmp;
3162  op->contr->shoottype = range_golem;
3163  op->contr->golem_count = tmp->count;
3164 
3165  /* Give the weapon to the golem now. A bit of a hack to check the
3166  * removed flag - it should only be set if object_split() was
3167  * used above.
3168  */
3169  if (!QUERY_FLAG(weapon, FLAG_REMOVED))
3170  object_remove(weapon);
3171  object_insert_in_ob(weapon, tmp);
3172 
3173  /* To do everything necessary to let a golem use the weapon is a pain,
3174  * so instead, just set it as equipped (otherwise, we need to update
3175  * body_info, skills, etc)
3176  */
3178  SET_FLAG(weapon, FLAG_APPLIED);
3179  fix_object(tmp);
3180 
3181  /* There used to be 'odd' code that basically seemed to take the absolute
3182  * value of the weapon->magic an use that. IMO, that doesn't make sense -
3183  * if you're using a crappy weapon, it shouldn't be as good.
3184  */
3185 
3186  /* modify weapon's animated wc */
3187  tmp->stats.wc = tmp->stats.wc
3188  -SP_level_range_adjust(caster, spell)
3189  -5*weapon->stats.Dex
3190  -2*weapon->stats.Str
3191  -weapon->magic;
3192  if (tmp->stats.wc < -127)
3193  tmp->stats.wc = -127;
3194 
3195  /* Modify hit points for weapon */
3196  tmp->stats.maxhp = tmp->stats.maxhp
3197  +spell->duration
3198  +SP_level_duration_adjust(caster, spell)
3199  +8*weapon->magic
3200  +12*weapon->stats.Con;
3201  if (tmp->stats.maxhp < 0)
3202  tmp->stats.maxhp = 10;
3203  tmp->stats.hp = tmp->stats.maxhp;
3204 
3205  /* Modify weapon's damage */
3206  tmp->stats.dam = spell->stats.dam
3207  +SP_level_dam_adjust(caster, spell)
3208  +weapon->stats.dam
3209  +weapon->magic
3210  +5*weapon->stats.Str;
3211  if (tmp->stats.dam < 0)
3212  tmp->stats.dam = 127;
3213 
3214  /* attacktype */
3215  if (!tmp->attacktype)
3216  tmp->attacktype = AT_PHYSICAL;
3217 
3218  mt = NULL;
3219  if (op->materialname != NULL)
3220  mt = name_to_material(op->materialname);
3221  if (mt != NULL) {
3222  for (i = 0; i < NROFATTACKS; i++)
3223  tmp->resist[i] = 50-(mt->save[i]*5);
3224  a = mt->save[0];
3225  } else {
3226  for (i = 0; i < NROFATTACKS; i++)
3227  tmp->resist[i] = 5;
3228  a = 10;
3229  }
3230  /* Set weapon's immunity */
3231  tmp->resist[ATNR_CONFUSION] = 100;
3232  tmp->resist[ATNR_POISON] = 100;
3233  tmp->resist[ATNR_SLOW] = 100;
3234  tmp->resist[ATNR_PARALYZE] = 100;
3235  tmp->resist[ATNR_TURN_UNDEAD] = 100;
3236  tmp->resist[ATNR_FEAR] = 100;
3237  tmp->resist[ATNR_DEPLETE] = 100;
3238  tmp->resist[ATNR_DEATH] = 100;
3239  tmp->resist[ATNR_BLIND] = 100;
3240 
3241  /* Improve weapon's armour value according to best save vs. physical of its material */
3242 
3243  if (a > 14)
3244  a = 14;
3245  tmp->resist[ATNR_PHYSICAL] = 100-(int)((100.0-(float)tmp->resist[ATNR_PHYSICAL])/(30.0-2.0*a));
3246 
3247  /* Determine golem's speed */
3248  tmp->speed = 0.4+0.1*SP_level_range_adjust(caster, spell);
3249 
3250  if (tmp->speed > 3.33)
3251  tmp->speed = 3.33;
3252 
3253  if (!spell->race) {
3254  snprintf(buf, sizeof(buf), "animated %s", weapon->name);
3255  if (tmp->name)
3256  free_string(tmp->name);
3257  tmp->name = add_string(buf);
3258 
3259  tmp->face = weapon->face;
3260  tmp->animation = weapon->animation;
3261  tmp->anim_speed = weapon->anim_speed;
3262  tmp->last_anim = weapon->last_anim;
3263  tmp->state = weapon->state;
3264  if (QUERY_FLAG(weapon, FLAG_ANIMATE)) {
3266  } else {
3268  }
3270  }
3271 
3272  /* make experience increase in proportion to the strength of the summoned creature. */
3273  tmp->stats.exp *= 1+(MAX(spell->stats.maxgrace, spell->stats.sp)/caster_level(caster, spell));
3274 
3275  tmp->speed_left = -1;
3276  tmp->direction = dir;
3277  object_insert_in_map_at(tmp, m, op, 0, x, y);
3278  return 1;
3279 }
3280 
3293 int cast_change_map_lightlevel(object *op, object *spell) {
3294  int success;
3295 
3296  if (!op->map)
3297  return 0; /* shouldnt happen */
3298 
3299  success = change_map_light(op->map, spell->stats.dam);
3300  if (!success) {
3301  if (spell->stats.dam < 0)
3303  "It can be no brighter here.");
3304  else
3306  "It can be no darker here.");
3307  }
3308  return success;
3309 }
3310 
3325 int create_aura(object *op, object *caster, object *spell) {
3326  int refresh = 0, i;
3327  object *new_aura;
3328 
3329  new_aura = arch_present_in_ob(spell->other_arch, op);
3330  if (new_aura)
3331  refresh = 1;
3332  else
3333  new_aura = arch_to_object(spell->other_arch);
3334 
3335  new_aura->duration = spell->duration+10*SP_level_duration_adjust(caster, spell);
3336  if (op->type == PLAYER)
3337  store_spell_expiry(new_aura);
3338 
3339  new_aura->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
3340 
3341  // If the range is zero, it's not an aura. Plain and simple. Minimum is one.
3342  // Also provides backward compatability on existing auras to be range 1
3343  new_aura->range = MAX(1, spell->range+SP_level_range_adjust(caster, spell));
3344 
3345  object_set_owner(new_aura, op);
3346  set_spell_skill(op, caster, spell, new_aura);
3347  new_aura->attacktype = spell->attacktype;
3348 
3349  new_aura->level = caster_level(caster, spell);
3350 
3351  /* Code below is so that auras can also provide resistances. For
3352  * example, fire shield both does damage to nearby enemies and also
3353  * provides some protection to fire. We need to use a different
3354  * FORCE object for this, as putting it in with the aura object
3355  * just puts too many meanings into that one object. Because
3356  * the duration of this force object is the same, we don't need
3357  * to set up spell expiry on it - this second object is really
3358  * an internal mechanic that should be invisible to the player.
3359  */
3360  for (i = 0; i < NROFATTACKS; i++) {
3361  if (spell->resist[i]) {
3362  int refresh1=1;
3363  object *force;
3364 
3366  if (!force) {
3368  force->subtype = FORCE_CHANGE_ABILITY;
3369  free_string(force->name);
3370  force->name = add_refcount(spell->name);
3371  free_string(force->name_pl);
3372  force->name_pl = add_refcount(spell->name);
3373  refresh1=0;
3374  }
3375  force->duration = new_aura->duration;
3376  force->speed = new_aura->speed;
3377  memcpy(&force->resist, spell->resist, sizeof(spell->resist));
3379 
3380  if (!refresh1)
3382  change_abil(op, new_aura);
3383  fix_object(op);
3384  break;
3385  }
3386  }
3387 
3388  if (refresh)
3390  "You recast the spell while in effect.");
3391  else
3392  object_insert_in_ob(new_aura, op);
3393  return 1;
3394 }
3395 
3411 int write_mark(object *op, object *spell, const char *msg) {
3412  char rune[HUGE_BUF];
3413  object *tmp;
3414 
3415  if (!msg || msg[0] == 0) {
3417  "Write what?");
3418  return 0;
3419  }
3420 
3421  if (strcasestr_local(msg, "endmsg")) {
3423  "Trying to cheat are we?");
3424  LOG(llevInfo, "write_rune: player %s tried to write bogus rune %s\n", op->name, msg);
3425  return 0;
3426  }
3427 
3428  if (!spell->other_arch)
3429  return 0;
3430  tmp = arch_to_object(spell->other_arch);
3431  strncpy(rune, msg, HUGE_BUF-2);
3432  rune[HUGE_BUF-2] = 0;
3433  strcat(rune, "\n");
3434  tmp->race = add_string(op->name); /*Save the owner of the rune*/
3435  object_set_msg(tmp, rune);
3437  return 1;
3438 }
SP_level_range_adjust
int SP_level_range_adjust(const object *caster, const object *spob)
Definition: spell_util.cpp:338
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:70
MSG_TYPE_SPELL_PERCEIVE_SELF
#define MSG_TYPE_SPELL_PERCEIVE_SELF
Definition: newclient.h:626
object::name_pl
sstring name_pl
Definition: object.h:323
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:170
FORCE_CHANGE_ABILITY
#define FORCE_CHANGE_ABILITY
Definition: spells.h:145
living::exp
int64_t exp
Definition: living.h:47
HAS_RANDOM_ITEMS
#define HAS_RANDOM_ITEMS(op)
Definition: define.h:184
UP_OBJ_FACE
#define UP_OBJ_FACE
Definition: object.h:533
write_mark
int write_mark(object *op, object *spell, const char *msg)
Definition: spell_effect.cpp:3411
PLAYER
@ PLAYER
Definition: object.h:112
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:94
LARGE_NUGGET
#define LARGE_NUGGET
Definition: spell_effect.cpp:2174
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:545
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.cpp:4297
cast_polymorph
int cast_polymorph(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_effect.cpp:425
settings
struct Settings settings
Definition: init.cpp:139
CF_HANDLE
@ CF_HANDLE
Definition: object.h:213
SOUND_TYPE_ITEM
#define SOUND_TYPE_ITEM
Definition: newclient.h:324
INS_NO_WALK_ON
#define INS_NO_WALK_ON
Definition: object.h:582
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:2268
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
remove_friendly_object
void remove_friendly_object(object *op)
Definition: friend.cpp:52
cast_change_ability
int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent)
Definition: spell_effect.cpp:1900
remove_curse
int remove_curse(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:2404
living::maxhp
int16_t maxhp
Definition: living.h:41
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Definition: object.cpp:4079
AT_POISON
#define AT_POISON
Definition: attack.h:86
object::weapontype
uint32_t weapontype
Definition: object.h:381
AT_MAGIC
#define AT_MAGIC
Definition: attack.h:77
CAN_PROBE
static bool CAN_PROBE(const object *ob)
Definition: object.h:616
object::map_layer
uint8_t map_layer
Definition: object.h:434
BOW
@ BOW
Definition: object.h:123
llevError
@ llevError
Definition: logger.h:11
FABS
#define FABS(x)
Definition: define.h:22
object::path_attuned
uint32_t path_attuned
Definition: object.h:353
WAND
@ WAND
Definition: object.h:225
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
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
object::inv
object * inv
Definition: object.h:298
altar_valkyrie.obj
obj
Definition: altar_valkyrie.py:33
BUTTON
@ BUTTON
Definition: object.h:212
diamondslots.x
x
Definition: diamondslots.py:15
perceive_self
int perceive_self(object *op)
Definition: spell_effect.cpp:1002
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.cpp:1762
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:756
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
archetypes_for_each
void archetypes_for_each(arch_op op)
Definition: assets.cpp:301
AssetsManager.h
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
magic_wall
int magic_wall(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.cpp:1456
cast_change_map_lightlevel
int cast_change_map_lightlevel(object *op, object *spell)
Definition: spell_effect.cpp:3293
ARCH_DEPLETION
#define ARCH_DEPLETION
Definition: object.h:590
map_find_by_archetype
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
Definition: object.cpp:3114
confuse_living
void confuse_living(object *op, object *hitter, int dam)
Definition: attack.cpp:2311
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.cpp:138
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
object::arch
struct archetype * arch
Definition: object.h:424
cast_spell
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Definition: spell_util.cpp:1424
disinfect.a
a
Definition: disinfect.py:13
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
object::attack_movement
uint16_t attack_movement
Definition: object.h:401
cast_wonder
int cast_wonder(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.cpp:968
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Definition: define.h:704
object::range
int8_t range
Definition: object.h:417
object::speed
float speed
Definition: object.h:337
GEM
@ GEM
Definition: object.h:172
artifactlist::items
std::vector< artifact * > items
Definition: artifact.h:28
food_value_choice
static int food_value_choice
Definition: spell_effect.cpp:594
object::invisible
int16_t invisible
Definition: object.h:370
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:439
living::Dex
int8_t Dex
Definition: living.h:36
object::x
int16_t x
Definition: object.h:335
object::speed_left
float speed_left
Definition: object.h:338
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.cpp:230
PREFER_LOW
#define PREFER_LOW
Definition: define.h:564
object::map
struct mapstruct * map
Definition: object.h:305
WEAPON
@ WEAPON
Definition: object.h:124
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.cpp:3595
arch_present_in_ob
object * arch_present_in_ob(const archetype *at, const object *op)
Definition: object.cpp:3218
object_set_owner
void object_set_owner(object *op, object *owner)
Definition: object.cpp:840
SMALL_NUGGET
#define SMALL_NUGGET
Definition: spell_effect.cpp:2173
artifact::item
object * item
Definition: artifact.h:15
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:909
MIN
#define MIN(x, y)
Definition: compat.h:21
cast_consecrate
int cast_consecrate(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:2985
ATNR_GODPOWER
#define ATNR_GODPOWER
Definition: attack.h:69
TREASURE
@ TREASURE
Definition: object.h:115
MSG_TYPE_VICTIM_SPELL
#define MSG_TYPE_VICTIM_SPELL
Definition: newclient.h:643
SP_level_duration_adjust
int SP_level_duration_adjust(const object *caster, const object *spob)
Definition: spell_util.cpp:312
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:1609
object::count
tag_t count
Definition: object.h:307
FLAG_WIZCAST
#define FLAG_WIZCAST
Definition: define.h:289
object::last_grace
int16_t last_grace
Definition: object.h:369
RUNE
@ RUNE
Definition: object.h:245
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
MAP_PLAYER_UNIQUE
#define MAP_PLAYER_UNIQUE
Definition: map.h:92
tolower
#define tolower(C)
Definition: c_new.cpp: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:233
polymorph_melt
static void polymorph_melt(object *who, object *op)
Definition: spell_effect.cpp:252
P_NO_MAGIC
#define P_NO_MAGIC
Definition: map.h:225
TRANSPORT
@ TRANSPORT
Definition: object.h:113
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
UPD_NROF
#define UPD_NROF
Definition: newclient.h:310
SIGN
@ SIGN
Definition: object.h:216
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
food_choice
static archetype * food_choice
Definition: spell_effect.cpp:593
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:1871
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:263
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:235
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
object::level
int16_t level
Definition: object.h:361
probe
int probe(object *op, object *caster, object *spell_ob, int dir, int level)
Definition: spell_effect.cpp:699
buf
StringBuffer * buf
Definition: readable.cpp:1565
getManager
AssetsManager * getManager()
Definition: assets.cpp:305
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:2853
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
MSG_TYPE_VICTIM
#define MSG_TYPE_VICTIM
Definition: newclient.h:404
MAX
#define MAX(x, y)
Definition: compat.h:24
object::resist
int16_t resist[NROFATTACKS]
Definition: object.h:351
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
MSG_TYPE_SPELL_TARGET
#define MSG_TYPE_SPELL_TARGET
Definition: newclient.h:627
ATNR_CONFUSION
#define ATNR_CONFUSION
Definition: attack.h:54
MSG_TYPE_SPELL_HEAL
#define MSG_TYPE_SPELL_HEAL
Definition: newclient.h:620
find_god
const object * find_god(const char *name)
Definition: holy.cpp:317
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:235
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Definition: define.h:711
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:595
MSG_TYPE_SPELL_SUCCESS
#define MSG_TYPE_SPELL_SUCCESS
Definition: newclient.h:624
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:1981
spell_effect
void spell_effect(object *spob, int x, int y, mapstruct *map, object *originator)
Definition: spell_util.cpp:144
ATNR_BLIND
#define ATNR_BLIND
Definition: attack.h:71
object::y
int16_t y
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:425
autojail.who
who
Definition: autojail.py:3
polymorph
void polymorph(object *op, object *who, int level)
Definition: spell_effect.cpp:371
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
object_update
void object_update(object *op, int action)
Definition: object.cpp:1434
cast_invisible
int cast_invisible(object *op, object *caster, object *spell_ob)
Definition: spell_effect.cpp:803
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:2781
disinfect.map
map
Definition: disinfect.py:4
object::subtype
uint8_t subtype
Definition: object.h:349
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::anim_speed
uint8_t anim_speed
Definition: object.h:429
object_present_in_ob_by_name
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.cpp:3199
alchemy_object
static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight)
Definition: spell_effect.cpp:2190
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:588
cast_word_of_recall
int cast_word_of_recall(object *op, object *caster, object *spell_ob)
Definition: spell_effect.cpp:906
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
archetype::clone
object clone
Definition: object.h:487
sword_of_souls.victim
victim
Definition: sword_of_souls.py:12
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
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:754
HEAD
#define HEAD(op)
Definition: object.h:607
change_map_light
int change_map_light(mapstruct *m, int change)
Definition: map.cpp:1986
object::move_type
MoveType move_type
Definition: object.h:436
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.cpp:513
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:128
MSG_TYPE_ITEM
#define MSG_TYPE_ITEM
Definition: newclient.h:401
object::face
const Face * face
Definition: object.h:341
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
object::value
int32_t value
Definition: object.h:360
is_identified
int is_identified(const object *op)
Definition: item.cpp:1348
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:129
HOLE
@ HOLE
Definition: object.h:214
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1349
object::last_anim
uint8_t last_anim
Definition: object.h:430
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:162
animate_weapon
int animate_weapon(object *op, object *caster, object *spell, int dir)
Definition: spell_effect.cpp:3063
object::type
uint8_t type
Definition: object.h:348
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:580
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
living::dam
int16_t dam
Definition: living.h:46
object::magic
int8_t magic
Definition: object.h:358
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:304
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:298
CFweardisguise.tag
tag
Definition: CFweardisguise.py:25
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1592
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:190
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:584
living::food
int32_t food
Definition: living.h:48
GOLEM
@ GOLEM
Definition: object.h:150
caster_level
int caster_level(const object *caster, const object *spell)
Definition: spell_util.cpp:194
disinfect.count
int count
Definition: disinfect.py:7
cast_detection
int cast_detection(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:2578
cast_create_town_portal
int cast_create_town_portal(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:1241
tag_t
uint32_t tag_t
Definition: object.h:14
archetype
Definition: object.h:483
ATNR_POISON
#define ATNR_POISON
Definition: attack.h:59
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
Definition: define.h:296
sproto.h
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
living::sp
int16_t sp
Definition: living.h:42
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.cpp:95
AssetsCollection::each
void each(std::function< void(T *)> op)
Definition: AssetsCollection.h:158
FOR_OB_AND_BELOW_PREPARE
#define FOR_OB_AND_BELOW_PREPARE(op_)
Definition: define.h:750
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Definition: newclient.h:400
BOOK
@ BOOK
Definition: object.h:119
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
object::race
sstring race
Definition: object.h:326
cast_item_curse_or_bless
int cast_item_curse_or_bless(object *op, object *spell_ob)
Definition: spell_effect.cpp:2452
object::animation
const Animations * animation
Definition: object.h:428
RING
@ RING
Definition: object.h:190
materialtype_t::save
int8_t save[NROFATTACKS]
Definition: material.h:36
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:231
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:2100
object::other_arch
struct archetype * other_arch
Definition: object.h:425
mapstruct::last_reset_time
long last_reset_time
Definition: map.h:354
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:247
AssetsManager::archetypes
Archetypes * archetypes()
Definition: AssetsManager.h:44
EXIT_X
#define EXIT_X(xyz)
Definition: define.h:441
MAX_BUF
#define MAX_BUF
Definition: define.h:35
INS_ON_TOP
#define INS_ON_TOP
Definition: object.h:583
object_new
object * object_new(void)
Definition: object.cpp:1273
describe_item
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Definition: item.cpp:951
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
object::weight
int32_t weight
Definition: object.h:375
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:1999
cast_magic_storm
void cast_magic_storm(object *op, object *tmp, int lvl)
Definition: spell_effect.cpp:49
living::wc
int8_t wc
Definition: living.h:37
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
living::maxgrace
int16_t maxgrace
Definition: living.h:45
cast_transfer
int cast_transfer(object *op, object *caster, object *spell, int dir)
Definition: spell_effect.cpp:2836
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
EXIT
@ EXIT
Definition: object.h:186
FLAG_KNOWN_MAGICAL
#define FLAG_KNOWN_MAGICAL
Definition: define.h:319
change_abil
int change_abil(object *op, object *tmp)
Definition: living.cpp:394
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
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:251
object::slaying
sstring slaying
Definition: object.h:327
object::glow_radius
int8_t glow_radius
Definition: object.h:374
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:1110
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
spells.h
object::name
sstring name
Definition: object.h:319
SP_level_dam_adjust
int SP_level_dam_adjust(const object *caster, const object *spob)
Definition: spell_util.cpp:287
polymorph_item
static void polymorph_item(object *who, object *op, int level)
Definition: spell_effect.cpp:280
MSG_TYPE_SPELL_FAILURE
#define MSG_TYPE_SPELL_FAILURE
Definition: newclient.h:622
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:32
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:300
ARCH_PORTAL_FAILED
#define ARCH_PORTAL_FAILED
Definition: object.h:592
FLAG_IS_BUILDABLE
#define FLAG_IS_BUILDABLE
Definition: define.h:367
living::maxsp
int16_t maxsp
Definition: living.h:43
is_magical
int is_magical(const object *op)
Definition: item.cpp:1227
mapstruct
Definition: map.h:313
object::last_sp
int32_t last_sp
Definition: object.h:368
counterspell
void counterspell(object *op, int dir)
Definition: spell_effect.cpp:2909
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:1745
object::skill
sstring skill
Definition: object.h:329
MSG_TYPE_SPELL_ERROR
#define MSG_TYPE_SPELL_ERROR
Definition: newclient.h:625
shop.h
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.cpp:2633
cast_bless
int cast_bless(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_effect.cpp:2048
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:3555
cast_create_obj
int cast_create_obj(object *op, object *new_op, int dir)
Definition: spell_util.cpp:494
object_set_msg
void object_set_msg(object *op, const char *msg)
Definition: object.cpp:4807
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:2282
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:220
cast_create_missile
int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg)
Definition: spell_effect.cpp:493
archetype::reference_count
int reference_count
Definition: object.h:490
ATNR_MAGIC
#define ATNR_MAGIC
Definition: attack.h:50
FLAG_NO_FIX_PLAYER
#define FLAG_NO_FIX_PLAYER
Definition: define.h:277
hit_player
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Definition: attack.cpp:1903
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
map_path_unique
bool map_path_unique(const char *path)
Definition: map.cpp:2713
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:1149
living::ac
int8_t ac
Definition: living.h:38
cast_create_food
int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
Definition: spell_effect.cpp:627
object::duration
int16_t duration
Definition: object.h:415
atnr_is_dragon_enabled
int atnr_is_dragon_enabled(int attacknr)
Definition: player.cpp:103
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:4273
map_newmap_cmd
void map_newmap_cmd(socket_struct *ns)
Definition: request.cpp:693
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:229
level
int level
Definition: readable.cpp:1563
object::flags
ob_flags flags
Definition: object.h:427
make_face_from_files.int
int
Definition: make_face_from_files.py:32
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:307
AT_COUNTERSPELL
#define AT_COUNTERSPELL
Definition: attack.h:95
AT_DISEASE
#define AT_DISEASE
Definition: attack.h:102
object::randomitems
struct treasurelist * randomitems
Definition: object.h:395
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:117
object_remove
void object_remove(object *op)
Definition: object.cpp:1833
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:270
ALTAR
@ ALTAR
Definition: object.h:127
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:295
DRINK
@ DRINK
Definition: object.h:162
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:544
update_all_los
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.cpp:595
object::state
uint8_t state
Definition: object.h:359
SP_WONDER
#define SP_WONDER
Definition: spells.h:83
archetype::name
sstring name
Definition: object.h:484
object::nrof
uint32_t nrof
Definition: object.h:342
FLAG_XRAYS
#define FLAG_XRAYS
Definition: define.h:300
materialtype_t
Definition: material.h:32
PETMOVE
#define PETMOVE
Definition: define.h:501
living::grace
int16_t grace
Definition: living.h:44
object::stats
living stats
Definition: object.h:378
object::move_allow
MoveType move_allow
Definition: object.h:438
artifact
Definition: artifact.h:14
object::more
object * more
Definition: object.h:303
get_attr_value
int8_t get_attr_value(const living *stats, int attr)
Definition: living.cpp:313
find_target_for_friendly_spell
object * find_target_for_friendly_spell(object *op, int dir)
Definition: spell_util.cpp:813
cast_identify
int cast_identify(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:2503
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:84
SPELL
@ SPELL
Definition: object.h:219
Settings::create_home_portals
uint8_t create_home_portals
Definition: global.h:311
object::attacktype
uint32_t attacktype
Definition: object.h:352
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:146
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
living.h
find_artifactlist
artifactlist * find_artifactlist(int type)
Definition: artifact.cpp:574
NDI_GREY
#define NDI_GREY
Definition: newclient.h:241
cast_earth_to_dust
int cast_earth_to_dust(object *op, object *caster, object *spell_ob)
Definition: spell_effect.cpp:855
NUM_STATS
@ NUM_STATS
Definition: living.h:18
MSG_TYPE_ITEM_INFO
#define MSG_TYPE_ITEM_INFO
Definition: newclient.h:634
find_marked_object
object * find_marked_object(object *op)
Definition: c_object.cpp:1520
object::move_block
MoveType move_block
Definition: object.h:437
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
living::hp
int16_t hp
Definition: living.h:40
FORCE
@ FORCE
Definition: object.h:229
alchemy
int alchemy(object *op, object *caster, object *spell_ob)
Definition: spell_effect.cpp:2304
HOLY_ALTAR
@ HOLY_ALTAR
Definition: object.h:166
TRAPDOOR
@ TRAPDOOR
Definition: object.h:215
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:3325
object.h
llevDebug
@ llevDebug
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:142
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:3975
P_BLOCKSVIEW
#define P_BLOCKSVIEW
Definition: map.h:224
GATE
@ GATE
Definition: object.h:211
FORCE_NAME
#define FORCE_NAME
Definition: spells.h:169
living::Con
int8_t Con
Definition: living.h:36
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:170
living::Str
int8_t Str
Definition: living.h:36
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:1421
level
Definition: level.py:1