Crossfire Server, Trunk  R20513
spell_effect.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
20 #include "global.h"
21 
22 #include <assert.h>
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "living.h"
28 #include "object.h"
29 #include "shop.h"
30 #include "sounds.h"
31 #include "spells.h"
32 #include "sproto.h"
33 
44 void cast_magic_storm(object *op, object *tmp, int lvl) {
45  if (!tmp)
46  return; /* error */
47  tmp->level = op->level;
48  tmp->range += lvl/5; /* increase the area of destruction */
49  tmp->duration += lvl/5;
50 
51  /* Put a cap on duration for this - if the player fails in their
52  * apartment, don't want it to go on so long that it kills them
53  * multiple times. Also, damage already increases with level,
54  * so don't really need to increase the duration as much either.
55  */
56  if (tmp->duration >= 40)
57  tmp->duration = 40;
58  tmp->stats.dam = lvl; /* nasty recoils! */
59  tmp->stats.maxhp = tmp->count; /* tract single parent */
60  if (tmp->stats.maxhp == 0)
61  tmp->stats.maxhp = 1;
62  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
63 }
64 
79 int recharge(object *op, object *caster, object *spell_ob) {
80  object *wand, *tmp;
81  int ncharges;
82  char name[MAX_BUF];
83 
84  wand = find_marked_object(op);
85  if (wand == NULL || wand->type != WAND) {
87  "You need to mark the wand you want to recharge.");
88  return 0;
89  }
90  if (!(random_roll(0, 3, op, PREFER_HIGH))) {
91  query_name(wand, name, MAX_BUF);
93  "The %s vibrates violently, then explodes!",
94  name);
95  play_sound_map(SOUND_TYPE_ITEM, wand, 0, "explode");
96  object_remove(wand);
97  object_free2(wand, 0);
98  tmp = create_archetype("fireball");
99  tmp->stats.dam = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob))/10;
100  if (!tmp->stats.dam)
101  tmp->stats.dam = 1;
102  tmp->stats.hp = tmp->stats.dam/2;
103  if (tmp->stats.hp < 2)
104  tmp->stats.hp = 2;
105  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
106  return 1;
107  }
108 
109  ncharges = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob));
110  if (wand->inv && wand->inv->level)
111  ncharges /= wand->inv->level;
112  else {
113  query_name(wand, name, MAX_BUF);
115  "Your %s is broken.",
116  name);
117  return 0;
118  }
119  if (!ncharges)
120  ncharges = 1;
121 
122  wand->stats.food += ncharges;
123  query_name(wand, name, MAX_BUF);
125  "The %s glows with power.",
126  name);
127 
128  if (wand->arch && QUERY_FLAG(&wand->arch->clone, FLAG_ANIMATE)) {
129  SET_FLAG(wand, FLAG_ANIMATE);
130  wand->speed = wand->arch->clone.speed;
131  object_update_speed(wand);
132  }
133  return 1;
134 }
135 
136 /******************************************************************************
137  * Start of polymorph related functions.
138  *
139  * Changed around for 0.94.3 - it will now look through and use all the
140  * possible choices for objects/monsters (before it was the first 80 -
141  * arbitrary hardcoded limit in this file.) Doing this will be a bit
142  * slower however - while before, it traversed the archetypes once and
143  * stored them into an array, it will now potentially traverse it
144  * an average of 1.5 times. This is probably more costly on the polymorph
145  * item function, since it is possible a couple lookups might be needed before
146  * an item of proper value is generated.
147  */
148 
157 static void polymorph_living(object *op, int level) {
158  archetype *at;
159  int x = op->x, y = op->y, numat = 0, choice, friendly;
160  mapstruct *map = op->map;
161  object *owner;
162 
163  op = HEAD(op);
164 
165  /* High level creatures are immune, as are creatures immune to magic. Otherwise,
166  * give the creature a saving throw.
167  */
168  if (op->level >= level*2
169  || did_make_save(op, op->level, op->resist[ATNR_MAGIC]/10)
170  || (op->resist[ATNR_MAGIC] == 100))
171  return;
172 
173  object_remove(op);
174 
175  /* First, count up the number of legal matches */
176  for (at = first_archetype; at != NULL; at = at->next)
177  if ((QUERY_FLAG((&at->clone), FLAG_MONSTER) == QUERY_FLAG(op, FLAG_MONSTER))
178  && (object_find_free_spot(&at->clone, map, x, y, 0, SIZEOFFREE) != -1)) {
179  numat++;
180  }
181  if (!numat) {
182  object_insert_in_map_at(op, map, NULL, 0, x, y);
183  return; /* no valid matches? if so, return */
184  }
185 
186  /* Next make a choice, and loop through until we get to it */
187  choice = rndm(0, numat-1);
188  for (at = first_archetype; at != NULL; at = at->next)
189  if ((QUERY_FLAG((&at->clone), FLAG_MONSTER) == QUERY_FLAG(op, FLAG_MONSTER)) && (object_find_free_spot(&at->clone, map, x, y, 0, SIZEOFFREE) != -1)) {
190  if (!choice)
191  break;
192  else
193  choice--;
194  }
195 
196  /* Look through the monster. Unapply anything they have applied,
197  * and remove any spells. Note that if this is extended
198  * to players, that would need to get fixed somehow.
199  */
200  FOR_INV_PREPARE(op, tmp) {
201  if (QUERY_FLAG(tmp, FLAG_APPLIED))
202  apply_manual(op, tmp, 0);
203  if (tmp->type == SPELL) {
204  object_remove(tmp);
205  object_free2(tmp, 0);
206  }
207  } FOR_INV_FINISH();
208 
209  /* Preserve some values for the new object */
210  owner = object_get_owner(op);
211  friendly = QUERY_FLAG(op, FLAG_FRIENDLY);
212  if (friendly)
214 
215  object_copy(&(at->clone), op);
216  if (owner != NULL)
217  object_set_owner(op, owner);
218  if (friendly) {
219  SET_FLAG(op, FLAG_FRIENDLY);
220  op->attack_movement = PETMOVE;
222  } else
224 
225  /* Put the new creature on the map */
226  if ((op = object_insert_in_map_at(op, map, owner, 0, x, y)) == NULL)
227  return;
228 
229  if (HAS_RANDOM_ITEMS(op))
231 
232  /* Apply any objects. */
234 }
235 
236 
248 static void polymorph_melt(object *who, object *op) {
249  /* Not unique */
250  char name[MAX_BUF];
251 
252  query_name(op, name, MAX_BUF);
253  if (op->nrof > 1)
255  "The %s glow red, melt and evaporate!",
256  name);
257  else
259  "The %s glows red, melts and evaporates!",
260  name);
261  play_sound_map(SOUND_TYPE_ITEM, op, 0, "evaporate");
262  object_remove(op);
263  object_free2(op, 0);
264  return;
265 }
266 
276 static void polymorph_item(object *who, object *op, int level) {
277  archetype *at;
278  int max_value, difficulty, tries = 0, choice, charges = op->stats.food, numat = 0;
279  object *new_ob;
280  mapstruct *m;
281  int16_t x, y;
282 
283  /* We try and limit the maximum value of the changed object. */
284  max_value = op->value*2;
285  if (max_value > 2000*(level/10))
286  max_value = 2000*(level/10)+(max_value-2000*(level/10))/3;
287 
288  /* Look through and try to find matching items. Can't turn into something
289  * invisible. Also, if the value is too high now, it would almost
290  * certainly be too high below.
291  */
292  for (at = first_archetype; at != NULL; at = at->next) {
293  if (at->clone.type == op->type
294  && !at->clone.invisible
295  && at->clone.value > 0
296  && at->clone.value < max_value
297  && !QUERY_FLAG(&at->clone, FLAG_NO_DROP)
298  && !QUERY_FLAG(&at->clone, FLAG_STARTEQUIP))
299  numat++;
300  }
301 
302  if (!numat)
303  return;
304 
305  difficulty = op->magic*5;
306  if (difficulty < 0)
307  difficulty = 0;
308  new_ob = object_new();
309  do {
310  choice = rndm(0, numat-1);
311  for (at = first_archetype; at != NULL; at = at->next) {
312  if (at->clone.type == op->type
313  && !at->clone.invisible
314  && at->clone.value > 0
315  && at->clone.value < max_value
316  && !QUERY_FLAG(&at->clone, FLAG_NO_DROP)
317  && !QUERY_FLAG(&at->clone, FLAG_STARTEQUIP)) {
318  if (!choice)
319  break;
320  else
321  choice--;
322  }
323  }
324  object_copy(&(at->clone), new_ob);
325  fix_generated_item(new_ob, op, difficulty, FABS(op->magic), GT_ENVIRONMENT);
326  ++tries;
327  } while (new_ob->value > max_value && tries < 10);
328  if (new_ob->invisible) {
329  LOG(llevError, "polymorph_item: fix_generated_object made %s invisible?!\n", new_ob->name);
331  return;
332  }
333 
334  /* Unable to generate an acceptable item? Melt it */
335  if (tries == 10) {
336  polymorph_melt(who, op);
338  return;
339  }
340 
341  if (op->nrof && new_ob->nrof) {
342  new_ob->nrof = op->nrof;
343  /* decrease the number of items */
344  if (new_ob->nrof > 2)
345  new_ob->nrof -= rndm(0, op->nrof/2-1);
346  }
347 
348  /* We don't want rings to keep sustenance/hungry status. There are probably
349  * other cases too that should be checked.
350  */
351  if (charges && op->type != RING && op->type != FOOD)
352  op->stats.food = charges;
353 
354  x = op->x;
355  y = op->y;
356  m = op->map;
357  object_remove(op);
359  /*
360  * Don't want objects merged or re-arranged, as it then messes up the
361  * order
362  */
363  object_insert_in_map_at(new_ob, m, new_ob, INS_NO_MERGE|INS_NO_WALK_ON, x, y);
364 }
365 
376 void polymorph(object *op, object *who, int level) {
377  int tmp;
378 
379  /* Can't polymorph players right now */
380  /* polymorphing generators opens up all sorts of abuses */
381  if (op->type == PLAYER || QUERY_FLAG(op, FLAG_GENERATOR))
382  return;
383 
384  if (QUERY_FLAG(op, FLAG_MONSTER)) {
385  polymorph_living(op, level);
386  return;
387  }
388  /* If it is a living object of some other type, don't handle
389  * it now.
390  */
391  if (QUERY_FLAG(op, FLAG_ALIVE))
392  return;
393 
394  /* Don't want to morph flying arrows, etc... */
395  if (FABS(op->speed) > 0.001 && !QUERY_FLAG(op, FLAG_ANIMATE))
396  return;
397 
398  /* Do some sanity checking here. type=0 is unknown, objects
399  * without archetypes are not good. As are a few other
400  * cases.
401  */
402  if (op->type == 0
403  || op->arch == NULL
404  || QUERY_FLAG(op, FLAG_NO_PICK)
405  || op->move_block
406  || op->type == TREASURE)
407  return;
408 
409  tmp = rndm(0, 7);
410  if (tmp)
411  polymorph_item(who, op, level);
412  else
413  polymorph_melt(who, op);
414 }
415 
416 
430 int cast_polymorph(object *op, object *caster, object *spell_ob, int dir) {
431  object *tmp;
432  int range, mflags, maxrange, level;
433  mapstruct *m;
434 
435  if (dir == 0)
436  return 0;
437 
438  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
439  level = caster_level(caster, spell_ob);
440  for (range = 1; range < maxrange; range++) {
441  int16_t x = op->x+freearr_x[dir]*range, y = op->y+freearr_y[dir]*range;
442  object *image;
443 
444  m = op->map;
445  mflags = get_map_flags(m, &m, x, y, &x, &y);
446 
447  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
448  break;
449 
450  if (GET_MAP_MOVE_BLOCK(m, x, y)&MOVE_FLY_LOW)
451  break;
452 
453  /* Get the top most object */
454  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above)
455  ;
456 
457  /* Now start polymorphing the objects, top down */
459  /* Once we find the floor, no need to go further */
460  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
461  break;
462  polymorph(tmp, op, level);
464  image = arch_to_object(spell_ob->other_arch);
465  image->stats.food = 5;
466  image->speed_left = 0.1;
467  object_insert_in_map_at(image, m, op, 0, x, y);
468  }
469  return 1;
470 }
471 
498 int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg) {
499  int missile_plus = 0, bonus_plus = 0;
500  const char *missile_name;
501  object *tmp, *missile;
502  tag_t tag;
503 
504  tmp = object_find_by_type_applied(op, BOW);
505  missile_name = tmp != NULL ? tmp->race : "arrow";
506 
507  missile_plus = spell->stats.dam+SP_level_dam_adjust(caster, spell);
508 
509  if (!strcmp(missile_name, "arrows"))
510  missile_name = "arrow";
511  else if (!strcmp(missile_name, "crossbow bolts"))
512  missile_name = "bolt";
513 
514  if (find_archetype(missile_name) == NULL) {
515  LOG(llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
516  return 0;
517  }
518  missile = create_archetype(missile_name);
519 
520  if (stringarg) {
521  /* If it starts with a letter, presume it is a description */
522  if (isalpha(*stringarg)) {
523  artifact *al = find_artifactlist(missile->type)->items;
524 
525  for (; al != NULL; al = al->next)
526  if (!strcasecmp(al->item->name, stringarg))
527  break;
528 
529  if (!al) {
532  "No such object %ss of %s",
533  missile_name, stringarg);
534  return 0;
535  }
536  if (al->item->slaying) {
539  "You are not allowed to create %ss of %s",
540  missile_name, stringarg);
541  return 0;
542  }
543  give_artifact_abilities(missile, al->item);
544  /* These special arrows cost something extra. Don't have them also be
545  * magical - otherwise, in most cases, not enough will be created.
546  * I don't want to get into the parsing both plus and type.
547  */
548  bonus_plus = 1+(al->item->value/5);
549  missile_plus = 0;
550  } else if (atoi(stringarg) < missile_plus)
551  missile_plus = atoi(stringarg);
552  }
553  if (missile_plus > 4)
554  missile_plus = 4;
555  else if (missile_plus < -4)
556  missile_plus = -4;
557 
558  missile->nrof = spell->duration+SP_level_duration_adjust(caster, spell);
559  if (missile->nrof <= (uint32_t)3 * (missile_plus + bonus_plus)) {
562  "This item is too powerful for you to create!");
563  return 0;
564  }
565  missile->nrof -= 3*(missile_plus+bonus_plus);
566  if (missile->nrof < 1)
567  missile->nrof = 1;
568 
569  missile->magic = missile_plus;
570  /* Can't get any money for these objects */
571  missile->value = 0;
572 
573  SET_FLAG(missile, FLAG_IDENTIFIED);
574  tag = missile->count;
575 
576  if (!cast_create_obj(op, missile, dir)
577  && op->type == PLAYER
578  && !object_was_destroyed(missile, tag)) {
579  pick_up(op, missile);
580  }
581  return 1;
582 }
583 
584 
605 int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg) {
606  int food_value;
607  archetype *at = NULL;
608  object *new_op;
609 
610  food_value = spell_ob->stats.food+50*SP_level_duration_adjust(caster, spell_ob);
611 
612  if (stringarg) {
613  at = find_archetype_by_object_type_name(FOOD, stringarg);
614  if (at == NULL)
615  at = find_archetype_by_object_type_name(DRINK, stringarg);
616  if (at == NULL || at->clone.stats.food > food_value)
617  stringarg = NULL;
618  }
619 
620  if (!stringarg) {
621  archetype *at_tmp;
622 
623  /* We try to find the archetype with the maximum food value.
624  * This removes the dependency of hard coded food values in this
625  * function, and addition of new food types is automatically added.
626  * We don't use flesh types because the weight values of those need
627  * to be altered from the donor.
628  */
629 
630  /* We assume the food items don't have multiple parts */
631  for (at_tmp = first_archetype; at_tmp != NULL; at_tmp = at_tmp->next) {
632  if (at_tmp->clone.type == FOOD || at_tmp->clone.type == DRINK) {
633  /* Basically, if the food value is something that is creatable
634  * under the limits of the spell and it is higher than
635  * the item we have now, take it instead.
636  */
637  if (at_tmp->clone.stats.food <= food_value
638  && (!at || at_tmp->clone.stats.food > at->clone.stats.food))
639  at = at_tmp;
640  }
641  }
642  }
643  /* Pretty unlikely (there are some very low food items), but you never
644  * know
645  */
646  if (!at) {
648  "You don't have enough experience to create any food.");
649  return 0;
650  }
651 
652  food_value /= at->clone.stats.food;
653  new_op = object_new();
654  object_copy(&at->clone, new_op);
655  new_op->nrof = food_value;
656 
657  new_op->value = 0;
658  if (new_op->nrof < 1)
659  new_op->nrof = 1;
660 
661  cast_create_obj(op, new_op, dir);
662  return 1;
663 }
664 
683 int probe(object *op, object *caster, object *spell_ob, int dir, int level) {
684  int r, mflags, maxrange;
685  mapstruct *m;
686 
687  if (!dir) {
688  examine_monster(op, op, level);
689  return 1;
690  }
691  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
692  for (r = 1; r < maxrange; r++) {
693  int16_t x = op->x+r*freearr_x[dir], y = op->y+r*freearr_y[dir];
694 
695  m = op->map;
696  mflags = get_map_flags(m, &m, x, y, &x, &y);
697 
698  if (mflags&P_OUT_OF_MAP)
699  break;
700 
701  if (!QUERY_FLAG(op, FLAG_WIZCAST) && (mflags&P_NO_MAGIC)) {
703  "Something blocks your magic.");
704  return 0;
705  }
706  if (mflags&P_IS_ALIVE) {
707  FOR_MAP_PREPARE(m, x, y, tmp)
708  if (QUERY_FLAG(tmp, FLAG_ALIVE) && (tmp->type == PLAYER || QUERY_FLAG(tmp, FLAG_MONSTER))) {
710  "You detect something.");
711  examine_monster(op, HEAD(tmp), level);
712  return 1;
713  }
714  FOR_MAP_FINISH();
715  }
716  }
718  "You detect nothing.");
719  return 1;
720 }
721 
722 
740 int makes_invisible_to(object *pl, object *mon) {
741  if (!pl->invisible)
742  return 0;
743  if (pl->type == PLAYER) {
744  /* If race isn't set, then invisible unless it is undead */
745  if (!pl->contr->invis_race) {
746  if (QUERY_FLAG(mon, FLAG_UNDEAD))
747  return 0;
748  return 1;
749  }
750  /* invis_race is set if we get here */
751  if (!strcmp(pl->contr->invis_race, "undead") && is_true_undead(mon))
752  return 1;
753  /* No race, can't be invisible to it */
754  if (!mon->race)
755  return 0;
756  if (strstr(mon->race, pl->contr->invis_race))
757  return 1;
758  /* Nothing matched above, return 0 */
759  return 0;
760  } else {
761  /* monsters are invisible to everything */
762  return 1;
763  }
764 }
765 
787 int cast_invisible(object *op, object *caster, object *spell_ob) {
788  object *tmp;
789 
790  if (op->invisible > 1000) {
792  "You can not extend the duration of your invisibility any further");
793  return 0;
794  }
795 
796  /* Remove the switch with 90% duplicate code - just handle the differences with
797  * and if statement or two.
798  */
799  op->invisible += spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
800  /* max duration */
801  if (op->invisible > 1000)
802  op->invisible = 1000;
803 
804  if (op->type == PLAYER) {
805  if (op->contr->invis_race)
807  if (spell_ob->race)
808  op->contr->invis_race = add_refcount(spell_ob->race);
809  if (QUERY_FLAG(spell_ob, FLAG_MAKE_INVIS))
810  op->contr->tmp_invis = 0;
811  else
812  op->contr->tmp_invis = 1;
813 
814  op->contr->hidden = 0;
815  }
816  if (makes_invisible_to(op, op))
818  "You can't see your hands!");
819  else
821  "You feel more transparent!");
822 
824 
825  /* Only search the active objects - only these should actually do
826  * harm to the player.
827  */
828  for (tmp = active_objects; tmp != NULL; tmp = tmp->active_next)
829  if (tmp->enemy == op)
830  object_set_enemy(tmp, NULL);
831  return 1;
832 }
833 
848 int cast_earth_to_dust(object *op, object *caster, object *spell_ob) {
849  int range, i, j, mflags;
850  int16_t sx, sy;
851  mapstruct *m;
852 
853  if (op->type != PLAYER)
854  return 0;
855 
856  range = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
857 
858  for (i = -range; i < range; i++)
859  for (j = -range; j < range; j++) {
860  sx = op->x+i;
861  sy = op->y+j;
862  m = op->map;
863  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
864 
865  if (mflags&P_OUT_OF_MAP)
866  continue;
867 
868  /* If the space doesn't block, no wall here to remove
869  * Don't care too much what it blocks - this allows for
870  * any sort of earthwall/airwall/waterwall, etc
871  * type effects.
872  */
873  if (GET_MAP_MOVE_BLOCK(m, sx, sy)) {
874  FOR_MAP_PREPARE(m, sx, sy, tmp)
875  if (tmp && QUERY_FLAG(tmp, FLAG_TEAR_DOWN))
876  hit_player(tmp, 9998, op, AT_PHYSICAL, 0);
877  FOR_MAP_FINISH();
878  }
879  }
880  return 1;
881 }
882 
899 int cast_word_of_recall(object *op, object *caster, object *spell_ob) {
900  object *dummy;
901  int time;
902 
903  if (op->type != PLAYER)
904  return 0;
905 
908  "You feel a force starting to build up inside you.");
909  return 1;
910  }
911 
912  dummy = create_archetype(FORCE_NAME);
913  if (dummy == NULL) {
915  "Oops, program error!");
916  LOG(llevError, "cast_word_of_recall: create_archetype(force) failed!\n");
917  return 0;
918  }
919  time = spell_ob->duration-SP_level_duration_adjust(caster, spell_ob);
920  if (time < 1)
921  time = 1;
922 
923  /* value of speed really doesn't make much difference, as long as it is
924  * positive. Lower value may be useful so that the problem doesn't
925  * do anything really odd if it say a -1000 or something.
926  */
927  dummy->speed = 0.002;
928  object_update_speed(dummy);
929  dummy->speed_left = -dummy->speed*time;
930  dummy->type = SPELL_EFFECT;
931  dummy->subtype = SP_WORD_OF_RECALL;
932 
933  /* If we could take advantage of enter_player_savebed() here, it would be
934  * nice, but until the map load fails, we can't.
935  */
936  EXIT_PATH(dummy) = add_string(op->contr->savebed_map);
937  EXIT_X(dummy) = op->contr->bed_x;
938  EXIT_Y(dummy) = op->contr->bed_y;
939 
940  (void)object_insert_in_ob(dummy, op);
942  "You feel a force starting to build up inside you.");
943  return 1;
944 }
945 
961 int cast_wonder(object *op, object *caster, int dir, object *spell_ob) {
962  object *newspell;
963 
964  if (!rndm(0, 3))
965  return cast_cone(op, caster, dir, spell_ob);
966 
967  if (spell_ob->randomitems) {
968  newspell = generate_treasure(spell_ob->randomitems, caster->level);
969  if (!newspell) {
970  LOG(llevError, "cast_wonder: Unable to get a spell!\n");
971  return 0;
972  }
973  if (newspell->type != SPELL) {
974  LOG(llevError, "cast_wonder: spell returned is not a spell (%d, %s)!\n", newspell->type, newspell->name);
975  return 0;
976  }
977  /* Prevent inifinite recursion */
978  if (newspell->subtype == SP_WONDER) {
979  LOG(llevError, "cast_wonder: spell returned is another wonder spell!\n");
980  return 0;
981  }
982  return cast_spell(op, caster, dir, newspell, NULL);
983  }
984  return 1;
985 }
986 
995 int perceive_self(object *op) {
996  char *cp, buf[MAX_BUF];
998  object *tmp;
999  const object *god;
1000  int i;
1001  StringBuffer *immunity;
1002 
1003  god = find_god(determine_god(op));
1004  if (god)
1006  "You worship %s",
1007  god->name);
1008  else
1010  "You worship no god");
1011 
1012  tmp = arch_present_in_ob(at, op);
1013 
1014  cp = stringbuffer_finish(describe_item(op, op, 0, NULL));
1015 
1016  if (*cp == '\0' && tmp == NULL)
1018  "You feel very mundane");
1019  else {
1021  "You have:");
1023  cp);
1024  if (tmp != NULL) {
1025  for (i = 0; i < NUM_STATS; i++) {
1026  if (get_attr_value(&tmp->stats, i) < 0) {
1028  "Your %s is depleted by %d",
1029  statname[i], -(get_attr_value(&tmp->stats, i)));
1030  }
1031  }
1032  }
1033  }
1034  free(cp);
1035 
1036  if (op->glow_radius > 0)
1038  "You glow in the dark.");
1039 
1040  immunity = NULL;
1041  for (tmp = op->inv; tmp; tmp = tmp->below) {
1042  if (tmp->type == SIGN) {
1043  if (immunity == NULL) {
1044  immunity = stringbuffer_new();
1045  stringbuffer_append_string(immunity, "You have been exposed to: ");
1046  } else {
1047  stringbuffer_append_string(immunity, ", ");
1048  }
1049  stringbuffer_append_string(immunity, tmp->name);
1050  if (tmp->level > 100)
1051  stringbuffer_append_string(immunity, " (full immunity)");
1052  else if (tmp->level > 70)
1053  stringbuffer_append_string(immunity, " (high immunity)");
1054  else if (tmp->level > 20)
1055  stringbuffer_append_string(immunity, " (partial immunity)");
1056  }
1057  }
1058 
1059  if (immunity != NULL) {
1060  cp = stringbuffer_finish(immunity);
1062  free(cp);
1063  }
1064 
1065  if (is_dragon_pl(op)) {
1066  /* now grab the 'dragon_ability'-force from the player's inventory */
1067  tmp = object_find_by_type_and_arch_name(op, FORCE, "dragon_ability_force");
1068  if (tmp != NULL) {
1069  StringBuffer *levels = NULL;
1070  int i;
1071 
1072  if (tmp->stats.exp == 0) {
1073  snprintf(buf, sizeof(buf), "Your metabolism isn't focused on anything.");
1074  } else {
1075  snprintf(buf, sizeof(buf), "Your metabolism is focused on %s.", change_resist_msg[tmp->stats.exp]);
1076  }
1078  buf);
1079 
1080  for (i = 0; i < NROFATTACKS; i++) {
1081  if (atnr_is_dragon_enabled(i) && tmp->resist[i] > 0) {
1082  if (levels == NULL) {
1083  levels = stringbuffer_new();
1084  stringbuffer_append_string(levels, "Ability levels:\n");
1085  }
1086  stringbuffer_append_printf(levels, "- %s: %d\n", change_resist_msg[i], tmp->resist[i]);
1087  }
1088  }
1089 
1090  if (levels != NULL) {
1091  cp = stringbuffer_finish(levels);
1093  free(cp);
1094  }
1095  }
1096  }
1097  return 1;
1098 }
1099 
1129 int cast_create_town_portal(object *op, object *caster, object *spell, int dir) {
1130  object *dummy, *force, *old_force, *tmp;
1131  archetype *perm_portal;
1132  char portal_name [1024], portal_message [1024];
1133  int16_t exitx, exity;
1134  mapstruct *exitmap;
1135  int op_level, x, y;
1136 
1137  /* Check to see if the map the player is currently on is a per player unique
1138  * map. This can be determined in that per player unique maps have the
1139  * full pathname listed. Ignore if settings.create_home_portals is true.
1140  */
1142  if (!strncmp(op->map->path, settings.localdir, strlen(settings.localdir))) {
1144  "You can't cast that here.");
1145  return 0;
1146  }
1147  }
1148 
1149  /* Check to see if the player is on a transport */
1150  if (op->contr && op->contr->transport) {
1152  "You need to exit the transport to cast that.");
1153  return 0;
1154  }
1155 
1156  /* The first thing to do is to check if we have a marked destination
1157  * dummy is used to make a check inventory for the force
1158  */
1159  dummy = arch_to_object(spell->other_arch);
1160  if (dummy == NULL) {
1162  "Oops, program error!");
1163  LOG(llevError, "object_new failed (force in cast_create_town_portal for %s!\n", op->name);
1164  return 0;
1165  }
1166  force = check_inv_recursive(op, dummy);
1167 
1168  if (force == NULL) {
1169  /* Here we know there is no destination marked up.
1170  * We have 2 things to do:
1171  * 1. Mark the destination in the player inventory.
1172  * 2. Let the player know it worked.
1173  */
1174  free_string(dummy->name);
1175  dummy->name = add_string(op->map->path);
1176  EXIT_X(dummy) = op->x;
1177  EXIT_Y(dummy) = op->y;
1178  dummy->weapontype = op->map->last_reset_time;
1179  object_insert_in_ob(dummy, op);
1181  "You fix this place in your mind and feel that you "
1182  "can come here from anywhere.");
1183  return 1;
1184  }
1186 
1187  /* Here we know where the town portal should go to
1188  * We should kill any existing portal associated with the player.
1189  * Than we should create the 2 portals.
1190  * For each of them, we need:
1191  * - To create the portal with the name of the player+destination map
1192  * - set the owner of the town portal
1193  * - To mark the position of the portal in the player's inventory
1194  * for easier destruction.
1195  *
1196  * The mark works has follow:
1197  * slaying: Existing town portal
1198  * hp, sp : x & y of the associated portal
1199  * name : name of the portal
1200  * race : map the portal is in
1201  */
1202 
1203  /* First step: killing existing town portals */
1204  dummy = create_archetype(spell->race);
1205  if (dummy == NULL) {
1207  "Oops, program error!");
1208  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1209  return 0;
1210  }
1211  perm_portal = find_archetype(spell->slaying);
1212 
1213  /* To kill a town portal, we go trough the player's inventory,
1214  * for each marked portal in player's inventory,
1215  * -We try load the associated map (if impossible, consider the portal destructed)
1216  * -We find any portal in the specified location.
1217  * If it has the good name, we destruct it.
1218  * -We destruct the force indicating that portal.
1219  */
1220  while ((old_force = check_inv_recursive(op, dummy))) {
1221  exitx = EXIT_X(old_force);
1222  exity = EXIT_Y(old_force);
1223  LOG(llevDebug, "Trying to kill a portal in %s (%d,%d)\n", old_force->race, exitx, exity);
1224 
1225  if (!strncmp(old_force->race, settings.localdir, strlen(settings.localdir)))
1226  exitmap = ready_map_name(old_force->race, MAP_PLAYER_UNIQUE);
1227  else
1228  exitmap = ready_map_name(old_force->race, 0);
1229 
1230  if (exitmap) {
1231  tmp = map_find_by_archetype(exitmap, exitx, exity, perm_portal);
1233  if (tmp->name == old_force->name) {
1234  object_remove(tmp);
1235  object_free2(tmp, 0);
1236  break;
1237  }
1239 
1240  /* kill any opening animation there is */
1241  tmp = map_find_by_archetype(exitmap, exitx, exity, find_archetype("town_portal_open"));
1243  if (tmp->name == old_force->name) {
1244  object_remove(tmp);
1246  break;
1247  }
1249  }
1250  object_remove(old_force);
1251  object_free2(old_force, 0);
1252  LOG(llevDebug, "\n");
1253  }
1255 
1256  /* Creating the portals.
1257  * The very first thing to do is to ensure
1258  * access to the destination map.
1259  * If we can't, don't fizzle. Simply warn player.
1260  * This ensure player pays his mana for the spell
1261  * because HE is responsible for forgetting.
1262  * 'force' is the destination of the town portal, which we got
1263  * from the players inventory above.
1264  */
1265 
1266  /* Ensure exit map is loaded*/
1267  if (!strncmp(force->name, settings.localdir, strlen(settings.localdir)))
1268  exitmap = ready_map_name(force->name, MAP_PLAYER_UNIQUE);
1269  else
1270  exitmap = ready_map_name(force->name, 0);
1271 
1272  /* If we were unable to load (ex. random map deleted), warn player*/
1273  if (exitmap == NULL) {
1275  "Something strange happens. You can't remember where to go!?");
1276  object_remove(force);
1277  object_free2(force, 0);
1279  return 1;
1280  } else if (exitmap->last_reset_time != force->weapontype) {
1282  "The spell effect has expired.");
1283  object_remove(force);
1284  object_free2(force, 0);
1286  return 1;
1287  }
1288 
1289  op_level = caster_level(caster, spell);
1290  if (op_level < 15)
1291  snprintf(portal_message, 1024, "\nThe air moves around you and\na huge smell of ammonia surrounds you as you pass through %s's tiny portal\nPouah!\n", op->name);
1292  else if (op_level < 30)
1293  snprintf(portal_message, 1024, "\n%s's portal smells of ozone.\nYou do a lot of movements and finally pass through the small hole in the air\n", op->name);
1294  else if (op_level < 60)
1295  snprintf(portal_message, 1024, "\nA shining door opens in the air in front of you, showing you the path to another place.\n");
1296  else
1297  snprintf(portal_message, 1024, "\nAs you walk through %s's portal, flowers come out from the ground around you.\nYou feel awed.\n", op->name);
1298 
1299  /* Create a portal in front of player
1300  * dummy contain the portal and
1301  * force contain the track to kill it later
1302  */
1303 
1304  snprintf(portal_name, 1024, "%s's portal to %s", op->name, force->name);
1305  dummy = create_archetype(spell->slaying); /*The portal*/
1306  if (dummy == NULL) {
1308  "Oops, program error!");
1309  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1310  return 0;
1311  }
1312  EXIT_PATH(dummy) = add_string(force->name);
1313  EXIT_X(dummy) = EXIT_X(force);
1314  EXIT_Y(dummy) = EXIT_Y(force);
1315  FREE_AND_COPY(dummy->name, portal_name);
1316  FREE_AND_COPY(dummy->name_pl, portal_name);
1317  object_set_msg(dummy, portal_message);
1318  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1319 
1320  /* create a nice animation */
1321  tmp = create_archetype("town_portal_open");
1322  FREE_AND_COPY(tmp->name, portal_name);
1323  FREE_AND_COPY(tmp->name_pl, portal_name);
1324  object_insert_in_ob(dummy, tmp);
1325  /* and put it on the floor, when it ends the portal will be on the ground */
1326  cast_create_obj(op, tmp, 0);
1327  x = tmp->x;
1328  y = tmp->y;
1329 
1330  /* Now we need to to create a town portal marker inside the player
1331  * object, so on future castings, we can know that he has an active
1332  * town portal.
1333  */
1334  tmp = create_archetype(spell->race);
1335  if (tmp == NULL) {
1337  "Oops, program error!");
1338  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1339  return 0;
1340  }
1341  tmp->race = add_string(op->map->path);
1342  FREE_AND_COPY(tmp->name, portal_name);
1343  EXIT_X(tmp) = x;
1344  EXIT_Y(tmp) = y;
1345  object_insert_in_ob(tmp, op);
1346 
1347  /* Create a portal in the destination map
1348  * dummy contain the portal and
1349  * force the track to kill it later
1350  * the 'force' variable still contains the 'reminder' of
1351  * where this portal goes to.
1352  */
1353  snprintf(portal_name, 1024, "%s's portal to %s", op->name, op->map->path);
1354  dummy = create_archetype(spell->slaying); /*The portal*/
1355  if (dummy == NULL) {
1357  "Oops, program error!");
1358  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1359  return 0;
1360  }
1361  EXIT_PATH(dummy) = add_string(op->map->path);
1362  EXIT_X(dummy) = op->x;
1363  EXIT_Y(dummy) = op->y;
1364  FREE_AND_COPY(dummy->name, portal_name);
1365  FREE_AND_COPY(dummy->name_pl, portal_name);
1366  object_set_msg(dummy, portal_message);
1367  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1368 
1369  /* animation here too */
1370  tmp = create_archetype("town_portal_open");
1371  FREE_AND_COPY(tmp->name, portal_name);
1372  FREE_AND_COPY(tmp->name_pl, portal_name);
1373  object_insert_in_ob(dummy, tmp);
1374  /* and put it on the floor, when it ends the portal will be on the ground */
1375  object_insert_in_map_at(tmp, exitmap, op, 0, EXIT_X(force), EXIT_Y(force));
1376  x = tmp->x;
1377  y = tmp->y;
1378 
1379  /* Now we create another town portal marker that
1380  * points back to the one we just made
1381  */
1382  tmp = create_archetype(spell->race);
1383  if (tmp == NULL) {
1385  "Oops, program error!");
1386  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1387  return 0;
1388  }
1389  tmp->race = add_string(force->name);
1390  FREE_AND_COPY(tmp->name, portal_name);
1391  EXIT_X(tmp) = x;
1392  EXIT_Y(tmp) = y;
1393  object_insert_in_ob(tmp, op);
1394 
1395  /* Describe the player what happened
1396  */
1398  "You see air moving and showing you the way home.");
1399  object_remove(force); /* Delete the force inside the player*/
1400  object_free2(force, 0);
1401  return 1;
1402 }
1403 
1404 
1422 int magic_wall(object *op, object *caster, int dir, object *spell_ob) {
1423  object *tmp, *tmp2;
1424  int i, posblocked, negblocked, maxrange;
1425  int16_t x, y;
1426  mapstruct *m;
1427  const char *name;
1428  archetype *at;
1429 
1430  if (!dir) {
1431  dir = op->facing;
1432  x = op->x;
1433  y = op->y;
1434  } else {
1435  x = op->x+freearr_x[dir];
1436  y = op->y+freearr_y[dir];
1437  }
1438  m = op->map;
1439 
1440  if ((spell_ob->move_block || x != op->x || y != op->y)
1441  && (get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE)
1442  || ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) == spell_ob->move_block))) {
1444  "Something is in the way.");
1445  return 0;
1446  }
1447  if (spell_ob->other_arch) {
1448  tmp = arch_to_object(spell_ob->other_arch);
1449  } else if (spell_ob->race) {
1450  char buf1[MAX_BUF];
1451 
1452  snprintf(buf1, sizeof(buf1), spell_ob->race, dir);
1453  at = find_archetype(buf1);
1454  if (!at) {
1455  LOG(llevError, "summon_wall: Unable to find archetype %s\n", buf1);
1457  "This spell is broken.");
1458  return 0;
1459  }
1460  tmp = arch_to_object(at);
1461  } else {
1462  LOG(llevError, "magic_wall: spell %s lacks other_arch\n", spell_ob->name);
1463  return 0;
1464  }
1465 
1466  if (tmp->type == SPELL_EFFECT) {
1467  tmp->attacktype = spell_ob->attacktype;
1468  tmp->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1469  tmp->stats.dam = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1470  tmp->range = 0;
1471  } else if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
1472  tmp->stats.hp = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1473  tmp->stats.maxhp = tmp->stats.hp;
1474  object_set_owner(tmp, op);
1475  set_spell_skill(op, caster, spell_ob, tmp);
1476  }
1477  if (QUERY_FLAG(spell_ob, FLAG_IS_USED_UP) || QUERY_FLAG(tmp, FLAG_IS_USED_UP)) {
1478  tmp->stats.food = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1479  SET_FLAG(tmp, FLAG_IS_USED_UP);
1480  }
1481  if (QUERY_FLAG(spell_ob, FLAG_TEAR_DOWN)) {
1482  tmp->stats.hp = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1483  tmp->stats.maxhp = tmp->stats.hp;
1484  SET_FLAG(tmp, FLAG_TEAR_DOWN);
1485  SET_FLAG(tmp, FLAG_ALIVE);
1486  }
1487 
1488  /* This can't really hurt - if the object doesn't kill anything,
1489  * these fields just won't be used.
1490  */
1491  object_set_owner(tmp, op);
1492  set_spell_skill(op, caster, spell_ob, tmp);
1493  tmp->level = caster_level(caster, spell_ob)/2;
1494 
1495  name = tmp->name;
1496  if ((tmp = object_insert_in_map_at(tmp, m, op, 0, x, y)) == NULL) {
1498  "Something destroys your %s",
1499  name);
1500  return 0;
1501  }
1502  /* If this is a spellcasting wall, need to insert the spell object */
1503  if (tmp->other_arch && tmp->other_arch->clone.type == SPELL)
1505 
1506  /* This code causes the wall to extend some distance in
1507  * each direction, or until an obstruction is encountered.
1508  * posblocked and negblocked help determine how far the
1509  * created wall can extend, it won't go extend through
1510  * blocked spaces.
1511  */
1512  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
1513  posblocked = 0;
1514  negblocked = 0;
1515 
1516  for (i = 1; i <= maxrange; i++) {
1517  int dir2;
1518 
1519  dir2 = (dir < 4) ? (dir+2) : dir-2;
1520 
1521  x = tmp->x+i*freearr_x[dir2];
1522  y = tmp->y+i*freearr_y[dir2];
1523  m = tmp->map;
1524 
1525  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1526  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1527  && !posblocked) {
1528  tmp2 = object_new();
1529  object_copy(tmp, tmp2);
1530  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1531  /* If this is a spellcasting wall, need to insert the spell object */
1532  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1534  } else
1535  posblocked = 1;
1536 
1537  x = tmp->x-i*freearr_x[dir2];
1538  y = tmp->y-i*freearr_y[dir2];
1539  m = tmp->map;
1540 
1541  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1542  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1543  && !negblocked) {
1544  tmp2 = object_new();
1545  object_copy(tmp, tmp2);
1546  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1547  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1549  } else
1550  negblocked = 1;
1551  }
1552 
1553  if (QUERY_FLAG(tmp, FLAG_BLOCKSVIEW))
1554  update_all_los(op->map, op->x, op->y);
1555 
1556  return 1;
1557 }
1558 
1575 int dimension_door(object *op, object *caster, object *spob, int dir) {
1576  uint32_t dist, maxdist;
1577  int mflags;
1578  mapstruct *m;
1579  int16_t sx, sy;
1580 
1581  if (op->type != PLAYER)
1582  return 0;
1583 
1584  if (!dir) {
1586  "In what direction?");
1587  return 0;
1588  }
1589 
1590  /* Given the new outdoor maps, can't let players dimension door for
1591  * ever, so put limits in.
1592  */
1593  maxdist = spob->range+SP_level_range_adjust(caster, spob);
1594 
1595  if (op->contr->count) {
1596  if (op->contr->count > maxdist) {
1598  "You can't dimension door that far!");
1599  return 0;
1600  }
1601 
1602  for (dist = 0; dist < op->contr->count; dist++) {
1603  mflags = get_map_flags(op->map, &m,
1604  op->x+freearr_x[dir]*(dist+1),
1605  op->y+freearr_y[dir]*(dist+1),
1606  &sx, &sy);
1607 
1608  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1609  break;
1610 
1611  if ((mflags&P_BLOCKSVIEW)
1612  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1613  break;
1614  }
1615 
1616  if (dist < op->contr->count) {
1618  "Something blocks the magic of the spell.");
1619  op->contr->count = 0;
1620  return 0;
1621  }
1622  op->contr->count = 0;
1623 
1624  /* Remove code that puts player on random space on maps. IMO,
1625  * a lot of maps probably have areas the player should not get to,
1626  * but may not be marked as NO_MAGIC (as they may be bounded
1627  * by such squares). Also, there are probably treasure rooms and
1628  * lots of other maps that protect areas with no magic, but the
1629  * areas themselves don't contain no magic spaces.
1630  */
1631  /* This call here is really just to normalize the coordinates */
1632  mflags = get_map_flags(op->map, &m, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist,
1633  &sx, &sy);
1634  if (mflags&P_IS_ALIVE || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy))) {
1636  "You cast your spell, but nothing happens.");
1637  return 1; /* Maybe the penalty should be more severe... */
1638  }
1639  } else {
1640  /* Player didn't specify a distance, so lets see how far
1641  * we can move the player. Don't know why this stopped on
1642  * spaces that blocked the players view.
1643  */
1644 
1645  for (dist = 0; dist < maxdist; dist++) {
1646  mflags = get_map_flags(op->map, &m,
1647  op->x+freearr_x[dir]*(dist+1),
1648  op->y+freearr_y[dir]*(dist+1),
1649  &sx, &sy);
1650 
1651  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1652  break;
1653 
1654  if ((mflags&P_BLOCKSVIEW)
1655  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1656  break;
1657  }
1658 
1659  /* If the destination is blocked, keep backing up until we
1660  * find a place for the player.
1661  */
1662  for (; dist > 0; dist--) {
1663  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))
1664  continue;
1665 
1666  if (!OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1667  break;
1668  }
1669  if (!dist) {
1671  "Your spell failed!");
1672  return 0;
1673  }
1674  }
1675 
1676  if (op->contr->transport && op->contr->transport->type == TRANSPORT) {
1677  ob_apply(op->contr->transport, op, 0);
1678  if (op->contr->transport) {
1680  "Your spell failed!");
1681  return 0;
1682  }
1683  }
1684 
1685  /* Actually move the player now */
1686  object_remove(op);
1687  if ((op = object_insert_in_map_at(op, op->map, op, 0, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist)) == NULL)
1688  return 1;
1689 
1690  if (op->type == PLAYER) {
1691  map_newmap_cmd(&op->contr->socket);
1693  }
1694  op->speed_left = -FABS(op->speed)*5; /* Freeze them for a short while */
1695  return 1;
1696 }
1697 
1698 
1711 int cast_heal(object *op, object *caster, object *spell, int dir) {
1712  object *target;
1713  archetype *at;
1714  object *poison;
1715  int heal = 0, success = 0;
1716 
1717  target = find_target_for_friendly_spell(op, dir);
1718 
1719  if (target == NULL)
1720  return 0;
1721 
1722  /* Figure out how many hp this spell might cure.
1723  * could be zero if this spell heals effects, not damage.
1724  */
1725  heal = spell->stats.dam;
1726  if (spell->stats.hp)
1727  heal += random_roll(spell->stats.hp, 6, op, PREFER_HIGH)+spell->stats.hp;
1728 
1729  if (heal) {
1730  if (target->stats.hp >= target->stats.maxhp) {
1732  "You are already fully healed.");
1733  } else {
1734  /* See how many points we actually heal. Instead of messages
1735  * based on type of spell, we instead do messages based
1736  * on amount of damage healed.
1737  */
1738  if (heal > (target->stats.maxhp-target->stats.hp))
1739  heal = target->stats.maxhp-target->stats.hp;
1740  target->stats.hp += heal;
1741 
1742  if (target->stats.hp >= target->stats.maxhp) {
1744  "You feel just fine!");
1745  } else if (heal > 50) {
1747  "Your wounds close!");
1748  } else if (heal > 25) {
1750  "Your wounds mostly close.");
1751  } else if (heal > 10) {
1753  "Your wounds start to fade.");
1754  } else {
1756  "Your wounds start to close.");
1757  }
1758  success = 1;
1759  }
1760  }
1761  if (spell->attacktype&AT_DISEASE)
1762  if (cure_disease(target, op, caster && caster->type != PLAYER ? caster->skill : spell->skill))
1763  success = 1;
1764 
1765  if (spell->attacktype&AT_POISON) {
1766  at = find_archetype("poisoning");
1767  poison = arch_present_in_ob(at, target);
1768  if (poison) {
1769  success = 1;
1771  "Your body feels cleansed");
1772  poison->stats.food = 1;
1773  }
1774  }
1775  if (spell->attacktype&AT_CONFUSION) {
1776  poison = object_present_in_ob_by_name(FORCE, "confusion", target);
1777  if (poison) {
1778  success = 1;
1780  "Your mind feels clearer");
1781  poison->duration = 1;
1782  }
1783  }
1784  if (spell->attacktype&AT_BLIND) {
1785  at = find_archetype("blindness");
1786  poison = arch_present_in_ob(at, target);
1787  if (poison) {
1788  success = 1;
1790  "Your vision begins to return.");
1791  poison->stats.food = 1;
1792  }
1793  }
1794  if (spell->last_sp && target->stats.sp < target->stats.maxsp) {
1795  target->stats.sp += spell->last_sp;
1796  if (target->stats.sp > target->stats.maxsp)
1797  target->stats.sp = target->stats.maxsp;
1798  success = 1;
1800  "Magical energies surge through your body!");
1801  }
1802  if (spell->last_grace && target->stats.grace < target->stats.maxgrace) {
1803  target->stats.grace += spell->last_grace;
1804  if (target->stats.grace > target->stats.maxgrace)
1805  target->stats.grace = target->stats.maxgrace;
1806  success = 1;
1808  "You feel redeemed with you god!");
1809  }
1810  if (spell->stats.food && target->stats.food < 999) {
1811  target->stats.food += spell->stats.food;
1812  if (target->stats.food > 999)
1813  target->stats.food = 999;
1814  success = 1;
1815  /* We could do something a bit better like the messages for healing above */
1817  "You feel your belly fill with food");
1818  }
1819 
1820  if (spell->other_arch != NULL && target->map != NULL) {
1821  object_insert_in_map_at(arch_to_object(spell->other_arch), target->map, NULL, INS_ON_TOP, target->x, target->y);
1822  }
1823 
1824  return success;
1825 }
1826 
1827 
1833 static const char *const no_gain_msgs[NUM_STATS] = {
1834  "You grow no stronger.",
1835  "You grow no more agile.",
1836  "You don't feel any healthier.",
1837  "no wis",
1838  "You are no easier to look at.",
1839  "no int",
1840  "no pow"
1841 };
1842 
1862 int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent) {
1863  object *tmp;
1864  object *force = NULL;
1865  int i;
1866 
1867  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1868  if (dir != 0) {
1869  tmp = find_target_for_friendly_spell(op, dir);
1870  } else {
1871  tmp = op;
1872  }
1873 
1874  if (tmp == NULL)
1875  return 0;
1876 
1877  /* If we've already got a force of this type, don't add a new one. */
1878  FOR_INV_PREPARE(tmp, tmp2)
1879  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
1880  if (tmp2->name == spell_ob->name) {
1881  force = tmp2; /* the old effect will be "refreshed" */
1882  break;
1883  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
1884  if (!silent)
1886  "You can not cast %s while %s is in effect",
1887  spell_ob->name, tmp2->name_pl);
1888  return 0;
1889  }
1890  }
1891  FOR_INV_FINISH();
1892  if (force == NULL) {
1893  force = create_archetype(FORCE_NAME);
1894  force->subtype = FORCE_CHANGE_ABILITY;
1895  free_string(force->name);
1896  if (spell_ob->race)
1897  force->name = add_refcount(spell_ob->race);
1898  else
1899  force->name = add_refcount(spell_ob->name);
1900  free_string(force->name_pl);
1901  force->name_pl = add_refcount(spell_ob->name);
1902  } else {
1903  int duration;
1904 
1905  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1906  if (duration > force->duration) {
1907  force->duration = duration;
1909  "You recast the spell while in effect.");
1910 
1911  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
1912  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
1913  }
1914 
1915  } else {
1917  "Recasting the spell had no effect.");
1918  }
1919  return 1;
1920  }
1921  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1922  if (op->type == PLAYER)
1923  store_spell_expiry(force);
1924  force->speed = 1.0;
1925  force->speed_left = -1.0;
1926  SET_FLAG(force, FLAG_APPLIED);
1927 
1928  /* Now start processing the effects. First, protections */
1929  for (i = 0; i < NROFATTACKS; i++) {
1930  if (spell_ob->resist[i]) {
1931  force->resist[i] = spell_ob->resist[i]+SP_level_dam_adjust(caster, spell_ob);
1932  if (force->resist[i] > 100)
1933  force->resist[i] = 100;
1934  }
1935  }
1936  if (spell_ob->stats.hp)
1937  force->stats.hp = spell_ob->stats.hp+SP_level_dam_adjust(caster, spell_ob);
1938 
1939  if (tmp->type == PLAYER) {
1940  /* Stat adjustment spells */
1941  for (i = 0; i < NUM_STATS; i++) {
1942  int8_t stat = get_attr_value(&spell_ob->stats, i), k, sm;
1943 
1944  if (stat) {
1945  sm = 0;
1946  for (k = 0; k < stat; k++)
1947  sm += rndm(1, 3);
1948 
1949  if ((get_attr_value(&tmp->stats, i)+sm) > (15+5*stat)) {
1950  sm = (15+5*stat)-get_attr_value(&tmp->stats, i);
1951  if (sm < 0)
1952  sm = 0;
1953  }
1954  set_attr_value(&force->stats, i, sm);
1955  if (!sm)
1957  no_gain_msgs[i]);
1958  }
1959  }
1960  }
1961 
1962  force->move_type = spell_ob->move_type;
1963 
1964  if (QUERY_FLAG(spell_ob, FLAG_SEE_IN_DARK))
1965  SET_FLAG(force, FLAG_SEE_IN_DARK);
1966 
1967  if (QUERY_FLAG(spell_ob, FLAG_XRAYS))
1968  SET_FLAG(force, FLAG_XRAYS);
1969 
1970  /* Haste/bonus speed */
1971  if (spell_ob->stats.exp) {
1972  if (op->speed > 0.5)
1973  force->stats.exp = (float)spell_ob->stats.exp/(op->speed+0.5);
1974  else
1975  force->stats.exp = spell_ob->stats.exp;
1976  }
1977 
1978  force->stats.wc = spell_ob->stats.wc;
1979  force->stats.ac = spell_ob->stats.ac;
1980  force->attacktype = spell_ob->attacktype;
1981 
1982  SET_FLAG(tmp, FLAG_NO_FIX_PLAYER); /* we don't want object_insert_in_ob() to call fix_object. */
1983  object_insert_in_ob(force, tmp);
1985  change_abil(tmp, force); /* Display any relevant messages, and call fix_object to update the player */
1986 
1987  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
1988  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
1989  }
1990 
1991  return 1;
1992 }
1993 
2010 int cast_bless(object *op, object *caster, object *spell_ob, int dir) {
2011  int i;
2012  const object *god = find_god(determine_god(op));
2013  object *force = NULL, *tmp;
2014 
2015  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
2016  if (dir != 0) {
2017  tmp = find_target_for_friendly_spell(op, dir);
2018  } else {
2019  tmp = op;
2020  }
2021 
2022  /* If we've already got a force of this type, don't add a new one. */
2023  FOR_INV_PREPARE(tmp, tmp2)
2024  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
2025  if (tmp2->name == spell_ob->name) {
2026  force = tmp2; /* the old effect will be "refreshed" */
2027  break;
2028  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
2030  "You can not cast %s while %s is in effect",
2031  spell_ob->name, tmp2->name_pl);
2032  return 0;
2033  }
2034  }
2035  FOR_INV_FINISH();
2036  if (force == NULL) {
2037  force = create_archetype(FORCE_NAME);
2038  force->subtype = FORCE_CHANGE_ABILITY;
2039  free_string(force->name);
2040  if (spell_ob->race)
2041  force->name = add_refcount(spell_ob->race);
2042  else
2043  force->name = add_refcount(spell_ob->name);
2044  free_string(force->name_pl);
2045  force->name_pl = add_refcount(spell_ob->name);
2046  } else {
2047  int duration;
2048 
2049  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2050  if (duration > force->duration) {
2051  force->duration = duration;
2053  "You recast the spell while in effect.");
2054  } else {
2056  "Recasting the spell had no effect.");
2057  }
2058  return 0;
2059  }
2060  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2061  force->speed = 1.0;
2062  force->speed_left = -1.0;
2063 
2064  if (!god) {
2066  "Your blessing seems empty.");
2067  } else {
2068  /* Only give out good benefits, and put a max on it */
2069  for (i = 0; i < NROFATTACKS; i++) {
2070  if (god->resist[i] > 0) {
2071  force->resist[i] = MIN(god->resist[i], spell_ob->resist[ATNR_GODPOWER]);
2072  }
2073  }
2074  force->path_attuned |= god->path_attuned;
2075  if (spell_ob->attacktype) {
2076  force->attacktype |= god->attacktype|AT_PHYSICAL;
2077  if (god->slaying)
2078  force->slaying = add_string(god->slaying);
2079  }
2080  if (tmp != op) {
2082  "You bless %s.",
2083  tmp->name);
2085  "%s blessed you.",
2086  op->name);
2087  } else {
2089  "You are blessed by %s!",
2090  god->name);
2091  }
2092  }
2093  force->stats.wc = spell_ob->stats.wc;
2094  force->stats.ac = spell_ob->stats.ac;
2095 
2096  store_spell_expiry(force);
2097  object_insert_in_ob(force, tmp);
2098  SET_FLAG(force, FLAG_APPLIED);
2099  change_abil(tmp, force); /* To display any messages, will call fix_object() */
2100 
2101  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2102  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2103  }
2104  return 1;
2105 }
2106 
2107 
2108 
2109 /*
2110  * Alchemy code by Mark Wedel
2111  *
2112  * This code adds a new spell, called alchemy. Alchemy will turn
2113  * objects to gold nuggets, the value of the gold nuggets being
2114  * from 5% to 40% of that of the item itself depending on casting level.
2115  * It uses the value of the object before charisma adjustments, because
2116  * the nuggets themselves will be will be adjusted by charisma when sold.
2117  *
2118  * Large nuggets are worth 25 gp each (base). You will always get
2119  * the maximum number of large nuggets you could get.
2120  * Small nuggets are worth 1 gp each (base). You will get from 0
2121  * to the max amount of small nuggets as you could get.
2122  *
2123  * For example, if an item is worth 110 gold, you will get
2124  * 4 large nuggets, and from 0-10 small nuggets.
2125  *
2126  * There is also a chance (1:30) that you will get nothing at all
2127  * for the object. There is also a maximum weight that will be
2128  * alchemied.
2129  */
2130 
2131 #define SMALL_NUGGET "smallnugget"
2132 #define LARGE_NUGGET "largenugget"
2133 
2148 static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight) {
2149  uint64_t value = price_base(obj);
2150  uint64_t small_value, large_value;
2152  /* Multiply the value of the object by value_adj, which should range
2153  * from 0.05 to 0.40. Set value to 0 instead if unpaid.
2154  */
2155  if (QUERY_FLAG(obj, FLAG_UNPAID))
2156  value = 0;
2157  else
2158  value *= value_adj;
2159 
2160  small_value = price_base(&find_archetype(SMALL_NUGGET)->clone);
2161  large_value = price_base(&find_archetype(LARGE_NUGGET)->clone);
2162 
2163  /* Give half of what value_adj says when we alchemy money (This should
2164  * hopefully make it so that it isn't worth it to alchemy money, sell
2165  * the nuggets, alchemy the gold from that, etc.
2166  */
2167  if (value && (obj->type == MONEY || obj->type == GEM))
2168  value /= 2;
2169 
2170  if ((obj->value > 0) && rndm(0, 29)) {
2171  int count;
2172 
2173  assert(large_value != 0 && small_value != 0);
2174  count = value/large_value;
2175  *large_nuggets += count;
2176  value -= (uint64_t)count*large_value;
2177  count = value/small_value;
2178  *small_nuggets += count;
2179  }
2180 
2181  /* Turn 25 small nuggets into 1 large nugget. If the value
2182  * of large nuggets is not evenly divisable by the small nugget
2183  * value, take off an extra small_nugget (Assuming small_nuggets!=0)
2184  */
2185  if (*small_nuggets*small_value >= large_value) {
2186  assert(small_value != 0);
2187  (*large_nuggets)++;
2188  *small_nuggets -= large_value/small_value;
2189  if (*small_nuggets && large_value%small_value)
2190  (*small_nuggets)--;
2191  }
2192 
2193  if (weight != NULL) {
2194  *weight += obj->weight;
2195  }
2196 
2197  object_remove(obj);
2199 }
2200 
2214 static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y) {
2215  object *tmp;
2216  int flag = 0;
2217 
2218  /* Put any nuggets below the player, but we can only pass this
2219  * flag if we are on the same space as the player
2220  */
2221  if (x == op->x && y == op->y && op->map == m)
2222  flag = INS_BELOW_ORIGINATOR;
2223 
2224  if (small_nuggets) {
2226  tmp-> nrof = small_nuggets;
2227  object_insert_in_map_at(tmp, m, op, flag, x, y);
2228  }
2229  if (large_nuggets) {
2231  tmp-> nrof = large_nuggets;
2232  object_insert_in_map_at(tmp, m, op, flag, x, y);
2233  }
2234 }
2235 
2250 int alchemy(object *op, object *caster, object *spell_ob) {
2251  int x, y, weight = 0, weight_max, large_nuggets, small_nuggets, mflags;
2252  int16_t nx, ny;
2253  float value_adj;
2254  mapstruct *mp;
2255 
2256  if (op->type != PLAYER)
2257  return 0;
2258 
2259  /* Put a maximum weight of items that can be alchemied. Limits the power
2260  * some, and also prevents people from alcheming every table/chair/clock
2261  * in sight
2262  */
2263  weight_max = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
2264  weight_max *= 1000;
2265 
2266  /* Set value_adj to be a multiplier for how much of the original value
2267  * will be in the nuggets. Starts at 0.05, increasing by 0.01 per casting
2268  * level, maxing out at 0.40.
2269  */
2270  value_adj = (SP_level_dam_adjust(caster, spell_ob)/100.00)+0.05;
2271 
2272  if (value_adj > 0.40)
2273  value_adj = 0.40;
2274 
2275  for (y = op->y-1; y <= op->y+1; y++) {
2276  for (x = op->x-1; x <= op->x+1; x++) {
2277  nx = x;
2278  ny = y;
2279 
2280  mp = op->map;
2281 
2282  mflags = get_map_flags(mp, &mp, nx, ny, &nx, &ny);
2283 
2284  if (mflags&(P_OUT_OF_MAP|P_NO_MAGIC))
2285  continue;
2286 
2287  /* Treat alchemy a little differently - most spell effects
2288  * use fly as the movement type - for alchemy, consider it
2289  * ground level effect.
2290  */
2291  if (GET_MAP_MOVE_BLOCK(mp, nx, ny)&MOVE_WALK)
2292  continue;
2293 
2294  small_nuggets = 0;
2295  large_nuggets = 0;
2296 
2297  FOR_MAP_PREPARE(mp, nx, ny, tmp) {
2298  if (tmp->weight > 0 && !QUERY_FLAG(tmp, FLAG_NO_PICK)
2299  && !QUERY_FLAG(tmp, FLAG_ALIVE)
2300  && !QUERY_FLAG(tmp, FLAG_IS_CAULDRON)) {
2301  if (tmp->inv) {
2302  FOR_INV_PREPARE(tmp, tmp1)
2303  if (tmp1->weight > 0 && !QUERY_FLAG(tmp1, FLAG_NO_PICK)
2304  && !QUERY_FLAG(tmp1, FLAG_ALIVE)
2305  && !QUERY_FLAG(tmp1, FLAG_IS_CAULDRON))
2306  alchemy_object(value_adj, tmp1, &small_nuggets, &large_nuggets, &weight);
2307  FOR_INV_FINISH();
2308  }
2309  alchemy_object(value_adj, tmp, &small_nuggets, &large_nuggets, &weight);
2310 
2311  if (weight > weight_max) {
2312  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2313  return 1;
2314  }
2315  } /* is alchemable object */
2316  } FOR_MAP_FINISH(); /* process all objects on this space */
2317 
2318  /* Insert all the nuggets at one time. This probably saves time, but
2319  * it also prevents us from alcheming nuggets that were just created
2320  * with this spell.
2321  */
2322  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2323  }
2324  }
2325 
2326  /* reset this so that if player standing on a big pile of stuff,
2327  * it is redrawn properly.
2328  */
2329  op->contr->socket.look_position = 0;
2330  return 1;
2331 }
2332 
2333 
2348 int remove_curse(object *op, object *caster, object *spell) {
2349  int success = 0, was_one = 0;
2350 
2351  FOR_INV_PREPARE(op, tmp)
2352  if (QUERY_FLAG(tmp, FLAG_APPLIED)
2353  && ((QUERY_FLAG(tmp, FLAG_CURSED) && QUERY_FLAG(spell, FLAG_CURSED))
2354  || (QUERY_FLAG(tmp, FLAG_DAMNED) && QUERY_FLAG(spell, FLAG_DAMNED)))) {
2355  was_one++;
2356  if (tmp->level <= caster_level(caster, spell)) {
2357  success++;
2358  if (QUERY_FLAG(spell, FLAG_DAMNED))
2359  CLEAR_FLAG(tmp, FLAG_DAMNED);
2360 
2361  CLEAR_FLAG(tmp, FLAG_CURSED);
2363  tmp->value = 0; /* Still can't sell it */
2364  if (op->type == PLAYER)
2365  esrv_update_item(UPD_FLAGS, op, tmp);
2366  }
2367  }
2368  FOR_INV_FINISH();
2369 
2370  if (op->type == PLAYER) {
2371  if (success) {
2373  "You feel like some of your items are looser now.");
2374  } else {
2375  if (was_one)
2377  "You failed to remove the curse.");
2378  else
2380  "You are not using any cursed items.");
2381  }
2382  }
2383  return success;
2384 }
2385 
2398 int cast_item_curse_or_curse(object *op, object *caster, object *spell_ob) {
2399  object *marked = find_marked_object(op);
2400  char name[HUGE_BUF];
2401 
2402  if (!marked) {
2404  "You need to mark an item first!");
2405  return 0;
2406  }
2407 
2408  if ((QUERY_FLAG(marked, FLAG_CURSED) && QUERY_FLAG(spell_ob, FLAG_CURSED))
2409  || (QUERY_FLAG(marked, FLAG_BLESSED) && QUERY_FLAG(spell_ob, FLAG_BLESSED))) {
2411  "The spell has no effect");
2412  return 0;
2413  }
2414 
2415  query_short_name(marked, name, HUGE_BUF);
2416  if (QUERY_FLAG(spell_ob, FLAG_CURSED)) {
2418  "Your %s emits a dark light for a few seconds.", name);
2419  SET_FLAG(marked, FLAG_CURSED);
2420  CLEAR_FLAG(marked, FLAG_KNOWN_CURSED);
2421  CLEAR_FLAG(marked, FLAG_IDENTIFIED);
2422  esrv_update_item(UPD_FLAGS, op, marked);
2423  return 1;
2424  }
2425 
2427  "Your %s glows blue for a few seconds.", name);
2428  SET_FLAG(marked, FLAG_BLESSED);
2429  SET_FLAG(marked, FLAG_KNOWN_BLESSED);
2430  SET_FLAG(marked, FLAG_STARTEQUIP);
2431  esrv_update_item(UPD_FLAGS, op, marked);
2432  return 1;
2433 }
2434 
2449 int cast_identify(object *op, object *caster, object *spell) {
2450  int success = 0, num_ident;
2451  char desc[MAX_BUF];
2452 
2453  num_ident = spell->stats.dam+SP_level_dam_adjust(caster, spell);
2454 
2455  if (num_ident < 1)
2456  num_ident = 1;
2457 
2458  FOR_INV_PREPARE(op, tmp)
2459  if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify(tmp)) {
2460  tmp = identify(tmp);
2461  if (op->type == PLAYER) {
2463  "You have %s.",
2464  ob_describe(tmp, op, desc, sizeof(desc)));
2465  if (tmp->msg) {
2467  "The item has a story:\n%s",
2468  tmp->msg);
2469  }
2470  }
2471  num_ident--;
2472  success = 1;
2473  if (!num_ident)
2474  break;
2475  }
2476  FOR_INV_FINISH();
2477  /* If all the power of the spell has been used up, don't go and identify
2478  * stuff on the floor. Only identify stuff on the floor if the spell
2479  * was not fully used.
2480  */
2481  if (num_ident) {
2482  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2483  if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED)
2484  && !tmp->invisible
2485  && need_identify(tmp)) {
2486  tmp = identify(tmp);
2487  if (op->type == PLAYER) {
2489  "On the ground is %s.",
2490  ob_describe(tmp, op, desc, sizeof(desc)));
2491  if (tmp->msg) {
2493  "The item has a story:\n%s",
2494  tmp->msg);
2495  }
2497  }
2498  num_ident--;
2499  success = 1;
2500  if (!num_ident)
2501  break;
2502  }
2503  FOR_MAP_FINISH();
2504  }
2505  if (!success)
2507  "You can't reach anything unidentified.");
2508  else {
2509  spell_effect(spell, op->x, op->y, op->map, op);
2510  }
2511  return success;
2512 }
2513 
2526 int cast_detection(object *op, object *caster, object *spell) {
2527  object *tmp, *last, *detect;
2528  const object *god;
2529  int done_one, range, mflags, floor, level;
2530  int16_t x, y, nx, ny;
2531  mapstruct *m;
2532 
2533  /* We precompute some values here so that we don't have to keep
2534  * doing it over and over again.
2535  */
2536  god = find_god(determine_god(op));
2537  level = caster_level(caster, spell);
2538  range = spell->range+SP_level_range_adjust(caster, spell);
2539 
2540  for (x = op->x-range; x <= op->x+range; x++)
2541  for (y = op->y-range; y <= op->y+range; y++) {
2542  m = op->map;
2543  mflags = get_map_flags(m, &m, x, y, &nx, &ny);
2544  if (mflags&P_OUT_OF_MAP)
2545  continue;
2546 
2547  /* For most of the detections, we only detect objects above the
2548  * floor. But this is not true for show invisible.
2549  * Basically, we just go and find the top object and work
2550  * down - that is easier than working up.
2551  */
2552 
2553  last = NULL;
2554  FOR_MAP_PREPARE(m, nx, ny, tmp)
2555  last = tmp;
2556  FOR_MAP_FINISH();
2557  /* Shouldn't happen, but if there are no objects on a space, this
2558  * would happen.
2559  */
2560  if (!last)
2561  continue;
2562 
2563  done_one = 0;
2564  floor = 0;
2565  detect = NULL;
2566  tmp = last;
2568  /* show invisible */
2569  if (QUERY_FLAG(spell, FLAG_MAKE_INVIS)
2570  /* Might there be other objects that we can make visibile? */
2571  && (tmp->invisible && (QUERY_FLAG(tmp, FLAG_MONSTER) ||
2572  (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)) ||
2573  tmp->type == CF_HANDLE ||
2574  tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
2575  tmp->type == BUTTON || tmp->type == TELEPORTER ||
2576  tmp->type == GATE || tmp->type == LOCKED_DOOR ||
2577  tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
2578  tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
2579  tmp->type == TREASURE || tmp->type == BOOK ||
2580  tmp->type == HOLY_ALTAR))) {
2581  if (random_roll(0, level-1, op, PREFER_HIGH) > tmp->level) {
2582  tmp->invisible = 0;
2583  done_one = 1;
2584  }
2585  }
2586  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2587  floor = 1;
2588 
2589  /* All detections below this point don't descend beneath the floor,
2590  * so just continue on. We could be clever and look at the type of
2591  * detection to completely break out if we don't care about objects beneath
2592  * the floor, but once we get to the floor, not likely a very big issue anyways.
2593  */
2594  if (floor)
2595  continue;
2596 
2597  /* I had thought about making detect magic and detect curse
2598  * show the flash the magic item like it does for detect monster.
2599  * however, if the object is within sight, this would then make it
2600  * difficult to see what object is magical/cursed, so the
2601  * effect wouldn't be as apparent.
2602  */
2603 
2604  /* detect magic */
2605  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2606  && !QUERY_FLAG(tmp, FLAG_KNOWN_MAGICAL)
2607  && !QUERY_FLAG(tmp, FLAG_IDENTIFIED)
2608  && is_magical(tmp)) {
2610  /* make runes more visible */
2611  if (tmp->type == RUNE && tmp->attacktype&AT_MAGIC)
2612  tmp->stats.Cha /= 4;
2613  done_one = 1;
2614  }
2615  /* detect monster */
2616  if (QUERY_FLAG(spell, FLAG_MONSTER)
2617  && (QUERY_FLAG(tmp, FLAG_MONSTER) || (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)))) {
2618  done_one = 2;
2619  if (!detect)
2620  detect = tmp;
2621  }
2622  /* Basically, if race is set in the spell, then the creatures race must
2623  * match that. if the spell race is set to GOD, then the gods opposing
2624  * race must match.
2625  */
2626  if (spell->race
2627  && QUERY_FLAG(tmp, FLAG_MONSTER)
2628  && tmp->race
2629  && ((!strcmp(spell->race, "GOD") && god && god->slaying && strstr(god->slaying, tmp->race)) || (strstr(spell->race, tmp->race)))) {
2630  done_one = 2;
2631  if (!detect)
2632  detect = tmp;
2633  }
2634  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2635  && !QUERY_FLAG(tmp, FLAG_KNOWN_CURSED)
2636  && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) {
2638  done_one = 1;
2639  }
2640  } FOR_OB_AND_BELOW_FINISH(); /* for stack of objects on this space */
2641 
2642  /* Code here puts an effect of the spell on the space, so you can see
2643  * where the magic is.
2644  */
2645  if (done_one) {
2646  object *detect_ob;
2647  int dx = nx, dy = ny;
2648 
2649  /* if this is set, we want to copy the face */
2650  if (done_one == 2 && detect) {
2651  /*
2652  * We can't simply copy the face to a single item, because
2653  * multipart objects need to have multipart glows.
2654  * So copy the initial item, erase some properties, and use that.
2655  */
2656 
2657  object *part;
2658  int flag;
2659 
2660  dx = HEAD(detect)->x;
2661  dy = HEAD(detect)->y;
2662 
2663  detect_ob = object_create_arch(HEAD(detect)->arch);
2664  for (part = detect_ob; part != NULL; part = part->more) {
2665  if (part->arch->reference_count > 0)
2666  part->arch->reference_count++;
2667  part->last_anim = 0;
2668  part->type = spell->other_arch->clone.type;
2669  for (flag = 0; flag < 4; flag++) {
2670  part->flags[flag] = spell->other_arch->clone.flags[flag];
2671  }
2672  part->stats.food = spell->other_arch->clone.stats.food;
2673  part->last_anim = 0;
2674  part->speed = spell->other_arch->clone.speed;
2675  part->speed_left = spell->other_arch->clone.speed_left;
2676  part->move_allow = spell->other_arch->clone.move_allow;
2677  part->move_block = spell->other_arch->clone.move_block;
2678  part->move_type = spell->other_arch->clone.move_type;
2679  part->glow_radius = spell->other_arch->clone.glow_radius;
2680  part->invisible = spell->other_arch->clone.invisible;
2681  part->weight = spell->other_arch->clone.weight;
2682  part->map_layer = spell->other_arch->clone.map_layer;
2683  FREE_AND_COPY(part->name, spell->other_arch->clone.name);
2684 
2685  /* by default, the detect_ob is already animated */
2686  if (!QUERY_FLAG(detect, FLAG_ANIMATE))
2687  CLEAR_FLAG(part, FLAG_ANIMATE);
2688  }
2689  object_update_speed(detect_ob);
2690  } else
2691  detect_ob = arch_to_object(spell->other_arch);
2692 
2693  object_insert_in_map_at(detect_ob, m, op, 0, dx, dy);
2694  }
2695  } /* for processing the surrounding spaces */
2696 
2697 
2698  /* Now process objects in the players inventory if detect curse or magic */
2699  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED) || QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)) {
2700  done_one = 0;
2701  FOR_INV_PREPARE(op, tmp) {
2702  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_IDENTIFIED)) {
2703  if (QUERY_FLAG(spell, FLAG_KNOWN_MAGICAL)
2704  && is_magical(tmp)
2705  && !QUERY_FLAG(tmp, FLAG_KNOWN_MAGICAL)) {
2707  if (op->type == PLAYER)
2708  esrv_send_item(op, tmp);
2709  }
2710  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED)
2711  && !QUERY_FLAG(tmp, FLAG_KNOWN_CURSED)
2712  && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) {
2714  if (op->type == PLAYER)
2715  esrv_send_item(op, tmp);
2716  }
2717  } /* if item is not identified */
2718  } FOR_INV_FINISH(); /* for the players inventory */
2719  } /* if detect magic/curse and object is a player */
2720  return 1;
2721 }
2722 
2730 static void charge_mana_effect(object *victim, int caster_level) {
2731  /* Prevent explosions for objects without mana. Without this check, doors
2732  * will explode, too.
2733  */
2734  if (victim->stats.maxsp <= 0)
2735  return;
2736 
2738  "You feel energy course through you.");
2739 
2740  if (victim->stats.sp >= victim->stats.maxsp*2) {
2741  object *tmp;
2742 
2744  "Your head explodes!");
2745 
2746  /* Explodes a fireball centered at player */
2748  tmp->dam_modifier = random_roll(1, caster_level, victim, PREFER_LOW)/5+1;
2749  tmp->stats.maxhp = random_roll(1, caster_level, victim, PREFER_LOW)/10+2;
2750  object_insert_in_map_at(tmp, victim->map, NULL, 0, victim->x, victim->y);
2751  victim->stats.sp = 2*victim->stats.maxsp;
2752  } else if (victim->stats.sp >= victim->stats.maxsp*1.88) {
2754  "You feel like your head is going to explode.");
2755  } else if (victim->stats.sp >= victim->stats.maxsp*1.66) {
2757  "You get a splitting headache!");
2758  } else if (victim->stats.sp >= victim->stats.maxsp*1.5) {
2760  "Chaos fills your world.");
2761  confuse_living(victim, victim, 99);
2762  } else if (victim->stats.sp >= victim->stats.maxsp*1.25) {
2764  "You start hearing voices.");
2765  }
2766 }
2767 
2785 int cast_transfer(object *op, object *caster, object *spell, int dir) {
2786  object *plyr = NULL;
2787  int16_t x, y;
2788  mapstruct *m;
2789  int mflags;
2790 
2791  m = op->map;
2792  x = op->x+freearr_x[dir];
2793  y = op->y+freearr_y[dir];
2794 
2795  mflags = get_map_flags(m, &m, x, y, &x, &y);
2796  if (!(mflags&P_OUT_OF_MAP) && mflags&P_IS_ALIVE) {
2797  FOR_MAP_PREPARE(m, x, y, tmp)
2798  plyr = tmp;
2799  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2800  break;
2801  FOR_MAP_FINISH();
2802  }
2803 
2804  /* If we did not find a player in the specified direction, transfer
2805  * to anyone on top of us. This is used for the rune of transference mostly.
2806  */
2807  if (plyr == NULL)
2808  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2809  plyr = tmp;
2810  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2811  break;
2812  FOR_MAP_FINISH();
2813 
2814  if (!plyr) {
2816  "There is no one there.");
2817  return 0;
2818  }
2819 
2820  /* give sp */
2821  if (spell->stats.dam > 0) {
2822  plyr->stats.sp += spell->stats.dam+SP_level_dam_adjust(caster, spell);
2823  charge_mana_effect(plyr, caster_level(caster, spell));
2824  return 1;
2825  /* suck sp away. Can't suck sp from yourself */
2826  } else if (op != plyr) {
2827  /* old dragin magic used floats. easier to just use ints and divide by 100 */
2828 
2829  int rate = -spell->stats.dam+SP_level_dam_adjust(caster, spell), sucked;
2830 
2831  if (rate > 95)
2832  rate = 95;
2833 
2834  sucked = (plyr->stats.sp*rate)/100;
2835  plyr->stats.sp -= sucked;
2836  if (QUERY_FLAG(op, FLAG_ALIVE)) {
2837  /* Player doesn't get full credit */
2838  sucked = (sucked*rate)/100;
2839  op->stats.sp += sucked;
2840  if (sucked > 0) {
2841  charge_mana_effect(op, caster_level(caster, spell));
2842  }
2843  }
2844  return 1;
2845  }
2846  return 0;
2847 }
2848 
2858 void counterspell(object *op, int dir) {
2859  object *head;
2860  int mflags;
2861  mapstruct *m;
2862  int16_t sx, sy;
2863 
2864  sx = op->x+freearr_x[dir];
2865  sy = op->y+freearr_y[dir];
2866  m = op->map;
2867  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2868  if (mflags&P_OUT_OF_MAP)
2869  return;
2870 
2871  FOR_MAP_PREPARE(m, sx, sy, tmp) {
2872  object *owner;
2873 
2874  /* Need to look at the head object - otherwise, if tmp
2875  * points to a monster, we don't have all the necessary
2876  * info for it.
2877  */
2878  head = HEAD(tmp);
2879 
2880  /* don't attack our own spells */
2881  owner = object_get_owner(tmp);
2882  if (owner != NULL && owner == object_get_owner(op))
2883  continue;
2884 
2885  /* Basically, if the object is magical and not counterspell,
2886  * we will more or less remove the object. Don't counterspell
2887  * monsters either.
2888  */
2889 
2890  if (head->attacktype&AT_MAGIC
2891  && !(head->attacktype&AT_COUNTERSPELL)
2892  && !QUERY_FLAG(head, FLAG_MONSTER)
2893  && (op->level > head->level)) {
2894  object_remove(head);
2895  object_free2(head, 0);
2896  } else switch (head->type) {
2897  case SPELL_EFFECT:
2898  if ((op->level > head->level) && !op->stats.food && !op->speed_left) {
2899  object_remove(head);
2900  object_free2(head, 0);
2901  }
2902  break;
2903 
2904  /* I really don't get this rune code that much - that
2905  * random chance seems really low.
2906  */
2907  case RUNE:
2908  if (rndm(0, 149) == 0) {
2909  head->stats.hp--; /* weaken the rune */
2910  if (!head->stats.hp) {
2911  object_remove(head);
2912  object_free2(head, 0);
2913  }
2914  }
2915  break;
2916  }
2917  } FOR_MAP_FINISH();
2918 }
2919 
2934 int cast_consecrate(object *op, object *caster, object *spell) {
2935  char buf[MAX_BUF];
2936  const object *god = find_god(determine_god(op));
2937 
2938  if (!god) {
2940  "You can't consecrate anything if you don't worship a god!");
2941  return 0;
2942  }
2943 
2944  FOR_BELOW_PREPARE(op, tmp) {
2945  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2946  break;
2947  if (tmp->type == HOLY_ALTAR) {
2948  if (tmp->level > caster_level(caster, spell)) {
2950  "You are not powerful enough to reconsecrate the %s",
2951  tmp->name);
2952  return 0;
2953  } else {
2954  /* If we got here, we are consecrating an altar */
2955  object *new_altar;
2956  size_t letter;
2957  archetype *altar_arch;
2958 
2959  snprintf(buf, MAX_BUF, "altar_");
2960  letter = strlen(buf);
2961  strncpy(buf+letter, god->name, MAX_BUF-letter);
2962  for (; letter < strlen(buf); letter++)
2963  buf[letter] = tolower(buf[letter]);
2964  altar_arch = find_archetype(buf);
2965  if (!altar_arch) {
2967  "You fail to consecrate the altar.");
2968  LOG(llevError, "cast_consecrate: can't find altar %s for god %s\n", buf, god->name);
2969  return 0;
2970  }
2971  new_altar = arch_to_object(altar_arch);
2972  new_altar->level = tmp->level;
2973  if (QUERY_FLAG(tmp, FLAG_IS_BUILDABLE))
2974  SET_FLAG(new_altar, FLAG_IS_BUILDABLE);
2975  object_insert_in_map_at(new_altar, tmp->map, tmp, INS_BELOW_ORIGINATOR, tmp->x, tmp->y);
2976  object_remove(tmp);
2978  "You consecrated the altar to %s!",
2979  god->name);
2980  return 1;
2981  }
2982  }
2983  } FOR_BELOW_FINISH();
2985  "You are not standing over an altar!");
2986  return 0;
2987 }
2988 
3012 int animate_weapon(object *op, object *caster, object *spell, int dir) {
3013  object *weapon, *tmp;
3014  char buf[MAX_BUF];
3015  int a, i;
3016  int16_t x, y;
3017  mapstruct *m;
3018  materialtype_t *mt;
3019 
3020  if (!spell->other_arch) {
3022  "Oops, program error!");
3023  LOG(llevError, "animate_weapon failed: spell %s missing other_arch!\n", spell->name);
3024  return 0;
3025  }
3026 
3027  /* exit if it's not a player using this spell. */
3028  if (op->type != PLAYER)
3029  return 0;
3030 
3031  /* if player already has a golem, abort */
3032  if (op->contr->ranges[range_golem] != NULL && op->contr->golem_count == op->contr->ranges[range_golem]->count) {
3034  return 0;
3035  }
3036 
3037  /* if no direction specified, pick one */
3038  if (!dir) {
3039  dir = object_find_free_spot(NULL, op->map, op->x, op->y, 1, 9);
3040  assert(dir != -1);
3041  }
3042 
3043  m = op->map;
3044  x = op->x+freearr_x[dir];
3045  y = op->y+freearr_y[dir];
3046 
3047  /* if there's no place to put the golem, abort */
3048  if ((dir == -1)
3049  || (get_map_flags(m, &m, x, y, &x, &y)&P_OUT_OF_MAP)
3050  || ((spell->other_arch->clone.move_type&GET_MAP_MOVE_BLOCK(m, x, y)) == spell->other_arch->clone.move_type)) {
3052  "There is something in the way.");
3053  return 0;
3054  }
3055 
3056  /* Use the weapon marked by the player. */
3057  weapon = find_marked_object(op);
3058 
3059  if (!weapon) {
3061  "You must mark a weapon to use with this spell!");
3062  return 0;
3063  }
3064  if (spell->race && strcmp(weapon->arch->name, spell->race)) {
3066  "The spell fails to transform your weapon.");
3067  return 0;
3068  }
3069  if (weapon->type != WEAPON) {
3071  "You need to mark a weapon to animate it.");
3072  return 0;
3073  }
3074  if (QUERY_FLAG(weapon, FLAG_UNPAID)) {
3076  "You need to pay for the weapon to animate it.");
3077  return 0;
3078  }
3079  if (QUERY_FLAG(weapon, FLAG_APPLIED)) {
3080  char wn[MAX_BUF];
3081 
3082  query_name(weapon, wn, MAX_BUF);
3084  "You need to unequip %s before using it in this spell",
3085  wn);
3086  return 0;
3087  }
3088 
3089  if (weapon->nrof > 1) {
3090  tmp = object_split(weapon, 1, NULL, 0);
3091  esrv_update_item(UPD_NROF, op, weapon);
3092  weapon = tmp;
3093  }
3094 
3095  /* create the golem object */
3096  tmp = arch_to_object(spell->other_arch);
3097 
3098  /* if animated by a player, give the player control of the golem */
3099  CLEAR_FLAG(tmp, FLAG_MONSTER);
3100  SET_FLAG(tmp, FLAG_FRIENDLY);
3101  tmp->stats.exp = 0;
3102  add_friendly_object(tmp);
3103  tmp->type = GOLEM;
3104  object_set_owner(tmp, op);
3105  set_spell_skill(op, caster, spell, tmp);
3106  op->contr->ranges[range_golem] = tmp;
3107  op->contr->shoottype = range_golem;
3108  op->contr->golem_count = tmp->count;
3109 
3110  /* Give the weapon to the golem now. A bit of a hack to check the
3111  * removed flag - it should only be set if object_split() was
3112  * used above.
3113  */
3114  if (!QUERY_FLAG(weapon, FLAG_REMOVED))
3115  object_remove(weapon);
3116  object_insert_in_ob(weapon, tmp);
3117 
3118  /* To do everything necessary to let a golem use the weapon is a pain,
3119  * so instead, just set it as equipped (otherwise, we need to update
3120  * body_info, skills, etc)
3121  */
3122  SET_FLAG(tmp, FLAG_USE_WEAPON);
3123  SET_FLAG(weapon, FLAG_APPLIED);
3124  fix_object(tmp);
3125 
3126  /* There used to be 'odd' code that basically seemed to take the absolute
3127  * value of the weapon->magic an use that. IMO, that doesn't make sense -
3128  * if you're using a crappy weapon, it shouldn't be as good.
3129  */
3130 
3131  /* modify weapon's animated wc */
3132  tmp->stats.wc = tmp->stats.wc
3133  -SP_level_range_adjust(caster, spell)
3134  -5*weapon->stats.Dex
3135  -2*weapon->stats.Str
3136  -weapon->magic;
3137  if (tmp->stats.wc < -127)
3138  tmp->stats.wc = -127;
3139 
3140  /* Modify hit points for weapon */
3141  tmp->stats.maxhp = tmp->stats.maxhp
3142  +spell->duration
3143  +SP_level_duration_adjust(caster, spell)
3144  +8*weapon->magic
3145  +12*weapon->stats.Con;
3146  if (tmp->stats.maxhp < 0)
3147  tmp->stats.maxhp = 10;
3148  tmp->stats.hp = tmp->stats.maxhp;
3149 
3150  /* Modify weapon's damage */
3151  tmp->stats.dam = spell->stats.dam
3152  +SP_level_dam_adjust(caster, spell)
3153  +weapon->stats.dam
3154  +weapon->magic
3155  +5*weapon->stats.Str;
3156  if (tmp->stats.dam < 0)
3157  tmp->stats.dam = 127;
3158 
3159  /* attacktype */
3160  if (!tmp->attacktype)
3161  tmp->attacktype = AT_PHYSICAL;
3162 
3163  mt = NULL;
3164  if (op->materialname != NULL)
3165  mt = name_to_material(op->materialname);
3166  if (mt != NULL) {
3167  for (i = 0; i < NROFATTACKS; i++)
3168  tmp->resist[i] = 50-(mt->save[i]*5);
3169  a = mt->save[0];
3170  } else {
3171  for (i = 0; i < NROFATTACKS; i++)
3172  tmp->resist[i] = 5;
3173  a = 10;
3174  }
3175  /* Set weapon's immunity */
3176  tmp->resist[ATNR_CONFUSION] = 100;
3177  tmp->resist[ATNR_POISON] = 100;
3178  tmp->resist[ATNR_SLOW] = 100;
3179  tmp->resist[ATNR_PARALYZE] = 100;
3180  tmp->resist[ATNR_TURN_UNDEAD] = 100;
3181  tmp->resist[ATNR_FEAR] = 100;
3182  tmp->resist[ATNR_DEPLETE] = 100;
3183  tmp->resist[ATNR_DEATH] = 100;
3184  tmp->resist[ATNR_BLIND] = 100;
3185 
3186  /* Improve weapon's armour value according to best save vs. physical of its material */
3187 
3188  if (a > 14)
3189  a = 14;
3190  tmp->resist[ATNR_PHYSICAL] = 100-(int)((100.0-(float)tmp->resist[ATNR_PHYSICAL])/(30.0-2.0*a));
3191 
3192  /* Determine golem's speed */
3193  tmp->speed = 0.4+0.1*SP_level_range_adjust(caster, spell);
3194 
3195  if (tmp->speed > 3.33)
3196  tmp->speed = 3.33;
3197 
3198  if (!spell->race) {
3199  snprintf(buf, sizeof(buf), "animated %s", weapon->name);
3200  if (tmp->name)
3201  free_string(tmp->name);
3202  tmp->name = add_string(buf);
3203 
3204  tmp->face = weapon->face;
3205  tmp->animation_id = weapon->animation_id;
3206  tmp->anim_speed = weapon->anim_speed;
3207  tmp->last_anim = weapon->last_anim;
3208  tmp->state = weapon->state;
3209  if (QUERY_FLAG(weapon, FLAG_ANIMATE)) {
3210  SET_FLAG(tmp, FLAG_ANIMATE);
3211  } else {
3212  CLEAR_FLAG(tmp, FLAG_ANIMATE);
3213  }
3214  object_update_speed(tmp);
3215  }
3216 
3217  /* make experience increase in proportion to the strength of the summoned creature. */
3218  tmp->stats.exp *= 1+(MAX(spell->stats.maxgrace, spell->stats.sp)/caster_level(caster, spell));
3219 
3220  tmp->speed_left = -1;
3221  tmp->direction = dir;
3222  object_insert_in_map_at(tmp, m, op, 0, x, y);
3223  return 1;
3224 }
3225 
3240 int cast_change_map_lightlevel(object *op, object *caster, object *spell) {
3241  int success;
3242 
3243  if (!op->map)
3244  return 0; /* shouldnt happen */
3245 
3246  success = change_map_light(op->map, spell->stats.dam);
3247  if (!success) {
3248  if (spell->stats.dam < 0)
3250  "It can be no brighter here.");
3251  else
3253  "It can be no darker here.");
3254  }
3255  return success;
3256 }
3257 
3272 int create_aura(object *op, object *caster, object *spell) {
3273  int refresh = 0, i;
3274  object *new_aura;
3275 
3276  new_aura = arch_present_in_ob(spell->other_arch, op);
3277  if (new_aura)
3278  refresh = 1;
3279  else
3280  new_aura = arch_to_object(spell->other_arch);
3281 
3282  new_aura->duration = spell->duration+10*SP_level_duration_adjust(caster, spell);
3283  if (op->type == PLAYER)
3284  store_spell_expiry(new_aura);
3285 
3286  new_aura->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
3287 
3288  object_set_owner(new_aura, op);
3289  set_spell_skill(op, caster, spell, new_aura);
3290  new_aura->attacktype = spell->attacktype;
3291 
3292  new_aura->level = caster_level(caster, spell);
3293 
3294  /* Code below is so that auras can also provide resistances. For
3295  * example, fire shield both does damage to nearby enemies and also
3296  * provides some protection to fire. We need to use a different
3297  * FORCE object for this, as putting it in with the aura object
3298  * just puts too many meanings into that one object. Because
3299  * the duration of this force object is the same, we don't need
3300  * to set up spell expiry on it - this second object is really
3301  * an internal mechanic that should be invisible to the player.
3302  */
3303  for (i = 0; i < NROFATTACKS; i++) {
3304  if (spell->resist[i]) {
3305  int refresh1=1;
3306  object *force;
3307 
3308  force = object_present_in_ob_by_name(FORCE, spell->name, op);
3309  if (!force) {
3311  force->subtype = FORCE_CHANGE_ABILITY;
3312  free_string(force->name);
3313  force->name = add_refcount(spell->name);
3314  free_string(force->name_pl);
3315  force->name_pl = add_refcount(spell->name);
3316  refresh1=0;
3317  }
3318  force->duration = new_aura->duration;
3319  force->speed = new_aura->speed;
3320  memcpy(&force->resist, spell->resist, sizeof(spell->resist));
3321  SET_FLAG(force, FLAG_APPLIED);
3322 
3323  if (!refresh1)
3324  object_insert_in_ob(force, op);
3325  change_abil(op, new_aura);
3326  fix_object(op);
3327  break;
3328  }
3329  }
3330 
3331  if (refresh)
3333  "You recast the spell while in effect.");
3334  else
3335  object_insert_in_ob(new_aura, op);
3336  return 1;
3337 }
3338 
3354 int write_mark(object *op, object *spell, const char *msg) {
3355  char rune[HUGE_BUF];
3356  object *tmp;
3357 
3358  if (!msg || msg[0] == 0) {
3360  "Write what?");
3361  return 0;
3362  }
3363 
3364  if (strcasestr_local(msg, "endmsg")) {
3366  "Trying to cheat are we?");
3367  LOG(llevInfo, "write_rune: player %s tried to write bogus rune %s\n", op->name, msg);
3368  return 0;
3369  }
3370 
3371  if (!spell->other_arch)
3372  return 0;
3373  tmp = arch_to_object(spell->other_arch);
3374  strncpy(rune, msg, HUGE_BUF-2);
3375  rune[HUGE_BUF-2] = 0;
3376  strcat(rune, "\n");
3377  tmp->race = add_string(op->name); /*Save the owner of the rune*/
3378  object_set_msg(tmp, rune);
3379  object_insert_in_map_at(tmp, op->map, op, INS_BELOW_ORIGINATOR, op->x, op->y);
3380  return 1;
3381 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: main.c:315
Error, serious thing.
Definition: logger.h:11
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:365
Main Crossfire structure, one ingame object.
Definition: object.h:274
#define FLAG_KNOWN_BLESSED
Item is known to be blessed.
Definition: define.h:379
void set_attr_value(living *stats, int attr, int8_t value)
Sets Str/Dex/con/Wis/Cha/Int/Pow in stats to value, depending on what attr is (STR to POW)...
Definition: living.c:218
int reference_count
How many times this temporary archetype is used.
Definition: object.h:473
#define FLAG_NO_DROP
Object can&#39;t be dropped.
Definition: define.h:289
One player.
Definition: player.h:92
void cast_magic_storm(object *op, object *tmp, int lvl)
This is really used mostly for spell fumbles and the like.
Definition: spell_effect.c:44
#define FLAG_SEE_IN_DARK
if set ob not effected by darkness
Definition: define.h:338
int apply_manual(object *op, object *tmp, int aflag)
Main apply handler.
Definition: apply.c:510
Sound-related defines.
const char * determine_god(object *op)
Determines if op worships a god.
Definition: gods.c:106
archetype * find_archetype(const char *name)
Finds, using the hashtable, which archetype matches the given name.
Definition: arch.c:695
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:318
#define FLAG_IS_FLOOR
Can&#39;t see what&#39;s underneath this object.
Definition: define.h:303
#define FLAG_UNPAID
Object hasn&#39;t been paid for yet.
Definition: define.h:236
int8_t ac
Armour Class, how hard to hit, the lower the better.
Definition: living.h:37
#define MOVE_WALK
Object walks.
Definition: define.h:407
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:519
uint8_t create_home_portals
If 1, can create portals in unique maps (apartments)
Definition: global.h:309
#define FORCE_CHANGE_ABILITY
Definition: spells.h:145
MoveType move_type
Type of movement this object uses.
Definition: object.h:424
see doc/Developers/objects
Definition: object.h:108
#define INS_BELOW_ORIGINATOR
Insert new object immediately below originator.
Definition: object.h:572
int cast_bless(object *op, object *caster, object *spell_ob, int dir)
Improve statistics of some living object.
#define MSG_TYPE_ITEM
Item related information.
Definition: newclient.h:388
Spell-related defines: spellpath, subtypes, ...
#define AT_COUNTERSPELL
Definition: attack.h:95
uint8_t dam_modifier
How going up in level affects damage.
Definition: object.h:407
Information.
Definition: logger.h:12
See Ring.
Definition: object.h:185
materialtype_t * name_to_material(const char *name)
Convert materialname to materialtype_t.
Definition: utils.c:247
const char * race
Human, goblin, dragon, etc.
Definition: object.h:318
int is_magical(const object *op)
Checks whether object is magical.
Definition: item.c:1242
#define ATNR_TURN_UNDEAD
Definition: attack.h:62
int cast_detection(object *op, object *caster, object *spell)
Detect magic or invisible items.
#define FOR_OB_AND_ABOVE_PREPARE(op_)
Constructs a loop iterating over an object and all objects above it in the same pile.
Definition: define.h:774
int caster_level(const object *caster, const object *spell)
This function returns the effective level the spell is being cast at.
Definition: spell_util.c:233
uint16_t attack_movement
What kind of attack movement.
Definition: object.h:391
void esrv_send_item(object *pl, object *op)
Sends item&#39;s info to player.
Definition: main.c:339
#define SET_FLAG(xyz, p)
Definition: define.h:223
sstring add_refcount(sstring str)
This will increase the refcount of the string str.
Definition: shstr.c:210
MoveType move_allow
What movement types explicitly allowed.
Definition: object.h:426
const artifactlist * find_artifactlist(int type)
Searches the artifact lists and returns one that has the same type of objects on it.
Definition: artifact.c:630
int16_t bed_x
Definition: player.h:98
object * object_find_by_type_applied(const object *who, int type)
Find applied object in inventory.
Definition: object.c:3974
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
int cure_disease(object *sufferer, object *caster, sstring skill)
Do the cure disease stuff, from the spell "cure disease".
Definition: disease.c:685
int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
Create food.
Definition: spell_effect.c:605
uint16_t animation_id
An index into the animation array.
Definition: object.h:416
#define MSG_TYPE_ITEM_INFO
Information related to items.
Definition: newclient.h:641
uint8_t anim_speed
Ticks between animation-frames.
Definition: object.h:417
#define FLAG_IS_USED_UP
When (–food<0) the object will exit.
Definition: define.h:260
static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y)
Place gold nuggets on the map.
int write_mark(object *op, object *spell, const char *msg)
This writes a rune that contains the appropriate message.
uint16_t look_position
Start of drawing of look window.
Definition: newserver.h:126
See Food.
Definition: object.h:112
#define NDI_ORANGE
Definition: newclient.h:225
uint8_t last_anim
Last sequence used to draw face.
Definition: object.h:418
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
#define P_NO_MAGIC
Spells (some) can&#39;t pass this object.
Definition: map.h:227
void player_update_bg_music(object player[static 1])
Definition: sounds.c:152
struct artifactstruct * items
Artifacts for this type.
Definition: artifact.h:30
object * mon
Definition: comet_perf.c:74
int8_t range
Range of the spell.
Definition: object.h:405
#define ATNR_DEPLETE
Definition: attack.h:65
#define MSG_TYPE_SPELL
Spell related info.
Definition: newclient.h:387
int8_t save[NROFATTACKS]
Save chances for the attacks.
Definition: material.h:37
#define FLAG_NO_FIX_PLAYER
fix_object() won&#39;t be called
Definition: define.h:277
#define EXPLODING_FIREBALL
This is used for fumbles - this arch is all set up to do the right just by inserting it...
Definition: spells.h:174
See Holy Altar.
Definition: object.h:161
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
mapstruct * ready_map_name(const char *name, int flags)
Makes sure the given map is loaded and swapped in.
Definition: map.c:1803
#define MSG_TYPE_SPELL_FAILURE
Spell failure messages.
Definition: newclient.h:628
int16_t maxgrace
Maximum grace.
Definition: living.h:44
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
Unused?
Definition: treasure.h:32
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.c:342
int alchemy(object *op, object *caster, object *spell_ob)
Change items to gold nuggets.
See Money.
Definition: object.h:137
void examine_monster(object *op, object *tmp, int level)
Player examine a monster.
Definition: c_object.c:1336
struct treasureliststruct * randomitems
Items to be generated.
Definition: object.h:385
int cast_invisible(object *op, object *caster, object *spell_ob)
Makes the player or character invisible.
Definition: spell_effect.c:787
void pick_up(object *op, object *alt)
Try to pick up an item.
Definition: c_object.c:446
int cast_word_of_recall(object *op, object *caster, object *spell_ob)
Word of recall causes the player to return &#39;home&#39;.
Definition: spell_effect.c:899
int magic_wall(object *op, object *caster, int dir, object *spell_ob)
This creates magic walls.
object clone
An object from which to do object_copy()
Definition: object.h:470
#define ATNR_SLOW
Definition: attack.h:60
int16_t duration
How long the spell lasts.
Definition: object.h:403
socket_struct socket
Socket information for this player.
Definition: player.h:94
int16_t invisible
How much longer the object will be invis.
Definition: object.h:360
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.c:65
#define PREFER_LOW
Definition: define.h:600
rangetype shoottype
Which range-attack is being used by player.
Definition: player.h:99
See Rune.
Definition: object.h:240
See Weapon.
Definition: object.h:119
const char * slaying
Which race to do double damage to.
Definition: object.h:319
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:358
object * ranges[range_size]
Object for each range.
Definition: player.h:103
uint8_t subtype
Subtype of object.
Definition: object.h:339
int cast_item_curse_or_curse(object *op, object *caster, object *spell_ob)
This alters player&#39;s marked item&#39;s cursed or blessed status, based on the spell_ob&#39;s fields...
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:297
int SP_level_dam_adjust(const object *caster, const object *spob)
Returns adjusted damage based on the caster.
Definition: spell_util.c:328
int64_t exp
Experience.
Definition: living.h:46
#define FLAG_BLESSED
Item has a blessing, opposite of cursed/damned.
Definition: define.h:378
int cast_earth_to_dust(object *op, object *caster, object *spell_ob)
Basically destroys earthwalls in the area.
Definition: spell_effect.c:848
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:533
struct obj * above
Pointer to the object stacked above this one.
Definition: object.h:288
See Drink.
Definition: object.h:157
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
Definition: object.h:68
int remove_curse(object *op, object *caster, object *spell)
This function removes the cursed/damned status on equipped items.
object * arch_present_in_ob(const archetype *at, const object *op)
Searches for any objects with a matching archetype in the inventory of the given object.
Definition: object.c:3061
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.c:313
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.c:56
uint32_t path_attuned
Paths the object is attuned to.
Definition: object.h:343
#define MAX(x, y)
Definition: compat.h:20
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.c:1239
method_ret ob_apply(object *op, object *applier, int aflags)
Applies an object.
Definition: ob_methods.c:42
#define FLAG_TEAR_DOWN
at->faces[hp*animations/maxhp] at hit
Definition: define.h:279
#define AT_BLIND
Definition: attack.h:98
int16_t sp
Spell points.
Definition: living.h:41
const object * find_god(const char *name)
Returns pointer to specified god&#39;s object through pntr_to_god_obj().
Definition: gods.c:80
#define NDI_BLACK
Definition: newclient.h:221
Global type definitions and header inclusions.
#define PETMOVE
If the upper four bits of attack_movement are set to this number, the monster follows a player until ...
Definition: define.h:517
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:132
struct obj * enemy
Monster/player to follow even if not closest.
Definition: object.h:381
struct archt * other_arch
Pointer used for various things - mostly used for what this objects turns into or what this object cr...
Definition: object.h:413
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.c:310
#define ATNR_CONFUSION
Definition: attack.h:54
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:465
char savebed_map[MAX_BUF]
Map where player will respawn after death.
Definition: player.h:97
See Wand & Staff.
Definition: object.h:220
#define MSG_TYPE_VICTIM_SPELL
Someone cast a bad spell on the player.
Definition: newclient.h:651
#define SP_WORD_OF_RECALL
Definition: spells.h:92
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
Definition: define.h:789
int16_t maxsp
Max spell points.
Definition: living.h:42
int8_t Con
Definition: living.h:35
#define MIN(x, y)
Definition: compat.h:17
int change_map_light(mapstruct *m, int change)
Used to change map light level (darkness) up or down.
Definition: map.c:1995
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
int16_t hp
Hit Points.
Definition: living.h:39
archetype * find_archetype_by_object_type_name(int type, const char *name)
This function retrieves an archetype by type and name that appears during the game.
Definition: arch.c:83
int cast_cone(object *op, object *caster, int dir, object *spell)
Casts a cone spell.
Definition: spell_attack.c:297
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.c:71
#define FLAG_KNOWN_MAGICAL
The object is known to be magical.
Definition: define.h:320
object * active_objects
List of active objects that need to be processed.
Definition: object.c:62
#define SOUND_TYPE_ITEM
Definition: newclient.h:310
#define NDI_NAVY
Definition: newclient.h:223
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.c:490
#define strcasestr_local
Definition: compat.h:24
void pets_control_golem(object *op, int dir)
Makes the golem go in specified direction.
Definition: pets.c:648
void polymorph(object *op, object *who, int level)
Handles polymorphing an object, living or not.
Definition: spell_effect.c:376
int rndm(int min, int max)
Returns a number between min and max.
Definition: utils.c:161
void map_newmap_cmd(socket_struct *ns)
Sound related function.
Definition: request.c:615
int probe(object *op, object *caster, object *spell_ob, int dir, int level)
Try to get information about a living thing.
Definition: spell_effect.c:683
#define FLAG_UNDEAD
Monster is undead.
Definition: define.h:270
void object_set_owner(object *op, object *owner)
Sets the owner and sets the skill and exp pointers to owner&#39;s current skill and experience objects...
Definition: object.c:601
#define MSG_TYPE_SPELL_TARGET
Target of non attack spell.
Definition: newclient.h:633
int change_abil(object *op, object *tmp)
Permanently alters an object&#39;s stats/flags based on another object.
Definition: living.c:394
int16_t y
Position in the map for this object.
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
int16_t maxhp
Max hit points.
Definition: living.h:40
#define FREE_OBJ_FREE_INVENTORY
Free inventory objects; if not set, drop inventory.
Definition: object.h:532
static void polymorph_item(object *who, object *op, int level)
Changes an item to another item of similar type.
Definition: spell_effect.c:276
See Shooting Weapon.
Definition: object.h:118
See Sign & Magic Mouth.
Definition: object.h:211
int cast_heal(object *op, object *caster, object *spell, int dir)
Heals something.
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
void confuse_living(object *op, object *hitter, int dam)
Confuse a living thing.
Definition: attack.c:2221
int recharge(object *op, object *caster, object *spell_ob)
Recharge wands.
Definition: spell_effect.c:79
See Book.
Definition: object.h:114
#define MSG_TYPE_VICTIM
Something bad is happening to the player.
Definition: newclient.h:392
See Exit.
Definition: object.h:181
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it...
Definition: object.c:1037
const char * name_pl
The plural name of the object.
Definition: object.h:315
object * create_archetype(const char *name)
Finds which archetype matches the given name, and returns a new object containing a copy of the arche...
Definition: arch.c:620
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
Definition: stringbuffer.c:95
#define FOR_OB_AND_ABOVE_FINISH()
Finishes FOR_OB_AND_ABOVE_PREPARE().
Definition: define.h:778
#define AT_DISEASE
Definition: attack.h:102
int cast_transfer(object *op, object *caster, object *spell, int dir)
This spell transfers sp from the player to another person.
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.c:2690
float speed_left
How much speed is left to spend this round.
Definition: object.h:329
#define MSG_TYPE_SPELL_SUCCESS
Spell succeeded messages.
Definition: newclient.h:630
#define ATNR_PARALYZE
Definition: attack.h:61
#define INS_ON_TOP
Always put object on top.
Definition: object.h:571
#define MSG_TYPE_SPELL_HEAL
Healing related spells.
Definition: newclient.h:626
signed short int16_t
Definition: win32.h:160
See Treasure.
Definition: object.h:110
See Special Key.
Definition: object.h:124
const char * materialname
Specific material name.
Definition: object.h:346
int32_t weight
Attributes of the object.
Definition: object.h:365
#define MOVE_FLY_LOW
Low flying object.
Definition: define.h:408
object * find_target_for_friendly_spell(object *op, int dir)
This function is commonly used to find a friendly target for spells such as heal or protection or arm...
Definition: spell_util.c:856
void update_all_los(const mapstruct *map, int x, int y)
This function makes sure that update_los() will be called for all players on the given map within the...
Definition: los.c:532
const char *const statname[NUM_STATS]
Name of stats.
Definition: living.c:183
uint32_t tmp_invis
Will invis go away when we attack?
Definition: player.h:125
uint32_t flags[4]
Various flags.
Definition: object.h:415
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.c:1757
int is_dragon_pl(const object *op)
Checks if player is a dragon.
Definition: player.c:114
#define ATNR_DEATH
Definition: attack.h:66
#define snprintf
Definition: win32.h:46
#define ARCH_DEPLETION
Archetype for depletion.
Definition: object.h:579
static void charge_mana_effect(object *victim, int caster_level)
Checks if victim has overcharged mana, and if so does some fireball.
#define SP_WONDER
Definition: spells.h:83
int cast_create_obj(object *op, object *new_op, int dir)
Creates object new_op in direction dir or if that is blocked, beneath the player (op).
Definition: spell_util.c:535
object * transport
Transport the player is in.
Definition: player.h:195
#define FLAG_IDENTIFIED
Player knows full info about item.
Definition: define.h:261
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:712
#define MSG_TYPE_SPELL_PERCEIVE_SELF
Perceive self messages.
Definition: newclient.h:632
int create_aura(object *op, object *caster, object *spell)
Create an aura spell object and put it in the player&#39;s inventory.
int SP_level_duration_adjust(const object *caster, const object *spob)
Adjust the duration of the spell based on level.
Definition: spell_util.c:353
Control golem.
Definition: player.h:21
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
#define ATNR_BLIND
Definition: attack.h:71
#define MSG_TYPE_SPELL_ERROR
Spell failure messages.
Definition: newclient.h:631
void add_friendly_object(object *op)
Add a new friendly object to the linked list of friendly objects.
Definition: friend.c:30
Definition: object.h:145
#define FLAG_BLOCKSVIEW
Object blocks view.
Definition: define.h:269
int dimension_door(object *op, object *caster, object *spob, int dir)
Teleport through some doors and space.
const char * name
The name of the object, obviously...
Definition: object.h:311
int16_t bed_y
x,y - coordinates of respawn (savebed).
Definition: player.h:98
int cast_identify(object *op, object *caster, object *spell)
Identifies objects in the players inventory/on the ground.
int cast_wonder(object *op, object *caster, int dir, object *spell_ob)
wonder is really just a spell that will likely cast another spell.
Definition: spell_effect.c:961
void spell_effect(object *spob, int x, int y, mapstruct *map, object *originator)
Inserts into map a spell effect based on other_arch.
Definition: spell_util.c:183
#define ATNR_FEAR
Definition: attack.h:63
int cast_change_map_lightlevel(object *op, object *caster, object *spell)
This changes the light level for the entire map.
uint8_t state
How the object was last drawn (animation)
Definition: object.h:349
int is_true_undead(object *op)
Is the object a true undead?
Definition: player.c:3961
struct obj * below
Pointer to the object stacked below this one.
Definition: object.h:287
#define EXIT_PATH(xyz)
Definition: define.h:455
uint64_t price_base(const object *obj)
Determine the base (intrinsic) value of an item.
Definition: shop.c:66
#define INS_NO_WALK_ON
Don&#39;t call check_walk_on against the originator.
Definition: object.h:570
int16_t last_grace
As last_sp, except for grace.
Definition: object.h:359
#define SMALL_NUGGET
One material type.
Definition: material.h:33
int8_t direction
Means the object is moving that way.
Definition: object.h:334
uint32_t nrof
How many of the objects.
Definition: object.h:333
int8_t Cha
Definition: living.h:35
EXTERN const char *const change_resist_msg[NROFATTACKS]
Definition: attack.h:135
#define ATNR_MAGIC
Definition: attack.h:50
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Basic macro to see if if ob1 can not move onto a space based on the &#39;type&#39; move_block parameter Add c...
Definition: define.h:447
#define UPD_FLAGS
Definition: newclient.h:290
#define FLAG_IS_CAULDRON
container can make alchemical stuff
Definition: define.h:339
#define SIZEOFFREE
Definition: define.h:154
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:251
Number of statistics.
Definition: living.h:18
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Gets the blocking state of a square.
Definition: map.h:192
See Trapdoor.
Definition: object.h:210
#define EXIT_X(xyz)
Definition: define.h:457
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
#define FLAG_XRAYS
X-ray vision.
Definition: define.h:301
object * find_marked_object(object *op)
Return the object the player has marked with the &#39;mark&#39; command below.
Definition: c_object.c:1256
#define FREE_AND_CLEAR_STR(xyz)
Release the shared string, and set it to NULL.
Definition: global.h:208
#define ATNR_PHYSICAL
Definition: attack.h:49
static void polymorph_melt(object *who, object *op)
Destroys item from polymorph failure.
Definition: spell_effect.c:248
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:12
long last_reset_time
A timestamp of the last original map loading.
Definition: map.h:366
static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight)
Compute how many nuggets an object is worth, and remove it.
#define ATNR_POISON
Definition: attack.h:59
#define AT_PHYSICAL
Definition: attack.h:76
float speed
The overall speed of this object.
Definition: object.h:328
unsigned __int64 uint64_t
Definition: win32.h:167
See Spell.
Definition: object.h:214
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
int animate_weapon(object *op, object *caster, object *spell, int dir)
Generalization of staff_to_snake().
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:594
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
uint32_t golem_count
To track the golem.
Definition: player.h:106
void fix_generated_item(object *op, object *creator, int difficulty, int max_magic, int flags)
fix_generated_item(): This is called after an item is generated, in order to set it up right...
Definition: treasure.c:1110
See Locked Door.
Definition: object.h:123
#define EXIT_Y(xyz)
Definition: define.h:458
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
This is one artifact, ie one special item.
Definition: artifact.h:14
char * ob_describe(const object *op, const object *observer, char *buf, size_t size)
Returns the description of an object, as seen by the given observer.
Definition: ob_methods.c:85
struct obj * active_next
Next object in the &#39;active&#39; list This is used in process_events so that the entire object list does n...
Definition: object.h:279
void give_artifact_abilities(object *op, const object *artifact)
Fixes the given object, giving it the abilities and titles it should have due to the second artifact-...
Definition: artifact.c:203
object * object_create_arch(archetype *at)
Create a full object using the given archetype.
Definition: arch.c:736
int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent)
Cast some stat-improving spell.
int16_t x
Definition: object.h:326
static const char *const no_gain_msgs[NUM_STATS]
This is used for the spells that gain stats.
const char * skill
Name of the skill this object uses/grants.
Definition: object.h:321
int8_t wc
Weapon Class, how skilled, the lower the better.
Definition: living.h:36
#define tolower(C)
Simple macro to convert a letter to lowercase.
Definition: c_new.c:29
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:343
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:765
int8_t Str
Definition: living.h:35
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:341
#define FLAG_KNOWN_CURSED
The object is known to be cursed.
Definition: define.h:321
int need_identify(const object *op)
This function really should not exist - by default, any item not identified should need it...
Definition: item.c:1331
#define FLAG_CURSED
The object is cursed.
Definition: define.h:317
unsigned int uint32_t
Definition: win32.h:162
See Player.
Definition: object.h:107
int perceive_self(object *op)
Living thing wants to know information.
Definition: spell_effect.c:995
object * check_inv_recursive(object *op, const object *trig)
Checks object and its inventory for specific item.
Definition: button.c:786
void store_spell_expiry(object *spell)
Stores in the spell when to warn player of expiration.
Definition: spell_util.c:2006
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Find object in inventory.
Definition: object.c:4195
#define AT_POISON
Definition: attack.h:86
#define FLAG_ANIMATE
The object looks at archetype for faces.
Definition: define.h:242
Object structure, the core of Crossfire.
#define PREFER_HIGH
Definition: define.h:599
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:342
#define FLAG_GENERATOR
Will generate type ob->stats.food.
Definition: define.h:248
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
object_split(ob,nr) splits up ob into two parts.
Definition: object.c:2463
uint8_t map_layer
What level to draw this on the map.
Definition: object.h:422
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Describes an item, in all its details.
Definition: item.c:980
#define INS_NO_MERGE
Don&#39;t try to merge with other items.
Definition: object.h:568
See Altar.
Definition: object.h:122
int cast_consecrate(object *op, object *caster, object *spell)
A spell to make an altar your god&#39;s.
int16_t grace
Grace.
Definition: living.h:43
#define FREE_AND_COPY(sv, nv)
Release the shared string if not NULL, and make it a reference to nv.
Definition: global.h:213
const char * invis_race
What race invisible to?
Definition: player.h:135
#define UPD_NROF
Definition: newclient.h:296
signed char int8_t
Type definitions for fixed-size integer types.
Definition: win32.h:158
int cast_polymorph(object *op, object *caster, object *spell_ob, int dir)
Polymorph spell casting.
Definition: spell_effect.c:430
int SP_level_range_adjust(const object *caster, const object *spob)
Adjust the range of the spell based on level.
Definition: spell_util.c:379
#define MAP_PLAYER_UNIQUE
This map is player-specific.
Definition: map.h:97
const char * localdir
Read/write data files.
Definition: global.h:245
tag_t count
Unique object number for this object.
Definition: object.h:299
living stats
Str, Con, Dex, etc.
Definition: object.h:368
#define FLAG_WIZCAST
The wizard can cast spells in no-magic area.
Definition: define.h:290
int8_t Dex
Definition: living.h:35
struct archt * arch
Pointer to archetype.
Definition: object.h:412
void set_spell_skill(object *op, object *caster, object *spob, object *dest)
Utility function to assign the correct skill when casting.
Definition: spell_util.c:94
See Button.
Definition: object.h:207
Only for debugging purposes.
Definition: logger.h:13
See Gate.
Definition: object.h:206
#define ATNR_GODPOWER
Definition: attack.h:69
#define FLAG_IS_BUILDABLE
Can build on item.
Definition: define.h:376
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.c:679
void object_free2(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1391
struct archt * next
Next archetype in a linked list.
Definition: object.h:467
See Handle.
Definition: object.h:208
uint32_t weapontype
Type of weapon.
Definition: object.h:371
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
#define NROFATTACKS
Definition: attack.h:17
void query_short_name(const object *op, char *buf, size_t size)
query_short_name(object) is similar to query_name(), but doesn&#39;t contain any information about object...
Definition: item.c:547
#define UPD_NAME
Definition: newclient.h:293
#define FLAG_MAKE_INVIS
(Item) gives invisibility when applied
Definition: define.h:329
#define NDI_GREY
Definition: newclient.h:232
#define FOR_OB_AND_BELOW_PREPARE(op_)
Constructs a loop iterating over an object and all objects below it in the same pile.
Definition: define.h:785
#define FLAG_STARTEQUIP
Object was given to player at start.
Definition: define.h:268
#define FORCE_NAME
Definition: spells.h:169
int64_t * levels
Number of levels for which we have experience.
Definition: exp.c:26
#define AT_MAGIC
Definition: attack.h:77
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
object * identify(object *op)
Identifies an item.
Definition: item.c:1437
#define ARCH_PORTAL_FAILED
Archetype for town portal failure.
Definition: object.h:581
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.c:104
#define GET_MAP_OB(M, X, Y)
Gets the bottom object on a map.
Definition: map.h:172
int strcasecmp(const char *s1, const char *s2)
Case-insensitive comparaison of strings.
Definition: porting.c:256
int8_t glow_radius
indicates the glow radius of the object
Definition: object.h:364
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
void object_copy(const object *src_ob, object *dest_ob)
Copy object first frees everything allocated by the second object, and then copies the contents of th...
Definition: object.c:838
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_...
Definition: map.c:302
struct obj * inv
Pointer to the first object in the inventory.
Definition: object.h:290
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
void counterspell(object *op, int dir)
Nullifies spell effects.
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
int makes_invisible_to(object *pl, object *mon)
This checks to see if &#39;pl&#39; is invisible to &#39;mon&#39;.
Definition: spell_effect.c:740
int did_make_save(const object *op, int level, int bonus)
This function takes an object (monster/player, op), and determines if it makes a basic save throw by ...
Definition: living.c:2175
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:758
MoveType move_block
What movement types this blocks.
Definition: object.h:425
int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg)
Create a missile (nonmagic - magic +4).
Definition: spell_effect.c:498
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
Plays a sound on a map.
Definition: sounds.c:101
Structure containing object statistics.
#define P_BLOCKSVIEW
This spot blocks the player&#39;s view.
Definition: map.h:226
void object_set_msg(object *op, const char *msg)
Set the message field of an object.
Definition: object.c:4695
See Pit.
Definition: object.h:209
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
object_find_free_spot(object, map, x, y, start, stop) will search for a spot at the given map and coo...
Definition: object.c:3415
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.c:625
object * item
Special values of the artifact.
Definition: artifact.h:15
#define LARGE_NUGGET
#define FOR_BELOW_PREPARE(op_, it_)
Constructs a loop iterating over all objects below an object.
Definition: define.h:739
object * generate_treasure(treasurelist *t, int difficulty)
Generate a treasure from a list generating a single item.
Definition: treasure.c:518
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
Searches for any objects with a matching archetype at the given map and coordinates.
Definition: object.c:2944
This is a game-map.
Definition: map.h:325
#define P_IS_ALIVE
Something alive is on this space.
Definition: map.h:237
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.c:42
const New_Face * face
Face with colors.
Definition: object.h:332
#define AT_CONFUSION
Definition: attack.h:81
See Jewel.
Definition: object.h:167
#define FLAG_NO_PICK
Object can&#39;t be picked up.
Definition: define.h:239
object * object_find_by_type_and_arch_name(const object *who, int type, const char *name)
Find object in inventory by type and archetype name.
Definition: object.c:4168
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.c:1861
int16_t level
Level of creature or object.
Definition: object.h:351
int8_t facing
Object is oriented/facing that way.
Definition: object.h:335
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.c:1120
EXTERN archetype * first_archetype
First archetype.
Definition: global.h:122
struct obj * more
Pointer to the rest of a large body of objects.
Definition: object.h:295
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.c:571
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.c:1129
int32_t value
How much money it is worth (or contains)
Definition: object.h:350
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.c:559
int8_t magic
Any magical bonuses to this item.
Definition: object.h:348
See Teleporter.
Definition: object.h:141
static void polymorph_living(object *op, int level)
Takes a living object (op) and turns it into another monster of some sort.
Definition: spell_effect.c:157
const char * name
More definite name, like "generate_kobold".
Definition: object.h:466
int cast_create_town_portal(object *op, object *caster, object *spell, int dir)
This function cast the spell of town portal for op.
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
#define FOR_BELOW_FINISH()
Finishes FOR_BELOW_PREPARE().
Definition: define.h:746
#define HAS_RANDOM_ITEMS(op)
This return TRUE if object has still randomitems which could be expanded.
Definition: define.h:183
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Searches for any objects with a matching type & name variable in the inventory of the given object...
Definition: object.c:3039
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:705
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Main dispatch when someone casts a spell.
Definition: spell_util.c:1471
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
struct artifactstruct * next
Next artifact in the list.
Definition: artifact.h:18
int atnr_is_dragon_enabled(int attacknr)
Determine if the attacktype represented by the specified attack-number is enabled for dragon players...
Definition: player.c:95
int32_t food
How much food in stomach.
Definition: living.h:47
uint32_t count
Any numbers typed before a command.
Definition: player.h:109
Definition: object.h:224