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