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 
673  cast_create_obj(op, new_op, dir);
674  return 1;
675 }
676 
695 int probe(object *op, object *caster, object *spell_ob, int dir, int level) {
696  int r, mflags, maxrange;
697  mapstruct *m;
698 
699  if (!dir) {
701  return 1;
702  }
703  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
704  for (r = 1; r < maxrange; r++) {
705  int16_t x = op->x+r*freearr_x[dir], y = op->y+r*freearr_y[dir];
706 
707  m = op->map;
708  mflags = get_map_flags(m, &m, x, y, &x, &y);
709 
710  if (mflags&P_OUT_OF_MAP)
711  break;
712 
713  if (!QUERY_FLAG(op, FLAG_WIZCAST) && (mflags&P_NO_MAGIC)) {
715  "Something blocks your magic.");
716  return 0;
717  }
718  if (mflags&P_IS_ALIVE) {
719  FOR_MAP_PREPARE(m, x, y, tmp)
720  if (CAN_PROBE(tmp)) {
722  "You detect something.");
724  return 1;
725  }
726  FOR_MAP_FINISH();
727  }
728  }
730  "You detect nothing.");
731  return 1;
732 }
733 
734 
752 int makes_invisible_to(object *pl, object *mon) {
753  if (!pl->invisible)
754  return 0;
755  if (pl->type == PLAYER) {
756  /* If race isn't set, then invisible unless it is undead */
757  if (!pl->contr->invis_race) {
758  if (QUERY_FLAG(mon, FLAG_UNDEAD))
759  return 0;
760  return 1;
761  }
762  /* invis_race is set if we get here */
763  if (!strcmp(pl->contr->invis_race, "undead") && is_true_undead(mon))
764  return 1;
765  /* No race, can't be invisible to it */
766  if (!mon->race)
767  return 0;
768  if (strstr(mon->race, pl->contr->invis_race))
769  return 1;
770  /* Nothing matched above, return 0 */
771  return 0;
772  } else {
773  /* monsters are invisible to everything */
774  return 1;
775  }
776 }
777 
799 int cast_invisible(object *op, object *caster, object *spell_ob) {
800  if (op->invisible > 1000) {
802  "You can not extend the duration of your invisibility any further");
803  return 0;
804  }
805 
806  /* Remove the switch with 90% duplicate code - just handle the differences with
807  * and if statement or two.
808  */
809  op->invisible += spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
810  /* max duration */
811  if (op->invisible > 1000)
812  op->invisible = 1000;
813 
814  if (op->type == PLAYER) {
815  if (op->contr->invis_race)
816  FREE_AND_CLEAR_STR(op->contr->invis_race);
817  if (spell_ob->race)
818  op->contr->invis_race = add_refcount(spell_ob->race);
819  if (QUERY_FLAG(spell_ob, FLAG_MAKE_INVIS))
820  op->contr->tmp_invis = 0;
821  else
822  op->contr->tmp_invis = 1;
823 
824  op->contr->hidden = 0;
825  }
826  if (makes_invisible_to(op, op))
828  "You can't see your hands!");
829  else
831  "You feel more transparent!");
832 
834  return 1;
835 }
836 
851 int cast_earth_to_dust(object *op, object *caster, object *spell_ob) {
852  int range, i, j, mflags;
853  int16_t sx, sy;
854  mapstruct *m;
855 
856  if (op->type != PLAYER)
857  return 0;
858 
859  range = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
860 
861  for (i = -range; i < range; i++)
862  for (j = -range; j < range; j++) {
863  sx = op->x+i;
864  sy = op->y+j;
865  m = op->map;
866  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
867 
868  if (mflags&P_OUT_OF_MAP)
869  continue;
870 
871  /* If the space doesn't block, no wall here to remove
872  * Don't care too much what it blocks - this allows for
873  * any sort of earthwall/airwall/waterwall, etc
874  * type effects.
875  */
876  if (GET_MAP_MOVE_BLOCK(m, sx, sy)) {
877  FOR_MAP_PREPARE(m, sx, sy, tmp)
878  if (tmp && QUERY_FLAG(tmp, FLAG_TEAR_DOWN))
879  hit_player(tmp, 9998, op, AT_PHYSICAL, 0);
880  FOR_MAP_FINISH();
881  }
882  }
883  return 1;
884 }
885 
902 int cast_word_of_recall(object *op, object *caster, object *spell_ob) {
903  object *dummy;
904  int time;
905 
906  if (op->type != PLAYER)
907  return 0;
908 
911  "You feel a force starting to build up inside you.");
912  return 1;
913  }
914 
915  dummy = create_archetype(FORCE_NAME);
916  if (dummy == NULL) {
918  "Oops, program error!");
919  LOG(llevError, "cast_word_of_recall: create_archetype(force) failed!\n");
920  return 0;
921  }
922  time = spell_ob->duration-SP_level_duration_adjust(caster, spell_ob);
923  if (time < 1)
924  time = 1;
925 
926  /* value of speed really doesn't make much difference, as long as it is
927  * positive. Lower value may be useful so that the problem doesn't
928  * do anything really odd if it say a -1000 or something.
929  */
930  dummy->speed = 0.002;
931  object_update_speed(dummy);
932  dummy->speed_left = -dummy->speed*time;
933  dummy->type = SPELL_EFFECT;
934  dummy->subtype = SP_WORD_OF_RECALL;
935 
936  /* If we could take advantage of enter_player_savebed() here, it would be
937  * nice, but until the map load fails, we can't.
938  */
939  EXIT_PATH(dummy) = add_string(op->contr->savebed_map);
940  EXIT_X(dummy) = op->contr->bed_x;
941  EXIT_Y(dummy) = op->contr->bed_y;
942 
943  (void)object_insert_in_ob(dummy, op);
945  "You feel a force starting to build up inside you.");
946  return 1;
947 }
948 
964 int cast_wonder(object *op, object *caster, int dir, object *spell_ob) {
965  object *newspell;
966 
967  if (!rndm(0, 3))
968  return cast_cone(op, caster, dir, spell_ob);
969 
970  if (spell_ob->randomitems) {
971  newspell = generate_treasure(spell_ob->randomitems, caster->level);
972  if (!newspell) {
973  LOG(llevError, "cast_wonder: Unable to get a spell!\n");
974  return 0;
975  }
976  if (newspell->type != SPELL) {
977  LOG(llevError, "cast_wonder: spell returned is not a spell (%d, %s)!\n", newspell->type, newspell->name);
978  return 0;
979  }
980  /* Prevent inifinite recursion */
981  if (newspell->subtype == SP_WONDER) {
982  LOG(llevError, "cast_wonder: spell returned is another wonder spell!\n");
983  return 0;
984  }
985  return cast_spell(op, caster, dir, newspell, NULL);
986  }
987  return 1;
988 }
989 
998 int perceive_self(object *op) {
999  char *cp, buf[MAX_BUF];
1001  if (at == NULL) {
1002  return 1;
1003  }
1004  object *tmp;
1005  const object *god;
1006  int i;
1007  StringBuffer *immunity;
1008 
1009  god = find_god(determine_god(op));
1010  if (god)
1012  "You worship %s",
1013  god->name);
1014  else
1016  "You worship no god");
1017 
1018  tmp = arch_present_in_ob(at, op);
1019 
1020  cp = stringbuffer_finish(describe_item(op, op, 0, NULL));
1021 
1022  if (*cp == '\0' && tmp == NULL)
1024  "You feel very mundane");
1025  else {
1027  "You have:");
1029  cp);
1030  if (tmp != NULL) {
1031  for (i = 0; i < NUM_STATS; i++) {
1032  if (get_attr_value(&tmp->stats, i) < 0) {
1034  "Your %s is depleted by %d",
1035  statname[i], -(get_attr_value(&tmp->stats, i)));
1036  }
1037  }
1038  }
1039  }
1040  free(cp);
1041 
1042  if (op->glow_radius > 0)
1044  "You glow in the dark.");
1045 
1046  immunity = NULL;
1047  for (tmp = op->inv; tmp; tmp = tmp->below) {
1048  if (tmp->type == SIGN) {
1049  if (immunity == NULL) {
1050  immunity = stringbuffer_new();
1051  stringbuffer_append_string(immunity, "You have been exposed to: ");
1052  } else {
1053  stringbuffer_append_string(immunity, ", ");
1054  }
1055  stringbuffer_append_string(immunity, tmp->name);
1056  if (tmp->level > 100)
1057  stringbuffer_append_string(immunity, " (full immunity)");
1058  else if (tmp->level > 70)
1059  stringbuffer_append_string(immunity, " (high immunity)");
1060  else if (tmp->level > 20)
1061  stringbuffer_append_string(immunity, " (partial immunity)");
1062  }
1063  }
1064 
1065  if (immunity != NULL) {
1066  cp = stringbuffer_finish(immunity);
1068  free(cp);
1069  }
1070 
1071  if (is_dragon_pl(op)) {
1072  /* now grab the 'dragon_ability'-force from the player's inventory */
1073  tmp = object_find_by_type_and_arch_name(op, FORCE, "dragon_ability_force");
1074  if (tmp != NULL) {
1075  StringBuffer *levels = NULL;
1076  int i;
1077 
1078  if (tmp->stats.exp == 0) {
1079  snprintf(buf, sizeof(buf), "Your metabolism isn't focused on anything.");
1080  } else {
1081  snprintf(buf, sizeof(buf), "Your metabolism is focused on %s.", change_resist_msg[tmp->stats.exp]);
1082  }
1084  buf);
1085 
1086  for (i = 0; i < NROFATTACKS; i++) {
1087  if (atnr_is_dragon_enabled(i) && tmp->resist[i] > 0) {
1088  if (levels == NULL) {
1090  stringbuffer_append_string(levels, "Ability levels:\n");
1091  }
1092  stringbuffer_append_printf(levels, "- %s: %d\n", change_resist_msg[i], tmp->resist[i]);
1093  }
1094  }
1095 
1096  if (levels != NULL) {
1099  free(cp);
1100  }
1101  }
1102  }
1103  return 1;
1104 }
1105 
1106 static object* town_portal_find_force(object* op, object* spell) {
1107  object *dummy, *force;
1108 
1109  /* The first thing to do is to check if we have a marked destination
1110  * dummy is used to make a check inventory for the force
1111  */
1112  dummy = arch_to_object(spell->other_arch);
1113  if (dummy == NULL) {
1115  "Oops, program error!");
1116  LOG(llevError, "object_new failed (force in cast_create_town_portal for %s!\n", op->name);
1117  return NULL;
1118  }
1119 
1120  force = check_inv_recursive(op, dummy);
1121  if (force == NULL) {
1122  /* Here we know there is no destination marked up.
1123  * We have 2 things to do:
1124  * 1. Mark the destination in the player inventory.
1125  * 2. Let the player know it worked.
1126  */
1127  free_string(dummy->name);
1128  dummy->name = add_string(op->map->path);
1129  EXIT_X(dummy) = op->x;
1130  EXIT_Y(dummy) = op->y;
1131  dummy->weapontype = op->map->last_reset_time;
1132  object_insert_in_ob(dummy, op);
1134  "You fix this place in your mind and feel that you "
1135  "can come here from anywhere.");
1136  } else {
1138  }
1139  return force;
1140 }
1141 
1145 static int town_portal_destroy_existing(object* op, object* spell) {
1146  object* dummy = create_archetype(spell->race);
1147  object* old_force;
1148  if (dummy == NULL) {
1150  "Oops, program error!");
1151  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1152  return 0;
1153  }
1154  archetype *perm_portal;
1155  perm_portal = try_find_archetype(spell->slaying);
1156  if (perm_portal == NULL) {
1158  "Oops, program error!");
1159  return 0;
1160  }
1161 
1162  /* To kill a town portal, we go trough the player's inventory,
1163  * for each marked portal in player's inventory,
1164  * -We try load the associated map (if impossible, consider the portal destructed)
1165  * -We find any portal in the specified location.
1166  * If it has the good name, we destruct it.
1167  * -We destruct the force indicating that portal.
1168  */
1169  while ((old_force = check_inv_recursive(op, dummy))) {
1170  int16_t exitx = EXIT_X(old_force);
1171  int16_t exity = EXIT_Y(old_force);
1172  LOG(llevDebug, "Trying to kill a portal in %s (%d,%d)\n", old_force->race, exitx, exity);
1173 
1174  mapstruct *exitmap;
1175  if (!strncmp(old_force->race, settings.localdir, strlen(settings.localdir)))
1176  exitmap = ready_map_name(old_force->race, MAP_PLAYER_UNIQUE);
1177  else
1178  exitmap = ready_map_name(old_force->race, 0);
1179 
1180  if (exitmap) {
1181  object* tmp = map_find_by_archetype(exitmap, exitx, exity, perm_portal);
1183  if (tmp->name == old_force->name) {
1184  object_remove(tmp);
1185  object_free(tmp, 0);
1186  break;
1187  }
1189 
1190  /* kill any opening animation there is */
1191  archetype *arch = try_find_archetype("town_portal_open");
1192  if (arch != NULL) {
1193  tmp = map_find_by_archetype(exitmap, exitx, exity, arch);
1195  if (tmp->name == old_force->name) {
1196  object_remove(tmp);
1198  break;
1199  }
1201  }
1202  }
1203  object_remove(old_force);
1204  object_free(old_force, 0);
1205  }
1207  return 0;
1208 }
1209 
1237 int cast_create_town_portal(object *op, object *caster, object *spell) {
1238  object *dummy, *force, *tmp;
1239  char portal_name [1024], portal_message [1024];
1240  mapstruct *exitmap;
1241  int op_level, x, y;
1242 
1243  /* Check to see if the map the player is currently on is a per player unique
1244  * map. This can be determined in that per player unique maps have the
1245  * full pathname listed. Ignore if settings.create_home_portals is true.
1246  */
1248  if (!strncmp(op->map->path, settings.localdir, strlen(settings.localdir))) {
1250  "You can't cast that here.");
1251  return 0;
1252  }
1253  }
1254 
1255  /* Check to see if the player is on a transport */
1256  if (op->contr && op->contr->transport) {
1258  "You need to exit the transport to cast that.");
1259  return 0;
1260  }
1261 
1262  force = town_portal_find_force(op, spell);
1263  if (force == NULL) {
1264  return 1;
1265  }
1266 
1267  /* Here we know where the town portal should go to
1268  * We should kill any existing portal associated with the player.
1269  * Than we should create the 2 portals.
1270  * For each of them, we need:
1271  * - To create the portal with the name of the player+destination map
1272  * - set the owner of the town portal
1273  * - To mark the position of the portal in the player's inventory
1274  * for easier destruction.
1275  *
1276  * The mark works has follow:
1277  * slaying: Existing town portal
1278  * hp, sp : x & y of the associated portal
1279  * name : name of the portal
1280  * race : map the portal is in
1281  */
1282  if (town_portal_destroy_existing(op, spell) != 0) {
1283  return 1;
1284  }
1285 
1286  /* Creating the portals.
1287  * The very first thing to do is to ensure
1288  * access to the destination map.
1289  * If we can't, don't fizzle. Simply warn player.
1290  * This ensure player pays his mana for the spell
1291  * because HE is responsible for forgetting.
1292  * 'force' is the destination of the town portal, which we got
1293  * from the players inventory above.
1294  */
1295 
1296  /* Ensure exit map is loaded*/
1297  if (!strncmp(force->name, settings.localdir, strlen(settings.localdir)))
1298  exitmap = ready_map_name(force->name, MAP_PLAYER_UNIQUE);
1299  else
1300  exitmap = ready_map_name(force->name, 0);
1301 
1302  /* If we were unable to load (ex. random map deleted), warn player*/
1303  if (exitmap == NULL) {
1305  "Something strange happens. You can't remember where to go!?");
1307  object_free(force, 0);
1309  return 1;
1310  } else if (exitmap->last_reset_time != force->weapontype) {
1312  "The spell effect has expired.");
1314  object_free(force, 0);
1316  return 1;
1317  }
1318 
1319  op_level = caster_level(caster, spell);
1320  if (op_level < 15)
1321  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);
1322  else if (op_level < 30)
1323  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);
1324  else if (op_level < 60)
1325  snprintf(portal_message, 1024, "A shining door opens in the air in front of you, showing you the path to another place.");
1326  else
1327  snprintf(portal_message, 1024, "As you walk through %s's portal, flowers come out from the ground around you. You feel awed.", op->name);
1328 
1329  /* Create a portal in front of player
1330  * dummy contain the portal and
1331  * force contain the track to kill it later
1332  */
1333 
1334  snprintf(portal_name, 1024, "%s's portal to %s", op->name, force->name);
1335  dummy = create_archetype(spell->slaying); /*The portal*/
1336  if (dummy == NULL) {
1338  "Oops, program error!");
1339  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1340  return 0;
1341  }
1342  EXIT_PATH(dummy) = add_string(force->name);
1343  EXIT_X(dummy) = EXIT_X(force);
1344  EXIT_Y(dummy) = EXIT_Y(force);
1345  FREE_AND_COPY(dummy->name, portal_name);
1346  FREE_AND_COPY(dummy->name_pl, portal_name);
1347  object_set_msg(dummy, portal_message);
1348  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1349 
1350  /* create a nice animation */
1351  tmp = create_archetype("town_portal_open");
1352  FREE_AND_COPY(tmp->name, portal_name);
1353  FREE_AND_COPY(tmp->name_pl, portal_name);
1354  object_insert_in_ob(dummy, tmp);
1355  /* and put it on the floor, when it ends the portal will be on the ground */
1356  cast_create_obj(op, tmp, 0);
1357  x = tmp->x;
1358  y = tmp->y;
1359 
1360  /* Now we need to to create a town portal marker inside the player
1361  * object, so on future castings, we can know that he has an active
1362  * town portal.
1363  */
1364  tmp = create_archetype(spell->race);
1365  if (tmp == NULL) {
1367  "Oops, program error!");
1368  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1369  return 0;
1370  }
1371  tmp->race = add_string(op->map->path);
1372  FREE_AND_COPY(tmp->name, portal_name);
1373  EXIT_X(tmp) = x;
1374  EXIT_Y(tmp) = y;
1376 
1377  /* Create a portal in the destination map
1378  * dummy contain the portal and
1379  * force the track to kill it later
1380  * the 'force' variable still contains the 'reminder' of
1381  * where this portal goes to.
1382  */
1383  snprintf(portal_name, 1024, "%s's portal to %s", op->name, op->map->path);
1384  dummy = create_archetype(spell->slaying); /*The portal*/
1385  if (dummy == NULL) {
1387  "Oops, program error!");
1388  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1389  return 0;
1390  }
1391  EXIT_PATH(dummy) = add_string(op->map->path);
1392  EXIT_X(dummy) = op->x;
1393  EXIT_Y(dummy) = op->y;
1394  FREE_AND_COPY(dummy->name, portal_name);
1395  FREE_AND_COPY(dummy->name_pl, portal_name);
1396  object_set_msg(dummy, portal_message);
1397  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1398 
1399  /* animation here too */
1400  tmp = create_archetype("town_portal_open");
1401  FREE_AND_COPY(tmp->name, portal_name);
1402  FREE_AND_COPY(tmp->name_pl, portal_name);
1403  object_insert_in_ob(dummy, tmp);
1404  /* and put it on the floor, when it ends the portal will be on the ground */
1406  x = tmp->x;
1407  y = tmp->y;
1408 
1409  /* Now we create another town portal marker that
1410  * points back to the one we just made
1411  */
1412  tmp = create_archetype(spell->race);
1413  if (tmp == NULL) {
1415  "Oops, program error!");
1416  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1417  return 0;
1418  }
1419  tmp->race = add_string(force->name);
1420  FREE_AND_COPY(tmp->name, portal_name);
1421  EXIT_X(tmp) = x;
1422  EXIT_Y(tmp) = y;
1424 
1425  /* Describe the player what happened
1426  */
1428  "You see air moving and showing you the way home.");
1429  object_remove(force); /* Delete the force inside the player*/
1430  object_free(force, 0);
1431  return 1;
1432 }
1433 
1434 
1452 int magic_wall(object *op, object *caster, int dir, object *spell_ob) {
1453  object *tmp, *tmp2;
1454  int i, posblocked, negblocked, maxrange;
1455  int16_t x, y;
1456  mapstruct *m;
1457  const char *name;
1458  archetype *at;
1459 
1460  if (!dir) {
1461  dir = op->facing;
1462  x = op->x;
1463  y = op->y;
1464  } else {
1465  x = op->x+freearr_x[dir];
1466  y = op->y+freearr_y[dir];
1467  }
1468  m = op->map;
1469 
1470  if ((spell_ob->move_block || x != op->x || y != op->y)
1471  && (get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE)
1472  || ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) == spell_ob->move_block))) {
1474  "Something is in the way.");
1475  return 0;
1476  }
1477  if (spell_ob->other_arch) {
1478  tmp = arch_to_object(spell_ob->other_arch);
1479  } else if (spell_ob->race) {
1480  char buf1[MAX_BUF];
1481 
1482  snprintf(buf1, sizeof(buf1), spell_ob->race, dir);
1483  at = try_find_archetype(buf1);
1484  if (!at) {
1485  LOG(llevError, "summon_wall: Unable to find archetype %s\n", buf1);
1487  "This spell is broken.");
1488  return 0;
1489  }
1490  tmp = arch_to_object(at);
1491  } else {
1492  LOG(llevError, "magic_wall: spell %s lacks other_arch\n", spell_ob->name);
1493  return 0;
1494  }
1495 
1496  if (tmp->type == SPELL_EFFECT) {
1497  tmp->attacktype = spell_ob->attacktype;
1498  tmp->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1499  tmp->stats.dam = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1500  tmp->range = 0;
1501  } else if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
1502  tmp->stats.hp = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1503  tmp->stats.maxhp = tmp->stats.hp;
1505  set_spell_skill(op, caster, spell_ob, tmp);
1506  }
1508  tmp->stats.food = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1510  }
1511  if (QUERY_FLAG(spell_ob, FLAG_TEAR_DOWN)) {
1512  tmp->stats.hp = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1513  tmp->stats.maxhp = tmp->stats.hp;
1516  }
1517 
1518  /* This can't really hurt - if the object doesn't kill anything,
1519  * these fields just won't be used.
1520  */
1522  set_spell_skill(op, caster, spell_ob, tmp);
1523  tmp->level = caster_level(caster, spell_ob)/2;
1524 
1525  name = tmp->name;
1526  if ((tmp = object_insert_in_map_at(tmp, m, op, 0, x, y)) == NULL) {
1528  "Something destroys your %s",
1529  name);
1530  return 0;
1531  }
1532  /* If this is a spellcasting wall, need to insert the spell object */
1533  if (tmp->other_arch && tmp->other_arch->clone.type == SPELL)
1534  object_insert_in_ob(arch_to_object(tmp->other_arch), tmp);
1535 
1536  /* This code causes the wall to extend some distance in
1537  * each direction, or until an obstruction is encountered.
1538  * posblocked and negblocked help determine how far the
1539  * created wall can extend, it won't go extend through
1540  * blocked spaces.
1541  */
1542  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
1543  posblocked = 0;
1544  negblocked = 0;
1545 
1546  for (i = 1; i <= maxrange; i++) {
1547  int dir2;
1548 
1549  dir2 = (dir < 4) ? (dir+2) : dir-2;
1550 
1551  x = tmp->x+i*freearr_x[dir2];
1552  y = tmp->y+i*freearr_y[dir2];
1553  m = tmp->map;
1554 
1555  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1556  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1557  && !posblocked) {
1558  tmp2 = object_new();
1559  object_copy(tmp, tmp2);
1560  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1561  /* If this is a spellcasting wall, need to insert the spell object */
1562  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1564  } else
1565  posblocked = 1;
1566 
1567  x = tmp->x-i*freearr_x[dir2];
1568  y = tmp->y-i*freearr_y[dir2];
1569  m = tmp->map;
1570 
1571  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1572  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1573  && !negblocked) {
1574  tmp2 = object_new();
1575  object_copy(tmp, tmp2);
1576  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1577  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1579  } else
1580  negblocked = 1;
1581  }
1582 
1584  update_all_los(op->map, op->x, op->y);
1585 
1586  return 1;
1587 }
1588 
1605 int dimension_door(object *op, object *caster, object *spob, int dir) {
1606  uint32_t dist, maxdist;
1607  int mflags;
1608  mapstruct *m;
1609  int16_t sx, sy;
1610 
1611  if (op->type != PLAYER)
1612  return 0;
1613 
1614  if (!dir) {
1616  "In what direction?");
1617  return 0;
1618  }
1619 
1620  /* Given the new outdoor maps, can't let players dimension door for
1621  * ever, so put limits in.
1622  */
1623  maxdist = spob->range+SP_level_range_adjust(caster, spob);
1624 
1625  if (op->contr->count) {
1626  if (op->contr->count > maxdist) {
1628  "You can't dimension door that far!");
1629  return 0;
1630  }
1631 
1632  for (dist = 0; dist < op->contr->count; dist++) {
1633  mflags = get_map_flags(op->map, &m,
1634  op->x+freearr_x[dir]*(dist+1),
1635  op->y+freearr_y[dir]*(dist+1),
1636  &sx, &sy);
1637 
1638  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1639  break;
1640 
1641  if ((mflags&P_BLOCKSVIEW)
1642  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1643  break;
1644  }
1645 
1646  if (dist < op->contr->count) {
1648  "Something blocks the magic of the spell.");
1649  op->contr->count = 0;
1650  return 0;
1651  }
1652  op->contr->count = 0;
1653 
1654  /* Remove code that puts player on random space on maps. IMO,
1655  * a lot of maps probably have areas the player should not get to,
1656  * but may not be marked as NO_MAGIC (as they may be bounded
1657  * by such squares). Also, there are probably treasure rooms and
1658  * lots of other maps that protect areas with no magic, but the
1659  * areas themselves don't contain no magic spaces.
1660  */
1661  /* This call here is really just to normalize the coordinates */
1662  mflags = get_map_flags(op->map, &m, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist,
1663  &sx, &sy);
1664  if (mflags&P_IS_ALIVE || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy))) {
1666  "You cast your spell, but nothing happens.");
1667  return 1; /* Maybe the penalty should be more severe... */
1668  }
1669  } else {
1670  /* Player didn't specify a distance, so lets see how far
1671  * we can move the player. Don't know why this stopped on
1672  * spaces that blocked the players view.
1673  */
1674 
1675  for (dist = 0; dist < maxdist; dist++) {
1676  mflags = get_map_flags(op->map, &m,
1677  op->x+freearr_x[dir]*(dist+1),
1678  op->y+freearr_y[dir]*(dist+1),
1679  &sx, &sy);
1680 
1681  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1682  break;
1683 
1684  if ((mflags&P_BLOCKSVIEW)
1685  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1686  break;
1687  }
1688 
1689  /* If the destination is blocked, keep backing up until we
1690  * find a place for the player.
1691  */
1692  for (; dist > 0; dist--) {
1693  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))
1694  continue;
1695 
1696  if (!OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1697  break;
1698  }
1699  if (!dist) {
1701  "Your spell failed!");
1702  return 0;
1703  }
1704  }
1705 
1706  if (op->contr->transport && op->contr->transport->type == TRANSPORT) {
1707  ob_apply(op->contr->transport, op, 0);
1708  if (op->contr->transport) {
1710  "Your spell failed!");
1711  return 0;
1712  }
1713  }
1714 
1715  /* Actually move the player now */
1716  object_remove(op);
1717  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)
1718  return 1;
1719 
1720  if (op->type == PLAYER) {
1721  map_newmap_cmd(op->contr->socket);
1723  }
1724  op->speed_left = -FABS(op->speed)*5; /* Freeze them for a short while */
1725  return 1;
1726 }
1727 
1728 
1741 int cast_heal(object *op, object *caster, object *spell, int dir) {
1742  object *target;
1743  archetype *at;
1744  object *poison;
1745  int heal = 0, success = 0;
1746 
1747  target = find_target_for_friendly_spell(op, dir);
1748 
1749  if (target == NULL)
1750  return 0;
1751 
1752  /* Figure out how many hp this spell might cure.
1753  * could be zero if this spell heals effects, not damage.
1754  */
1755  heal = spell->stats.dam;
1756  if (spell->stats.hp)
1757  heal += random_roll(spell->stats.hp, 6, op, PREFER_HIGH)+spell->stats.hp;
1758 
1759  if (heal) {
1760  if (target->stats.hp >= target->stats.maxhp) {
1762  "You are already fully healed.");
1763  } else {
1764  /* See how many points we actually heal. Instead of messages
1765  * based on type of spell, we instead do messages based
1766  * on amount of damage healed.
1767  */
1768  if (heal > (target->stats.maxhp-target->stats.hp))
1769  heal = target->stats.maxhp-target->stats.hp;
1770  target->stats.hp += heal;
1771 
1772  if (target->stats.hp >= target->stats.maxhp) {
1774  "You feel just fine!");
1775  } else if (heal > 50) {
1777  "Your wounds close!");
1778  } else if (heal > 25) {
1780  "Your wounds mostly close.");
1781  } else if (heal > 10) {
1783  "Your wounds start to fade.");
1784  } else {
1786  "Your wounds start to close.");
1787  }
1788  success = 1;
1789  }
1790  }
1791  if (spell->attacktype&AT_DISEASE)
1792  if (cure_disease(target, op, caster && caster->type != PLAYER ? caster->skill : spell->skill))
1793  success = 1;
1794 
1795  if (spell->attacktype&AT_POISON) {
1796  at = try_find_archetype("poisoning");
1797  if (at != NULL) {
1798  poison = arch_present_in_ob(at, target);
1799  if (poison) {
1800  success = 1;
1802  "Your body feels cleansed");
1803  poison->stats.food = 1;
1804  }
1805  }
1806  }
1807  if (spell->attacktype&AT_CONFUSION) {
1808  poison = object_present_in_ob_by_name(FORCE, "confusion", target);
1809  if (poison) {
1810  success = 1;
1812  "Your mind feels clearer");
1813  poison->duration = 1;
1814  }
1815  }
1816  if (spell->attacktype&AT_BLIND) {
1817  at = try_find_archetype("blindness");
1818  if (at != NULL) {
1819  poison = arch_present_in_ob(at, target);
1820  if (poison) {
1821  success = 1;
1823  "Your vision begins to return.");
1824  poison->stats.food = 1;
1825  }
1826  }
1827  }
1828  if (spell->last_sp && target->stats.sp < target->stats.maxsp) {
1829  target->stats.sp += spell->last_sp;
1830  if (target->stats.sp > target->stats.maxsp)
1831  target->stats.sp = target->stats.maxsp;
1832  success = 1;
1834  "Magical energies surge through your body!");
1835  }
1836  if (spell->last_grace && target->stats.grace < target->stats.maxgrace) {
1837  target->stats.grace += spell->last_grace;
1838  if (target->stats.grace > target->stats.maxgrace)
1839  target->stats.grace = target->stats.maxgrace;
1840  success = 1;
1842  "You feel redeemed with you god!");
1843  }
1844  if (spell->stats.food && target->stats.food < MAX_FOOD) {
1845  target->stats.food += spell->stats.food;
1846  if (target->stats.food > MAX_FOOD)
1847  target->stats.food = MAX_FOOD;
1848  success = 1;
1849  /* We could do something a bit better like the messages for healing above */
1851  "You feel your belly fill with food");
1852  }
1853 
1854  if (spell->other_arch != NULL && target->map != NULL) {
1855  object_insert_in_map_at(arch_to_object(spell->other_arch), target->map, NULL, INS_ON_TOP, target->x, target->y);
1856  }
1857 
1858  return success;
1859 }
1860 
1861 
1867 static const char *const no_gain_msgs[NUM_STATS] = {
1868  "You grow no stronger.",
1869  "You grow no more agile.",
1870  "You don't feel any healthier.",
1871  "no wis",
1872  "You are no easier to look at.",
1873  "no int",
1874  "no pow"
1875 };
1876 
1896 int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent) {
1897  object *tmp;
1898  object *force = NULL;
1899  int i;
1900 
1901  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1902  if (dir != 0) {
1904  } else {
1905  tmp = op;
1906  }
1907 
1908  if (tmp == NULL)
1909  return 0;
1910 
1911  /* If we've already got a force of this type, don't add a new one. */
1912  FOR_INV_PREPARE(tmp, tmp2)
1913  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
1914  if (tmp2->name == spell_ob->name) {
1915  force = tmp2; /* the old effect will be "refreshed" */
1916  break;
1917  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
1918  if (!silent)
1920  "You can not cast %s while %s is in effect",
1921  spell_ob->name, tmp2->name_pl);
1922  return 0;
1923  }
1924  }
1925  FOR_INV_FINISH();
1926  if (force == NULL) {
1928  force->subtype = FORCE_CHANGE_ABILITY;
1929  free_string(force->name);
1930  if (spell_ob->race)
1931  force->name = add_refcount(spell_ob->race);
1932  else
1933  force->name = add_refcount(spell_ob->name);
1934  free_string(force->name_pl);
1935  force->name_pl = add_refcount(spell_ob->name);
1936  } else {
1937  int duration;
1938 
1939  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1940  if (duration > force->duration) {
1941  force->duration = duration;
1943  "You recast the spell while in effect.");
1944 
1945  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
1946  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
1947  }
1948 
1949  } else {
1951  "Recasting the spell had no effect.");
1952  }
1953  return 1;
1954  }
1955  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1956  if (op->type == PLAYER)
1958  force->speed = 1.0;
1959  force->speed_left = -1.0;
1961 
1962  /* Now start processing the effects. First, protections */
1963  for (i = 0; i < NROFATTACKS; i++) {
1964  if (spell_ob->resist[i]) {
1965  force->resist[i] = spell_ob->resist[i]+SP_level_dam_adjust(caster, spell_ob);
1966  if (force->resist[i] > 100)
1967  force->resist[i] = 100;
1968  }
1969  }
1970  if (spell_ob->stats.hp)
1971  force->stats.hp = spell_ob->stats.hp+SP_level_dam_adjust(caster, spell_ob);
1972 
1973  if (tmp->type == PLAYER) {
1974  /* Stat adjustment spells */
1975  for (i = 0; i < NUM_STATS; i++) {
1976  int8_t stat = get_attr_value(&spell_ob->stats, i), k, sm;
1977 
1978  if (stat) {
1979  sm = 0;
1980  for (k = 0; k < stat; k++)
1981  sm += rndm(1, 3);
1982 
1983  if ((get_attr_value(&tmp->stats, i)+sm) > (15+5*stat)) {
1984  sm = (15+5*stat)-get_attr_value(&tmp->stats, i);
1985  if (sm < 0)
1986  sm = 0;
1987  }
1988  set_attr_value(&force->stats, i, sm);
1989  if (!sm)
1991  no_gain_msgs[i]);
1992  }
1993  }
1994  }
1995 
1996  force->move_type = spell_ob->move_type;
1997 
1998  if (QUERY_FLAG(spell_ob, FLAG_SEE_IN_DARK))
2000 
2001  if (QUERY_FLAG(spell_ob, FLAG_XRAYS))
2003 
2004  /* Haste/bonus speed */
2005  if (spell_ob->stats.exp) {
2006  if (op->speed > 0.5)
2007  force->stats.exp = (float)spell_ob->stats.exp/(op->speed+0.5);
2008  else
2009  force->stats.exp = spell_ob->stats.exp;
2010  }
2011 
2012  force->stats.wc = spell_ob->stats.wc;
2013  force->stats.ac = spell_ob->stats.ac;
2014  force->attacktype = spell_ob->attacktype;
2015 
2016  SET_FLAG(tmp, FLAG_NO_FIX_PLAYER); /* we don't want object_insert_in_ob() to call fix_object. */
2019  change_abil(tmp, force); /* Display any relevant messages, and call fix_object to update the player */
2020 
2021  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2022  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2023  }
2024 
2025  return 1;
2026 }
2027 
2044 int cast_bless(object *op, object *caster, object *spell_ob, int dir) {
2045  int i;
2046  const object *god = find_god(determine_god(op));
2047  object *force = NULL, *tmp;
2048 
2049  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
2050  if (dir != 0) {
2052  } else {
2053  tmp = op;
2054  }
2055 
2056  /* If we've already got a force of this type, don't add a new one. */
2057  FOR_INV_PREPARE(tmp, tmp2)
2058  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
2059  if (tmp2->name == spell_ob->name) {
2060  force = tmp2; /* the old effect will be "refreshed" */
2061  break;
2062  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
2064  "You can not cast %s while %s is in effect",
2065  spell_ob->name, tmp2->name_pl);
2066  return 0;
2067  }
2068  }
2069  FOR_INV_FINISH();
2070  if (force == NULL) {
2072  force->subtype = FORCE_CHANGE_ABILITY;
2073  free_string(force->name);
2074  if (spell_ob->race)
2075  force->name = add_refcount(spell_ob->race);
2076  else
2077  force->name = add_refcount(spell_ob->name);
2078  free_string(force->name_pl);
2079  force->name_pl = add_refcount(spell_ob->name);
2080  } else {
2081  int duration;
2082 
2083  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2084  if (duration > force->duration) {
2085  force->duration = duration;
2087  "You recast the spell while in effect.");
2088  } else {
2090  "Recasting the spell had no effect.");
2091  }
2092  return 0;
2093  }
2094  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2095  force->speed = 1.0;
2096  force->speed_left = -1.0;
2097 
2098  if (!god) {
2100  "Your blessing seems empty.");
2101  } else {
2102  /* Only give out good benefits, and put a max on it */
2103  const int16_t resist_max = spell_ob->resist[ATNR_GODPOWER];
2104  for (i = 0; i < NROFATTACKS; i++) {
2105  if (god->resist[i] > 0) {
2106  force->resist[i] = MIN(god->resist[i], resist_max);
2107  }
2108  }
2109  // Also grant appropriate amount of godpower resistance.
2110  force->resist[ATNR_GODPOWER] = spell_ob->resist[ATNR_GODPOWER];
2111 
2112  force->path_attuned |= god->path_attuned;
2113  if (spell_ob->attacktype) {
2114  force->attacktype |= god->attacktype|AT_PHYSICAL;
2115  if (god->slaying)
2116  force->slaying = add_string(god->slaying);
2117  }
2118  if (tmp != op) {
2120  "You bless %s.",
2121  tmp->name);
2123  "%s blessed you.",
2124  op->name);
2125  } else {
2127  "You are blessed by %s!",
2128  god->name);
2129  }
2130  }
2131  force->stats.wc = spell_ob->stats.wc;
2132  force->stats.ac = spell_ob->stats.ac;
2133 
2137  change_abil(tmp, force); /* To display any messages, will call fix_object() */
2138 
2139  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2140  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2141  }
2142  return 1;
2143 }
2144 
2145 
2146 
2147 /*
2148  * Alchemy code by Mark Wedel
2149  *
2150  * This code adds a new spell, called alchemy. Alchemy will turn
2151  * objects to gold nuggets, the value of the gold nuggets being
2152  * from 5% to 40% of that of the item itself depending on casting level.
2153  * It uses the value of the object before charisma adjustments, because
2154  * the nuggets themselves will be will be adjusted by charisma when sold.
2155  *
2156  * Large nuggets are worth 25 gp each (base). You will always get
2157  * the maximum number of large nuggets you could get.
2158  * Small nuggets are worth 1 gp each (base). You will get from 0
2159  * to the max amount of small nuggets as you could get.
2160  *
2161  * For example, if an item is worth 110 gold, you will get
2162  * 4 large nuggets, and from 0-10 small nuggets.
2163  *
2164  * There is also a chance (1:30) that you will get nothing at all
2165  * for the object. There is also a maximum weight that will be
2166  * alchemied.
2167  */
2168 
2169 #define SMALL_NUGGET "smallnugget"
2170 #define LARGE_NUGGET "largenugget"
2171 
2186 static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight) {
2187  uint64_t value = price_base(obj);
2188  uint64_t small_value, large_value;
2190  /* Multiply the value of the object by value_adj, which should range
2191  * from 0.05 to 0.40. Set value to 0 instead if unpaid.
2192  */
2193  if (QUERY_FLAG(obj, FLAG_UNPAID))
2194  value = 0;
2195  else
2196  value *= value_adj;
2197 
2198  archetype *small_nugget_arch = try_find_archetype(SMALL_NUGGET);
2199  if (small_nugget_arch == NULL) {
2200  return;
2201  }
2202  small_value = price_base(&small_nugget_arch->clone);
2203  archetype *large_nugget_arch = try_find_archetype(LARGE_NUGGET);
2204  if (large_nugget_arch == NULL) {
2205  return;
2206  }
2207  large_value = price_base(&large_nugget_arch->clone);
2208 
2209  /* Give half of what value_adj says when we alchemy money (This should
2210  * hopefully make it so that it isn't worth it to alchemy money, sell
2211  * the nuggets, alchemy the gold from that, etc.
2212  */
2213  if (value && (obj->type == MONEY || obj->type == GEM))
2214  value /= 2;
2215 
2216  if ((obj->value > 0) && rndm(0, 29)) {
2217  int count;
2218 
2219  assert(large_value != 0 && small_value != 0);
2220  count = value/large_value;
2221  *large_nuggets += count;
2222  value -= (uint64_t)count*large_value;
2223  count = value/small_value;
2224  *small_nuggets += count;
2225  }
2226 
2227  /* Turn 25 small nuggets into 1 large nugget. If the value
2228  * of large nuggets is not evenly divisable by the small nugget
2229  * value, take off an extra small_nugget (Assuming small_nuggets!=0)
2230  */
2231  if (*small_nuggets*small_value >= large_value) {
2232  assert(small_value != 0);
2233  (*large_nuggets)++;
2234  *small_nuggets -= large_value/small_value;
2235  if (*small_nuggets && large_value%small_value)
2236  (*small_nuggets)--;
2237  }
2238 
2239  if (weight != NULL) {
2240  *weight += obj->weight;
2241  }
2242 
2243  object_remove(obj);
2245 }
2246 
2260 static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y) {
2261  object *tmp;
2262  int flag = 0;
2263 
2264  /* Put any nuggets below the player, but we can only pass this
2265  * flag if we are on the same space as the player
2266  */
2267  if (x == op->x && y == op->y && op->map == m)
2268  flag = INS_BELOW_ORIGINATOR;
2269 
2270  if (small_nuggets) {
2272  tmp-> nrof = small_nuggets;
2273  object_insert_in_map_at(tmp, m, op, flag, x, y);
2274  }
2275  if (large_nuggets) {
2277  tmp-> nrof = large_nuggets;
2278  object_insert_in_map_at(tmp, m, op, flag, x, y);
2279  }
2280 }
2281 
2296 int alchemy(object *op, object *caster, object *spell_ob) {
2297  int x, y, weight = 0, weight_max, large_nuggets, small_nuggets, mflags;
2298  int16_t nx, ny;
2299  float value_adj;
2300  mapstruct *mp;
2301 
2302  if (op->type != PLAYER)
2303  return 0;
2304 
2305  /* Put a maximum weight of items that can be alchemied. Limits the power
2306  * some, and also prevents people from alcheming every table/chair/clock
2307  * in sight
2308  */
2309  weight_max = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
2310  weight_max *= 1000;
2311 
2312  /* Set value_adj to be a multiplier for how much of the original value
2313  * will be in the nuggets. Starts at 0.05, increasing by 0.01 per casting
2314  * level, maxing out at 0.40.
2315  */
2316  value_adj = (SP_level_dam_adjust(caster, spell_ob)/100.00)+0.05;
2317 
2318  if (value_adj > 0.40)
2319  value_adj = 0.40;
2320 
2321  for (y = op->y-1; y <= op->y+1; y++) {
2322  for (x = op->x-1; x <= op->x+1; x++) {
2323  nx = x;
2324  ny = y;
2325 
2326  mp = op->map;
2327 
2328  mflags = get_map_flags(mp, &mp, nx, ny, &nx, &ny);
2329 
2330  if (mflags&(P_OUT_OF_MAP|P_NO_MAGIC))
2331  continue;
2332 
2333  /* Treat alchemy a little differently - most spell effects
2334  * use fly as the movement type - for alchemy, consider it
2335  * ground level effect.
2336  */
2337  if (GET_MAP_MOVE_BLOCK(mp, nx, ny)&MOVE_WALK)
2338  continue;
2339 
2340  small_nuggets = 0;
2341  large_nuggets = 0;
2342 
2343  FOR_MAP_PREPARE(mp, nx, ny, tmp) {
2344  if (tmp->weight > 0 && !QUERY_FLAG(tmp, FLAG_NO_PICK)
2345  && !QUERY_FLAG(tmp, FLAG_ALIVE)
2346  // If a multitile monster has unalive pieces, then don't zap those.
2347  && (!tmp->head || !QUERY_FLAG(tmp->head, FLAG_ALIVE))
2349  if (tmp->inv) {
2350  FOR_INV_PREPARE(tmp, tmp1)
2351  if (tmp1->weight > 0 && !QUERY_FLAG(tmp1, FLAG_NO_PICK)
2352  && !QUERY_FLAG(tmp1, FLAG_ALIVE)
2353  && !QUERY_FLAG(tmp1, FLAG_IS_CAULDRON))
2354  alchemy_object(value_adj, tmp1, &small_nuggets, &large_nuggets, &weight);
2355  FOR_INV_FINISH();
2356  }
2357  alchemy_object(value_adj, tmp, &small_nuggets, &large_nuggets, &weight);
2358 
2359  if (weight > weight_max) {
2360  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2361  return 1;
2362  }
2363  } /* is alchemable object */
2364  } FOR_MAP_FINISH(); /* process all objects on this space */
2365 
2366  /* Insert all the nuggets at one time. This probably saves time, but
2367  * it also prevents us from alcheming nuggets that were just created
2368  * with this spell.
2369  */
2370  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2371  }
2372  }
2373 
2374  /* reset this so that if player standing on a big pile of stuff,
2375  * it is redrawn properly.
2376  */
2377  op->contr->socket->look_position = 0;
2378  return 1;
2379 }
2380 
2381 
2396 int remove_curse(object *op, object *caster, object *spell) {
2397  int success = 0, was_one = 0;
2398 
2401  && ((QUERY_FLAG(tmp, FLAG_CURSED) && QUERY_FLAG(spell, FLAG_CURSED))
2402  || (QUERY_FLAG(tmp, FLAG_DAMNED) && QUERY_FLAG(spell, FLAG_DAMNED)))) {
2403  was_one++;
2404  if (tmp->level <= caster_level(caster, spell)) {
2405  success++;
2406  if (QUERY_FLAG(spell, FLAG_DAMNED))
2408 
2411  tmp->value = 0; /* Still can't sell it */
2412  if (op->type == PLAYER)
2414  }
2415  }
2416  FOR_INV_FINISH();
2417 
2418  if (op->type == PLAYER) {
2419  if (success) {
2421  "You feel like some of your items are looser now.");
2422  } else {
2423  if (was_one)
2425  "You failed to remove the curse.");
2426  else
2428  "You are not using any cursed items.");
2429  }
2430  }
2431  return success;
2432 }
2433 
2444 int cast_item_curse_or_curse(object *op, object *spell_ob) {
2445  object *marked = find_marked_object(op);
2446  char name[HUGE_BUF];
2447 
2448  if (!marked) {
2450  "You need to mark an item first!");
2451  return 0;
2452  }
2453 
2454  if ((QUERY_FLAG(marked, FLAG_CURSED) && QUERY_FLAG(spell_ob, FLAG_CURSED))
2455  || (QUERY_FLAG(marked, FLAG_BLESSED) && QUERY_FLAG(spell_ob, FLAG_BLESSED))) {
2457  "The spell has no effect");
2458  return 0;
2459  }
2460 
2462  if (QUERY_FLAG(spell_ob, FLAG_CURSED)) {
2464  "Your %s emits a dark light for a few seconds.", name);
2469  return 1;
2470  }
2471 
2473  "Your %s glows blue for a few seconds.", name);
2478  return 1;
2479 }
2480 
2495 int cast_identify(object *op, object *caster, object *spell) {
2496  int success = 0, num_ident;
2497  char desc[MAX_BUF];
2498 
2499  num_ident = spell->stats.dam+SP_level_dam_adjust(caster, spell);
2500 
2501  if (num_ident < 1)
2502  num_ident = 1;
2503 
2505  if (!tmp->invisible && !is_identified(tmp)) {
2506  tmp = identify(tmp);
2507  if (op->type == PLAYER) {
2509  "You have %s.",
2510  ob_describe(tmp, op, 1, desc, sizeof(desc)));
2511  if (tmp->msg) {
2513  "The item has a story:\n%s",
2514  tmp->msg);
2515  }
2516  }
2517  num_ident--;
2518  success = 1;
2519  if (!num_ident)
2520  break;
2521  }
2522  FOR_INV_FINISH();
2523  /* If all the power of the spell has been used up, don't go and identify
2524  * stuff on the floor. Only identify stuff on the floor if the spell
2525  * was not fully used.
2526  */
2527  if (num_ident) {
2528  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2529  if (!tmp->invisible && !is_identified(tmp)) {
2530  tmp = identify(tmp);
2531  if (op->type == PLAYER) {
2533  "On the ground is %s.",
2534  ob_describe(tmp, op, 1, desc, sizeof(desc)));
2535  if (tmp->msg) {
2537  "The item has a story:\n%s",
2538  tmp->msg);
2539  }
2541  }
2542  num_ident--;
2543  success = 1;
2544  if (!num_ident)
2545  break;
2546  }
2547  FOR_MAP_FINISH();
2548  }
2549  if (!success)
2551  "You can't reach anything unidentified.");
2552  else {
2553  spell_effect(spell, op->x, op->y, op->map, op);
2554  }
2555  return success;
2556 }
2557 
2570 int cast_detection(object *op, object *caster, object *spell) {
2571  object *tmp, *last, *detect;
2572  const object *god;
2573  int done_one, range, mflags, floor, level;
2574  int16_t x, y, nx, ny;
2575  mapstruct *m;
2576 
2577  /* We precompute some values here so that we don't have to keep
2578  * doing it over and over again.
2579  */
2580  god = find_god(determine_god(op));
2581  level = caster_level(caster, spell);
2582  range = spell->range+SP_level_range_adjust(caster, spell);
2583 
2584  for (x = op->x-range; x <= op->x+range; x++)
2585  for (y = op->y-range; y <= op->y+range; y++) {
2586  m = op->map;
2587  mflags = get_map_flags(m, &m, x, y, &nx, &ny);
2588  if (mflags&P_OUT_OF_MAP)
2589  continue;
2590 
2591  /* For most of the detections, we only detect objects above the
2592  * floor. But this is not true for show invisible.
2593  * Basically, we just go and find the top object and work
2594  * down - that is easier than working up.
2595  */
2596 
2597  last = NULL;
2598  FOR_MAP_PREPARE(m, nx, ny, tmp)
2599  last = tmp;
2600  FOR_MAP_FINISH();
2601  /* Shouldn't happen, but if there are no objects on a space, this
2602  * would happen.
2603  */
2604  if (!last)
2605  continue;
2606 
2607  done_one = 0;
2608  floor = 0;
2609  detect = NULL;
2610  tmp = last;
2612  /* show invisible */
2613  if (QUERY_FLAG(spell, FLAG_MAKE_INVIS)
2614  /* Might there be other objects that we can make visibile? */
2615  && (tmp->invisible && (QUERY_FLAG(tmp, FLAG_MONSTER) ||
2616  (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)) ||
2617  tmp->type == CF_HANDLE ||
2618  tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
2619  tmp->type == BUTTON || tmp->type == TELEPORTER ||
2620  tmp->type == GATE || tmp->type == LOCKED_DOOR ||
2621  tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
2622  tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
2623  tmp->type == TREASURE || tmp->type == BOOK ||
2624  tmp->type == HOLY_ALTAR))) {
2625  if (random_roll(0, level-1, op, PREFER_HIGH) > tmp->level) {
2626  tmp->invisible = 0;
2627  done_one = 1;
2628  }
2629  }
2631  floor = 1;
2632 
2633  /* All detections below this point don't descend beneath the floor,
2634  * so just continue on. We could be clever and look at the type of
2635  * detection to completely break out if we don't care about objects beneath
2636  * the floor, but once we get to the floor, not likely a very big issue anyways.
2637  */
2638  if (floor)
2639  continue;
2640 
2641  /* I had thought about making detect magic and detect curse
2642  * show the flash the magic item like it does for detect monster.
2643  * however, if the object is within sight, this would then make it
2644  * difficult to see what object is magical/cursed, so the
2645  * effect wouldn't be as apparent.
2646  */
2647 
2648  /* detect magic */
2649  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2651  && is_magical(tmp)) {
2653  /* make runes more visible */
2654  if (tmp->type == RUNE && tmp->attacktype&AT_MAGIC)
2655  tmp->stats.Cha /= 4;
2656  done_one = 1;
2657  }
2658  /* detect monster */
2659  if (QUERY_FLAG(spell, FLAG_MONSTER)
2660  && (QUERY_FLAG(tmp, FLAG_MONSTER) || (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)))) {
2661  done_one = 2;
2662  if (!detect)
2663  detect = tmp;
2664  }
2665  /* Basically, if race is set in the spell, then the creatures race must
2666  * match that. if the spell race is set to GOD, then the gods opposing
2667  * race must match.
2668  */
2669  if (spell->race
2671  && tmp->race
2672  && ((!strcmp(spell->race, "GOD") && god && god->slaying && strstr(god->slaying, tmp->race)) || (strstr(spell->race, tmp->race)))) {
2673  done_one = 2;
2674  if (!detect)
2675  detect = tmp;
2676  }
2677  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2681  done_one = 1;
2682  }
2683  } FOR_OB_AND_BELOW_FINISH(); /* for stack of objects on this space */
2684 
2685  /* Code here puts an effect of the spell on the space, so you can see
2686  * where the magic is.
2687  */
2688  if (done_one) {
2689  object *detect_ob;
2690  int dx = nx, dy = ny;
2691 
2692  /* if this is set, we want to copy the face */
2693  if (done_one == 2 && detect) {
2694  /*
2695  * We can't simply copy the face to a single item, because
2696  * multipart objects need to have multipart glows.
2697  * So copy the initial item, erase some properties, and use that.
2698  */
2699 
2700  object *part;
2701  int flag;
2702 
2703  dx = HEAD(detect)->x;
2704  dy = HEAD(detect)->y;
2705 
2706  detect_ob = object_create_arch(HEAD(detect)->arch);
2707  for (part = detect_ob; part != NULL; part = part->more) {
2708  if (part->arch->reference_count > 0)
2709  part->arch->reference_count++;
2710  part->last_anim = 0;
2711  part->type = spell->other_arch->clone.type;
2712  for (flag = 0; flag < 4; flag++) {
2713  part->flags[flag] = spell->other_arch->clone.flags[flag];
2714  }
2715  part->stats.food = spell->other_arch->clone.stats.food;
2716  part->last_anim = 0;
2717  part->speed = spell->other_arch->clone.speed;
2718  part->speed_left = spell->other_arch->clone.speed_left;
2719  part->move_allow = spell->other_arch->clone.move_allow;
2720  part->move_block = spell->other_arch->clone.move_block;
2721  part->move_type = spell->other_arch->clone.move_type;
2722  part->glow_radius = spell->other_arch->clone.glow_radius;
2723  part->invisible = spell->other_arch->clone.invisible;
2724  part->weight = spell->other_arch->clone.weight;
2725  part->map_layer = spell->other_arch->clone.map_layer;
2726  FREE_AND_COPY(part->name, spell->other_arch->clone.name);
2727 
2728  /* by default, the detect_ob is already animated */
2729  if (!QUERY_FLAG(detect, FLAG_ANIMATE))
2730  CLEAR_FLAG(part, FLAG_ANIMATE);
2731  }
2732  object_update_speed(detect_ob);
2733  } else
2734  detect_ob = arch_to_object(spell->other_arch);
2735 
2736  object_insert_in_map_at(detect_ob, m, op, 0, dx, dy);
2737  }
2738  } /* for processing the surrounding spaces */
2739 
2740 
2741  /* Now process objects in the players inventory if detect curse or magic */
2742  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED) || QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)) {
2743  done_one = 0;
2744  FOR_INV_PREPARE(op, tmp) {
2745  if (!tmp->invisible) {
2746  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2747  && is_magical(tmp)
2750  if (op->type == PLAYER)
2751  esrv_send_item(op, tmp);
2752  }
2753  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2757  if (op->type == PLAYER)
2758  esrv_send_item(op, tmp);
2759  }
2760  } /* if item is not identified */
2761  } FOR_INV_FINISH(); /* for the players inventory */
2762  } /* if detect magic/curse and object is a player */
2763  return 1;
2764 }
2765 
2773 static void charge_mana_effect(object *victim, int caster_level) {
2774  /* Prevent explosions for objects without mana. Without this check, doors
2775  * will explode, too.
2776  */
2777  if (victim->stats.maxsp <= 0)
2778  return;
2779 
2781  "You feel energy course through you.");
2782 
2783  if (victim->stats.sp >= victim->stats.maxsp*2) {
2784  object *tmp;
2785 
2787  "Your head explodes!");
2788 
2789  /* Explodes a fireball centered at player */
2791  tmp->dam_modifier = random_roll(1, caster_level, victim, PREFER_LOW)/5+1;
2792  tmp->stats.maxhp = random_roll(1, caster_level, victim, PREFER_LOW)/10+2;
2793  object_insert_in_map_at(tmp, victim->map, NULL, 0, victim->x, victim->y);
2794  victim->stats.sp = 2*victim->stats.maxsp;
2795  } else if (victim->stats.sp >= victim->stats.maxsp*1.88) {
2797  "You feel like your head is going to explode.");
2798  } else if (victim->stats.sp >= victim->stats.maxsp*1.66) {
2800  "You get a splitting headache!");
2801  } else if (victim->stats.sp >= victim->stats.maxsp*1.5) {
2803  "Chaos fills your world.");
2805  } else if (victim->stats.sp >= victim->stats.maxsp*1.25) {
2807  "You start hearing voices.");
2808  }
2809 }
2810 
2828 int cast_transfer(object *op, object *caster, object *spell, int dir) {
2829  object *plyr = NULL;
2830  int16_t x, y;
2831  mapstruct *m;
2832  int mflags;
2833 
2834  m = op->map;
2835  x = op->x+freearr_x[dir];
2836  y = op->y+freearr_y[dir];
2837 
2838  mflags = get_map_flags(m, &m, x, y, &x, &y);
2839  if (!(mflags&P_OUT_OF_MAP) && mflags&P_IS_ALIVE) {
2840  FOR_MAP_PREPARE(m, x, y, tmp)
2841  plyr = tmp;
2842  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2843  break;
2844  FOR_MAP_FINISH();
2845  }
2846 
2847  /* If we did not find a player in the specified direction, transfer
2848  * to anyone on top of us. This is used for the rune of transference mostly.
2849  */
2850  if (plyr == NULL)
2851  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2852  plyr = tmp;
2853  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2854  break;
2855  FOR_MAP_FINISH();
2856 
2857  if (!plyr) {
2859  "There is no one there.");
2860  return 0;
2861  }
2862 
2863  /* give sp */
2864  if (spell->stats.dam > 0) {
2865  plyr->stats.sp += spell->stats.dam+SP_level_dam_adjust(caster, spell);
2866  charge_mana_effect(plyr, caster_level(caster, spell));
2867  return 1;
2868  /* suck sp away. Can't suck sp from yourself */
2869  } else if (op != plyr) {
2870  /* old dragin magic used floats. easier to just use ints and divide by 100 */
2871 
2872  int rate = -spell->stats.dam+SP_level_dam_adjust(caster, spell), sucked;
2873 
2874  if (rate > 95)
2875  rate = 95;
2876 
2877  sucked = (plyr->stats.sp*rate)/100;
2878  plyr->stats.sp -= sucked;
2879  if (QUERY_FLAG(op, FLAG_ALIVE)) {
2880  /* Player doesn't get full credit */
2881  sucked = (sucked*rate)/100;
2882  op->stats.sp += sucked;
2883  if (sucked > 0) {
2884  charge_mana_effect(op, caster_level(caster, spell));
2885  }
2886  }
2887  return 1;
2888  }
2889  return 0;
2890 }
2891 
2901 void counterspell(object *op, int dir) {
2902  object *head;
2903  int mflags;
2904  mapstruct *m;
2905  int16_t sx, sy;
2906 
2907  sx = op->x+freearr_x[dir];
2908  sy = op->y+freearr_y[dir];
2909  m = op->map;
2910  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2911  if (mflags&P_OUT_OF_MAP)
2912  return;
2913 
2914  FOR_MAP_PREPARE(m, sx, sy, tmp) {
2915  object *owner;
2916 
2917  /* Need to look at the head object - otherwise, if tmp
2918  * points to a monster, we don't have all the necessary
2919  * info for it.
2920  */
2921  head = HEAD(tmp);
2922 
2923  /* don't attack our own spells */
2924  owner = object_get_owner(tmp);
2925  if (owner != NULL && owner == object_get_owner(op))
2926  continue;
2927 
2928  /* Basically, if the object is magical and not counterspell,
2929  * we will more or less remove the object. Don't counterspell
2930  * monsters either.
2931  */
2932 
2933  if (head->attacktype&AT_MAGIC
2934  && !(head->attacktype&AT_COUNTERSPELL)
2935  && !QUERY_FLAG(head, FLAG_MONSTER)
2936  && (op->level > head->level)) {
2937  object_remove(head);
2938  object_free(head, 0);
2939  } else switch (head->type) {
2940  case SPELL_EFFECT:
2941  if ((op->level > head->level) && !op->stats.food && !op->speed_left) {
2942  object_remove(head);
2943  object_free(head, 0);
2944  }
2945  break;
2946 
2947  /* I really don't get this rune code that much - that
2948  * random chance seems really low.
2949  */
2950  case RUNE:
2951  if (rndm(0, 149) == 0) {
2952  head->stats.hp--; /* weaken the rune */
2953  if (!head->stats.hp) {
2954  object_remove(head);
2955  object_free(head, 0);
2956  }
2957  }
2958  break;
2959  }
2960  } FOR_MAP_FINISH();
2961 }
2962 
2977 int cast_consecrate(object *op, object *caster, object *spell) {
2978  char buf[MAX_BUF];
2979  const object *god = find_god(determine_god(op));
2980 
2981  if (!god) {
2983  "You can't consecrate anything if you don't worship a god!");
2984  return 0;
2985  }
2986 
2989  break;
2990  if (tmp->type == HOLY_ALTAR) {
2991  if (tmp->level > caster_level(caster, spell)) {
2993  "You are not powerful enough to reconsecrate the %s",
2994  tmp->name);
2995  return 0;
2996  } else {
2997  /* If we got here, we are consecrating an altar */
2998  object *new_altar;
2999  size_t letter;
3000  archetype *altar_arch;
3001 
3002  snprintf(buf, MAX_BUF, "altar_");
3003  letter = strlen(buf);
3004  strncpy(buf+letter, god->name, MAX_BUF-letter);
3005  for (; letter < strlen(buf); letter++)
3006  buf[letter] = tolower(buf[letter]);
3007  altar_arch = try_find_archetype(buf);
3008  if (!altar_arch) {
3010  "You fail to consecrate the altar.");
3011  LOG(llevError, "cast_consecrate: can't find altar %s for god %s\n", buf, god->name);
3012  return 0;
3013  }
3014  new_altar = arch_to_object(altar_arch);
3015  new_altar->level = tmp->level;
3017  SET_FLAG(new_altar, FLAG_IS_BUILDABLE);
3018  object_insert_in_map_at(new_altar, tmp->map, tmp, INS_BELOW_ORIGINATOR, tmp->x, tmp->y);
3019  object_remove(tmp);
3021  "You consecrated the altar to %s!",
3022  god->name);
3023  return 1;
3024  }
3025  }
3026  } FOR_BELOW_FINISH();
3028  "You are not standing over an altar!");
3029  return 0;
3030 }
3031 
3055 int animate_weapon(object *op, object *caster, object *spell, int dir) {
3056  object *weapon, *tmp;
3057  char buf[MAX_BUF];
3058  int a, i;
3059  int16_t x, y;
3060  mapstruct *m;
3061  materialtype_t *mt;
3062 
3063  if (!spell->other_arch) {
3065  "Oops, program error!");
3066  LOG(llevError, "animate_weapon failed: spell %s missing other_arch!\n", spell->name);
3067  return 0;
3068  }
3069 
3070  /* exit if it's not a player using this spell. */
3071  if (op->type != PLAYER)
3072  return 0;
3073 
3074  /* if player already has a golem, abort */
3075  if (op->contr->ranges[range_golem] != NULL && op->contr->golem_count == op->contr->ranges[range_golem]->count) {
3076  pets_control_golem(op->contr->ranges[range_golem], dir);
3077  return 0;
3078  }
3079 
3080  /* if no direction specified, pick one */
3081  if (!dir) {
3082  dir = object_find_free_spot(NULL, op->map, op->x, op->y, 1, 9);
3083  if ( dir == -1 ) {
3085  "There is something in the way.");
3086  return 0;
3087  }
3088  }
3089 
3090  m = op->map;
3091  x = op->x+freearr_x[dir];
3092  y = op->y+freearr_y[dir];
3093 
3094  /* if there's no place to put the golem, abort */
3095  if ((dir == -1)
3096  || (get_map_flags(m, &m, x, y, &x, &y)&P_OUT_OF_MAP)
3097  || ((spell->other_arch->clone.move_type&GET_MAP_MOVE_BLOCK(m, x, y)) == spell->other_arch->clone.move_type)) {
3099  "There is something in the way.");
3100  return 0;
3101  }
3102 
3103  /* Use the weapon marked by the player. */
3104  weapon = find_marked_object(op);
3105 
3106  if (!weapon) {
3108  "You must mark a weapon to use with this spell!");
3109  return 0;
3110  }
3111  if (spell->race && strcmp(weapon->arch->name, spell->race)) {
3113  "The spell fails to transform your weapon.");
3114  return 0;
3115  }
3116  if (weapon->type != WEAPON) {
3118  "You need to mark a weapon to animate it.");
3119  return 0;
3120  }
3121  if (QUERY_FLAG(weapon, FLAG_UNPAID)) {
3123  "You need to pay for the weapon to animate it.");
3124  return 0;
3125  }
3126  if (QUERY_FLAG(weapon, FLAG_APPLIED)) {
3127  char wn[MAX_BUF];
3128 
3129  query_name(weapon, wn, MAX_BUF);
3131  "You need to unequip %s before using it in this spell",
3132  wn);
3133  return 0;
3134  }
3135 
3136  if (weapon->nrof > 1) {
3137  tmp = object_split(weapon, 1, NULL, 0);
3138  esrv_update_item(UPD_NROF, op, weapon);
3139  weapon = tmp;
3140  }
3141 
3142  /* create the golem object */
3143  tmp = arch_to_object(spell->other_arch);
3144 
3145  /* if animated by a player, give the player control of the golem */
3148  tmp->stats.exp = 0;
3150  tmp->type = GOLEM;
3152  set_spell_skill(op, caster, spell, tmp);
3153  op->contr->ranges[range_golem] = tmp;
3154  op->contr->shoottype = range_golem;
3155  op->contr->golem_count = tmp->count;
3156 
3157  /* Give the weapon to the golem now. A bit of a hack to check the
3158  * removed flag - it should only be set if object_split() was
3159  * used above.
3160  */
3161  if (!QUERY_FLAG(weapon, FLAG_REMOVED))
3162  object_remove(weapon);
3163  object_insert_in_ob(weapon, tmp);
3164 
3165  /* To do everything necessary to let a golem use the weapon is a pain,
3166  * so instead, just set it as equipped (otherwise, we need to update
3167  * body_info, skills, etc)
3168  */
3170  SET_FLAG(weapon, FLAG_APPLIED);
3171  fix_object(tmp);
3172 
3173  /* There used to be 'odd' code that basically seemed to take the absolute
3174  * value of the weapon->magic an use that. IMO, that doesn't make sense -
3175  * if you're using a crappy weapon, it shouldn't be as good.
3176  */
3177 
3178  /* modify weapon's animated wc */
3179  tmp->stats.wc = tmp->stats.wc
3180  -SP_level_range_adjust(caster, spell)
3181  -5*weapon->stats.Dex
3182  -2*weapon->stats.Str
3183  -weapon->magic;
3184  if (tmp->stats.wc < -127)
3185  tmp->stats.wc = -127;
3186 
3187  /* Modify hit points for weapon */
3188  tmp->stats.maxhp = tmp->stats.maxhp
3189  +spell->duration
3190  +SP_level_duration_adjust(caster, spell)
3191  +8*weapon->magic
3192  +12*weapon->stats.Con;
3193  if (tmp->stats.maxhp < 0)
3194  tmp->stats.maxhp = 10;
3195  tmp->stats.hp = tmp->stats.maxhp;
3196 
3197  /* Modify weapon's damage */
3198  tmp->stats.dam = spell->stats.dam
3199  +SP_level_dam_adjust(caster, spell)
3200  +weapon->stats.dam
3201  +weapon->magic
3202  +5*weapon->stats.Str;
3203  if (tmp->stats.dam < 0)
3204  tmp->stats.dam = 127;
3205 
3206  /* attacktype */
3207  if (!tmp->attacktype)
3208  tmp->attacktype = AT_PHYSICAL;
3209 
3210  mt = NULL;
3211  if (op->materialname != NULL)
3212  mt = name_to_material(op->materialname);
3213  if (mt != NULL) {
3214  for (i = 0; i < NROFATTACKS; i++)
3215  tmp->resist[i] = 50-(mt->save[i]*5);
3216  a = mt->save[0];
3217  } else {
3218  for (i = 0; i < NROFATTACKS; i++)
3219  tmp->resist[i] = 5;
3220  a = 10;
3221  }
3222  /* Set weapon's immunity */
3223  tmp->resist[ATNR_CONFUSION] = 100;
3224  tmp->resist[ATNR_POISON] = 100;
3225  tmp->resist[ATNR_SLOW] = 100;
3226  tmp->resist[ATNR_PARALYZE] = 100;
3227  tmp->resist[ATNR_TURN_UNDEAD] = 100;
3228  tmp->resist[ATNR_FEAR] = 100;
3229  tmp->resist[ATNR_DEPLETE] = 100;
3230  tmp->resist[ATNR_DEATH] = 100;
3231  tmp->resist[ATNR_BLIND] = 100;
3232 
3233  /* Improve weapon's armour value according to best save vs. physical of its material */
3234 
3235  if (a > 14)
3236  a = 14;
3237  tmp->resist[ATNR_PHYSICAL] = 100-(int)((100.0-(float)tmp->resist[ATNR_PHYSICAL])/(30.0-2.0*a));
3238 
3239  /* Determine golem's speed */
3240  tmp->speed = 0.4+0.1*SP_level_range_adjust(caster, spell);
3241 
3242  if (tmp->speed > 3.33)
3243  tmp->speed = 3.33;
3244 
3245  if (!spell->race) {
3246  snprintf(buf, sizeof(buf), "animated %s", weapon->name);
3247  if (tmp->name)
3248  free_string(tmp->name);
3249  tmp->name = add_string(buf);
3250 
3251  tmp->face = weapon->face;
3252  tmp->animation = weapon->animation;
3253  tmp->anim_speed = weapon->anim_speed;
3254  tmp->last_anim = weapon->last_anim;
3255  tmp->state = weapon->state;
3256  if (QUERY_FLAG(weapon, FLAG_ANIMATE)) {
3258  } else {
3260  }
3262  }
3263 
3264  /* make experience increase in proportion to the strength of the summoned creature. */
3265  tmp->stats.exp *= 1+(MAX(spell->stats.maxgrace, spell->stats.sp)/caster_level(caster, spell));
3266 
3267  tmp->speed_left = -1;
3268  tmp->direction = dir;
3269  object_insert_in_map_at(tmp, m, op, 0, x, y);
3270  return 1;
3271 }
3272 
3285 int cast_change_map_lightlevel(object *op, object *spell) {
3286  int success;
3287 
3288  if (!op->map)
3289  return 0; /* shouldnt happen */
3290 
3291  success = change_map_light(op->map, spell->stats.dam);
3292  if (!success) {
3293  if (spell->stats.dam < 0)
3295  "It can be no brighter here.");
3296  else
3298  "It can be no darker here.");
3299  }
3300  return success;
3301 }
3302 
3317 int create_aura(object *op, object *caster, object *spell) {
3318  int refresh = 0, i;
3319  object *new_aura;
3320 
3321  new_aura = arch_present_in_ob(spell->other_arch, op);
3322  if (new_aura)
3323  refresh = 1;
3324  else
3325  new_aura = arch_to_object(spell->other_arch);
3326 
3327  new_aura->duration = spell->duration+10*SP_level_duration_adjust(caster, spell);
3328  if (op->type == PLAYER)
3329  store_spell_expiry(new_aura);
3330 
3331  new_aura->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
3332 
3333  // If the range is zero, it's not an aura. Plain and simple. Minimum is one.
3334  // Also provides backward compatability on existing auras to be range 1
3335  new_aura->range = MAX(1, spell->range+SP_level_range_adjust(caster, spell));
3336 
3337  object_set_owner(new_aura, op);
3338  set_spell_skill(op, caster, spell, new_aura);
3339  new_aura->attacktype = spell->attacktype;
3340 
3341  new_aura->level = caster_level(caster, spell);
3342 
3343  /* Code below is so that auras can also provide resistances. For
3344  * example, fire shield both does damage to nearby enemies and also
3345  * provides some protection to fire. We need to use a different
3346  * FORCE object for this, as putting it in with the aura object
3347  * just puts too many meanings into that one object. Because
3348  * the duration of this force object is the same, we don't need
3349  * to set up spell expiry on it - this second object is really
3350  * an internal mechanic that should be invisible to the player.
3351  */
3352  for (i = 0; i < NROFATTACKS; i++) {
3353  if (spell->resist[i]) {
3354  int refresh1=1;
3355  object *force;
3356 
3358  if (!force) {
3360  force->subtype = FORCE_CHANGE_ABILITY;
3361  free_string(force->name);
3362  force->name = add_refcount(spell->name);
3363  free_string(force->name_pl);
3364  force->name_pl = add_refcount(spell->name);
3365  refresh1=0;
3366  }
3367  force->duration = new_aura->duration;
3368  force->speed = new_aura->speed;
3369  memcpy(&force->resist, spell->resist, sizeof(spell->resist));
3371 
3372  if (!refresh1)
3374  change_abil(op, new_aura);
3375  fix_object(op);
3376  break;
3377  }
3378  }
3379 
3380  if (refresh)
3382  "You recast the spell while in effect.");
3383  else
3384  object_insert_in_ob(new_aura, op);
3385  return 1;
3386 }
3387 
3403 int write_mark(object *op, object *spell, const char *msg) {
3404  char rune[HUGE_BUF];
3405  object *tmp;
3406 
3407  if (!msg || msg[0] == 0) {
3409  "Write what?");
3410  return 0;
3411  }
3412 
3413  if (strcasestr_local(msg, "endmsg")) {
3415  "Trying to cheat are we?");
3416  LOG(llevInfo, "write_rune: player %s tried to write bogus rune %s\n", op->name, msg);
3417  return 0;
3418  }
3419 
3420  if (!spell->other_arch)
3421  return 0;
3422  tmp = arch_to_object(spell->other_arch);
3423  strncpy(rune, msg, HUGE_BUF-2);
3424  rune[HUGE_BUF-2] = 0;
3425  strcat(rune, "\n");
3426  tmp->race = add_string(op->name); /*Save the owner of the rune*/
3427  object_set_msg(tmp, rune);
3429  return 1;
3430 }
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:68
MSG_TYPE_SPELL_PERCEIVE_SELF
#define MSG_TYPE_SPELL_PERCEIVE_SELF
Definition: newclient.h:637
object::name_pl
sstring name_pl
Definition: object.h:321
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Definition: map.h:173
FORCE_CHANGE_ABILITY
#define FORCE_CHANGE_ABILITY
Definition: spells.h:145
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:522
write_mark
int write_mark(object *op, object *spell, const char *msg)
Definition: spell_effect.cpp:3403
PLAYER
@ PLAYER
Definition: object.h:110
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:2170
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:534
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Definition: object.cpp:4294
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:211
SOUND_TYPE_ITEM
#define SOUND_TYPE_ITEM
Definition: newclient.h:335
INS_NO_WALK_ON
#define INS_NO_WALK_ON
Definition: object.h:571
place_alchemy_objects
static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y)
Definition: spell_effect.cpp:2260
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:1896
remove_curse
int remove_curse(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:2396
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:4076
AT_POISON
#define AT_POISON
Definition: attack.h:86
object::weapontype
uint32_t weapontype
Definition: object.h:379
AT_MAGIC
#define AT_MAGIC
Definition: attack.h:77
CAN_PROBE
static bool CAN_PROBE(const object *ob)
Definition: object.h:605
object::map_layer
uint8_t map_layer
Definition: object.h:430
BOW
@ BOW
Definition: object.h:121
llevError
@ llevError
Definition: logger.h:11
FABS
#define FABS(x)
Definition: define.h:22
object::path_attuned
uint32_t path_attuned
Definition: object.h:351
WAND
@ WAND
Definition: object.h:223
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
strcasestr_local
#define strcasestr_local
Definition: compat.h:28
FLAG_UNDEAD
#define FLAG_UNDEAD
Definition: define.h:270
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
find_archetype_by_object_type_name
archetype * find_archetype_by_object_type_name(int type, const char *name)
Definition: arch.cpp:66
FLAG_GENERATOR
#define FLAG_GENERATOR
Definition: define.h:248
object::inv
object * inv
Definition: object.h:296
altar_valkyrie.obj
obj
Definition: altar_valkyrie.py:33
BUTTON
@ BUTTON
Definition: object.h:210
diamondslots.x
x
Definition: diamondslots.py:15
perceive_self
int perceive_self(object *op)
Definition: spell_effect.cpp:998
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.cpp:1793
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:752
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:137
magic_wall
int magic_wall(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.cpp:1452
cast_change_map_lightlevel
int cast_change_map_lightlevel(object *op, object *spell)
Definition: spell_effect.cpp:3285
ARCH_DEPLETION
#define ARCH_DEPLETION
Definition: object.h:579
cast_item_curse_or_curse
int cast_item_curse_or_curse(object *op, object *spell_ob)
Definition: spell_effect.cpp:2444
map_find_by_archetype
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
Definition: object.cpp:3111
confuse_living
void confuse_living(object *op, object *hitter, int dam)
Definition: attack.cpp:2270
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:420
cast_spell
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Definition: spell_util.cpp:1421
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:399
cast_wonder
int cast_wonder(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.cpp:964
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Definition: define.h:704
object::range
int8_t range
Definition: object.h:413
object::speed
float speed
Definition: object.h:335
GEM
@ GEM
Definition: object.h:170
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:368
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:333
object::speed_left
float speed_left
Definition: object.h:336
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:303
WEAPON
@ WEAPON
Definition: object.h:122
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.cpp:3592
arch_present_in_ob
object * arch_present_in_ob(const archetype *at, const object *op)
Definition: object.cpp:3215
object_set_owner
void object_set_owner(object *op, object *owner)
Definition: object.cpp:840
SMALL_NUGGET
#define SMALL_NUGGET
Definition: spell_effect.cpp:2169
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:898
MIN
#define MIN(x, y)
Definition: compat.h:21
cast_consecrate
int cast_consecrate(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:2977
ATNR_GODPOWER
#define ATNR_GODPOWER
Definition: attack.h:69
TREASURE
@ TREASURE
Definition: object.h:113
MSG_TYPE_VICTIM_SPELL
#define MSG_TYPE_VICTIM_SPELL
Definition: newclient.h:654
SP_level_duration_adjust
int SP_level_duration_adjust(const object *caster, const object *spob)
Definition: spell_util.cpp: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:1605
object::count
tag_t count
Definition: object.h:305
FLAG_WIZCAST
#define FLAG_WIZCAST
Definition: define.h:289
object::last_grace
int16_t last_grace
Definition: object.h:367
RUNE
@ RUNE
Definition: object.h:243
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:97
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:244
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:228
TRANSPORT
@ TRANSPORT
Definition: object.h:111
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
UPD_NROF
#define UPD_NROF
Definition: newclient.h:321
SIGN
@ SIGN
Definition: object.h:214
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
food_choice
static archetype * food_choice
Definition: spell_effect.cpp: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:1867
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:258
P_IS_ALIVE
#define P_IS_ALIVE
Definition: map.h:238
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
object::level
int16_t level
Definition: object.h:359
probe
int probe(object *op, object *caster, object *spell_ob, int dir, int level)
Definition: spell_effect.cpp:695
buf
StringBuffer * buf
Definition: readable.cpp:1551
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:2851
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
MSG_TYPE_VICTIM
#define MSG_TYPE_VICTIM
Definition: newclient.h:415
MAX
#define MAX(x, y)
Definition: compat.h:24
object::resist
int16_t resist[NROFATTACKS]
Definition: object.h:349
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
MSG_TYPE_SPELL_TARGET
#define MSG_TYPE_SPELL_TARGET
Definition: newclient.h:638
ATNR_CONFUSION
#define ATNR_CONFUSION
Definition: attack.h:54
MSG_TYPE_SPELL_HEAL
#define MSG_TYPE_SPELL_HEAL
Definition: newclient.h:631
find_god
const object * find_god(const char *name)
Definition: holy.cpp:317
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:246
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:635
FOR_OB_AND_ABOVE_PREPARE
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Definition: define.h:739
store_spell_expiry
void store_spell_expiry(object *spell)
Definition: spell_util.cpp:1978
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:333
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:799
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:2773
disinfect.map
map
Definition: disinfect.py:4
object::subtype
uint8_t subtype
Definition: object.h:347
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:425
object_present_in_ob_by_name
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.cpp:3196
alchemy_object
static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight)
Definition: spell_effect.cpp:2186
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:585
cast_word_of_recall
int cast_word_of_recall(object *op, object *caster, object *spell_ob)
Definition: spell_effect.cpp:902
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:476
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:596
change_map_light
int change_map_light(mapstruct *m, int change)
Definition: map.cpp:2017
object::move_type
MoveType move_type
Definition: object.h:432
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.cpp:510
set_attr_value
void set_attr_value(living *stats, int attr, int8_t value)
Definition: living.cpp:218
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:126
MSG_TYPE_ITEM
#define MSG_TYPE_ITEM
Definition: newclient.h:412
object::face
const Face * face
Definition: object.h:339
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:358
is_identified
int is_identified(const object *op)
Definition: item.cpp:1336
ob_describe
char * ob_describe(const object *op, const object *observer, int use_media_tags, char *buf, size_t size)
Definition: ob_methods.cpp:91
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:127
HOLE
@ HOLE
Definition: object.h:212
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1349
object::last_anim
uint8_t last_anim
Definition: object.h:426
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Definition: global.h:208
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:3055
object::type
uint8_t type
Definition: object.h:346
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:569
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:356
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:315
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:193
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:573
living::food
int32_t food
Definition: living.h:48
GOLEM
@ GOLEM
Definition: object.h:148
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:2570
cast_create_town_portal
int cast_create_town_portal(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:1237
tag_t
uint32_t tag_t
Definition: object.h:12
archetype
Definition: object.h:472
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:411
BOOK
@ BOOK
Definition: object.h:117
GT_ENVIRONMENT
@ GT_ENVIRONMENT
Definition: treasure.h:31
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.cpp:42
object::race
sstring race
Definition: object.h:324
object::animation
const Animations * animation
Definition: object.h:424
RING
@ RING
Definition: object.h:188
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:242
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.cpp:2098
object::other_arch
struct archetype * other_arch
Definition: object.h:421
mapstruct::last_reset_time
long last_reset_time
Definition: map.h:358
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:250
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:572
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:941
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
object::weight
int32_t weight
Definition: object.h:373
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
monster_check_apply_all
void monster_check_apply_all(object *monster)
Definition: monster.cpp:1997
cast_magic_storm
void cast_magic_storm(object *op, object *tmp, int lvl)
Definition: spell_effect.cpp: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:202
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:2828
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
EXIT
@ EXIT
Definition: object.h:184
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:262
object::slaying
sstring slaying
Definition: object.h:325
object::glow_radius
int8_t glow_radius
Definition: object.h:372
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:1106
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
spells.h
object::name
sstring name
Definition: object.h:317
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:633
is_dragon_pl
int is_dragon_pl(const object *op)
Definition: player.cpp:122
add_friendly_object
void add_friendly_object(object *op)
Definition: friend.cpp: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:301
ARCH_PORTAL_FAILED
#define ARCH_PORTAL_FAILED
Definition: object.h:581
FLAG_IS_BUILDABLE
#define FLAG_IS_BUILDABLE
Definition: define.h:367
reputation.victim
victim
Definition: reputation.py:14
living::maxsp
int16_t maxsp
Definition: living.h:43
is_magical
int is_magical(const object *op)
Definition: item.cpp:1215
mapstruct
Definition: map.h:316
object::last_sp
int32_t last_sp
Definition: object.h:366
counterspell
void counterspell(object *op, int dir)
Definition: spell_effect.cpp:2901
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:1741
object::skill
sstring skill
Definition: object.h:327
MSG_TYPE_SPELL_ERROR
#define MSG_TYPE_SPELL_ERROR
Definition: newclient.h:636
shop.h
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.cpp:2631
cast_bless
int cast_bless(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_effect.cpp:2044
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:3552
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:4804
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.cpp:359
did_make_save
int did_make_save(const object *op, int level, int bonus)
Definition: living.cpp:2280
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:218
cast_create_missile
int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg)
Definition: spell_effect.cpp:493
archetype::reference_count
int reference_count
Definition: object.h:479
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:1864
EXIT_Y
#define EXIT_Y(xyz)
Definition: define.h:442
diamondslots.y
y
Definition: diamondslots.py:16
assets.h
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
ob_apply
method_ret ob_apply(object *op, object *applier, int aflags)
Definition: ob_methods.cpp:44
town_portal_destroy_existing
static int town_portal_destroy_existing(object *op, object *spell)
Definition: spell_effect.cpp:1145
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:411
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:4270
map_newmap_cmd
void map_newmap_cmd(socket_struct *ns)
Definition: request.cpp:621
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:229
level
int level
Definition: readable.cpp:1549
object::flags
ob_flags flags
Definition: object.h:423
make_face_from_files.int
int
Definition: make_face_from_files.py:26
FLAG_IS_USED_UP
#define FLAG_IS_USED_UP
Definition: define.h:260
FLAG_ANIMATE
#define FLAG_ANIMATE
Definition: define.h:242
UPD_NAME
#define UPD_NAME
Definition: newclient.h:318
AT_COUNTERSPELL
#define AT_COUNTERSPELL
Definition: attack.h:95
AT_DISEASE
#define AT_DISEASE
Definition: attack.h:102
object::randomitems
struct treasurelist * randomitems
Definition: object.h:393
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.cpp:308
FOOD
@ FOOD
Definition: object.h:115
object_remove
void object_remove(object *op)
Definition: object.cpp: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:125
positioning_system.marked
marked
Definition: positioning_system.py:21
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
AT_CONFUSION
#define AT_CONFUSION
Definition: attack.h:81
OB_TYPE_MOVE_BLOCK
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Definition: define.h:432
generate_treasure
object * generate_treasure(treasurelist *t, int difficulty)
Definition: treasure.cpp:290
DRINK
@ DRINK
Definition: object.h:160
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:533
update_all_los
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.cpp:536
object::state
uint8_t state
Definition: object.h:357
SP_WONDER
#define SP_WONDER
Definition: spells.h:83
archetype::name
sstring name
Definition: object.h:473
object::nrof
uint32_t nrof
Definition: object.h:340
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:376
object::move_allow
MoveType move_allow
Definition: object.h:434
artifact
Definition: artifact.h:14
object::more
object * more
Definition: object.h:301
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:2495
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:217
Settings::create_home_portals
uint8_t create_home_portals
Definition: global.h:315
object::attacktype
uint32_t attacktype
Definition: object.h:350
FLAG_CURSED
#define FLAG_CURSED
Definition: define.h:316
pick_up
void pick_up(object *op, object *alt)
Definition: c_object.cpp:519
TELEPORTER
@ TELEPORTER
Definition: object.h:144
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:252
cast_earth_to_dust
int cast_earth_to_dust(object *op, object *caster, object *spell_ob)
Definition: spell_effect.cpp:851
NUM_STATS
@ NUM_STATS
Definition: living.h:18
MSG_TYPE_ITEM_INFO
#define MSG_TYPE_ITEM_INFO
Definition: newclient.h:645
find_marked_object
object * find_marked_object(object *op)
Definition: c_object.cpp:1520
object::move_block
MoveType move_block
Definition: object.h:433
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:227
alchemy
int alchemy(object *op, object *caster, object *spell_ob)
Definition: spell_effect.cpp:2296
HOLY_ALTAR
@ HOLY_ALTAR
Definition: object.h:164
TRAPDOOR
@ TRAPDOOR
Definition: object.h:213
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
create_aura
int create_aura(object *op, object *caster, object *spell)
Definition: spell_effect.cpp:3317
object.h
llevDebug
@ llevDebug
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:140
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:3953
P_BLOCKSVIEW
#define P_BLOCKSVIEW
Definition: map.h:227
GATE
@ GATE
Definition: object.h:209
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:161
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:1409
level
Definition: level.py:1
Settings::localdir
const char * localdir
Definition: global.h:253