Crossfire Server, Branches 1.12  R18729
spell_effect.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_spell_effect_c =
3  * "$Id: spell_effect.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 
7 /*
8  CrossFire, A Multiplayer game for X-windows
9 
10  Copyright (C) 2002-2006 Mark Wedel & Crossfire Development Team
11  Copyright (C) 1992 Frank Tore Johansen
12 
13  This program is free software; you can redistribute it and/or modify
14  it under the terms of the GNU General Public License as published by
15  the Free Software Foundation; either version 2 of the License, or
16  (at your option) any later version.
17 
18  This program is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with this program; if not, write to the Free Software
25  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 
27  The authors can be reached via e-mail at crossfire-devel@real-time.com
28 */
29 
36 #include <global.h>
37 #include <object.h>
38 #include <living.h>
39 #ifndef __CEXTRACT__
40 #include <sproto.h>
41 #endif
42 #include <spells.h>
43 #include <sounds.h>
44 
55 void cast_magic_storm(object *op, object *tmp, int lvl) {
56  if (!tmp)
57  return; /* error */
58  tmp->level = op->level;
59  tmp->x = op->x;
60  tmp->y = op->y;
61  tmp->range += lvl/5; /* increase the area of destruction */
62  tmp->duration += lvl/5;
63 
64  /* Put a cap on duration for this - if the player fails in their
65  * apartment, don't want it to go on so long that it kills them
66  * multiple times. Also, damge already increases with level,
67  * so don't really need to increase the duration as much either.
68  */
69  if (tmp->duration >= 40)
70  tmp->duration = 40;
71  tmp->stats.dam = lvl; /* nasty recoils! */
72  tmp->stats.maxhp = tmp->count; /* tract single parent */
73  insert_ob_in_map(tmp, op->map, op, 0);
74 }
75 
90 int recharge(object *op, object *caster, object *spell_ob) {
91  object *wand, *tmp;
92  int ncharges;
93  char name[MAX_BUF];
94 
95  wand = find_marked_object(op);
96  if (wand == NULL || wand->type != WAND) {
98  "You need to mark the wand you want to recharge.", NULL);
99  return 0;
100  }
101  if (!(random_roll(0, 3, op, PREFER_HIGH))) {
102  query_name(wand, name, MAX_BUF);
104  "The %s vibrates violently, then explodes!",
105  "The %s vibrates violently, then explodes!",
106  name);
107  play_sound_map(SOUND_TYPE_ITEM, wand, 0, "explode");
108  remove_ob(wand);
109  free_object(wand);
110  tmp = create_archetype("fireball");
111  tmp->stats.dam = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob))/10;
112  if (!tmp->stats.dam)
113  tmp->stats.dam = 1;
114  tmp->stats.hp = tmp->stats.dam/2;
115  if (tmp->stats.hp < 2)
116  tmp->stats.hp = 2;
117  tmp->x = op->x;
118  tmp->y = op->y;
119  insert_ob_in_map(tmp, op->map, NULL, 0);
120  return 1;
121  }
122 
123  ncharges = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob));
124  if (wand->inv && wand->inv->level)
125  ncharges /= wand->inv->level;
126  else {
127  query_name(wand, name, MAX_BUF);
129  "Your %s is broken.",
130  "Your %s is broken.",
131  name);
132  return 0;
133  }
134  if (!ncharges)
135  ncharges = 1;
136 
137  wand->stats.food += ncharges;
138  query_name(wand, name, MAX_BUF);
140  "The %s glows with power.",
141  "The %s glows with power.",
142  name);
143 
144  if (wand->arch && QUERY_FLAG(&wand->arch->clone, FLAG_ANIMATE)) {
145  SET_FLAG(wand, FLAG_ANIMATE);
146  wand->speed = wand->arch->clone.speed;
147  update_ob_speed(wand);
148  }
149  return 1;
150 }
151 
152 /******************************************************************************
153  * Start of polymorph related functions.
154  *
155  * Changed around for 0.94.3 - it will now look through and use all the
156  * possible choices for objects/monsters (before it was teh first 80 -
157  * arbitrary hardcoded limit in this file.) Doing this will be a bit
158  * slower however - while before, it traversed the archetypes once and
159  * stored them into an array, it will now potentially traverse it
160  * an average of 1.5 times. This is probably more costly on the polymorph
161  * item function, since it is possible a couple lookups might be needed before
162  * an item of proper value is generated.
163  */
164 
173 static void polymorph_living(object *op, int level) {
174  archetype *at;
175  int x = op->x, y = op->y, numat = 0, choice, friendly;
176  mapstruct *map = op->map;
177  object *tmp, *next, *owner;
178 
179  if (op->head)
180  op = op->head;
181 
182  /* High level creatures are immune, as are creatures immune to magic. Otherwise,
183  * give the creature a saving throw.
184  */
185  if (op->level >= level*2
186  || did_make_save(op, op->level, op->resist[ATNR_MAGIC]/10)
187  || (op->resist[ATNR_MAGIC] == 100))
188  return;
189 
190  remove_ob(op);
191 
192  /* First, count up the number of legal matches */
193  for (at = first_archetype; at != NULL; at = at->next)
194  if ((QUERY_FLAG((&at->clone), FLAG_MONSTER) == QUERY_FLAG(op, FLAG_MONSTER))
195  && (find_free_spot(&at->clone, map, x, y, 0, SIZEOFFREE) != -1)) {
196  numat++;
197  }
198  if (!numat) {
199  insert_ob_in_map(op, map, NULL, 0);
200  return; /* no valid matches? if so, return */
201  }
202 
203  /* Next make a choice, and loop through until we get to it */
204  choice = rndm(0, numat-1);
205  for (at = first_archetype; at != NULL; at = at->next)
206  if ((QUERY_FLAG((&at->clone), FLAG_MONSTER) == QUERY_FLAG(op, FLAG_MONSTER)) && (find_free_spot(&at->clone, map, x, y, 0, SIZEOFFREE) != -1)) {
207  if (!choice)
208  break;
209  else
210  choice--;
211  }
212 
213  /* Look through the monster. Unapply anything they have applied,
214  * and remove any spells. Note that if this is extended
215  * to players, that would need to get fixed somehow.
216  */
217  for (tmp = op->inv; tmp != NULL; tmp = next) {
218  next = tmp->below;
219  if (QUERY_FLAG(tmp, FLAG_APPLIED))
220  manual_apply(op, tmp, 0);
221  if (tmp->type == SPELL) {
222  remove_ob(tmp);
223  free_object(tmp);
224  }
225  }
226 
227  /* Preserve some values for the new object */
228  owner = get_owner(op);
229  friendly = QUERY_FLAG(op, FLAG_FRIENDLY);
230  if (friendly)
232 
233  copy_object(&(at->clone), op);
234  if (owner != NULL)
235  set_owner(op, owner);
236  if (friendly) {
237  SET_FLAG(op, FLAG_FRIENDLY);
238  op->attack_movement = PETMOVE;
240  } else
242 
243  /* Put the new creature on the map */
244  op->x = x;
245  op->y = y;
246  if ((op = insert_ob_in_map(op, map, owner, 0)) == NULL)
247  return;
248 
249  if (HAS_RANDOM_ITEMS(op))
250  /* No GT_APPLY here because we'll do it manually. */
252 
253  /* Apply any objects. */
254  for (tmp = op->inv; tmp != NULL; tmp = next) {
255  next = tmp->below;
256  monster_check_apply(op, tmp);
257  }
258 }
259 
260 
272 static void polymorph_melt(object *who, object *op) {
273  /* Not unique */
274  char name[MAX_BUF];
275 
276  query_name(op, name, MAX_BUF);
277  if (op->nrof > 1)
279  "The %s glow red, melt and evaporate!",
280  "The %s glow red, melt and evaporate!",
281  name);
282  else
284  "The %s glows red, melts and evaporates!",
285  "The %s glows red, melts and evaporates!",
286  name);
287  play_sound_map(SOUND_TYPE_ITEM, op, 0, "evaporate");
288  remove_ob(op);
289  free_object(op);
290  return;
291 }
292 
302 static void polymorph_item(object *who, object *op, int level) {
303  archetype *at;
304  int max_value, difficulty, tries = 0, choice, charges = op->stats.food, numat = 0;
305  object *new_ob;
306 
307  /* We try and limit the maximum value of the changed object. */
308  max_value = op->value*2;
309  if (max_value > 2000*(level/10))
310  max_value = 2000*(level/10)+(max_value-2000*(level/10))/3;
311 
312  /* Look through and try to find matching items. Can't turn into something
313  * invisible. Also, if the value is too high now, it would almost
314  * certainly be too high below.
315  */
316  for (at = first_archetype; at != NULL; at = at->next) {
317  if (at->clone.type == op->type
318  && !at->clone.invisible
319  && at->clone.value > 0
320  && at->clone.value < max_value
321  && !QUERY_FLAG(&at->clone, FLAG_NO_DROP)
322  && !QUERY_FLAG(&at->clone, FLAG_STARTEQUIP))
323  numat++;
324  }
325 
326  if (!numat)
327  return;
328 
329  difficulty = op->magic*5;
330  if (difficulty < 0)
331  difficulty = 0;
332  new_ob = get_object();
333  do {
334  choice = rndm(0, numat-1);
335  for (at = first_archetype; at != NULL; at = at->next) {
336  if (at->clone.type == op->type
337  && !at->clone.invisible
338  && at->clone.value > 0
339  && at->clone.value < max_value
340  && !QUERY_FLAG(&at->clone, FLAG_NO_DROP)
341  && !QUERY_FLAG(&at->clone, FLAG_STARTEQUIP)) {
342  if (!choice)
343  break;
344  else
345  choice--;
346  }
347  }
348  copy_object(&(at->clone), new_ob);
349  fix_generated_item(new_ob, op, difficulty, FABS(op->magic), GT_ENVIRONMENT);
350  ++tries;
351  } while (new_ob->value > max_value && tries < 10);
352  if (new_ob->invisible) {
353  LOG(llevError, "polymorph_item: fix_generated_object made %s invisible?!\n", new_ob->name);
354  free_object(new_ob);
355  return;
356  }
357 
358  /* Unable to generate an acceptable item? Melt it */
359  if (tries == 10) {
360  polymorph_melt(who, op);
361  free_object(new_ob);
362  return;
363  }
364 
365  if (op->nrof && new_ob->nrof) {
366  new_ob->nrof = op->nrof;
367  /* decrease the number of items */
368  if (new_ob->nrof > 2)
369  new_ob->nrof -= rndm(0, op->nrof/2-1);
370  }
371 
372  /* We don't want rings to keep sustenance/hungry status. There are probably
373  * other cases too that should be checked.
374  */
375  if (charges && op->type != RING && op->type != FOOD)
376  op->stats.food = charges;
377 
378  new_ob->x = op->x;
379  new_ob->y = op->y;
380  remove_ob(op);
381  free_object(op);
382  /*
383  * Don't want objects merged or re-arranged, as it then messes up the
384  * order
385  */
386  insert_ob_in_map(new_ob, who->map, new_ob, INS_NO_MERGE|INS_NO_WALK_ON);
387 }
388 
399 void polymorph(object *op, object *who, int level) {
400  int tmp;
401 
402  /* Can't polymorph players right now */
403  /* polymorphing generators opens up all sorts of abuses */
404  if (op->type == PLAYER || QUERY_FLAG(op, FLAG_GENERATOR))
405  return;
406 
407  if (QUERY_FLAG(op, FLAG_MONSTER)) {
408  polymorph_living(op, level);
409  return;
410  }
411  /* If it is a living object of some other type, don't handle
412  * it now.
413  */
414  if (QUERY_FLAG(op, FLAG_ALIVE))
415  return;
416 
417  /* Don't want to morph flying arrows, etc... */
418  if (FABS(op->speed) > 0.001 && !QUERY_FLAG(op, FLAG_ANIMATE))
419  return;
420 
421  /* Do some sanity checking here. type=0 is unknown, objects
422  * without archetypes are not good. As are a few other
423  * cases.
424  */
425  if (op->type == 0
426  || op->arch == NULL
427  || QUERY_FLAG(op, FLAG_NO_PICK)
428  || op->move_block
429  || op->type == TREASURE)
430  return;
431 
432  tmp = rndm(0, 7);
433  if (tmp)
434  polymorph_item(who, op, level);
435  else
436  polymorph_melt(who, op);
437 }
438 
439 
453 int cast_polymorph(object *op, object *caster, object *spell_ob, int dir) {
454  object *tmp, *next;
455  int range, mflags, maxrange, level;
456  mapstruct *m;
457 
458  if (dir == 0)
459  return 0;
460 
461  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
462  level = caster_level(caster, spell_ob);
463  for (range = 1; range < maxrange; range++) {
464  sint16 x = op->x+freearr_x[dir]*range, y = op->y+freearr_y[dir]*range;
465  object *image;
466 
467  m = op->map;
468  mflags = get_map_flags(m, &m, x, y, &x, &y);
469 
470  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
471  break;
472 
473  if (GET_MAP_MOVE_BLOCK(m, x, y)&MOVE_FLY_LOW)
474  break;
475 
476  /* Get the top most object */
477  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above)
478  ;
479 
480  /* Now start polymorphing the objects, top down */
481  while (tmp != NULL) {
482  /* Once we find the floor, no need to go further */
483  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
484  break;
485  next = tmp->below;
486  polymorph(tmp, op, level);
487  tmp = next;
488  }
489  image = arch_to_object(spell_ob->other_arch);
490  image->x = x;
491  image->y = y;
492  image->stats.food = 5;
493  image->speed_left = 0.1;
494  insert_ob_in_map(image, m, op, 0);
495  }
496  return 1;
497 }
498 
525 int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg) {
526  int missile_plus = 0, bonus_plus = 0;
527  const char *missile_name;
528  object *tmp, *missile;
529  tag_t tag;
530 
531  missile_name = "arrow";
532 
533  for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
534  if (tmp->type == BOW && QUERY_FLAG(tmp, FLAG_APPLIED))
535  missile_name = tmp->race;
536 
537  missile_plus = spell->stats.dam+SP_level_dam_adjust(caster, spell);
538 
539  if (!strcmp(missile_name, "arrows"))
540  missile_name = "arrow";
541  else if (!strcmp(missile_name, "crossbow bolts"))
542  missile_name = "bolt";
543 
544  if (find_archetype(missile_name) == NULL) {
545  LOG(llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
546  return 0;
547  }
548  missile = create_archetype(missile_name);
549 
550  if (stringarg) {
551  /* If it starts with a letter, presume it is a description */
552  if (isalpha(*stringarg)) {
553  artifact *al = find_artifactlist(missile->type)->items;
554 
555  for (; al != NULL; al = al->next)
556  if (!strcasecmp(al->item->name, stringarg))
557  break;
558 
559  if (!al) {
560  free_object(missile);
562  "No such object %ss of %s",
563  "No such object %ss of %s",
564  missile_name, stringarg);
565  return 0;
566  }
567  if (al->item->slaying) {
568  free_object(missile);
570  "You are not allowed to create %ss of %s",
571  "You are not allowed to create %ss of %s",
572  missile_name, stringarg);
573  return 0;
574  }
575  give_artifact_abilities(missile, al->item);
576  /* These special arrows cost something extra. Don't have them also be
577  * magical - otherwise, in most cases, not enough will be created.
578  * I don't want to get into the parsing of having to do both plus and
579  * type.
580  */
581  bonus_plus = 1+(al->item->value/5);
582  missile_plus = 0;
583  } else if (atoi(stringarg) < missile_plus)
584  missile_plus = atoi(stringarg);
585  }
586  if (missile_plus > 4)
587  missile_plus = 4;
588  else if (missile_plus < -4)
589  missile_plus = -4;
590 
591  missile->nrof = spell->duration+SP_level_duration_adjust(caster, spell);
592  if (missile->nrof <= 3*(missile_plus+bonus_plus)) {
593  free_object(missile);
595  "This item is too powerful for you to create!",
596  NULL);
597  return 0;
598  }
599  missile->nrof -= 3*(missile_plus+bonus_plus);
600  if (missile->nrof < 1)
601  missile->nrof = 1;
602 
603  missile->magic = missile_plus;
604  /* Can't get any money for these objects */
605  missile->value = 0;
606 
607  SET_FLAG(missile, FLAG_IDENTIFIED);
608  tag = missile->count;
609 
610  if (!cast_create_obj(op, missile, dir)
611  && op->type == PLAYER
612  && !was_destroyed(missile, tag)) {
613  pick_up(op, missile);
614  }
615  return 1;
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  archetype *at_tmp;
656 
657  /* We try to find the archetype with the maximum food value.
658  * This removes the dependancy of hard coded food values in this
659  * function, and addition of new food types is automatically added.
660  * We don't use flesh types because the weight values of those need
661  * to be altered from the donor.
662  */
663 
664  /* We assume the food items don't have multiple parts */
665  for (at_tmp = first_archetype; at_tmp != NULL; at_tmp = at_tmp->next) {
666  if (at_tmp->clone.type == FOOD || at_tmp->clone.type == DRINK) {
667  /* Basically, if the food value is something that is creatable
668  * under the limits of the spell and it is higher than
669  * the item we have now, take it instead.
670  */
671  if (at_tmp->clone.stats.food <= food_value
672  && (!at || at_tmp->clone.stats.food > at->clone.stats.food))
673  at = at_tmp;
674  }
675  }
676  }
677  /* Pretty unlikely (there are some very low food items), but you never
678  * know
679  */
680  if (!at) {
682  "You don't have enough experience to create any food.", NULL);
683  return 0;
684  }
685 
686  food_value /= at->clone.stats.food;
687  new_op = get_object();
688  copy_object(&at->clone, new_op);
689  new_op->nrof = food_value;
690 
691  new_op->value = 0;
692  if (new_op->nrof < 1)
693  new_op->nrof = 1;
694 
695  cast_create_obj(op, new_op, dir);
696  return 1;
697 }
698 
715 int probe(object *op, object *caster, object *spell_ob, int dir) {
716  int r, mflags, maxrange;
717  object *tmp;
718  mapstruct *m;
719 
720  if (!dir) {
721  examine_monster(op, op);
722  return 1;
723  }
724  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
725  for (r = 1; r < maxrange; r++) {
726  sint16 x = op->x+r*freearr_x[dir], y = op->y+r*freearr_y[dir];
727 
728  m = op->map;
729  mflags = get_map_flags(m, &m, x, y, &x, &y);
730 
731  if (mflags&P_OUT_OF_MAP)
732  break;
733 
734  if (!QUERY_FLAG(op, FLAG_WIZCAST) && (mflags&P_NO_MAGIC)) {
736  "Something blocks your magic.", NULL);
737  return 0;
738  }
739  if (mflags&P_IS_ALIVE) {
740  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL; tmp = tmp->above)
741  if (QUERY_FLAG(tmp, FLAG_ALIVE)&&(tmp->type == PLAYER || QUERY_FLAG(tmp, FLAG_MONSTER))) {
743  "You detect something.", NULL);
744  if (tmp->head != NULL)
745  tmp = tmp->head;
746  examine_monster(op, tmp);
747  return 1;
748  }
749  }
750  }
752  "You detect nothing.", NULL);
753  return 1;
754 }
755 
756 
774 int makes_invisible_to(object *pl, object *mon) {
775  if (!pl->invisible)
776  return 0;
777  if (pl->type == PLAYER) {
778  /* If race isn't set, then invisible unless it is undead */
779  if (!pl->contr->invis_race) {
780  if (QUERY_FLAG(mon, FLAG_UNDEAD))
781  return 0;
782  return 1;
783  }
784  /* invis_race is set if we get here */
785  if (!strcmp(pl->contr->invis_race, "undead") && is_true_undead(mon))
786  return 1;
787  /* No race, can't be invisible to it */
788  if (!mon->race)
789  return 0;
790  if (strstr(mon->race, pl->contr->invis_race))
791  return 1;
792  /* Nothing matched above, return 0 */
793  return 0;
794  } else {
795  /* monsters are invisible to everything */
796  return 1;
797  }
798 }
799 
821 int cast_invisible(object *op, object *caster, object *spell_ob) {
822  object *tmp;
823 
824  if (op->invisible > 1000) {
826  "You can not extend the duration of your invisibility any further", NULL);
827  return 0;
828  }
829 
830  /* Remove the switch with 90% duplicate code - just handle the differences with
831  * and if statement or two.
832  */
833  op->invisible += spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
834  /* max duration */
835  if (op->invisible > 1000)
836  op->invisible = 1000;
837 
838  if (op->type == PLAYER) {
839  if (op->contr->invis_race)
841  if (spell_ob->race)
842  op->contr->invis_race = add_refcount(spell_ob->race);
843  if (QUERY_FLAG(spell_ob, FLAG_MAKE_INVIS))
844  op->contr->tmp_invis = 0;
845  else
846  op->contr->tmp_invis = 1;
847 
848  op->contr->hidden = 0;
849  }
850  if (makes_invisible_to(op, op))
852  "You can't see your hands!", NULL);
853  else
855  "You feel more transparent!", NULL);
856 
858 
859  /* Only search the active objects - only these should actually do
860  * harm to the player.
861  */
862  for (tmp = active_objects; tmp != NULL; tmp = tmp->active_next)
863  if (tmp->enemy == op)
864  tmp->enemy = NULL;
865  return 1;
866 }
867 
882 int cast_earth_to_dust(object *op, object *caster, object *spell_ob) {
883  object *tmp, *next;
884  int range, i, j, mflags;
885  sint16 sx, sy;
886  mapstruct *m;
887 
888  if (op->type != PLAYER)
889  return 0;
890 
891  range = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
892 
893  for (i = -range; i < range; i++)
894  for (j = -range; j < range; j++) {
895  sx = op->x+i;
896  sy = op->y+j;
897  m = op->map;
898  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
899 
900  if (mflags&P_OUT_OF_MAP)
901  continue;
902 
903  /* If the space doesn't block, no wall here to remove
904  * Don't care too much what it blocks - this allows for
905  * any sort of earthwall/airwall/waterwall, etc
906  * type effects.
907  */
908  if (GET_MAP_MOVE_BLOCK(m, sx, sy)) {
909  for (tmp = GET_MAP_OB(m, sx, sy); tmp != NULL; tmp = next) {
910  next = tmp->above;
911  if (tmp && QUERY_FLAG(tmp, FLAG_TEAR_DOWN))
912  hit_player(tmp, 9998, op, AT_PHYSICAL, 0);
913  }
914  }
915  }
916  return 1;
917 }
918 
935 int cast_word_of_recall(object *op, object *caster, object *spell_ob) {
936  object *dummy;
937  int time;
938 
939  if (op->type != PLAYER)
940  return 0;
941 
944  "You feel a force starting to build up inside you.", NULL);
945  return 1;
946  }
947 
948  dummy = create_archetype(FORCE_NAME);
949  if (dummy == NULL) {
951  "Oops, program error!", NULL);
952  LOG(llevError, "cast_word_of_recall: create_archetype(force) failed!\n");
953  return 0;
954  }
955  time = spell_ob->duration-SP_level_duration_adjust(caster, spell_ob);
956  if (time < 1)
957  time = 1;
958 
959  /* value of speed really doesn't make much difference, as long as it is
960  * positive. Lower value may be useful so that the problem doesn't
961  * do anything really odd if it say a -1000 or something.
962  */
963  dummy->speed = 0.002;
964  update_ob_speed(dummy);
965  dummy->speed_left = -dummy->speed*time;
966  dummy->type = SPELL_EFFECT;
967  dummy->subtype = SP_WORD_OF_RECALL;
968 
969  /* If we could take advantage of enter_player_savebed() here, it would be
970  * nice, but until the map load fails, we can't.
971  */
972  EXIT_PATH(dummy) = add_string(op->contr->savebed_map);
973  EXIT_X(dummy) = op->contr->bed_x;
974  EXIT_Y(dummy) = op->contr->bed_y;
975 
976  (void)insert_ob_in_ob(dummy, op);
978  "You feel a force starting to build up inside you.", NULL);
979  return 1;
980 }
981 
997 int cast_wonder(object *op, object *caster, int dir, object *spell_ob) {
998  object *newspell;
999 
1000  if (!rndm(0, 3))
1001  return cast_cone(op, caster, dir, spell_ob);
1002 
1003  if (spell_ob->randomitems) {
1004  newspell = generate_treasure(spell_ob->randomitems, caster->level);
1005  if (!newspell) {
1006  LOG(llevError, "cast_wonder: Unable to get a spell!\n");
1007  return 0;
1008  }
1009  if (newspell->type != SPELL) {
1010  LOG(llevError, "cast_wonder: spell returned is not a spell (%d, %s)!\n", newspell->type, newspell->name);
1011  return 0;
1012  }
1013  /* Prevent inifinit recursion */
1014  if (newspell->subtype == SP_WONDER) {
1015  LOG(llevError, "cast_wonder: spell returned is another wonder spell!\n");
1016  return 0;
1017  }
1018  return cast_spell(op, caster, dir, newspell, NULL);
1019  }
1020  return 1;
1021 }
1022 
1031 int perceive_self(object *op) {
1032  char cp[VERY_BIG_BUF], buf[MAX_BUF];
1034  object *tmp;
1035  const object *god;
1036  int i;
1037 
1038  describe_item(op, op, cp, VERY_BIG_BUF);
1039 
1040  god = find_god(determine_god(op));
1041  if (god)
1043  "You worship %s",
1044  "You worship %s",
1045  god->name);
1046  else
1048  "You worship no god", NULL);
1049 
1050  tmp = present_arch_in_ob(at, op);
1051 
1052  if (*cp == '\0' && tmp == NULL)
1054  "You feel very mundane", NULL);
1055  else {
1057  "You have:", NULL);
1059  cp, cp);
1060  if (tmp != NULL) {
1061  for (i = 0; i < NUM_STATS; i++) {
1062  if (get_attr_value(&tmp->stats, i) < 0) {
1064  "Your %s is depleted by %d",
1065  "Your %s is depleted by %d",
1066  statname[i], -(get_attr_value(&tmp->stats, i)));
1067  }
1068  }
1069  }
1070  }
1071  if (op->glow_radius > 0)
1073  "You glow in the dark.", NULL);
1074 
1075  if (is_dragon_pl(op)) {
1076  /* now grab the 'dragon_ability'-force from the player's inventory */
1077  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
1078  if (tmp->type == FORCE && !strcmp(tmp->arch->name, "dragon_ability_force")) {
1079  if (tmp->stats.exp == 0) {
1080  snprintf(buf, sizeof(buf), "Your metabolism isn't focused on anything.");
1081  } else {
1082  snprintf(buf, sizeof(buf), "Your metabolism is focused on %s.", change_resist_msg[tmp->stats.exp]);
1083  }
1085  buf, buf);
1086  break;
1087  }
1088  }
1089  }
1090  return 1;
1091 }
1092 
1122 int cast_create_town_portal(object *op, object *caster, object *spell, int dir) {
1123  object *dummy, *force, *old_force, *tmp;
1124  archetype *perm_portal;
1125  char portal_name [1024], portal_message [1024];
1126  sint16 exitx, exity;
1127  mapstruct *exitmap;
1128  int op_level;
1129 
1130  /* Check to see if the map the player is currently on is a per player unique
1131  * map. This can be determined in that per player unique maps have the
1132  * full pathname listed. Ignore if settings.create_home_portals is true.
1133  */
1135  if (!strncmp(op->map->path, settings.localdir, strlen(settings.localdir))) {
1137  "You can't cast that here.", NULL);
1138  return 0;
1139  }
1140  }
1141 
1142  /* Check to see if the player is on a transport */
1143  if (op->contr && op->contr->transport) {
1145  "You need to exit the transport to cast that.", NULL);
1146  return 0;
1147  }
1148 
1149  /* The first thing to do is to check if we have a marked destination
1150  * dummy is used to make a check inventory for the force
1151  */
1152  dummy = arch_to_object(spell->other_arch);
1153  if (dummy == NULL) {
1155  "Oops, program error!", NULL);
1156  LOG(llevError, "get_object failed (force in cast_create_town_portal for %s!\n", op->name);
1157  return 0;
1158  }
1159  force = check_inv_recursive(op, dummy);
1160 
1161  if (force == NULL) {
1162  /* Here we know there is no destination marked up.
1163  * We have 2 things to do:
1164  * 1. Mark the destination in the player inventory.
1165  * 2. Let the player know it worked.
1166  */
1167  free_string(dummy->name);
1168  dummy->name = add_string(op->map->path);
1169  EXIT_X(dummy) = op->x;
1170  EXIT_Y(dummy) = op->y;
1171  dummy->weapontype = op->map->last_reset_time.tv_sec;
1172  insert_ob_in_ob(dummy, op);
1174  "You fix this place in your mind and feel that you"
1175  "can come here from anywhere.",
1176  NULL);
1177  return 1;
1178  }
1179  free_object(dummy);
1180 
1181  /* Here we know where the town portal should go to
1182  * We should kill any existing portal associated with the player.
1183  * Than we should create the 2 portals.
1184  * For each of them, we need:
1185  * - To create the portal with the name of the player+destination map
1186  * - set the owner of the town portal
1187  * - To mark the position of the portal in the player's inventory
1188  * for easier destruction.
1189  *
1190  * The mark works has follow:
1191  * slaying: Existing town portal
1192  * hp, sp : x & y of the associated portal
1193  * name : name of the portal
1194  * race : map the portal is in
1195  */
1196 
1197  /* First step: killing existing town portals */
1198  dummy = create_archetype(spell->race);
1199  if (dummy == NULL) {
1201  "Oops, program error!", NULL);
1202  LOG(llevError, "get_object failed (force) in cast_create_town_portal for %s!\n", op->name);
1203  return 0;
1204  }
1205  perm_portal = find_archetype(spell->slaying);
1206 
1207  /* To kill a town portal, we go trough the player's inventory,
1208  * for each marked portal in player's inventory,
1209  * -We try load the associated map (if impossible, consider the portal destructed)
1210  * -We find any portal in the specified location.
1211  * If it has the good name, we destruct it.
1212  * -We destruct the force indicating that portal.
1213  */
1214  while ((old_force = check_inv_recursive(op, dummy))) {
1215  exitx = EXIT_X(old_force);
1216  exity = EXIT_Y(old_force);
1217  LOG(llevDebug, "Trying to kill a portal in %s (%d,%d)\n", old_force->race, exitx, exity);
1218 
1219  if (!strncmp(old_force->race, settings.localdir, strlen(settings.localdir)))
1220  exitmap = ready_map_name(old_force->race, MAP_PLAYER_UNIQUE);
1221  else
1222  exitmap = ready_map_name(old_force->race, 0);
1223 
1224  if (exitmap) {
1225  tmp = present_arch(perm_portal, exitmap, exitx, exity);
1226  while (tmp) {
1227  if (tmp->name == old_force->name) {
1228  remove_ob(tmp);
1229  free_object(tmp);
1230  break;
1231  } else {
1232  tmp = tmp->above;
1233  }
1234  }
1235  }
1236  remove_ob(old_force);
1237  free_object(old_force);
1238  LOG(llevDebug, "\n");
1239  }
1240  free_object(dummy);
1241 
1242  /* Creating the portals.
1243  * The very first thing to do is to ensure
1244  * access to the destination map.
1245  * If we can't, don't fizzle. Simply warn player.
1246  * This ensure player pays his mana for the spell
1247  * because HE is responsible of forgotting.
1248  * 'force' is the destination of the town portal, which we got
1249  * from the players inventory above.
1250  */
1251 
1252  /* Ensure exit map is loaded*/
1253  if (!strncmp(force->name, settings.localdir, strlen(settings.localdir)))
1254  exitmap = ready_map_name(force->name, MAP_PLAYER_UNIQUE);
1255  else
1256  exitmap = ready_map_name(force->name, 0);
1257 
1258  /* If we were unable to load (ex. random map deleted), warn player*/
1259  if (exitmap == NULL) {
1261  "Something strange happens. You can't remember where to go!?",
1262  NULL);
1263  remove_ob(force);
1264  free_object(force);
1265  return 1;
1266  } else if (exitmap->last_reset_time.tv_sec != force->weapontype) {
1268  "The spell effect has expired.", NULL);
1269  remove_ob(force);
1270  free_object(force);
1271  return 1;
1272  }
1273 
1274  op_level = caster_level(caster, spell);
1275  if (op_level < 15)
1276  snprintf(portal_message, 1024, "\nThe air moves around you and\na huge smell of ammonia\nsurounds you as you pass\nthrough %s's tiny portal\nPouah!\n", op->name);
1277  else if (op_level < 30)
1278  snprintf(portal_message, 1024, "\n%s's portal smells of ozone.\nYou do a lot of movements and finally pass\nthrough the small hole in the air\n", op->name);
1279  else if (op_level < 60)
1280  snprintf(portal_message, 1024, "\nA shining door opens in the air in front of you,\nshowing you the path to another place.\n");
1281  else
1282  snprintf(portal_message, 1024, "\nAs you walk through %s's portal, flowers come out\nfrom the ground around you.\nYou feel awed.\n", op->name);
1283 
1284  /* Create a portal in front of player
1285  * dummy contain the portal and
1286  * force contain the track to kill it later
1287  */
1288 
1289  snprintf(portal_name, 1024, "%s's portal to %s", op->name, force->name);
1290  dummy = create_archetype(spell->slaying); /*The portal*/
1291  if (dummy == NULL) {
1293  "Oops, program error!", NULL);
1294  LOG(llevError, "get_object failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1295  return 0;
1296  }
1297  EXIT_PATH(dummy) = add_string(force->name);
1298  EXIT_X(dummy) = EXIT_X(force);
1299  EXIT_Y(dummy) = EXIT_Y(force);
1300  FREE_AND_COPY(dummy->name, portal_name);
1301  FREE_AND_COPY(dummy->name_pl, portal_name);
1302  dummy->msg = add_string(portal_message);
1303  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1304  cast_create_obj(op, dummy, 0);
1305 
1306  /* Now we need to to create a town portal marker inside the player
1307  * object, so on future castings, we can know that he has an active
1308  * town portal.
1309  */
1310  tmp = create_archetype(spell->race);
1311  if (tmp == NULL) {
1313  "Oops, program error!", NULL);
1314  LOG(llevError, "get_object failed (force) in cast_create_town_portal for %s!\n", op->name);
1315  return 0;
1316  }
1317  tmp->race = add_string(op->map->path);
1318  FREE_AND_COPY(tmp->name, portal_name);
1319  EXIT_X(tmp) = dummy->x;
1320  EXIT_Y(tmp) = dummy->y;
1321  insert_ob_in_ob(tmp, op);
1322 
1323  /* Create a portal in the destination map
1324  * dummy contain the portal and
1325  * force the track to kill it later
1326  * the 'force' variable still contains the 'reminder' of
1327  * where this portal goes to.
1328  */
1329  snprintf(portal_name, 1024, "%s's portal to %s", op->name, op->map->path);
1330  dummy = create_archetype(spell->slaying); /*The portal*/
1331  if (dummy == NULL) {
1333  "Oops, program error!", NULL);
1334  LOG(llevError, "get_object failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1335  return 0;
1336  }
1337  EXIT_PATH(dummy) = add_string(op->map->path);
1338  EXIT_X(dummy) = op->x;
1339  EXIT_Y(dummy) = op->y;
1340  FREE_AND_COPY(dummy->name, portal_name);
1341  FREE_AND_COPY(dummy->name_pl, portal_name);
1342  dummy->msg = add_string(portal_message);
1343  dummy->x = EXIT_X(force);
1344  dummy->y = EXIT_Y(force);
1345  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1346  insert_ob_in_map(dummy, exitmap, op, 0);
1347 
1348  /* Now we create another town portal marker that
1349  * points back to the one we just made
1350  */
1351  tmp = create_archetype(spell->race);
1352  if (tmp == NULL) {
1354  "Oops, program error!", NULL);
1355  LOG(llevError, "get_object failed (force) in cast_create_town_portal for %s!\n", op->name);
1356  return 0;
1357  }
1358  tmp->race = add_string(force->name);
1359  FREE_AND_COPY(tmp->name, portal_name);
1360  EXIT_X(tmp) = dummy->x;
1361  EXIT_Y(tmp) = dummy->y;
1362  insert_ob_in_ob(tmp, op);
1363 
1364  /* Describe the player what happened
1365  */
1367  "You see air moving and showing you the way home.", NULL);
1368  remove_ob(force); /* Delete the force inside the player*/
1369  free_object(force);
1370  return 1;
1371 }
1372 
1373 
1391 int magic_wall(object *op, object *caster, int dir, object *spell_ob) {
1392  object *tmp, *tmp2;
1393  int i, posblocked, negblocked, maxrange;
1394  sint16 x, y;
1395  mapstruct *m;
1396  const char *name;
1397  archetype *at;
1398 
1399  if (!dir) {
1400  dir = op->facing;
1401  x = op->x;
1402  y = op->y;
1403  } else {
1404  x = op->x+freearr_x[dir];
1405  y = op->y+freearr_y[dir];
1406  }
1407  m = op->map;
1408 
1409  if ((spell_ob->move_block || x != op->x || y != op->y)
1410  && (get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE)
1411  || ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) == spell_ob->move_block))) {
1413  "Something is in the way.", NULL);
1414  return 0;
1415  }
1416  if (spell_ob->other_arch) {
1417  tmp = arch_to_object(spell_ob->other_arch);
1418  } else if (spell_ob->race) {
1419  char buf1[MAX_BUF];
1420 
1421  snprintf(buf1, sizeof(buf1), spell_ob->race, dir);
1422  at = find_archetype(buf1);
1423  if (!at) {
1424  LOG(llevError, "summon_wall: Unable to find archetype %s\n", buf1);
1426  "This spell is broken.", NULL);
1427  return 0;
1428  }
1429  tmp = arch_to_object(at);
1430  } else {
1431  LOG(llevError, "magic_wall: spell %s lacks other_arch\n", spell_ob->name);
1432  return 0;
1433  }
1434 
1435  if (tmp->type == SPELL_EFFECT) {
1436  tmp->attacktype = spell_ob->attacktype;
1437  tmp->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1438  tmp->stats.dam = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1439  tmp->range = 0;
1440  } else if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
1441  tmp->stats.hp = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1442  tmp->stats.maxhp = tmp->stats.hp;
1443  set_owner(tmp, op);
1444  set_spell_skill(op, caster, spell_ob, tmp);
1445  }
1446  if (QUERY_FLAG(spell_ob, FLAG_IS_USED_UP) || QUERY_FLAG(tmp, FLAG_IS_USED_UP)) {
1447  tmp->stats.food = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1448  SET_FLAG(tmp, FLAG_IS_USED_UP);
1449  }
1450  if (QUERY_FLAG(spell_ob, FLAG_TEAR_DOWN)) {
1451  tmp->stats.hp = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1452  tmp->stats.maxhp = tmp->stats.hp;
1453  SET_FLAG(tmp, FLAG_TEAR_DOWN);
1454  SET_FLAG(tmp, FLAG_ALIVE);
1455  }
1456 
1457  /* This can't really hurt - if the object doesn't kill anything,
1458  * these fields just won't be used.
1459  */
1460  set_owner(tmp, op);
1461  set_spell_skill(op, caster, spell_ob, tmp);
1462  tmp->x = x;
1463  tmp->y = y;
1464  tmp->level = caster_level(caster, spell_ob)/2;
1465 
1466  name = tmp->name;
1467  if ((tmp = insert_ob_in_map(tmp, m, op, 0)) == NULL) {
1469  "Something destroys your %s",
1470  "Something destroys your %s",
1471  name);
1472  return 0;
1473  }
1474  /* If this is a spellcasting wall, need to insert the spell object */
1475  if (tmp->other_arch && tmp->other_arch->clone.type == SPELL)
1477 
1478  /* This code causes the wall to extend some distance in
1479  * each direction, or until an obstruction is encountered.
1480  * posblocked and negblocked help determine how far the
1481  * created wall can extend, it won't go extend through
1482  * blocked spaces.
1483  */
1484  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
1485  posblocked = 0;
1486  negblocked = 0;
1487 
1488  for (i = 1; i <= maxrange; i++) {
1489  int dir2;
1490 
1491  dir2 = (dir < 4) ? (dir+2) : dir-2;
1492 
1493  x = tmp->x+i*freearr_x[dir2];
1494  y = tmp->y+i*freearr_y[dir2];
1495  m = tmp->map;
1496 
1497  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1498  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1499  && !posblocked) {
1500  tmp2 = get_object();
1501  copy_object(tmp, tmp2);
1502  tmp2->x = x;
1503  tmp2->y = y;
1504  insert_ob_in_map(tmp2, m, op, 0);
1505  /* If this is a spellcasting wall, need to insert the spell object */
1506  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1508  } else
1509  posblocked = 1;
1510 
1511  x = tmp->x-i*freearr_x[dir2];
1512  y = tmp->y-i*freearr_y[dir2];
1513  m = tmp->map;
1514 
1515  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1516  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1517  && !negblocked) {
1518  tmp2 = get_object();
1519  copy_object(tmp, tmp2);
1520  tmp2->x = x;
1521  tmp2->y = y;
1522  insert_ob_in_map(tmp2, m, op, 0);
1523  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1525  } else
1526  negblocked = 1;
1527  }
1528 
1529  if (QUERY_FLAG(tmp, FLAG_BLOCKSVIEW))
1530  update_all_los(op->map, op->x, op->y);
1531 
1532  return 1;
1533 }
1534 
1551 int dimension_door(object *op, object *caster, object *spob, int dir) {
1552  uint32 dist, maxdist;
1553  int mflags;
1554  mapstruct *m;
1555  sint16 sx, sy;
1556 
1557  if (op->type != PLAYER)
1558  return 0;
1559 
1560  if (!dir) {
1562  "In what direction?", NULL);
1563  return 0;
1564  }
1565 
1566  /* Given the new outdoor maps, can't let players dimension door for
1567  * ever, so put limits in.
1568  */
1569  maxdist = spob->range+SP_level_range_adjust(caster, spob);
1570 
1571  if (op->contr->count) {
1572  if (op->contr->count > maxdist) {
1574  "You can't dimension door that far!", NULL);
1575  return 0;
1576  }
1577 
1578  for (dist = 0; dist < op->contr->count; dist++) {
1579  mflags = get_map_flags(op->map, &m,
1580  op->x+freearr_x[dir]*(dist+1),
1581  op->y+freearr_y[dir]*(dist+1),
1582  &sx, &sy);
1583 
1584  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1585  break;
1586 
1587  if ((mflags&P_BLOCKSVIEW)
1588  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1589  break;
1590  }
1591 
1592  if (dist < op->contr->count) {
1594  "Something blocks the magic of the spell.", NULL);
1595  op->contr->count = 0;
1596  return 0;
1597  }
1598  op->contr->count = 0;
1599 
1600  /* Remove code that puts player on random space on maps. IMO,
1601  * a lot of maps probably have areas the player should not get to,
1602  * but may not be marked as NO_MAGIC (as they may be bounded
1603  * by such squares). Also, there are probably treasure rooms and
1604  * lots of other maps that protect areas with no magic, but the
1605  * areas themselves don't contain no magic spaces.
1606  */
1607  /* This call here is really just to normalize the coordinates */
1608  mflags = get_map_flags(op->map, &m, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist,
1609  &sx, &sy);
1610  if (mflags&P_IS_ALIVE || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy))) {
1612  "You cast your spell, but nothing happens.", NULL);
1613  return 1; /* Maybe the penalty should be more severe... */
1614  }
1615  } else {
1616  /* Player didn't specify a distance, so lets see how far
1617  * we can move the player. Don't know why this stopped on
1618  * spaces that blocked the players view.
1619  */
1620 
1621  for (dist = 0; dist < maxdist; dist++) {
1622  mflags = get_map_flags(op->map, &m,
1623  op->x+freearr_x[dir]*(dist+1),
1624  op->y+freearr_y[dir]*(dist+1),
1625  &sx, &sy);
1626 
1627  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1628  break;
1629 
1630  if ((mflags&P_BLOCKSVIEW)
1631  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1632  break;
1633 
1634  }
1635 
1636  /* If the destination is blocked, keep backing up until we
1637  * find a place for the player.
1638  */
1639  for (; dist > 0; dist--) {
1640  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))
1641  continue;
1642 
1643  if (!OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1644  break;
1645  }
1646  if (!dist) {
1648  "Your spell failed!", NULL);
1649  return 0;
1650  }
1651  }
1652 
1653  /* Actually move the player now */
1654  remove_ob(op);
1655  op->x += freearr_x[dir]*dist;
1656  op->y += freearr_y[dir]*dist;
1657  if ((op = insert_ob_in_map(op, op->map, op, 0)) == NULL)
1658  return 1;
1659 
1660  if (op->type == PLAYER)
1661  map_newmap_cmd(&op->contr->socket);
1662  op->speed_left = -FABS(op->speed)*5; /* Freeze them for a short while */
1663  return 1;
1664 }
1665 
1666 
1679 int cast_heal(object *op, object *caster, object *spell, int dir) {
1680  object *tmp;
1681  archetype *at;
1682  object *poison;
1683  int heal = 0, success = 0;
1684 
1685  tmp = find_target_for_friendly_spell(op, dir);
1686 
1687  if (tmp == NULL)
1688  return 0;
1689 
1690  /* Figure out how many hp this spell might cure.
1691  * could be zero if this spell heals effects, not damage.
1692  */
1693  heal = spell->stats.dam;
1694  if (spell->stats.hp)
1695  heal += random_roll(spell->stats.hp, 6, op, PREFER_HIGH)+spell->stats.hp;
1696 
1697  if (heal) {
1698  if (tmp->stats.hp >= tmp->stats.maxhp) {
1700  "You are already fully healed.", NULL);
1701  } else {
1702  /* See how many points we actually heal. Instead of messages
1703  * based on type of spell, we instead do messages based
1704  * on amount of damage healed.
1705  */
1706  if (heal > (tmp->stats.maxhp-tmp->stats.hp))
1707  heal = tmp->stats.maxhp-tmp->stats.hp;
1708  tmp->stats.hp += heal;
1709 
1710  if (tmp->stats.hp >= tmp->stats.maxhp) {
1712  "You feel just fine!", NULL);
1713  } else if (heal > 50) {
1715  "Your wounds close!", NULL);
1716  } else if (heal > 25) {
1718  "Your wounds mostly close.", NULL);
1719  } else if (heal > 10) {
1721  "Your wounds start to fade.", NULL);
1722  } else {
1724  "Your wounds start to close.", NULL);
1725  }
1726  success = 1;
1727  }
1728  }
1729  if (spell->attacktype&AT_DISEASE)
1730  if (cure_disease(tmp, op))
1731  success = 1;
1732 
1733  if (spell->attacktype&AT_POISON) {
1734  at = find_archetype("poisoning");
1735  poison = present_arch_in_ob(at, tmp);
1736  if (poison) {
1737  success = 1;
1739  "Your body feels cleansed", NULL);
1740  poison->stats.food = 1;
1741  }
1742  }
1743  if (spell->attacktype&AT_CONFUSION) {
1744  poison = present_in_ob_by_name(FORCE, "confusion", tmp);
1745  if (poison) {
1746  success = 1;
1748  "Your mind feels clearer", NULL);
1749  poison->duration = 1;
1750  }
1751  }
1752  if (spell->attacktype&AT_BLIND) {
1753  at = find_archetype("blindness");
1754  poison = present_arch_in_ob(at, tmp);
1755  if (poison) {
1756  success = 1;
1758  "Your vision begins to return.", NULL);
1759  poison->stats.food = 1;
1760  }
1761  }
1762  if (spell->last_sp && tmp->stats.sp < tmp->stats.maxsp) {
1763  tmp->stats.sp += spell->last_sp;
1764  if (tmp->stats.sp > tmp->stats.maxsp)
1765  tmp->stats.sp = tmp->stats.maxsp;
1766  success = 1;
1768  "Magical energies surge through your body!", NULL);
1769  }
1770  if (spell->last_grace && tmp->stats.grace < tmp->stats.maxgrace) {
1771  tmp->stats.grace += spell->last_grace;
1772  if (tmp->stats.grace > tmp->stats.maxgrace)
1773  tmp->stats.grace = tmp->stats.maxgrace;
1774  success = 1;
1776  "You feel redeemed with you god!", NULL);
1777  }
1778  if (spell->stats.food && tmp->stats.food < 999) {
1779  tmp->stats.food += spell->stats.food;
1780  if (tmp->stats.food > 999)
1781  tmp->stats.food = 999;
1782  success = 1;
1783  /* We could do something a bit better like the messages for healing above */
1785  "You feel your belly fill with food", NULL);
1786  }
1787  return success;
1788 }
1789 
1790 
1796 static const char *const no_gain_msgs[NUM_STATS] = {
1797  "You grow no stronger.",
1798  "You grow no more agile.",
1799  "You don't feel any healthier.",
1800  "no wis",
1801  "You are no easier to look at.",
1802  "no int",
1803  "no pow"
1804 };
1805 
1825 int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent) {
1826  object *tmp, *tmp2 = NULL;
1827  object *force = NULL;
1828  int i;
1829 
1830  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1831  if (dir != 0) {
1832  tmp = find_target_for_friendly_spell(op, dir);
1833  } else {
1834  tmp = op;
1835  }
1836 
1837  if (tmp == NULL)
1838  return 0;
1839 
1840  /* If we've already got a force of this type, don't add a new one. */
1841  for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below) {
1842  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
1843  if (tmp2->name == spell_ob->name) {
1844  force = tmp2; /* the old effect will be "refreshed" */
1845  break;
1846  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
1847  if (!silent)
1849  "You can not cast %s while %s is in effect",
1850  "You can not cast %s while %s is in effect",
1851  spell_ob->name, tmp2->name_pl);
1852  return 0;
1853  }
1854  }
1855  }
1856  if (force == NULL) {
1857  force = create_archetype(FORCE_NAME);
1858  force->subtype = FORCE_CHANGE_ABILITY;
1859  free_string(force->name);
1860  if (spell_ob->race)
1861  force->name = add_refcount(spell_ob->race);
1862  else
1863  force->name = add_refcount(spell_ob->name);
1864  free_string(force->name_pl);
1865  force->name_pl = add_refcount(spell_ob->name);
1866  } else {
1867  int duration;
1868 
1869  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1870  if (duration > force->duration) {
1871  force->duration = duration;
1873  "You recast the spell while in effect.", NULL);
1874  } else {
1876  "Recasting the spell had no effect.", NULL);
1877  }
1878  return 1;
1879  }
1880  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1881  if (op->type == PLAYER)
1882  store_spell_expiry(force);
1883  force->speed = 1.0;
1884  force->speed_left = -1.0;
1885  SET_FLAG(force, FLAG_APPLIED);
1886 
1887  /* Now start processing the effects. First, protections */
1888  for (i = 0; i < NROFATTACKS; i++) {
1889  if (spell_ob->resist[i]) {
1890  force->resist[i] = spell_ob->resist[i]+SP_level_dam_adjust(caster, spell_ob);
1891  if (force->resist[i] > 100)
1892  force->resist[i] = 100;
1893  }
1894  }
1895  if (spell_ob->stats.hp)
1896  force->stats.hp = spell_ob->stats.hp+SP_level_dam_adjust(caster, spell_ob);
1897 
1898  if (tmp->type == PLAYER) {
1899  /* Stat adjustment spells */
1900  for (i = 0; i < NUM_STATS; i++) {
1901  sint8 stat = get_attr_value(&spell_ob->stats, i), k, sm;
1902 
1903  if (stat) {
1904  sm = 0;
1905  for (k = 0; k < stat; k++)
1906  sm += rndm(1, 3);
1907 
1908  if ((get_attr_value(&tmp->stats, i)+sm) > (15+5*stat)) {
1909  sm = (15+5*stat)-get_attr_value(&tmp->stats, i);
1910  if (sm < 0)
1911  sm = 0;
1912  }
1913  set_attr_value(&force->stats, i, sm);
1914  if (!sm)
1916  no_gain_msgs[i], no_gain_msgs[i]);
1917  }
1918  }
1919  }
1920 
1921  force->move_type = spell_ob->move_type;
1922 
1923  if (QUERY_FLAG(spell_ob, FLAG_SEE_IN_DARK))
1924  SET_FLAG(force, FLAG_SEE_IN_DARK);
1925 
1926  if (QUERY_FLAG(spell_ob, FLAG_XRAYS))
1927  SET_FLAG(force, FLAG_XRAYS);
1928 
1929  /* Haste/bonus speed */
1930  if (spell_ob->stats.exp) {
1931  if (op->speed > 0.5)
1932  force->stats.exp = (float)spell_ob->stats.exp/(op->speed+0.5);
1933  else
1934  force->stats.exp = spell_ob->stats.exp;
1935  }
1936 
1937  force->stats.wc = spell_ob->stats.wc;
1938  force->stats.ac = spell_ob->stats.ac;
1939  force->attacktype = spell_ob->attacktype;
1940 
1941  SET_FLAG(tmp, FLAG_NO_FIX_PLAYER); /* we don't want insert_ob_in_ob to call fix_object. */
1942  insert_ob_in_ob(force, tmp);
1944  change_abil(tmp, force); /* Display any relevant messages, and call fix_object to update the player */
1945 
1946  return 1;
1947 }
1948 
1965 int cast_bless(object *op, object *caster, object *spell_ob, int dir) {
1966  int i;
1967  const object *god = find_god(determine_god(op));
1968  object *tmp2, *force = NULL, *tmp;
1969 
1970  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1971  if (dir != 0) {
1972  tmp = find_target_for_friendly_spell(op, dir);
1973  } else {
1974  tmp = op;
1975  }
1976 
1977  /* If we've already got a force of this type, don't add a new one. */
1978  for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below) {
1979  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
1980  if (tmp2->name == spell_ob->name) {
1981  force = tmp2; /* the old effect will be "refreshed" */
1982  break;
1983  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
1985  "You can not cast %s while %s is in effect",
1986  "You can not cast %s while %s is in effect",
1987  spell_ob->name, tmp2->name_pl);
1988  return 0;
1989  }
1990  }
1991  }
1992  if (force == NULL) {
1993  force = create_archetype(FORCE_NAME);
1994  force->subtype = FORCE_CHANGE_ABILITY;
1995  free_string(force->name);
1996  if (spell_ob->race)
1997  force->name = add_refcount(spell_ob->race);
1998  else
1999  force->name = add_refcount(spell_ob->name);
2000  free_string(force->name_pl);
2001  force->name_pl = add_refcount(spell_ob->name);
2002  } else {
2003  int duration;
2004 
2005  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2006  if (duration > force->duration) {
2007  force->duration = duration;
2009  "You recast the spell while in effect.", NULL);
2010  } else {
2012  "Recasting the spell had no effect.", NULL);
2013  }
2014  return 0;
2015  }
2016  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2017  force->speed = 1.0;
2018  force->speed_left = -1.0;
2019  SET_FLAG(force, FLAG_APPLIED);
2020 
2021  if (!god) {
2023  "Your blessing seems empty.", NULL);
2024  } else {
2025  /* Only give out good benefits, and put a max on it */
2026  for (i = 0; i < NROFATTACKS; i++) {
2027  if (god->resist[i] > 0) {
2028  force->resist[i] = MIN(god->resist[i], spell_ob->resist[ATNR_GODPOWER]);
2029  }
2030  }
2031  force->path_attuned |= god->path_attuned;
2032  if (spell_ob->attacktype) {
2033  force->attacktype |= god->attacktype|AT_PHYSICAL;
2034  if (god->slaying)
2035  force->slaying = add_string(god->slaying);
2036  }
2037  if (tmp != op) {
2039  "You bless %s.",
2040  "You bless %s.",
2041  tmp->name);
2043  "%s blessed you.",
2044  "%s blessed you.",
2045  op->name);
2046  } else {
2048  "You are blessed by %s!",
2049  "You are blessed by %s!",
2050  god->name);
2051  }
2052  }
2053  force->stats.wc = spell_ob->stats.wc;
2054  force->stats.ac = spell_ob->stats.ac;
2055 
2056  change_abil(tmp, force); /* Mostly to display any messages */
2057  insert_ob_in_ob(force, tmp);
2058  fix_object(tmp);
2059  return 1;
2060 }
2061 
2062 
2063 
2064 /*
2065  * Alchemy code by Mark Wedel
2066  *
2067  * This code adds a new spell, called alchemy. Alchemy will turn
2068  * objects to gold nuggets, the value of the gold nuggets being
2069  * from 5% to 40% of that of the item itself depending on casting level.
2070  * It uses the value of the object before charisma adjustments, because
2071  * the nuggets themselves will be will be adjusted by charisma when sold.
2072  *
2073  * Large nuggets are worth 25 gp each (base). You will always get
2074  * the maximum number of large nuggets you could get.
2075  * Small nuggets are worth 1 gp each (base). You will get from 0
2076  * to the max amount of small nuggets as you could get.
2077  *
2078  * For example, if an item is worth 110 gold, you will get
2079  * 4 large nuggets, and from 0-10 small nuggets.
2080  *
2081  * There is also a chance (1:30) that you will get nothing at all
2082  * for the object. There is also a maximum weight that will be
2083  * alchemied.
2084  */
2085 
2086 /* I didn't feel like passing these as arguements to the
2087  * two functions that need them. Real values are put in them
2088  * when the spell is cast, and these are freed when the spell
2089  * is finished.
2090  */
2091 static object *small, *large;
2093 static uint64 small_value, large_value;
2109 static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight) {
2110  uint64 value = query_cost(obj, NULL, F_TRUE);
2111 
2112  /* Multiply the value of the object by value_adj, which should range
2113  * from 0.05 to 0.40. Set value to 0 instead if unpaid.
2114  */
2115  if (QUERY_FLAG(obj, FLAG_UNPAID))
2116  value = 0;
2117  else
2118  value *= value_adj;
2119 
2120 
2121  /* Give half of what value_adj says when we alchemy money (This should
2122  * hopefully make it so that it isn't worth it to alchemy money, sell
2123  * the nuggets, alchemy the gold from that, etc.
2124  */
2125  if (value && (obj->type == MONEY || obj->type == GEM))
2126  value /= 2;
2127 
2128  if ((obj->value > 0) && rndm(0, 29)) {
2129  int count;
2130 
2131  count = value/large_value;
2132  *large_nuggets += count;
2133  value -= (uint64)count*large_value;
2134  count = value/small_value;
2135  *small_nuggets += count;
2136  }
2137 
2138  /* Turn 25 small nuggets into 1 large nugget. If the value
2139  * of large nuggets is not evenly divisable by the small nugget
2140  * value, take off an extra small_nugget (Assuming small_nuggets!=0)
2141  */
2142  if (*small_nuggets*small_value >= large_value) {
2143  (*large_nuggets)++;
2144  *small_nuggets -= large_value/small_value;
2145  if (*small_nuggets && large_value%small_value)
2146  (*small_nuggets)--;
2147  }
2148  weight += obj->weight;
2149  remove_ob(obj);
2150  free_object(obj);
2151 }
2152 
2166 static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y) {
2167  object *tmp;
2168  int flag = 0;
2169 
2170  /* Put any nuggets below the player, but we can only pass this
2171  * flag if we are on the same space as the player
2172  */
2173  if (x == op->x && y == op->y && op->map == m)
2174  flag = INS_BELOW_ORIGINATOR;
2175 
2176  if (small_nuggets) {
2177  tmp = get_object();
2178  copy_object(small, tmp);
2179  tmp-> nrof = small_nuggets;
2180  tmp->x = x;
2181  tmp->y = y;
2182  insert_ob_in_map(tmp, m, op, flag);
2183  }
2184  if (large_nuggets) {
2185  tmp = get_object();
2186  copy_object(large, tmp);
2187  tmp-> nrof = large_nuggets;
2188  tmp->x = x;
2189  tmp->y = y;
2190  insert_ob_in_map(tmp, m, op, flag);
2191  }
2192 }
2193 
2208 int alchemy(object *op, object *caster, object *spell_ob) {
2209  int x, y, weight = 0, weight_max, large_nuggets, small_nuggets, mflags;
2210  sint16 nx, ny;
2211  float value_adj;
2212  object *next, *tmp;
2213  mapstruct *mp;
2214 
2215  if (op->type != PLAYER)
2216  return 0;
2217 
2218  /* Put a maximum weight of items that can be alchemied. Limits the power
2219  * some, and also prevents people from alcheming every table/chair/clock
2220  * in sight
2221  */
2222  weight_max = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
2223  weight_max *= 1000;
2224  small = create_archetype("smallnugget"),
2225  large = create_archetype("largenugget");
2226  small_value = query_cost(small, NULL, F_TRUE);
2227  large_value = query_cost(large, NULL, F_TRUE);
2228 
2229  /* Set value_adj to be a multiplier for how much of the original value
2230  * will be in the nuggets. Starts at 0.05, increasing by 0.01 per casting
2231  * level, maxing out at 0.40.
2232  */
2233  value_adj = (SP_level_dam_adjust(caster, spell_ob)/100.00)+0.05;
2234 
2235  if (value_adj > 0.40)
2236  value_adj = 0.40;
2237 
2238  for (y = op->y-1; y <= op->y+1; y++) {
2239  for (x = op->x-1; x <= op->x+1; x++) {
2240  nx = x;
2241  ny = y;
2242 
2243  mp = op->map;
2244 
2245  mflags = get_map_flags(mp, &mp, nx, ny, &nx, &ny);
2246 
2247  if (mflags&(P_OUT_OF_MAP|P_NO_MAGIC))
2248  continue;
2249 
2250  /* Treat alchemy a little differently - most spell effects
2251  * use fly as the movement type - for alchemy, consider it
2252  * ground level effect.
2253  */
2254  if (GET_MAP_MOVE_BLOCK(mp, nx, ny)&MOVE_WALK)
2255  continue;
2256 
2257  small_nuggets = 0;
2258  large_nuggets = 0;
2259 
2260  for (tmp = GET_MAP_OB(mp, nx, ny); tmp != NULL; tmp = next) {
2261  next = tmp->above;
2262  if (tmp->weight > 0 && !QUERY_FLAG(tmp, FLAG_NO_PICK)
2263  && !QUERY_FLAG(tmp, FLAG_ALIVE)
2264  && !QUERY_FLAG(tmp, FLAG_IS_CAULDRON)) {
2265  if (tmp->inv) {
2266  object *next1, *tmp1;
2267  for (tmp1 = tmp->inv; tmp1 != NULL; tmp1 = next1) {
2268  next1 = tmp1->below;
2269  if (tmp1->weight > 0 && !QUERY_FLAG(tmp1, FLAG_NO_PICK)
2270  && !QUERY_FLAG(tmp1, FLAG_ALIVE)
2271  && !QUERY_FLAG(tmp1, FLAG_IS_CAULDRON))
2272  alchemy_object(value_adj, tmp1, &small_nuggets, &large_nuggets, &weight);
2273  }
2274  }
2275  alchemy_object(value_adj, tmp, &small_nuggets, &large_nuggets, &weight);
2276 
2277  if (weight > weight_max) {
2278  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2279  free_object(large);
2280  free_object(small);
2281  return 1;
2282  }
2283  } /* is alchemable object */
2284  } /* process all objects on this space */
2285 
2286  /* Insert all the nuggets at one time. This probably saves time, but
2287  * it also prevents us from alcheming nuggets that were just created
2288  * with this spell.
2289  */
2290  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2291  }
2292  }
2293  free_object(large);
2294  free_object(small);
2295  /* reset this so that if player standing on a big pile of stuff,
2296  * it is redrawn properly.
2297  */
2298  op->contr->socket.look_position = 0;
2299  return 1;
2300 }
2301 
2302 
2317 int remove_curse(object *op, object *caster, object *spell) {
2318  object *tmp;
2319  int success = 0, was_one = 0;
2320 
2321  for (tmp = op->inv; tmp; tmp = tmp->below)
2322  if (QUERY_FLAG(tmp, FLAG_APPLIED)
2323  && ((QUERY_FLAG(tmp, FLAG_CURSED) && QUERY_FLAG(spell, FLAG_CURSED))
2324  || (QUERY_FLAG(tmp, FLAG_DAMNED) && QUERY_FLAG(spell, FLAG_DAMNED)))) {
2325  was_one++;
2326  if (tmp->level <= caster_level(caster, spell)) {
2327  success++;
2328  if (QUERY_FLAG(spell, FLAG_DAMNED))
2329  CLEAR_FLAG(tmp, FLAG_DAMNED);
2330 
2331  CLEAR_FLAG(tmp, FLAG_CURSED);
2333  tmp->value = 0; /* Still can't sell it */
2334  if (op->type == PLAYER)
2335  esrv_update_item(UPD_FLAGS, op, tmp);
2336  }
2337  }
2338 
2339  if (op->type == PLAYER) {
2340  if (success) {
2342  "You feel like some of your items are looser now.", NULL);
2343  } else {
2344  if (was_one)
2346  "You failed to remove the curse.", NULL);
2347  else
2349  "You are not using any cursed items.", NULL);
2350  }
2351  }
2352  return success;
2353 }
2354 
2367 int cast_item_curse_or_curse(object *op, object *caster, object *spell_ob) {
2368  object *marked = find_marked_object(op);
2369  char name[HUGE_BUF];
2370 
2371  if (!marked) {
2373  "You need to mark an item first!", NULL);
2374  return 0;
2375  }
2376 
2377  if ((QUERY_FLAG(marked, FLAG_CURSED) && QUERY_FLAG(spell_ob, FLAG_CURSED))
2378  || (QUERY_FLAG(marked, FLAG_BLESSED) && QUERY_FLAG(spell_ob, FLAG_BLESSED))) {
2380  "The spell has no effect", NULL);
2381  return 0;
2382  }
2383 
2384  query_short_name(marked, name, HUGE_BUF);
2385  if (QUERY_FLAG(spell_ob, FLAG_CURSED)) {
2387  "Your %s emits a dark light for a few seconds.", "Your %s emits a dark light for a few seconds.", name);
2388  SET_FLAG(marked, FLAG_CURSED);
2389  CLEAR_FLAG(marked, FLAG_KNOWN_CURSED);
2390  CLEAR_FLAG(marked, FLAG_IDENTIFIED);
2391  esrv_update_item(UPD_FLAGS, op, marked);
2392  return 1;
2393 
2394  }
2395 
2397  "Your %s glows blue for a few seconds.", "Your %s glows blue for a few seconds.", name);
2398  SET_FLAG(marked, FLAG_BLESSED);
2399  SET_FLAG(marked, FLAG_KNOWN_BLESSED);
2400  SET_FLAG(marked, FLAG_STARTEQUIP);
2401  esrv_update_item(UPD_FLAGS, op, marked);
2402  return 1;
2403 }
2404 
2419 int cast_identify(object *op, object *caster, object *spell) {
2420  object *tmp;
2421  int success = 0, num_ident;
2422  char desc[MAX_BUF];
2423 
2424  num_ident = spell->stats.dam+SP_level_dam_adjust(caster, spell);
2425 
2426  if (num_ident < 1)
2427  num_ident = 1;
2428 
2429  for (tmp = op->inv; tmp; tmp = tmp->below) {
2430  if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify(tmp)) {
2431  identify(tmp);
2432  if (op->type == PLAYER) {
2434  "You have %s.",
2435  "You have %s.",
2436  ob_describe(tmp, op, desc, sizeof(desc)));
2437  if (tmp->msg) {
2439  "The item has a story:\n%s",
2440  "The item has a story:\n%s",
2441  tmp->msg);
2442  }
2443  }
2444  num_ident--;
2445  success = 1;
2446  if (!num_ident)
2447  break;
2448  }
2449  }
2450  /* If all the power of the spell has been used up, don't go and identify
2451  * stuff on the floor. Only identify stuff on the floor if the spell
2452  * was not fully used.
2453  */
2454  if (num_ident) {
2455  for (tmp = GET_MAP_OB(op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
2456  if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED)
2457  && !tmp->invisible
2458  && need_identify(tmp)) {
2459  identify(tmp);
2460  if (op->type == PLAYER) {
2462  "On the ground is %s.",
2463  "On the ground is %s.",
2464  ob_describe(tmp, op, desc, sizeof(desc)));
2465  if (tmp->msg) {
2467  "The item has a story:\n%s",
2468  "The item has a story:\n%s",
2469  tmp->msg);
2470  }
2472  }
2473  num_ident--;
2474  success = 1;
2475  if (!num_ident)
2476  break;
2477  }
2478  }
2479  if (!success)
2481  "You can't reach anything unidentified.", NULL);
2482  else {
2483  spell_effect(spell, op->x, op->y, op->map, op);
2484  }
2485  return success;
2486 }
2487 
2500 int cast_detection(object *op, object *caster, object *spell) {
2501  object *tmp, *last, *detect;
2502  const object *god;
2503  int done_one, range, mflags, floor, level;
2504  sint16 x, y, nx, ny;
2505  mapstruct *m;
2506 
2507  /* We precompute some values here so that we don't have to keep
2508  * doing it over and over again.
2509  */
2510  god = find_god(determine_god(op));
2511  level = caster_level(caster, spell);
2512  range = spell->range+SP_level_range_adjust(caster, spell);
2513 
2514  for (x = op->x-range; x <= op->x+range; x++)
2515  for (y = op->y-range; y <= op->y+range; y++) {
2516 
2517  m = op->map;
2518  mflags = get_map_flags(m, &m, x, y, &nx, &ny);
2519  if (mflags&P_OUT_OF_MAP)
2520  continue;
2521 
2522  /* For most of the detections, we only detect objects above the
2523  * floor. But this is not true for show invisible.
2524  * Basically, we just go and find the top object and work
2525  * down - that is easier than working up.
2526  */
2527 
2528  for (last = NULL, tmp = GET_MAP_OB(m, nx, ny); tmp; tmp = tmp->above)
2529  last = tmp;
2530  /* Shouldn't happen, but if there are no objects on a space, this
2531  * would happen.
2532  */
2533  if (!last)
2534  continue;
2535 
2536  done_one = 0;
2537  floor = 0;
2538  detect = NULL;
2539  for (tmp = last; tmp; tmp = tmp->below) {
2540  /* show invisible */
2541  if (QUERY_FLAG(spell, FLAG_MAKE_INVIS)
2542  /* Might there be other objects that we can make visibile? */
2543  && (tmp->invisible && (QUERY_FLAG(tmp, FLAG_MONSTER) ||
2544  (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)) ||
2545  tmp->type == CF_HANDLE ||
2546  tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
2547  tmp->type == BUTTON || tmp->type == TELEPORTER ||
2548  tmp->type == GATE || tmp->type == LOCKED_DOOR ||
2549  tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
2550  tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
2551  tmp->type == TREASURE || tmp->type == BOOK ||
2552  tmp->type == HOLY_ALTAR))) {
2553  if (random_roll(0, level-1, op, PREFER_HIGH) > tmp->level) {
2554  tmp->invisible = 0;
2555  done_one = 1;
2556  }
2557  }
2558  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2559  floor = 1;
2560 
2561  /* All detections below this point don't descend beneath the floor,
2562  * so just continue on. We could be clever and look at the type of
2563  * detection to completely break out if we don't care about objects beneath
2564  * the floor, but once we get to the floor, not likely a very big issue anyways.
2565  */
2566  if (floor)
2567  continue;
2568 
2569  /* I had thought about making detect magic and detect curse
2570  * show the flash the magic item like it does for detect monster.
2571  * however, if the object is within sight, this would then make it
2572  * difficult to see what object is magical/cursed, so the
2573  * effect wouldn't be as apparant.
2574  */
2575 
2576  /* detect magic */
2577  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2578  && !QUERY_FLAG(tmp, FLAG_KNOWN_MAGICAL)
2579  && !QUERY_FLAG(tmp, FLAG_IDENTIFIED)
2580  && is_magical(tmp)) {
2582  /* make runes more visibile */
2583  if (tmp->type == RUNE && tmp->attacktype&AT_MAGIC)
2584  tmp->stats.Cha /= 4;
2585  done_one = 1;
2586  }
2587  /* detect monster */
2588  if (QUERY_FLAG(spell, FLAG_MONSTER)
2589  && (QUERY_FLAG(tmp, FLAG_MONSTER) || (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)))) {
2590  done_one = 2;
2591  if (!detect)
2592  detect = tmp;
2593  }
2594  /* Basically, if race is set in the spell, then the creatures race must
2595  * match that. if the spell race is set to GOD, then the gods opposing
2596  * race must match.
2597  */
2598  if (spell->race
2599  && QUERY_FLAG(tmp, FLAG_MONSTER)
2600  && tmp->race
2601  && ((!strcmp(spell->race, "GOD") && god && god->slaying && strstr(god->slaying, tmp->race)) || (strstr(spell->race, tmp->race)))) {
2602  done_one = 2;
2603  if (!detect)
2604  detect = tmp;
2605  }
2606  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2607  && !QUERY_FLAG(tmp, FLAG_KNOWN_CURSED)
2608  && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) {
2610  done_one = 1;
2611  }
2612  } /* for stack of objects on this space */
2613 
2614  /* Code here puts an effect of the spell on the space, so you can see
2615  * where the magic is.
2616  */
2617  if (done_one) {
2618  object *detect_ob = arch_to_object(spell->other_arch);
2619 
2620  detect_ob->x = nx;
2621  detect_ob->y = ny;
2622  /* if this is set, we want to copy the face */
2623  if (done_one == 2 && detect) {
2624  detect_ob->face = detect->face;
2625  detect_ob->animation_id = detect->animation_id;
2626  detect_ob->anim_speed = detect->anim_speed;
2627  detect_ob->last_anim = 0;
2628  /* by default, the detect_ob is already animated */
2629  if (!QUERY_FLAG(detect, FLAG_ANIMATE))
2630  CLEAR_FLAG(detect_ob, FLAG_ANIMATE);
2631  }
2632  insert_ob_in_map(detect_ob, m, op, 0);
2633  }
2634  } /* for processing the surrounding spaces */
2635 
2636 
2637  /* Now process objects in the players inventory if detect curse or magic */
2638  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED) || QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)) {
2639  done_one = 0;
2640  for (tmp = op->inv; tmp; tmp = tmp->below) {
2641  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_IDENTIFIED)) {
2642  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2643  && is_magical(tmp)
2644  && !QUERY_FLAG(tmp, FLAG_KNOWN_MAGICAL)) {
2646  if (op->type == PLAYER)
2647  esrv_send_item(op, tmp);
2648  }
2649  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2650  && !QUERY_FLAG(tmp, FLAG_KNOWN_CURSED)
2651  && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) {
2653  if (op->type == PLAYER)
2654  esrv_send_item(op, tmp);
2655  }
2656  } /* if item is not identified */
2657  } /* for the players inventory */
2658  } /* if detect magic/curse and object is a player */
2659  return 1;
2660 }
2661 
2669 static void charge_mana_effect(object *victim, int caster_level) {
2670  /* Prevent explosions for objects without mana. Without this check, doors
2671  * will explode, too.
2672  */
2673  if (victim->stats.maxsp <= 0)
2674  return;
2675 
2677  "You feel energy course through you.", NULL);
2678 
2679  if (victim->stats.sp >= victim->stats.maxsp*2) {
2680  object *tmp;
2681 
2683  "Your head explodes!", NULL);
2684 
2685  /* Explodes a fireball centered at player */
2687  tmp->dam_modifier = random_roll(1, caster_level, victim, PREFER_LOW)/5+1;
2688  tmp->stats.maxhp = random_roll(1, caster_level, victim, PREFER_LOW)/10+2;
2689  tmp->x = victim->x;
2690  tmp->y = victim->y;
2691  insert_ob_in_map(tmp, victim->map, NULL, 0);
2692  victim->stats.sp = 2*victim->stats.maxsp;
2693  } else if (victim->stats.sp >= victim->stats.maxsp*1.88) {
2695  "You feel like your head is going to explode.", NULL);
2696  } else if (victim->stats.sp >= victim->stats.maxsp*1.66) {
2698  "You get a splitting headache!", NULL);
2699  } else if (victim->stats.sp >= victim->stats.maxsp*1.5) {
2701  "Chaos fills your world.", NULL);
2702  confuse_living(victim, victim, 99);
2703  } else if (victim->stats.sp >= victim->stats.maxsp*1.25) {
2705  "You start hearing voices.", NULL);
2706  }
2707 }
2708 
2726 int cast_transfer(object *op, object *caster, object *spell, int dir) {
2727  object *plyr = NULL;
2728  sint16 x, y;
2729  mapstruct *m;
2730  int mflags;
2731 
2732  m = op->map;
2733  x = op->x+freearr_x[dir];
2734  y = op->y+freearr_y[dir];
2735 
2736  mflags = get_map_flags(m, &m, x, y, &x, &y);
2737  if (!(mflags&P_OUT_OF_MAP) && mflags&P_IS_ALIVE) {
2738  for (plyr = GET_MAP_OB(m, x, y); plyr != NULL; plyr = plyr->above)
2739  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2740  break;
2741  }
2742 
2743  /* If we did not find a player in the specified direction, transfer
2744  * to anyone on top of us. This is used for the rune of transference mostly.
2745  */
2746  if (plyr == NULL)
2747  for (plyr = GET_MAP_OB(op->map, op->x, op->y); plyr != NULL; plyr = plyr->above)
2748  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2749  break;
2750 
2751  if (!plyr) {
2753  "There is no one there.", NULL);
2754  return 0;
2755  }
2756 
2757  /* give sp */
2758  if (spell->stats.dam > 0) {
2759  plyr->stats.sp += spell->stats.dam+SP_level_dam_adjust(caster, spell);
2760  charge_mana_effect(plyr, caster_level(caster, spell));
2761  return 1;
2762  /* suck sp away. Can't suck sp from yourself */
2763  } else if (op != plyr) {
2764  /* old dragin magic used floats. easier to just use ints and divide by 100 */
2765 
2766  int rate = -spell->stats.dam+SP_level_dam_adjust(caster, spell), sucked;
2767 
2768  if (rate > 95)
2769  rate = 95;
2770 
2771  sucked = (plyr->stats.sp*rate)/100;
2772  plyr->stats.sp -= sucked;
2773  if (QUERY_FLAG(op, FLAG_ALIVE)) {
2774  /* Player doesn't get full credit */
2775  sucked = (sucked*rate)/100;
2776  op->stats.sp += sucked;
2777  if (sucked > 0) {
2778  charge_mana_effect(op, caster_level(caster, spell));
2779  }
2780  }
2781  return 1;
2782  }
2783  return 0;
2784 }
2785 
2795 void counterspell(object *op, int dir) {
2796  object *tmp, *head, *next;
2797  int mflags;
2798  mapstruct *m;
2799  sint16 sx, sy;
2800 
2801  sx = op->x+freearr_x[dir];
2802  sy = op->y+freearr_y[dir];
2803  m = op->map;
2804  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2805  if (mflags&P_OUT_OF_MAP)
2806  return;
2807 
2808  for (tmp = GET_MAP_OB(m, sx, sy); tmp != NULL; tmp = next) {
2809  next = tmp->above;
2810 
2811  /* Need to look at the head object - otherwise, if tmp
2812  * points to a monster, we don't have all the necessary
2813  * info for it.
2814  */
2815  if (tmp->head)
2816  head = tmp->head;
2817  else
2818  head = tmp;
2819 
2820  /* don't attack our own spells */
2821  if (tmp->owner && tmp->owner == op->owner)
2822  continue;
2823 
2824  /* Basically, if the object is magical and not counterspell,
2825  * we will more or less remove the object. Don't counterspell
2826  * monsters either.
2827  */
2828 
2829  if (head->attacktype&AT_MAGIC
2830  && !(head->attacktype&AT_COUNTERSPELL)
2831  && !QUERY_FLAG(head, FLAG_MONSTER)
2832  && (op->level > head->level)) {
2833  remove_ob(head);
2834  free_object(head);
2835  } else switch (head->type) {
2836  case SPELL_EFFECT:
2837  if ((op->level > head->level) && !op->stats.food && !op->speed_left) {
2838  remove_ob(head);
2839  free_object(head);
2840  }
2841  break;
2842 
2843  /* I really don't get this rune code that much - that
2844  * random chance seems really low.
2845  */
2846  case RUNE:
2847  if (rndm(0, 149) == 0) {
2848  head->stats.hp--; /* weaken the rune */
2849  if (!head->stats.hp) {
2850  remove_ob(head);
2851  free_object(head);
2852  }
2853  }
2854  break;
2855  }
2856  }
2857 }
2858 
2873 int cast_consecrate(object *op, object *caster, object *spell) {
2874  char buf[MAX_BUF];
2875  object *tmp;
2876  const object *god = find_god(determine_god(op));
2877 
2878  if (!god) {
2880  "You can't consecrate anything if you don't worship a god!", NULL);
2881  return 0;
2882  }
2883 
2884  for (tmp = op->below; tmp; tmp = tmp->below) {
2885  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2886  break;
2887  if (tmp->type == HOLY_ALTAR) {
2888  if (tmp->level > caster_level(caster, spell)) {
2890  "You are not powerful enough to reconsecrate the %s",
2891  "You are not powerful enough to reconsecrate the %s",
2892  tmp->name);
2893  return 0;
2894  } else {
2895  /* If we got here, we are consecrating an altar */
2896  object *new_altar;
2897  int letter;
2898  archetype *altar_arch;
2899 
2900  snprintf(buf, MAX_BUF, "altar_");
2901  letter = strlen(buf);
2902  strncpy(buf+letter, god->name, MAX_BUF-letter);
2903  for (; letter < strlen(buf); letter++)
2904  buf[letter] = tolower(buf[letter]);
2905  altar_arch = find_archetype(buf);
2906  if (!altar_arch) {
2908  "You fail to consecrate the altar.", NULL);
2909  LOG(llevError, "cast_consecrate: can't find altar %s for god %s\n", buf, god->name);
2910  return 0;
2911  }
2912  new_altar = arch_to_object(altar_arch);
2913  new_altar->x = tmp->x;
2914  new_altar->y = tmp->y;
2915  new_altar->level = tmp->level;
2916  insert_ob_in_map(new_altar, tmp->map, tmp, INS_BELOW_ORIGINATOR);
2917  remove_ob(tmp);
2919  "You consecrated the altar to %s!",
2920  "You consecrated the altar to %s!",
2921  god->name);
2922  return 1;
2923  }
2924  }
2925  }
2927  "You are not standing over an altar!", NULL);
2928  return 0;
2929 }
2930 
2954 int animate_weapon(object *op, object *caster, object *spell, int dir) {
2955  object *weapon, *tmp;
2956  char buf[MAX_BUF];
2957  int a, i;
2958  sint16 x, y;
2959  mapstruct *m;
2960  materialtype_t *mt;
2961 
2962  if (!spell->other_arch) {
2964  "Oops, program error!", NULL);
2965  LOG(llevError, "animate_weapon failed: spell %s missing other_arch!\n", spell->name);
2966  return 0;
2967  }
2968 
2969  /* exit if it's not a player using this spell. */
2970  if (op->type != PLAYER)
2971  return 0;
2972 
2973  /* if player already has a golem, abort */
2974  if (op->contr->ranges[range_golem] != NULL && op->contr->golem_count == op->contr->ranges[range_golem]->count) {
2975  control_golem(op->contr->ranges[range_golem], dir);
2976  return 0;
2977  }
2978 
2979  /* if no direction specified, pick one */
2980  if (!dir)
2981  dir = find_free_spot(NULL, op->map, op->x, op->y, 1, 9);
2982 
2983  m = op->map;
2984  x = op->x+freearr_x[dir];
2985  y = op->y+freearr_y[dir];
2986 
2987  /* if there's no place to put the golem, abort */
2988  if ((dir == -1)
2989  || (get_map_flags(m, &m, x, y, &x, &y)&P_OUT_OF_MAP)
2990  || ((spell->other_arch->clone.move_type&GET_MAP_MOVE_BLOCK(m, x, y)) == spell->other_arch->clone.move_type)) {
2992  "There is something in the way.", NULL);
2993  return 0;
2994  }
2995 
2996  /* Use the weapon marked by the player. */
2997  weapon = find_marked_object(op);
2998 
2999  if (!weapon) {
3001  "You must mark a weapon to use with this spell!", NULL);
3002  return 0;
3003  }
3004  if (spell->race && strcmp(weapon->arch->name, spell->race)) {
3006  "The spell fails to transform your weapon.", NULL);
3007  return 0;
3008  }
3009  if (weapon->type != WEAPON) {
3011  "You need to mark a weapon to animate it.", NULL);
3012  return 0;
3013  }
3014  if (QUERY_FLAG(weapon, FLAG_UNPAID)) {
3016  "You need to pay for the weapon to animate it.", NULL);
3017  return 0;
3018  }
3019  if (QUERY_FLAG(weapon, FLAG_APPLIED)) {
3020  char wn[MAX_BUF];
3021 
3022  query_name(weapon, wn, MAX_BUF);
3024  "You need to unequip %s before using it in this spell",
3025  "You need to unequip %s before using it in this spell",
3026  wn);
3027  return 0;
3028  }
3029 
3030  if (weapon->nrof > 1) {
3031  tmp = get_split_ob(weapon, 1, NULL, 0);
3032  esrv_update_item(UPD_NROF, op, weapon);
3033  weapon = tmp;
3034  }
3035 
3036  /* create the golem object */
3037  tmp = arch_to_object(spell->other_arch);
3038 
3039  /* if animated by a player, give the player control of the golem */
3040  CLEAR_FLAG(tmp, FLAG_MONSTER);
3041  SET_FLAG(tmp, FLAG_FRIENDLY);
3042  tmp->stats.exp = 0;
3043  add_friendly_object(tmp);
3044  tmp->type = GOLEM;
3045  set_owner(tmp, op);
3046  set_spell_skill(op, caster, spell, tmp);
3047  op->contr->ranges[range_golem] = tmp;
3048  op->contr->shoottype = range_golem;
3049  op->contr->golem_count = tmp->count;
3050 
3051  /* Give the weapon to the golem now. A bit of a hack to check the
3052  * removed flag - it should only be set if get_split_object was
3053  * used above.
3054  */
3055  if (!QUERY_FLAG(weapon, FLAG_REMOVED))
3056  remove_ob(weapon);
3057  insert_ob_in_ob(weapon, tmp);
3058 
3059  /* To do everything necessary to let a golem use the weapon is a pain,
3060  * so instead, just set it as equipped (otherwise, we need to update
3061  * body_info, skills, etc)
3062  */
3063  SET_FLAG(tmp, FLAG_USE_WEAPON);
3064  SET_FLAG(weapon, FLAG_APPLIED);
3065  fix_object(tmp);
3066 
3067  /* There used to be 'odd' code that basically seemed to take the absolute
3068  * value of the weapon->magic an use that. IMO, that doesn't make sense -
3069  * if you're using a crappy weapon, it shouldn't be as good.
3070  */
3071 
3072  /* modify weapon's animated wc */
3073  tmp->stats.wc = tmp->stats.wc
3074  -SP_level_range_adjust(caster, spell)
3075  -5*weapon->stats.Dex
3076  -2*weapon->stats.Str
3077  -weapon->magic;
3078  if (tmp->stats.wc < -127)
3079  tmp->stats.wc = -127;
3080 
3081  /* Modify hit points for weapon */
3082  tmp->stats.maxhp = tmp->stats.maxhp
3083  +spell->duration
3084  +SP_level_duration_adjust(caster, spell)
3085  +8*weapon->magic
3086  +12*weapon->stats.Con;
3087  if (tmp->stats.maxhp < 0)
3088  tmp->stats.maxhp = 10;
3089  tmp->stats.hp = tmp->stats.maxhp;
3090 
3091  /* Modify weapon's damage */
3092  tmp->stats.dam = spell->stats.dam
3093  +SP_level_dam_adjust(caster, spell)
3094  +weapon->stats.dam
3095  +weapon->magic
3096  +5*weapon->stats.Str;
3097  if (tmp->stats.dam < 0)
3098  tmp->stats.dam = 127;
3099 
3100  /* attacktype */
3101  if (!tmp->attacktype)
3102  tmp->attacktype = AT_PHYSICAL;
3103 
3104  mt = NULL;
3105  if (op->materialname != NULL)
3106  mt = name_to_material(op->materialname);
3107  if (mt != NULL) {
3108  for (i = 0; i < NROFATTACKS; i++)
3109  tmp->resist[i] = 50-(mt->save[i]*5);
3110  a = mt->save[0];
3111  } else {
3112  for (i = 0; i < NROFATTACKS; i++)
3113  tmp->resist[i] = 5;
3114  a = 10;
3115  }
3116  /* Set weapon's immunity */
3117  tmp->resist[ATNR_CONFUSION] = 100;
3118  tmp->resist[ATNR_POISON] = 100;
3119  tmp->resist[ATNR_SLOW] = 100;
3120  tmp->resist[ATNR_PARALYZE] = 100;
3121  tmp->resist[ATNR_TURN_UNDEAD] = 100;
3122  tmp->resist[ATNR_FEAR] = 100;
3123  tmp->resist[ATNR_DEPLETE] = 100;
3124  tmp->resist[ATNR_DEATH] = 100;
3125  tmp->resist[ATNR_BLIND] = 100;
3126 
3127  /* Improve weapon's armour value according to best save vs. physical of its material */
3128 
3129  if (a > 14)
3130  a = 14;
3131  tmp->resist[ATNR_PHYSICAL] = 100-(int)((100.0-(float)tmp->resist[ATNR_PHYSICAL])/(30.0-2.0*a));
3132 
3133  /* Determine golem's speed */
3134  tmp->speed = 0.4+0.1*SP_level_range_adjust(caster, spell);
3135 
3136  if (tmp->speed > 3.33)
3137  tmp->speed = 3.33;
3138 
3139  if (!spell->race) {
3140  snprintf(buf, sizeof(buf), "animated %s", weapon->name);
3141  if (tmp->name)
3142  free_string(tmp->name);
3143  tmp->name = add_string(buf);
3144 
3145  tmp->face = weapon->face;
3146  tmp->animation_id = weapon->animation_id;
3147  tmp->anim_speed = weapon->anim_speed;
3148  tmp->last_anim = weapon->last_anim;
3149  tmp->state = weapon->state;
3150  if (QUERY_FLAG(weapon, FLAG_ANIMATE)) {
3151  SET_FLAG(tmp, FLAG_ANIMATE);
3152  } else {
3153  CLEAR_FLAG(tmp, FLAG_ANIMATE);
3154  }
3155  update_ob_speed(tmp);
3156  }
3157 
3158  /* make experience increase in proportion to the strength of the summoned creature. */
3159  tmp->stats.exp *= 1+(MAX(spell->stats.maxgrace, spell->stats.sp)/caster_level(caster, spell));
3160 
3161  tmp->speed_left = -1;
3162  tmp->x = x;
3163  tmp->y = y;
3164  tmp->direction = dir;
3165  insert_ob_in_map(tmp, m, op, 0);
3166  return 1;
3167 }
3168 
3183 int cast_change_map_lightlevel(object *op, object *caster, object *spell) {
3184  int success;
3185 
3186  if (!op->map)
3187  return 0; /* shouldnt happen */
3188 
3189  success = change_map_light(op->map, spell->stats.dam);
3190  if (!success) {
3191  if (spell->stats.dam < 0)
3193  "It can be no brighter here.", NULL);
3194  else
3196  "It can be no darker here.", NULL);
3197  }
3198  return success;
3199 }
3200 
3213 int create_aura(object *op, object *caster, object *spell) {
3214  int refresh = 0;
3215  object *new_aura;
3216 
3217  new_aura = present_arch_in_ob(spell->other_arch, op);
3218  if (new_aura)
3219  refresh = 1;
3220  else
3221  new_aura = arch_to_object(spell->other_arch);
3222 
3223  new_aura->duration = spell->duration+10*SP_level_duration_adjust(caster, spell);
3224  if (op->type == PLAYER)
3225  store_spell_expiry(new_aura);
3226 
3227  new_aura->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
3228 
3229  set_owner(new_aura, op);
3230  set_spell_skill(op, caster, spell, new_aura);
3231  new_aura->attacktype = spell->attacktype;
3232 
3233  new_aura->level = caster_level(caster, spell);
3234  if (refresh)
3236  "You recast the spell while in effect.", NULL);
3237  else
3238  insert_ob_in_ob(new_aura, op);
3239  return 1;
3240 }
3241 
3257 int write_mark(object *op, object *spell, const char *msg) {
3258  char rune[HUGE_BUF];
3259  object *tmp;
3260 
3261  if (!msg || msg[0] == 0) {
3263  "Write what?", NULL);
3264  return 0;
3265  }
3266 
3267  if (strcasestr_local(msg, "endmsg")) {
3269  "Trying to cheat are we?", NULL);
3270  LOG(llevInfo, "write_rune: player %s tried to write bogus rune %s\n", op->name, msg);
3271  return 0;
3272  }
3273 
3274  if (!spell->other_arch)
3275  return 0;
3276  tmp = arch_to_object(spell->other_arch);
3277  strncpy(rune, msg, HUGE_BUF-2);
3278  rune[HUGE_BUF-2] = 0;
3279  strcat(rune, "\n");
3280  tmp->race = add_string(op->name); /*Save the owner of the rune*/
3281  tmp->msg = add_string(rune);
3282  tmp->x = op->x;
3283  tmp->y = op->y;
3284  insert_ob_in_map(tmp, op->map, op, INS_BELOW_ORIGINATOR);
3285  return 1;
3286 }
sint16 bed_x
Definition: player.h:152
#define UPD_FLAGS
Definition: newclient.h:255
char path[HUGE_BUF]
Definition: map.h:384
Definition: object.h:132
#define FLAG_KNOWN_BLESSED
Definition: define.h:675
#define FOOD
Definition: define.h:118
#define RING
Definition: define.h:232
signed char sint8
Definition: global.h:80
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, sint16 x, sint16 y, sint16 *nx, sint16 *ny)
Definition: map.c:330
#define FLAG_NO_DROP
Definition: define.h:585
Definition: player.h:146
void cast_magic_storm(object *op, object *tmp, int lvl)
Definition: spell_effect.c:55
#define FLAG_SEE_IN_DARK
Definition: define.h:634
const char * determine_god(object *op)
Definition: gods.c:118
archetype * find_archetype(const char *name)
Definition: arch.c:700
#define FLAG_DAMNED
Definition: define.h:614
#define FLAG_IS_FLOOR
Definition: define.h:599
#define FLAG_UNPAID
Definition: define.h:532
sint8 ac
Definition: living.h:79
#define MOVE_WALK
Definition: define.h:700
#define UP_OBJ_FACE
Definition: object.h:356
#define FORCE_CHANGE_ABILITY
Definition: spells.h:172
MoveType move_type
Definition: object.h:277
#define INS_BELOW_ORIGINATOR
Definition: object.h:398
#define BUTTON
Definition: define.h:274
int cast_bless(object *op, object *caster, object *spell_ob, int dir)
#define AT_COUNTERSPELL
Definition: attack.h:123
#define TRAPDOOR
Definition: define.h:277
signed short sint16
Definition: global.h:72
#define TELEPORTER
Definition: define.h:155
object * find_obj_by_type_subtype(const object *who, int type, int subtype)
Definition: object.c:3656
materialtype_t * name_to_material(const char *name)
Definition: utils.c:262
const char * race
Definition: object.h:171
void set_owner(object *op, object *owner)
Definition: object.c:564
int is_magical(const object *op)
Definition: item.c:1312
#define ATNR_TURN_UNDEAD
Definition: attack.h:90
int cast_detection(object *op, object *caster, object *spell)
int caster_level(const object *caster, const object *spell)
Definition: spell_util.c:237
uint16 attack_movement
Definition: object.h:242
void esrv_send_item(object *pl, object *op)
Definition: standalone.c:197
#define SET_FLAG(xyz, p)
Definition: define.h:510
sstring add_refcount(sstring str)
Definition: shstr.c:202
#define FABS(x)
Definition: define.h:61
static uint64 large_value
int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
Definition: spell_effect.c:639
sint8 range
Definition: object.h:256
#define WAND
Definition: define.h:291
#define UPD_NAME
Definition: newclient.h:258
#define FLAG_IS_USED_UP
Definition: define.h:556
static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y)
int write_mark(object *op, object *spell, const char *msg)
#define NDI_ORANGE
Definition: newclient.h:199
#define FLAG_FRIENDLY
Definition: define.h:542
#define P_NO_MAGIC
Definition: map.h:248
#define MONEY
Definition: define.h:148
#define MSG_TYPE_ITEM
Definition: newclient.h:334
struct artifactstruct * items
Definition: artifact.h:52
object * mon
Definition: comet_perf.c:74
#define ATNR_DEPLETE
Definition: attack.h:93
#define FLAG_NO_FIX_PLAYER
Definition: define.h:573
#define EXPLODING_FIREBALL
Definition: spells.h:201
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.c:1809
sint8 get_attr_value(const living *stats, int attr)
Definition: living.c:377
sint16 maxgrace
Definition: living.h:86
void free_string(sstring str)
Definition: shstr.c:272
#define MSG_TYPE_SPELL_FAILURE
Definition: newclient.h:548
#define HUGE_BUF
Definition: define.h:83
void esrv_update_item(int flags, object *pl, object *op)
Definition: standalone.c:200
int alchemy(object *op, object *caster, object *spell_ob)
struct treasureliststruct * randomitems
Definition: object.h:236
int cast_invisible(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:821
void pick_up(object *op, object *alt)
Definition: c_object.c:462
int cast_word_of_recall(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:935
int magic_wall(object *op, object *caster, int dir, object *spell_ob)
object clone
Definition: object.h:326
#define ATNR_SLOW
Definition: attack.h:88
sint16 duration
Definition: object.h:254
socket_struct socket
Definition: player.h:148
sint16 invisible
Definition: object.h:211
short freearr_x[SIZEOFFREE]
Definition: object.c:75
#define PREFER_LOW
Definition: define.h:909
uint8 last_anim
Definition: object.h:269
rangetype shoottype
Definition: player.h:153
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
const char * slaying
Definition: object.h:172
sint32 last_sp
Definition: object.h:209
#define MSG_TYPE_SPELL_ERROR
Definition: newclient.h:551
object * ranges[range_size]
Definition: player.h:157
void update_object(object *op, int action)
Definition: object.c:1112
uint8 subtype
Definition: object.h:190
#define MSG_TYPE_SPELL
Definition: newclient.h:333
int cast_item_curse_or_curse(object *op, object *caster, object *spell_ob)
#define FLAG_USE_WEAPON
Definition: define.h:593
int SP_level_dam_adjust(const object *caster, const object *spob)
Definition: spell_util.c:332
sint64 exp
Definition: living.h:88
#define RUNE
Definition: define.h:325
int cast_earth_to_dust(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:882
struct obj * above
Definition: object.h:146
void control_golem(object *op, int dir)
Definition: pets.c:648
int remove_curse(object *op, object *caster, object *spell)
int manual_apply(object *op, object *tmp, int aflag)
Definition: apply.c:512
#define GOLEM
Definition: define.h:168
static object * small
sint16 x
Definition: object.h:179
void remove_friendly_object(object *op)
Definition: friend.c:69
uint32 path_attuned
Definition: object.h:194
#define F_TRUE
Definition: define.h:777
#define FLAG_TEAR_DOWN
Definition: define.h:575
#define AT_BLIND
Definition: attack.h:126
sint16 sp
Definition: living.h:83
const object * find_god(const char *name)
Definition: gods.c:92
#define NDI_BLACK
Definition: newclient.h:195
#define PETMOVE
Definition: define.h:826
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
struct obj * enemy
Definition: object.h:232
struct archt * other_arch
Definition: object.h:264
#define ATNR_CONFUSION
Definition: attack.h:82
Definition: object.h:321
char savebed_map[MAX_BUF]
Definition: player.h:151
int probe(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_effect.c:715
uint8 dam_modifier
Definition: object.h:258
#define SP_WORD_OF_RECALL
Definition: spells.h:120
#define PLAYER
Definition: define.h:113
sint16 maxsp
Definition: living.h:84
sint8 Con
Definition: living.h:78
int change_map_light(mapstruct *m, int change)
Definition: map.c:2000
#define FLAG_REMOVED
Definition: define.h:528
sint16 hp
Definition: living.h:81
archetype * find_archetype_by_object_type_name(int type, const char *name)
Definition: arch.c:96
int cast_cone(object *op, object *caster, int dir, object *spell)
Definition: spell_attack.c:403
short freearr_y[SIZEOFFREE]
Definition: object.c:81
#define FLAG_KNOWN_MAGICAL
Definition: define.h:616
object * active_objects
Definition: object.c:72
#define SOUND_TYPE_ITEM
Definition: sounds.h:37
#define NDI_NAVY
Definition: newclient.h:197
#define SPECIAL_KEY
Definition: define.h:133
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.c:499
void polymorph(object *op, object *who, int level)
Definition: spell_effect.c:399
int rndm(int min, int max)
Definition: utils.c:174
void map_newmap_cmd(socket_struct *ns)
Definition: request.c:672
#define FLAG_UNDEAD
Definition: define.h:566
uint32 tag_t
Definition: object.h:40
int change_abil(object *op, object *tmp)
Definition: living.c:443
void remove_ob(object *op)
Definition: object.c:1515
sint16 maxhp
Definition: living.h:82
static uint64 small_value
static void polymorph_item(object *who, object *op, int level)
Definition: spell_effect.c:302
int cast_heal(object *op, object *caster, object *spell, int dir)
#define FLAG_ALIVE
Definition: define.h:526
void confuse_living(object *op, object *hitter, int dam)
Definition: attack.c:2237
int recharge(object *op, object *caster, object *spell_ob)
Definition: spell_effect.c:90
uint32 golem_count
Definition: player.h:160
const char * name_pl
Definition: object.h:168
object * create_archetype(const char *name)
Definition: arch.c:625
artifactlist * find_artifactlist(int type)
Definition: treasure.c:1431
#define AT_DISEASE
Definition: attack.h:130
uint8 create_home_portals
Definition: global.h:400
int cast_transfer(object *op, object *caster, object *spell, int dir)
float speed_left
Definition: object.h:182
uint32 hidden
Definition: player.h:186
#define ATNR_PARALYZE
Definition: attack.h:89
#define MSG_TYPE_VICTIM
Definition: newclient.h:336
const char * materialname
Definition: object.h:197
sint32 weight
Definition: object.h:216
#define MOVE_FLY_LOW
Definition: define.h:701
object * find_target_for_friendly_spell(object *op, int dir)
Definition: spell_util.c:779
void update_all_los(const mapstruct *map, int x, int y)
Definition: los.c:544
#define MSG_TYPE_SPELL_HEAL
Definition: newclient.h:546
const char *const statname[NUM_STATS]
Definition: living.c:273
#define MSG_TYPE_ITEM_INFO
Definition: newclient.h:560
struct mapdef * map
Definition: object.h:155
int is_dragon_pl(const object *op)
Definition: player.c:125
void set_attr_value(living *stats, int attr, sint8 value)
Definition: living.c:296
#define ATNR_DEATH
Definition: attack.h:94
#define ARCH_DEPLETION
Definition: object.h:405
static void charge_mana_effect(object *victim, int caster_level)
#define SP_WONDER
Definition: spells.h:111
int cast_create_obj(object *op, object *new_op, int dir)
Definition: spell_util.c:517
object * transport
Definition: player.h:249
#define FLAG_IDENTIFIED
Definition: define.h:557
void identify(object *op)
Definition: item.c:1447
int create_aura(object *op, object *caster, object *spell)
int SP_level_duration_adjust(const object *caster, const object *spob)
Definition: spell_util.c:357
sint16 dam
Definition: living.h:87
#define ATNR_BLIND
Definition: attack.h:99
void add_friendly_object(object *op)
Definition: friend.c:43
struct timeval last_reset_time
Definition: map.h:385
#define FLAG_BLOCKSVIEW
Definition: define.h:565
int cure_disease(object *sufferer, object *caster)
Definition: disease.c:715
int dimension_door(object *op, object *caster, object *spob, int dir)
const char * name
Definition: object.h:167
void monster_check_apply(object *mon, object *item)
Definition: standalone.c:219
int cast_identify(object *op, object *caster, object *spell)
int cast_wonder(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.c:997
#define SPELL
Definition: define.h:283
uint32 tmp_invis
Definition: player.h:179
void spell_effect(object *spob, int x, int y, mapstruct *map, object *originator)
Definition: spell_util.c:182
#define ATNR_FEAR
Definition: attack.h:91
int cast_change_map_lightlevel(object *op, object *caster, object *spell)
object * get_owner(object *op)
Definition: object.c:524
int is_true_undead(object *op)
Definition: player.c:3731
struct obj * below
Definition: object.h:145
uint16 difficulty
Definition: map.h:364
#define EXIT_PATH(xyz)
Definition: define.h:748
#define INS_NO_WALK_ON
Definition: object.h:396
sint16 last_grace
Definition: object.h:210
void examine_monster(object *op, object *tmp)
Definition: c_object.c:1424
uint32 nrof
Definition: object.h:184
sint8 Cha
Definition: living.h:78
EXTERN const char *const change_resist_msg[NROFATTACKS]
Definition: attack.h:163
#define ATNR_MAGIC
Definition: attack.h:78
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Definition: define.h:740
object * present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.c:2840
#define FLAG_IS_CAULDRON
Definition: define.h:635
#define SIZEOFFREE
Definition: define.h:441
#define P_OUT_OF_MAP
Definition: map.h:272
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:213
#define EXIT_X(xyz)
Definition: define.h:750
sint8 facing
Definition: object.h:186
sint16 y
Definition: object.h:179
#define LOCKED_DOOR
Definition: define.h:132
struct pl * contr
Definition: object.h:134
#define WEAPON
Definition: define.h:127
void play_sound_map(sint8 sound_type, object *emitter, int dir, const char *action)
Definition: sounds.c:90
#define FLAG_XRAYS
Definition: define.h:597
#define UPD_NROF
Definition: newclient.h:261
object * find_marked_object(object *op)
Definition: c_object.c:1339
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:283
#define ATNR_PHYSICAL
Definition: attack.h:77
static void polymorph_melt(object *who, object *op)
Definition: spell_effect.c:272
#define TRIGGER_PEDESTAL
Definition: define.h:144
object * present_arch(const archetype *at, mapstruct *m, int x, int y)
Definition: object.c:2755
static object * large
#define MAX(x, y)
Definition: define.h:70
uint32 count
Definition: player.h:163
static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight)
#define ATNR_POISON
Definition: attack.h:87
#define AT_PHYSICAL
Definition: attack.h:104
float speed
Definition: object.h:181
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
int animate_weapon(object *op, object *caster, object *spell, int dir)
uint8 state
Definition: object.h:200
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
#define FLAG_WIZ
Definition: define.h:527
#define GEM
Definition: define.h:202
void fix_generated_item(object *op, object *creator, int difficulty, int max_magic, int flags)
Definition: treasure.c:1070
#define EXIT
Definition: define.h:228
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
#define EXIT_Y(xyz)
Definition: define.h:751
sint8 save[NROFATTACKS]
Definition: material.h:66
#define MAX_BUF
Definition: define.h:81
char * ob_describe(const object *op, const object *observer, char *buf, size_t size)
Definition: ob_methods.c:102
struct obj * active_next
Definition: object.h:137
object * get_object(void)
Definition: object.c:921
int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent)
#define MSG_TYPE_SPELL_TARGET
Definition: newclient.h:553
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
static const char *const no_gain_msgs[NUM_STATS]
#define BOOK
Definition: define.h:120
#define SIGN
Definition: define.h:280
sint8 wc
Definition: living.h:79
uint16 look_position
Definition: newserver.h:142
#define tolower(C)
Definition: c_new.c:42
#define MIN(x, y)
Definition: define.h:67
sint8 Str
Definition: living.h:78
sint16 resist[NROFATTACKS]
Definition: object.h:192
#define FLAG_KNOWN_CURSED
Definition: define.h:617
int need_identify(const object *op)
Definition: item.c:1401
#define FLAG_CURSED
Definition: define.h:613
#define MSG_TYPE_SPELL_PERCEIVE_SELF
Definition: newclient.h:552
int perceive_self(object *op)
object * check_inv_recursive(object *op, const object *trig)
Definition: button.c:788
uint64 query_cost(const object *tmp, object *who, int flag)
Definition: shop.c:121
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
void store_spell_expiry(object *spell)
Definition: spell_util.c:1829
sint16 bed_y
Definition: player.h:152
#define AT_POISON
Definition: attack.h:114
#define FORCE
Definition: define.h:296
#define FLAG_ANIMATE
Definition: define.h:538
#define PREFER_HIGH
Definition: define.h:908
#define ALTAR
Definition: define.h:130
uint32 attacktype
Definition: object.h:193
#define NUM_STATS
Definition: living.h:48
#define FLAG_GENERATOR
Definition: define.h:544
#define INS_NO_MERGE
Definition: object.h:394
sint8 direction
Definition: object.h:185
int cast_consecrate(object *op, object *caster, object *spell)
struct obj * owner
Definition: object.h:228
#define VERY_BIG_BUF
Definition: define.h:82
sint16 grace
Definition: living.h:85
#define FREE_AND_COPY(sv, nv)
Definition: global.h:288
const char * invis_race
Definition: player.h:189
int cast_polymorph(object *op, object *caster, object *spell_ob, int dir)
Definition: spell_effect.c:453
int SP_level_range_adjust(const object *caster, const object *spob)
Definition: spell_util.c:383
#define MAP_PLAYER_UNIQUE
Definition: map.h:117
const char * localdir
Definition: global.h:335
tag_t count
Definition: object.h:157
living stats
Definition: object.h:219
#define FLAG_WIZCAST
Definition: define.h:586
sint8 Dex
Definition: living.h:78
struct archt * arch
Definition: object.h:263
void set_spell_skill(object *op, object *caster, object *spob, object *dest)
Definition: spell_util.c:105
object * present_arch_in_ob(const archetype *at, const object *op)
Definition: object.c:2859
#define ATNR_GODPOWER
Definition: attack.h:97
#define CF_HANDLE
Definition: define.h:275
struct Settings settings
Definition: init.c:48
struct archt * next
Definition: object.h:323
uint32 weapontype
Definition: object.h:222
#define SPELL_EFFECT
Definition: define.h:284
#define FLAG_APPLIED
Definition: define.h:531
#define NROFATTACKS
Definition: attack.h:45
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.c:551
const char * msg
Definition: object.h:175
#define FLAG_MAKE_INVIS
Definition: define.h:625
uint16 animation_id
Definition: object.h:267
#define NDI_GREY
Definition: newclient.h:206
#define FLAG_STARTEQUIP
Definition: define.h:564
#define FORCE_NAME
Definition: spells.h:196
void describe_item(const object *op, const object *owner, char *retbuf, size_t size)
Definition: item.c:1018
void update_ob_speed(object *op)
Definition: object.c:1008
#define AT_MAGIC
Definition: attack.h:105
#define MSG_TYPE_SPELL_SUCCESS
Definition: newclient.h:550
#define BOW
Definition: define.h:126
sstring add_string(const char *str)
Definition: shstr.c:116
#define DRINK
Definition: define.h:187
#define GET_MAP_OB(M, X, Y)
Definition: map.h:193
int strcasecmp(const char *s1, const char *s2)
Definition: porting.c:434
int find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3200
sint8 glow_radius
Definition: object.h:215
#define FLAG_MONSTER
Definition: define.h:541
#define TREASURE
Definition: define.h:116
uint8 anim_speed
Definition: object.h:268
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
struct obj * head
Definition: object.h:154
void counterspell(object *op, int dir)
void give_artifact_abilities(object *op, object *artifact)
Definition: treasure.c:1884
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
const char * strcasestr_local(const char *s, const char *find)
Definition: porting.c:461
object * get_split_ob(object *orig_ob, uint32 nr, char *err, size_t size)
Definition: object.c:2313
int makes_invisible_to(object *pl, object *mon)
Definition: spell_effect.c:774
int did_make_save(const object *op, int level, int bonus)
Definition: living.c:2121
unsigned int uint32
Definition: global.h:58
#define was_destroyed(op, old_tag)
Definition: object.h:94
MoveType move_block
Definition: object.h:278
int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg)
Definition: spell_effect.c:525
#define HOLE
Definition: define.h:276
#define P_BLOCKSVIEW
Definition: map.h:247
void copy_object(object *op2, object *op)
Definition: object.c:758
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
object * item
Definition: artifact.h:38
#define MSG_TYPE_VICTIM_SPELL
Definition: newclient.h:569
object * generate_treasure(treasurelist *t, int difficulty)
Definition: treasure.c:524
void free_object(object *ob)
Definition: object.c:1238
Definition: map.h:346
#define P_IS_ALIVE
Definition: map.h:258
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:51
New_Face * face
Definition: object.h:183
#define AT_CONFUSION
Definition: attack.h:109
#define FLAG_BLESSED
Definition: define.h:674
#define FLAG_NO_PICK
Definition: define.h:535
#define HOLY_ALTAR
Definition: define.h:193
sint16 level
Definition: object.h:202
void fix_object(object *op)
Definition: living.c:900
#define GATE
Definition: define.h:273
EXTERN archetype * first_archetype
Definition: global.h:195
object * arch_to_object(archetype *at)
Definition: arch.c:576
sint32 value
Definition: object.h:201
sint8 magic
Definition: object.h:199
static void polymorph_living(object *op, int level)
Definition: spell_effect.c:173
const char * name
Definition: object.h:322
int hit_player(object *op, int dam, object *hitter, uint32 type, int full_hit)
Definition: attack.c:1868
int cast_create_town_portal(object *op, object *caster, object *spell, int dir)
#define HAS_RANDOM_ITEMS(op)
Definition: define.h:470
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Definition: spell_util.c:1308
uint8 type
Definition: object.h:189
struct artifactstruct * next
Definition: artifact.h:41
sint32 food
Definition: living.h:89