Crossfire Server, Trunk  1.75.0
spell_effect.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE // strcasestr() is a GNU extension in string.h
21 #endif
22 
23 #include "global.h"
24 
25 #include <assert.h>
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "living.h"
31 #include "object.h"
32 #include "shop.h"
33 #include "sounds.h"
34 #include "spells.h"
35 #include "sproto.h"
36 #include "assets.h"
37 #include "AssetsManager.h"
38 
49 void cast_magic_storm(object *op, object *tmp, int lvl) {
50  if (!tmp)
51  return; /* error */
52  tmp->level = op->level;
53  tmp->range += lvl/5; /* increase the area of destruction */
54  tmp->duration += lvl/5;
55 
56  /* Put a cap on duration for this - if the player fails in their
57  * apartment, don't want it to go on so long that it kills them
58  * multiple times. Also, damage already increases with level,
59  * so don't really need to increase the duration as much either.
60  */
61  if (tmp->duration >= 40)
62  tmp->duration = 40;
63  tmp->stats.dam = lvl; /* nasty recoils! */
64  tmp->stats.maxhp = tmp->count; /* tract single parent */
65  if (tmp->stats.maxhp == 0)
66  tmp->stats.maxhp = 1;
67  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
68 }
69 
84 int recharge(object *op, object *caster, object *spell_ob) {
85  object *wand, *tmp;
86  int ncharges;
87  char name[MAX_BUF];
88 
89  wand = find_marked_object(op);
90  if (wand == NULL || wand->type != WAND) {
92  "You need to mark the wand you want to recharge.");
93  return 0;
94  }
95  if (!(random_roll(0, 3, op, PREFER_HIGH))) {
96  query_name(wand, name, MAX_BUF);
98  "The %s vibrates violently, then explodes!",
99  name);
100  play_sound_map(SOUND_TYPE_ITEM, wand, 0, "explode");
101  object_remove(wand);
102  object_free(wand, 0);
103  tmp = create_archetype("fireball");
104  tmp->stats.dam = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob))/10;
105  if (!tmp->stats.dam)
106  tmp->stats.dam = 1;
107  tmp->stats.hp = tmp->stats.dam/2;
108  if (tmp->stats.hp < 2)
109  tmp->stats.hp = 2;
110  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
111  return 1;
112  }
113 
114  ncharges = (spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob));
115  if (wand->inv && wand->inv->level)
116  ncharges /= wand->inv->level;
117  else {
118  query_name(wand, name, MAX_BUF);
120  "Your %s is broken.",
121  name);
122  return 0;
123  }
124  if (!ncharges)
125  ncharges = 1;
126 
127  wand->stats.food += ncharges;
128  query_name(wand, name, MAX_BUF);
130  "The %s glows with power.",
131  name);
132 
133  if (wand->arch && QUERY_FLAG(&wand->arch->clone, FLAG_ANIMATE)) {
134  SET_FLAG(wand, FLAG_ANIMATE);
135  wand->speed = wand->arch->clone.speed;
136  object_update_speed(wand);
137  }
138  return 1;
139 }
140 
141 /******************************************************************************
142  * Start of polymorph related functions.
143  *
144  * Changed around for 0.94.3 - it will now look through and use all the
145  * possible choices for objects/monsters (before it was the first 80 -
146  * arbitrary hardcoded limit in this file.) Doing this will be a bit
147  * slower however - while before, it traversed the archetypes once and
148  * stored them into an array, it will now potentially traverse it
149  * an average of 1.5 times. This is probably more costly on the polymorph
150  * item function, since it is possible a couple lookups might be needed before
151  * an item of proper value is generated.
152  */
153 
162 static void polymorph_living(object *op, int level) {
163  int x = op->x, y = op->y, choice, friendly;
164  mapstruct *map = op->map;
165  object *owner, *replacing;
166 
167  op = HEAD(op);
168 
169  /* High level creatures are immune, as are creatures immune to magic. Otherwise,
170  * give the creature a saving throw.
171  */
172  if (op->level >= level*2
173  || did_make_save(op, op->level, op->resist[ATNR_MAGIC]/10)
174  || (op->resist[ATNR_MAGIC] == 100))
175  return;
176 
177  object_remove(op);
178 
179  std::vector<std::pair<archetype *, int>> candidates;
180 
181  getManager()->archetypes()->each([&] (auto at) {
182  int pos;
183  if ((!at->head) && (QUERY_FLAG((&at->clone), FLAG_MONSTER) == QUERY_FLAG(op, FLAG_MONSTER))
184  && ((pos = object_find_first_free_spot(&at->clone, map, x, y)) != -1)) {
185  candidates.push_back(std::make_pair(at, pos));
186  }
187  });
188 
189  if (candidates.empty()) {
190  object_insert_in_map_at(op, map, NULL, 0, x, y);
191  return; /* no valid matches? if so, return */
192  }
193 
194  /* Next make a choice, and loop through until we get to it */
195  choice = rndm(0, candidates.size() - 1);
196  auto at = candidates[choice].first;
197  int pos = candidates[choice].second;
198 
199  /* Look through the monster. Unapply anything they have applied,
200  * and remove any spells. Note that if this is extended
201  * to players, that would need to get fixed somehow.
202  */
203  FOR_INV_PREPARE(op, tmp) {
204  if (QUERY_FLAG(tmp, FLAG_APPLIED))
205  apply_manual(op, tmp, 0);
206  if (tmp->type == SPELL) {
207  object_remove(tmp);
208  object_free(tmp, 0);
209  }
210  } FOR_INV_FINISH();
211 
212  /* Preserve some values for the new object */
213  owner = object_get_owner(op);
215  if (friendly)
217 
218  replacing = object_create_arch(at);
219  if (owner != NULL)
220  object_set_owner(replacing, owner);
221  if (friendly) {
222  SET_FLAG(replacing, FLAG_FRIENDLY);
223  replacing->attack_movement = PETMOVE;
224  add_friendly_object(replacing);
225  } else
226  CLEAR_FLAG(replacing, FLAG_FRIENDLY);
228 
229  /* Put the new creature on the map */
230  if ((replacing = object_insert_in_map_at(replacing, map, owner, 0, x + freearr_x[pos], y + freearr_y[pos])) == NULL)
231  return;
232 
233  if (HAS_RANDOM_ITEMS(replacing))
234  create_treasure(replacing->randomitems, replacing, GT_INVISIBLE, map->difficulty, 0);
235 
236  /* Apply any objects. */
237  monster_check_apply_all(replacing);
238 }
239 
240 
252 static void polymorph_melt(object *who, object *op) {
253  /* Not unique */
254  char name[MAX_BUF];
255 
256  query_name(op, name, MAX_BUF);
257  if (op->nrof > 1)
259  "The %s glow red, melt and evaporate!",
260  name);
261  else
263  "The %s glows red, melts and evaporates!",
264  name);
265  play_sound_map(SOUND_TYPE_ITEM, op, 0, "evaporate");
266  object_remove(op);
267  object_free(op, 0);
268  return;
269 }
270 
280 static void polymorph_item(object *who, object *op, int level) {
281  archetype *at;
282  int max_value, difficulty, tries = 0, choice, charges = op->stats.food;
283  object *new_ob;
284  mapstruct *m;
285  int16_t x, y;
286 
287  /* We try and limit the maximum value of the changed object. */
288  max_value = op->value*2;
289  if (max_value > 2000*(level/10))
290  max_value = 2000*(level/10)+(max_value-2000*(level/10))/3;
291 
292  std::vector<archetype *> candidates;
293 
294  /* Look through and try to find matching items. Can't turn into something
295  * invisible. Also, if the value is too high now, it would almost
296  * certainly be too high below.
297  */
298  getManager()->archetypes()->each([&] (auto at) {
299  if (at->clone.type == op->type
300  && !at->clone.invisible
301  && at->clone.value > 0
302  && at->clone.value < max_value
303  && !QUERY_FLAG(&at->clone, FLAG_NO_DROP)
304  && !QUERY_FLAG(&at->clone, FLAG_STARTEQUIP))
305  candidates.push_back(at);
306  });
307 
308  if (candidates.empty())
309  return;
310 
311  difficulty = op->magic*5;
312  if (difficulty < 0)
313  difficulty = 0;
314  new_ob = object_new();
315  do {
316  choice = rndm(0, candidates.size() - 1);
317  at = candidates[choice];
318 
319  object_copy(&(at->clone), new_ob);
320  fix_generated_item(new_ob, op, difficulty, FABS(op->magic), GT_ENVIRONMENT);
321  ++tries;
322  } while (new_ob->value > max_value && tries < 10);
323  if (new_ob->invisible) {
324  LOG(llevError, "polymorph_item: fix_generated_object made %s invisible?!\n", new_ob->name);
326  return;
327  }
328 
329  /* Unable to generate an acceptable item? Melt it */
330  if (tries == 10) {
331  polymorph_melt(who, op);
333  return;
334  }
335 
336  if (op->nrof && new_ob->nrof) {
337  new_ob->nrof = op->nrof;
338  /* decrease the number of items */
339  if (new_ob->nrof > 2)
340  new_ob->nrof -= rndm(0, op->nrof/2-1);
341  }
342 
343  /* We don't want rings to keep sustenance/hungry status. There are probably
344  * other cases too that should be checked.
345  */
346  if (charges && op->type != RING && op->type != FOOD)
347  op->stats.food = charges;
348 
349  x = op->x;
350  y = op->y;
351  m = op->map;
352  object_remove(op);
354  /*
355  * Don't want objects merged or re-arranged, as it then messes up the
356  * order
357  */
358  object_insert_in_map_at(new_ob, m, new_ob, INS_NO_MERGE|INS_NO_WALK_ON, x, y);
359 }
360 
371 void polymorph(object *op, object *who, int level) {
372  int tmp;
373 
374  /* Can't polymorph players right now */
375  /* polymorphing generators opens up all sorts of abuses */
376  if (op->type == PLAYER || QUERY_FLAG(op, FLAG_GENERATOR))
377  return;
378 
379  if (QUERY_FLAG(op, FLAG_MONSTER)) {
380  polymorph_living(op, level);
381  return;
382  }
383  /* If it is a living object of some other type, don't handle
384  * it now.
385  */
386  if (QUERY_FLAG(op, FLAG_ALIVE))
387  return;
388 
389  /* Don't want to morph flying arrows, etc... */
390  if (FABS(op->speed) > 0.001 && !QUERY_FLAG(op, FLAG_ANIMATE))
391  return;
392 
393  /* Do some sanity checking here. type=0 is unknown, objects
394  * without archetypes are not good. As are a few other
395  * cases.
396  */
397  if (op->type == 0
398  || op->arch == NULL
399  || QUERY_FLAG(op, FLAG_NO_PICK)
400  || op->move_block
401  || op->type == TREASURE)
402  return;
403 
404  tmp = rndm(0, 7);
405  if (tmp)
406  polymorph_item(who, op, level);
407  else
408  polymorph_melt(who, op);
409 }
410 
411 
425 int cast_polymorph(object *op, object *caster, object *spell_ob, int dir) {
426  object *tmp;
427  int range, mflags, maxrange, level;
428  mapstruct *m;
429 
430  if (dir == 0)
431  return 0;
432 
433  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
434  level = caster_level(caster, spell_ob);
435  for (range = 1; range < maxrange; range++) {
436  int16_t x = op->x+freearr_x[dir]*range, y = op->y+freearr_y[dir]*range;
437  object *image;
438 
439  m = op->map;
440  mflags = get_map_flags(m, &m, x, y, &x, &y);
441 
442  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
443  break;
444 
445  if (GET_MAP_MOVE_BLOCK(m, x, y)&MOVE_FLY_LOW)
446  break;
447 
448  /* Get the top most object */
449  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above)
450  ;
451 
452  /* Now start polymorphing the objects, top down */
454  /* Once we find the floor, no need to go further */
455  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
456  break;
457  polymorph(tmp, op, level);
459  image = arch_to_object(spell_ob->other_arch);
460  image->stats.food = 5;
461  image->speed_left = 0.1;
462  object_insert_in_map_at(image, m, op, 0, x, y);
463  }
464  return 1;
465 }
466 
493 int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg) {
494  int missile_plus = 0, bonus_plus = 0;
495  const char *missile_name;
496  object *tmp, *missile;
497  tag_t tag;
498 
499  tmp = object_find_by_type_applied(op, BOW);
500  missile_name = tmp != NULL ? tmp->race : "arrow";
501 
502  missile_plus = spell->stats.dam+SP_level_dam_adjust(caster, spell);
503 
504  if (!strcmp(missile_name, "arrows"))
505  missile_name = "arrow";
506  else if (!strcmp(missile_name, "crossbow bolts"))
507  missile_name = "bolt";
508 
509  /* Check if the type (bolt/arrow) was specified with the spell */
510  if ( stringarg && strncmp(stringarg,"of ",3)==0 ) stringarg +=3;
511  if ( stringarg && strncmp(stringarg,"bolt",4)==0 ) {
512  missile_name = "bolt";
513  stringarg += 4;
514  while ( isalpha(*stringarg) ) ++stringarg;
515  while ( *stringarg==' ' ) ++stringarg;
516  }
517  if ( stringarg && strncmp(stringarg,"arrow",5)==0 ) {
518  missile_name = "arrow";
519  stringarg += 5;
520  while ( isalpha(*stringarg) ) ++stringarg;
521  while ( *stringarg==' ' ) ++stringarg;
522  }
523 
524  if (try_find_archetype(missile_name) == NULL) {
525  LOG(llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
526  return 0;
527  }
528  missile = create_archetype(missile_name);
529 
530  if ( stringarg && strncmp(stringarg,"of ",3)==0 ) stringarg +=3;
531  if (stringarg) {
532  /* If it starts with a letter, presume it is a description */
533  if (isalpha(*stringarg)) {
534  auto items = find_artifactlist(missile->type)->items;
535  auto ial = std::find_if(items.cbegin(), items.cend(), [&] (const auto al) { return !strcasecmp(al->item->name, stringarg); });
536  if (ial == items.cend()) {
539  "No such object %ss of %s",
540  missile_name, stringarg);
541  return 0;
542  }
543  artifact *al = *ial;
544  if (al->item->slaying) {
547  "You are not allowed to create %ss of %s",
548  missile_name, stringarg);
549  return 0;
550  }
551  give_artifact_abilities(missile, al->item);
552  /* These special arrows cost something extra. Don't have them also be
553  * magical - otherwise, in most cases, not enough will be created.
554  * I don't want to get into the parsing both plus and type.
555  */
556  bonus_plus = 1+(al->item->value/5);
557  missile_plus = 0;
558  } else if (atoi(stringarg) < missile_plus)
559  missile_plus = atoi(stringarg);
560  }
561  if (missile_plus > 4)
562  missile_plus = 4;
563  else if (missile_plus < -4)
564  missile_plus = -4;
565 
566  missile->nrof = spell->duration+SP_level_duration_adjust(caster, spell);
567  if (missile->nrof <= (uint32_t)3 * (missile_plus + bonus_plus)) {
570  "This item is too powerful for you to create!");
571  return 0;
572  }
573  missile->nrof -= 3*(missile_plus+bonus_plus);
574  if (missile->nrof < 1)
575  missile->nrof = 1;
576 
577  missile->magic = missile_plus;
578  /* Can't get any money for these objects */
579  missile->value = 0;
580 
581  SET_FLAG(missile, FLAG_IDENTIFIED);
582  tag = missile->count;
583 
584  if (!cast_create_obj(op, missile, dir)
585  && op->type == PLAYER
586  && !object_was_destroyed(missile, tag)) {
587  pick_up(op, missile);
588  }
589  return 1;
590 }
591 
594 static int food_value_choice;
595 static void food_each(archetype *arch) {
596  if (arch->clone.type == FOOD || arch->clone.type == DRINK) {
597  /* Basically, if the food value is something that is creatable
598  * under the limits of the spell and it is higher than
599  * the item we have now, take it instead.
600  */
601  if (arch->clone.stats.food <= food_value_choice
603  food_choice = arch;
604  }
605 }
606 
627 int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg) {
628  int food_value;
629  archetype *at = NULL;
630  object *new_op;
631 
632  food_value = spell_ob->stats.food+50*SP_level_duration_adjust(caster, spell_ob);
633 
634  if (stringarg) {
635  at = find_archetype_by_object_type_name(FOOD, stringarg);
636  if (at == NULL)
637  at = find_archetype_by_object_type_name(DRINK, stringarg);
638  if (at == NULL || at->clone.stats.food > food_value)
639  stringarg = NULL;
640  }
641 
642  if (!stringarg) {
643  /* We try to find the archetype with the maximum food value.
644  * This removes the dependency of hard coded food values in this
645  * function, and addition of new food types is automatically added.
646  * We don't use flesh types because the weight values of those need
647  * to be altered from the donor.
648  */
649 
650  food_choice = at;
651  food_value_choice = food_value;
653  at = food_choice;
654  }
655  /* Pretty unlikely (there are some very low food items), but you never
656  * know
657  */
658  if (!at) {
660  "You don't have enough experience to create any food.");
661  return 0;
662  }
663 
664  food_value /= at->clone.stats.food;
665  new_op = object_new();
666  object_copy(&at->clone, new_op);
667  new_op->nrof = food_value;
668 
669  new_op->value = 0;
670  if (new_op->nrof < 1)
671  new_op->nrof = 1;
672  // Drinks are unidentified by default. Identify those.
673  if (!is_identified(new_op)) {
674  identify(new_op);
675  }
676 
677  cast_create_obj(op, new_op, dir);
678  return 1;
679 }
680 
699 int probe(object *op, object *caster, object *spell_ob, int dir, int level) {
700  int r, mflags, maxrange;
701  mapstruct *m;
702 
703  if (!dir) {
704  examine_monster(op, op, level);
705  return 1;
706  }
707  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
708  for (r = 1; r < maxrange; r++) {
709  int16_t x = op->x+r*freearr_x[dir], y = op->y+r*freearr_y[dir];
710 
711  m = op->map;
712  mflags = get_map_flags(m, &m, x, y, &x, &y);
713 
714  if (mflags&P_OUT_OF_MAP)
715  break;
716 
717  if (!QUERY_FLAG(op, FLAG_WIZCAST) && (mflags&P_NO_MAGIC)) {
719  "Something blocks your magic.");
720  return 0;
721  }
722  if (mflags&P_IS_ALIVE) {
723  FOR_MAP_PREPARE(m, x, y, tmp)
724  if (CAN_PROBE(tmp)) {
726  "You detect something.");
727  examine_monster(op, HEAD(tmp), level);
728  return 1;
729  }
730  FOR_MAP_FINISH();
731  }
732  }
734  "You detect nothing.");
735  return 1;
736 }
737 
738 
756 int makes_invisible_to(object *pl, object *mon) {
757  if (!pl->invisible)
758  return 0;
759  if (pl->type == PLAYER) {
760  /* If race isn't set, then invisible unless it is undead */
761  if (!pl->contr->invis_race) {
762  if (QUERY_FLAG(mon, FLAG_UNDEAD))
763  return 0;
764  return 1;
765  }
766  /* invis_race is set if we get here */
767  if (!strcmp(pl->contr->invis_race, "undead") && is_true_undead(mon))
768  return 1;
769  /* No race, can't be invisible to it */
770  if (!mon->race)
771  return 0;
772  if (strstr(mon->race, pl->contr->invis_race))
773  return 1;
774  /* Nothing matched above, return 0 */
775  return 0;
776  } else {
777  /* monsters are invisible to everything */
778  return 1;
779  }
780 }
781 
803 int cast_invisible(object *op, object *caster, object *spell_ob) {
804  if (op->invisible > 1000) {
806  "You can not extend the duration of your invisibility any further");
807  return 0;
808  }
809 
810  /* Remove the switch with 90% duplicate code - just handle the differences with
811  * and if statement or two.
812  */
813  op->invisible += spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
814  /* max duration */
815  if (op->invisible > 1000)
816  op->invisible = 1000;
817 
818  if (op->type == PLAYER) {
819  if (op->contr->invis_race)
821  if (spell_ob->race)
822  op->contr->invis_race = add_refcount(spell_ob->race);
823  if (QUERY_FLAG(spell_ob, FLAG_MAKE_INVIS))
824  op->contr->tmp_invis = 0;
825  else
826  op->contr->tmp_invis = 1;
827 
828  op->contr->hidden = 0;
829  }
830  if (makes_invisible_to(op, op))
832  "You can't see your hands!");
833  else
835  "You feel more transparent!");
836 
838  return 1;
839 }
840 
855 int cast_earth_to_dust(object *op, object *caster, object *spell_ob) {
856  int range, i, j, mflags;
857  int16_t sx, sy;
858  mapstruct *m;
859 
860  if (op->type != PLAYER)
861  return 0;
862 
863  range = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
864 
865  for (i = -range; i < range; i++)
866  for (j = -range; j < range; j++) {
867  sx = op->x+i;
868  sy = op->y+j;
869  m = op->map;
870  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
871 
872  if (mflags&P_OUT_OF_MAP)
873  continue;
874 
875  /* If the space doesn't block, no wall here to remove
876  * Don't care too much what it blocks - this allows for
877  * any sort of earthwall/airwall/waterwall, etc
878  * type effects.
879  */
880  if (GET_MAP_MOVE_BLOCK(m, sx, sy)) {
881  FOR_MAP_PREPARE(m, sx, sy, tmp)
882  if (tmp && QUERY_FLAG(tmp, FLAG_TEAR_DOWN))
883  hit_player(tmp, 9998, op, AT_PHYSICAL, 0);
884  FOR_MAP_FINISH();
885  }
886  }
887  return 1;
888 }
889 
906 int cast_word_of_recall(object *op, object *caster, object *spell_ob) {
907  object *dummy;
908  int time;
909 
910  if (op->type != PLAYER)
911  return 0;
912 
915  "You feel a force starting to build up inside you.");
916  return 1;
917  }
918 
919  dummy = create_archetype(FORCE_NAME);
920  if (dummy == NULL) {
922  "Oops, program error!");
923  LOG(llevError, "cast_word_of_recall: create_archetype(force) failed!\n");
924  return 0;
925  }
926  time = spell_ob->duration-SP_level_duration_adjust(caster, spell_ob);
927  if (time < 1)
928  time = 1;
929 
930  /* value of speed really doesn't make much difference, as long as it is
931  * positive. Lower value may be useful so that the problem doesn't
932  * do anything really odd if it say a -1000 or something.
933  */
934  dummy->speed = 0.002;
935  object_update_speed(dummy);
936  dummy->speed_left = -dummy->speed*time;
937  dummy->type = SPELL_EFFECT;
938  dummy->subtype = SP_WORD_OF_RECALL;
939 
940  /* If we could take advantage of enter_player_savebed() here, it would be
941  * nice, but until the map load fails, we can't.
942  */
943  EXIT_PATH(dummy) = add_string(op->contr->savebed_map);
944  EXIT_X(dummy) = op->contr->bed_x;
945  EXIT_Y(dummy) = op->contr->bed_y;
946 
947  (void)object_insert_in_ob(dummy, op);
949  "You feel a force starting to build up inside you.");
950  return 1;
951 }
952 
968 int cast_wonder(object *op, object *caster, int dir, object *spell_ob) {
969  object *newspell;
970 
971  if (!rndm(0, 3))
972  return cast_cone(op, caster, dir, spell_ob);
973 
974  if (spell_ob->randomitems) {
975  newspell = generate_treasure(spell_ob->randomitems, caster->level);
976  if (!newspell) {
977  LOG(llevError, "cast_wonder: Unable to get a spell!\n");
978  return 0;
979  }
980  if (newspell->type != SPELL) {
981  LOG(llevError, "cast_wonder: spell returned is not a spell (%d, %s)!\n", newspell->type, newspell->name);
982  return 0;
983  }
984  /* Prevent inifinite recursion */
985  if (newspell->subtype == SP_WONDER) {
986  LOG(llevError, "cast_wonder: spell returned is another wonder spell!\n");
987  return 0;
988  }
989  return cast_spell(op, caster, dir, newspell, NULL);
990  }
991  return 1;
992 }
993 
1002 int perceive_self(object *op) {
1003  char *cp, buf[MAX_BUF];
1005  if (at == NULL) {
1006  return 1;
1007  }
1008  object *tmp;
1009  const object *god;
1010  int i;
1011  StringBuffer *immunity;
1012 
1013  god = find_god(determine_god(op));
1014  if (god)
1016  "You worship %s",
1017  god->name);
1018  else
1020  "You worship no god");
1021 
1022  tmp = arch_present_in_ob(at, op);
1023 
1024  cp = stringbuffer_finish(describe_item(op, op, 0, NULL));
1025 
1026  if (*cp == '\0' && tmp == NULL)
1028  "You feel very mundane");
1029  else {
1031  "You have:");
1033  cp);
1034  if (tmp != NULL) {
1035  for (i = 0; i < NUM_STATS; i++) {
1036  if (get_attr_value(&tmp->stats, i) < 0) {
1038  "Your %s is depleted by %d",
1039  statname[i], -(get_attr_value(&tmp->stats, i)));
1040  }
1041  }
1042  }
1043  }
1044  free(cp);
1045 
1046  if (op->glow_radius > 0)
1048  "You glow in the dark.");
1049 
1050  immunity = NULL;
1051  for (tmp = op->inv; tmp; tmp = tmp->below) {
1052  if (tmp->type == SIGN) {
1053  if (immunity == NULL) {
1054  immunity = stringbuffer_new();
1055  stringbuffer_append_string(immunity, "You have been exposed to: ");
1056  } else {
1057  stringbuffer_append_string(immunity, ", ");
1058  }
1059  stringbuffer_append_string(immunity, tmp->name);
1060  if (tmp->level > 100)
1061  stringbuffer_append_string(immunity, " (full immunity)");
1062  else if (tmp->level > 70)
1063  stringbuffer_append_string(immunity, " (high immunity)");
1064  else if (tmp->level > 20)
1065  stringbuffer_append_string(immunity, " (partial immunity)");
1066  }
1067  }
1068 
1069  if (immunity != NULL) {
1070  cp = stringbuffer_finish(immunity);
1072  free(cp);
1073  }
1074 
1075  if (is_dragon_pl(op)) {
1076  /* now grab the 'dragon_ability'-force from the player's inventory */
1077  tmp = object_find_by_type_and_arch_name(op, FORCE, "dragon_ability_force");
1078  if (tmp != NULL) {
1079  StringBuffer *levels = NULL;
1080  int i;
1081 
1082  if (tmp->stats.exp == 0) {
1083  snprintf(buf, sizeof(buf), "Your metabolism isn't focused on anything.");
1084  } else {
1085  snprintf(buf, sizeof(buf), "Your metabolism is focused on %s.", change_resist_msg[tmp->stats.exp]);
1086  }
1088  buf);
1089 
1090  for (i = 0; i < NROFATTACKS; i++) {
1091  if (atnr_is_dragon_enabled(i) && tmp->resist[i] > 0) {
1092  if (levels == NULL) {
1094  stringbuffer_append_string(levels, "Ability levels:\n");
1095  }
1096  stringbuffer_append_printf(levels, "- %s: %d\n", change_resist_msg[i], tmp->resist[i]);
1097  }
1098  }
1099 
1100  if (levels != NULL) {
1103  free(cp);
1104  }
1105  }
1106  }
1107  return 1;
1108 }
1109 
1110 static object* town_portal_find_force(object* op, object* spell) {
1111  object *dummy, *force;
1112 
1113  /* The first thing to do is to check if we have a marked destination
1114  * dummy is used to make a check inventory for the force
1115  */
1116  dummy = arch_to_object(spell->other_arch);
1117  if (dummy == NULL) {
1119  "Oops, program error!");
1120  LOG(llevError, "object_new failed (force in cast_create_town_portal for %s!\n", op->name);
1121  return NULL;
1122  }
1123 
1124  force = check_inv_recursive(op, dummy);
1125  if (force == NULL) {
1126  /* Here we know there is no destination marked up.
1127  * We have 2 things to do:
1128  * 1. Mark the destination in the player inventory.
1129  * 2. Let the player know it worked.
1130  */
1131  free_string(dummy->name);
1132  dummy->name = add_string(op->map->path);
1133  EXIT_X(dummy) = op->x;
1134  EXIT_Y(dummy) = op->y;
1135  dummy->weapontype = op->map->last_reset_time;
1136  object_insert_in_ob(dummy, op);
1138  "You fix this place in your mind and feel that you "
1139  "can come here from anywhere.");
1140  } else {
1142  }
1143  return force;
1144 }
1145 
1149 static int town_portal_destroy_existing(object* op, object* spell) {
1150  object* dummy = create_archetype(spell->race);
1151  object* old_force;
1152  if (dummy == NULL) {
1154  "Oops, program error!");
1155  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1156  return 0;
1157  }
1158  archetype *perm_portal;
1159  perm_portal = try_find_archetype(spell->slaying);
1160  if (perm_portal == NULL) {
1162  "Oops, program error!");
1163  return 0;
1164  }
1165 
1166  /* To kill a town portal, we go trough the player's inventory,
1167  * for each marked portal in player's inventory,
1168  * -We try load the associated map (if impossible, consider the portal destructed)
1169  * -We find any portal in the specified location.
1170  * If it has the good name, we destruct it.
1171  * -We destruct the force indicating that portal.
1172  */
1173  while ((old_force = check_inv_recursive(op, dummy))) {
1174  int16_t exitx = EXIT_X(old_force);
1175  int16_t exity = EXIT_Y(old_force);
1176  LOG(llevDebug, "Trying to kill a portal in %s (%d,%d)\n", old_force->race, exitx, exity);
1177 
1178  mapstruct *exitmap;
1179  if (map_path_unique(old_force->race))
1180  exitmap = ready_map_name(old_force->race, MAP_PLAYER_UNIQUE);
1181  else
1182  exitmap = ready_map_name(old_force->race, 0);
1183 
1184  if (exitmap) {
1185  object* tmp = map_find_by_archetype(exitmap, exitx, exity, perm_portal);
1187  if (tmp->name == old_force->name) {
1188  object_remove(tmp);
1189  object_free(tmp, 0);
1190  break;
1191  }
1193 
1194  /* kill any opening animation there is */
1195  archetype *arch = try_find_archetype("town_portal_open");
1196  if (arch != NULL) {
1197  tmp = map_find_by_archetype(exitmap, exitx, exity, arch);
1199  if (tmp->name == old_force->name) {
1200  object_remove(tmp);
1202  break;
1203  }
1205  }
1206  }
1207  object_remove(old_force);
1208  object_free(old_force, 0);
1209  }
1211  return 0;
1212 }
1213 
1241 int cast_create_town_portal(object *op, object *caster, object *spell) {
1242  object *dummy, *force, *tmp;
1243  char portal_name [2 * HUGE_BUF], portal_message [1024];
1244  mapstruct *exitmap;
1245  int op_level, x, y;
1246 
1247  /* Check to see if the map the player is currently on is a per player unique
1248  * map. This can be determined in that per player unique maps have the
1249  * full pathname listed. Ignore if settings.create_home_portals is true.
1250  */
1252  if (op->map->unique) {
1254  "You can't cast that here.");
1255  return 0;
1256  }
1257  }
1258 
1259  /* Check to see if the player is on a transport */
1260  if (op->contr && op->contr->transport) {
1262  "You need to exit the transport to cast that.");
1263  return 0;
1264  }
1265 
1266  force = town_portal_find_force(op, spell);
1267  if (force == NULL) {
1268  return 1;
1269  }
1270 
1271  /* Here we know where the town portal should go to
1272  * We should kill any existing portal associated with the player.
1273  * Than we should create the 2 portals.
1274  * For each of them, we need:
1275  * - To create the portal with the name of the player+destination map
1276  * - set the owner of the town portal
1277  * - To mark the position of the portal in the player's inventory
1278  * for easier destruction.
1279  *
1280  * The mark works has follow:
1281  * slaying: Existing town portal
1282  * hp, sp : x & y of the associated portal
1283  * name : name of the portal
1284  * race : map the portal is in
1285  */
1286  if (town_portal_destroy_existing(op, spell) != 0) {
1287  return 1;
1288  }
1289 
1290  /* Creating the portals.
1291  * The very first thing to do is to ensure
1292  * access to the destination map.
1293  * If we can't, don't fizzle. Simply warn player.
1294  * This ensure player pays his mana for the spell
1295  * because HE is responsible for forgetting.
1296  * 'force' is the destination of the town portal, which we got
1297  * from the players inventory above.
1298  */
1299 
1300  /* Ensure exit map is loaded*/
1301  if (map_path_unique(force->name))
1302  exitmap = ready_map_name(force->name, MAP_PLAYER_UNIQUE);
1303  else
1304  exitmap = ready_map_name(force->name, 0);
1305 
1306  /* If we were unable to load (ex. random map deleted), warn player*/
1307  if (exitmap == NULL) {
1309  "Something strange happens. You can't remember where to go!?");
1310  object_remove(force);
1311  object_free(force, 0);
1313  return 1;
1314  } else if (exitmap->last_reset_time != force->weapontype) {
1316  "The spell effect has expired.");
1317  object_remove(force);
1318  object_free(force, 0);
1320  return 1;
1321  }
1322 
1323  op_level = caster_level(caster, spell);
1324  if (op_level < 15)
1325  snprintf(portal_message, 1024, "The air moves around you and a huge smell of ammonia surrounds you as you pass through %s's tiny portal. Pouah!", op->name);
1326  else if (op_level < 30)
1327  snprintf(portal_message, 1024, "%s's portal smells of ozone. You do a lot of movements and finally pass through the small hole in the air.", op->name);
1328  else if (op_level < 60)
1329  snprintf(portal_message, 1024, "A shining door opens in the air in front of you, showing you the path to another place.");
1330  else
1331  snprintf(portal_message, 1024, "As you walk through %s's portal, flowers come out from the ground around you. You feel awed.", op->name);
1332 
1333  /* Create a portal in front of player
1334  * dummy contain the portal and
1335  * force contain the track to kill it later
1336  */
1337 
1338  snprintf(portal_name, sizeof(portal_name), "%s's portal to %s", op->name, force->name);
1339  dummy = create_archetype(spell->slaying); /*The portal*/
1340  if (dummy == NULL) {
1342  "Oops, program error!");
1343  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1344  return 0;
1345  }
1346  EXIT_PATH(dummy) = add_string(force->name);
1347  EXIT_X(dummy) = EXIT_X(force);
1348  EXIT_Y(dummy) = EXIT_Y(force);
1349  FREE_AND_COPY(dummy->name, portal_name);
1350  FREE_AND_COPY(dummy->name_pl, portal_name);
1351  object_set_msg(dummy, portal_message);
1352  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1353 
1354  /* create a nice animation */
1355  tmp = create_archetype("town_portal_open");
1356  FREE_AND_COPY(tmp->name, portal_name);
1357  FREE_AND_COPY(tmp->name_pl, portal_name);
1358  object_insert_in_ob(dummy, tmp);
1359  /* and put it on the floor, when it ends the portal will be on the ground */
1360  cast_create_obj(op, tmp, 0);
1361  x = tmp->x;
1362  y = tmp->y;
1363 
1364  /* Now we need to to create a town portal marker inside the player
1365  * object, so on future castings, we can know that he has an active
1366  * town portal.
1367  */
1368  tmp = create_archetype(spell->race);
1369  if (tmp == NULL) {
1371  "Oops, program error!");
1372  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1373  return 0;
1374  }
1375  tmp->race = add_string(op->map->path);
1376  FREE_AND_COPY(tmp->name, portal_name);
1377  EXIT_X(tmp) = x;
1378  EXIT_Y(tmp) = y;
1379  object_insert_in_ob(tmp, op);
1380 
1381  /* Create a portal in the destination map
1382  * dummy contain the portal and
1383  * force the track to kill it later
1384  * the 'force' variable still contains the 'reminder' of
1385  * where this portal goes to.
1386  */
1387  snprintf(portal_name, sizeof(portal_name), "%s's portal to %s", op->name, op->map->path);
1388  dummy = create_archetype(spell->slaying); /*The portal*/
1389  if (dummy == NULL) {
1391  "Oops, program error!");
1392  LOG(llevError, "object_new failed (perm_magic_portal) in cast_create_town_portal for %s!\n", op->name);
1393  return 0;
1394  }
1395  EXIT_PATH(dummy) = add_string(op->map->path);
1396  EXIT_X(dummy) = op->x;
1397  EXIT_Y(dummy) = op->y;
1398  FREE_AND_COPY(dummy->name, portal_name);
1399  FREE_AND_COPY(dummy->name_pl, portal_name);
1400  object_set_msg(dummy, portal_message);
1401  dummy->race = add_string(op->name); /*Save the owner of the portal*/
1402 
1403  /* animation here too */
1404  tmp = create_archetype("town_portal_open");
1405  FREE_AND_COPY(tmp->name, portal_name);
1406  FREE_AND_COPY(tmp->name_pl, portal_name);
1407  object_insert_in_ob(dummy, tmp);
1408  /* and put it on the floor, when it ends the portal will be on the ground */
1409  object_insert_in_map_at(tmp, exitmap, op, 0, EXIT_X(force), EXIT_Y(force));
1410  x = tmp->x;
1411  y = tmp->y;
1412 
1413  /* Now we create another town portal marker that
1414  * points back to the one we just made
1415  */
1416  tmp = create_archetype(spell->race);
1417  if (tmp == NULL) {
1419  "Oops, program error!");
1420  LOG(llevError, "object_new failed (force) in cast_create_town_portal for %s!\n", op->name);
1421  return 0;
1422  }
1423  tmp->race = add_string(force->name);
1424  FREE_AND_COPY(tmp->name, portal_name);
1425  EXIT_X(tmp) = x;
1426  EXIT_Y(tmp) = y;
1427  object_insert_in_ob(tmp, op);
1428 
1429  /* Describe the player what happened
1430  */
1432  "You see air moving and showing you the way home.");
1433  object_remove(force); /* Delete the force inside the player*/
1434  object_free(force, 0);
1435  return 1;
1436 }
1437 
1438 
1456 int magic_wall(object *op, object *caster, int dir, object *spell_ob) {
1457  object *tmp, *tmp2;
1458  int i, posblocked, negblocked, maxrange;
1459  int16_t x, y;
1460  mapstruct *m;
1461  const char *name;
1462  archetype *at;
1463 
1464  if (!dir) {
1465  dir = op->facing;
1466  x = op->x;
1467  y = op->y;
1468  } else {
1469  x = op->x+freearr_x[dir];
1470  y = op->y+freearr_y[dir];
1471  }
1472  m = op->map;
1473 
1474  if ((spell_ob->move_block || x != op->x || y != op->y)
1475  && (get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE)
1476  || ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) == spell_ob->move_block))) {
1478  "Something is in the way.");
1479  return 0;
1480  }
1481  if (spell_ob->other_arch) {
1482  tmp = arch_to_object(spell_ob->other_arch);
1483  } else if (spell_ob->race) {
1484  char buf1[MAX_BUF];
1485 
1486  snprintf(buf1, sizeof(buf1), spell_ob->race, dir);
1487  at = try_find_archetype(buf1);
1488  if (!at) {
1489  LOG(llevError, "summon_wall: Unable to find archetype %s\n", buf1);
1491  "This spell is broken.");
1492  return 0;
1493  }
1494  tmp = arch_to_object(at);
1495  } else {
1496  LOG(llevError, "magic_wall: spell %s lacks other_arch\n", spell_ob->name);
1497  return 0;
1498  }
1499 
1500  if (tmp->type == SPELL_EFFECT) {
1501  tmp->attacktype = spell_ob->attacktype;
1502  tmp->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1503  tmp->stats.dam = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1504  tmp->range = 0;
1505  } else if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
1506  tmp->stats.hp = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1507  tmp->stats.maxhp = tmp->stats.hp;
1508  object_set_owner(tmp, op);
1509  set_spell_skill(op, caster, spell_ob, tmp);
1510  }
1511  if (QUERY_FLAG(spell_ob, FLAG_IS_USED_UP) || QUERY_FLAG(tmp, FLAG_IS_USED_UP)) {
1512  tmp->stats.food = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
1513  SET_FLAG(tmp, FLAG_IS_USED_UP);
1514  }
1515  if (QUERY_FLAG(spell_ob, FLAG_TEAR_DOWN)) {
1516  tmp->stats.hp = spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
1517  tmp->stats.maxhp = tmp->stats.hp;
1518  SET_FLAG(tmp, FLAG_TEAR_DOWN);
1519  SET_FLAG(tmp, FLAG_ALIVE);
1520  }
1521 
1522  /* This can't really hurt - if the object doesn't kill anything,
1523  * these fields just won't be used.
1524  */
1525  object_set_owner(tmp, op);
1526  set_spell_skill(op, caster, spell_ob, tmp);
1527  tmp->level = caster_level(caster, spell_ob)/2;
1528 
1529  name = tmp->name;
1530  if ((tmp = object_insert_in_map_at(tmp, m, op, 0, x, y)) == NULL) {
1532  "Something destroys your %s",
1533  name);
1534  return 0;
1535  }
1536  /* If this is a spellcasting wall, need to insert the spell object */
1537  if (tmp->other_arch && tmp->other_arch->clone.type == SPELL)
1539 
1540  /* This code causes the wall to extend some distance in
1541  * each direction, or until an obstruction is encountered.
1542  * posblocked and negblocked help determine how far the
1543  * created wall can extend, it won't go extend through
1544  * blocked spaces.
1545  */
1546  maxrange = spell_ob->range+SP_level_range_adjust(caster, spell_ob);
1547  posblocked = 0;
1548  negblocked = 0;
1549 
1550  for (i = 1; i <= maxrange; i++) {
1551  int dir2;
1552 
1553  dir2 = (dir < 4) ? (dir+2) : dir-2;
1554 
1555  x = tmp->x+i*freearr_x[dir2];
1556  y = tmp->y+i*freearr_y[dir2];
1557  m = tmp->map;
1558 
1559  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1560  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1561  && !posblocked) {
1562  tmp2 = object_new();
1563  object_copy(tmp, tmp2);
1564  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1565  /* If this is a spellcasting wall, need to insert the spell object */
1566  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1568  } else
1569  posblocked = 1;
1570 
1571  x = tmp->x-i*freearr_x[dir2];
1572  y = tmp->y-i*freearr_y[dir2];
1573  m = tmp->map;
1574 
1575  if (!(get_map_flags(m, &m, x, y, &x, &y)&(P_OUT_OF_MAP|P_IS_ALIVE))
1576  && ((spell_ob->move_block&GET_MAP_MOVE_BLOCK(m, x, y)) != spell_ob->move_block)
1577  && !negblocked) {
1578  tmp2 = object_new();
1579  object_copy(tmp, tmp2);
1580  object_insert_in_map_at(tmp2, m, op, 0, x, y);
1581  if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1583  } else
1584  negblocked = 1;
1585  }
1586 
1587  if (QUERY_FLAG(tmp, FLAG_BLOCKSVIEW))
1588  update_all_los(op->map, op->x, op->y);
1589 
1590  return 1;
1591 }
1592 
1609 int dimension_door(object *op, object *caster, object *spob, int dir) {
1610  uint32_t dist, maxdist;
1611  int mflags;
1612  mapstruct *m;
1613  int16_t sx, sy;
1614 
1615  if (op->type != PLAYER)
1616  return 0;
1617 
1618  if (!dir) {
1620  "In what direction?");
1621  return 0;
1622  }
1623 
1624  /* Given the new outdoor maps, can't let players dimension door for
1625  * ever, so put limits in.
1626  */
1627  maxdist = spob->range+SP_level_range_adjust(caster, spob);
1628 
1629  if (op->contr->count) {
1630  if (op->contr->count > maxdist) {
1632  "You can't dimension door that far!");
1633  return 0;
1634  }
1635 
1636  for (dist = 0; dist < op->contr->count; dist++) {
1637  mflags = get_map_flags(op->map, &m,
1638  op->x+freearr_x[dir]*(dist+1),
1639  op->y+freearr_y[dir]*(dist+1),
1640  &sx, &sy);
1641 
1642  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1643  break;
1644 
1645  if ((mflags&P_BLOCKSVIEW)
1646  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1647  break;
1648  }
1649 
1650  if (dist < op->contr->count) {
1652  "Something blocks the magic of the spell.");
1653  op->contr->count = 0;
1654  return 0;
1655  }
1656  op->contr->count = 0;
1657 
1658  /* Remove code that puts player on random space on maps. IMO,
1659  * a lot of maps probably have areas the player should not get to,
1660  * but may not be marked as NO_MAGIC (as they may be bounded
1661  * by such squares). Also, there are probably treasure rooms and
1662  * lots of other maps that protect areas with no magic, but the
1663  * areas themselves don't contain no magic spaces.
1664  */
1665  /* This call here is really just to normalize the coordinates */
1666  mflags = get_map_flags(op->map, &m, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist,
1667  &sx, &sy);
1668  if (mflags&P_IS_ALIVE || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy))) {
1670  "You cast your spell, but nothing happens.");
1671  return 1; /* Maybe the penalty should be more severe... */
1672  }
1673  } else {
1674  /* Player didn't specify a distance, so lets see how far
1675  * we can move the player. Don't know why this stopped on
1676  * spaces that blocked the players view.
1677  */
1678 
1679  for (dist = 0; dist < maxdist; dist++) {
1680  mflags = get_map_flags(op->map, &m,
1681  op->x+freearr_x[dir]*(dist+1),
1682  op->y+freearr_y[dir]*(dist+1),
1683  &sx, &sy);
1684 
1685  if (mflags&(P_NO_MAGIC|P_OUT_OF_MAP))
1686  break;
1687 
1688  if ((mflags&P_BLOCKSVIEW)
1689  && OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1690  break;
1691  }
1692 
1693  /* If the destination is blocked, keep backing up until we
1694  * find a place for the player.
1695  */
1696  for (; dist > 0; dist--) {
1697  if (get_map_flags(op->map, &m, op->x+freearr_x[dir]*dist, op->y+freearr_y[dir]*dist, &sx, &sy)&(P_OUT_OF_MAP|P_IS_ALIVE))
1698  continue;
1699 
1700  if (!OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy)))
1701  break;
1702  }
1703  if (!dist) {
1705  "Your spell failed!");
1706  return 0;
1707  }
1708  }
1709 
1710  if (op->contr->transport && op->contr->transport->type == TRANSPORT) {
1711  ob_apply(op->contr->transport, op, 0);
1712  if (op->contr->transport) {
1714  "Your spell failed!");
1715  return 0;
1716  }
1717  }
1718 
1719  /* Actually move the player now */
1720  const int dx = freearr_x[dir]*dist;
1721  const int dy = freearr_y[dir]*dist;
1722  object_remove(op);
1723  if ((op = object_insert_in_map_at(op, op->map, op, 0, op->x+dx, op->y+dy)) == NULL)
1724  return 1;
1725 
1726  if (op->type == PLAYER) {
1727  esrv_map_scroll(op->contr->socket, dx, dy);
1729  }
1730  op->speed_left = -FABS(op->speed)*5; /* Freeze them for a short while */
1731  return 1;
1732 }
1733 
1734 
1747 int cast_heal(object *op, object *caster, object *spell, int dir) {
1748  object *target;
1749  archetype *at;
1750  object *poison;
1751  int heal = 0, success = 0;
1752 
1753  target = find_target_for_friendly_spell(op, dir);
1754 
1755  if (target == NULL)
1756  return 0;
1757 
1758  /* Figure out how many hp this spell might cure.
1759  * could be zero if this spell heals effects, not damage.
1760  */
1761  heal = spell->stats.dam;
1762  if (spell->stats.hp)
1763  heal += random_roll(spell->stats.hp, 6, op, PREFER_HIGH)+spell->stats.hp;
1764 
1765  if (heal) {
1766  if (target->stats.hp >= target->stats.maxhp) {
1768  "You are already fully healed.");
1769  } else {
1770  /* See how many points we actually heal. Instead of messages
1771  * based on type of spell, we instead do messages based
1772  * on amount of damage healed.
1773  */
1774  if (heal > (target->stats.maxhp-target->stats.hp))
1775  heal = target->stats.maxhp-target->stats.hp;
1776  target->stats.hp += heal;
1777 
1778  if (target->stats.hp >= target->stats.maxhp) {
1780  "You feel just fine!");
1781  } else if (heal > 50) {
1783  "Your wounds close!");
1784  } else if (heal > 25) {
1786  "Your wounds mostly close.");
1787  } else if (heal > 10) {
1789  "Your wounds start to fade.");
1790  } else {
1792  "Your wounds start to close.");
1793  }
1794  success = 1;
1795  }
1796  }
1797  if (spell->attacktype&AT_DISEASE)
1798  if (cure_disease(target, op, caster && caster->type != PLAYER ? caster->skill : spell->skill))
1799  success = 1;
1800 
1801  if (spell->attacktype&AT_POISON) {
1802  at = try_find_archetype("poisoning");
1803  if (at != NULL) {
1804  poison = arch_present_in_ob(at, target);
1805  if (poison) {
1806  success = 1;
1808  "Your body feels cleansed");
1809  poison->stats.food = 1;
1810  }
1811  }
1812  }
1813  if (spell->attacktype&AT_CONFUSION) {
1814  poison = object_present_in_ob_by_name(FORCE, "confusion", target);
1815  if (poison) {
1816  success = 1;
1818  "Your mind feels clearer");
1819  poison->duration = 1;
1820  }
1821  }
1822  if (spell->attacktype&AT_BLIND) {
1823  at = try_find_archetype("blindness");
1824  if (at != NULL) {
1825  poison = arch_present_in_ob(at, target);
1826  if (poison) {
1827  success = 1;
1829  "Your vision begins to return.");
1830  poison->stats.food = 1;
1831  }
1832  }
1833  }
1834  if (spell->last_sp && target->stats.sp < target->stats.maxsp) {
1835  target->stats.sp += spell->last_sp;
1836  if (target->stats.sp > target->stats.maxsp)
1837  target->stats.sp = target->stats.maxsp;
1838  success = 1;
1840  "Magical energies surge through your body!");
1841  }
1842  if (spell->last_grace && target->stats.grace < target->stats.maxgrace) {
1843  target->stats.grace += spell->last_grace;
1844  if (target->stats.grace > target->stats.maxgrace)
1845  target->stats.grace = target->stats.maxgrace;
1846  success = 1;
1848  "You feel redeemed with you god!");
1849  }
1850  if (spell->stats.food && target->stats.food < MAX_FOOD) {
1851  target->stats.food += spell->stats.food;
1852  if (target->stats.food > MAX_FOOD)
1853  target->stats.food = MAX_FOOD;
1854  success = 1;
1855  /* We could do something a bit better like the messages for healing above */
1857  "You feel your belly fill with food");
1858  }
1859 
1860  if (spell->other_arch != NULL && target->map != NULL) {
1861  object_insert_in_map_at(arch_to_object(spell->other_arch), target->map, NULL, INS_ON_TOP, target->x, target->y);
1862  }
1863 
1864  return success;
1865 }
1866 
1867 
1873 static const char *const no_gain_msgs[NUM_STATS] = {
1874  "You grow no stronger.",
1875  "You grow no more agile.",
1876  "You don't feel any healthier.",
1877  "no wis",
1878  "You are no easier to look at.",
1879  "no int",
1880  "no pow"
1881 };
1882 
1902 int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent) {
1903  object *tmp;
1904  object *force = NULL;
1905  int i;
1906 
1907  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1908  if (dir != 0) {
1909  tmp = find_target_for_friendly_spell(op, dir);
1910  } else {
1911  tmp = op;
1912  }
1913 
1914  if (tmp == NULL)
1915  return 0;
1916 
1917  /* If we've already got a force of this type, don't add a new one. */
1918  FOR_INV_PREPARE(tmp, tmp2)
1919  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
1920  if (tmp2->name == spell_ob->name) {
1921  force = tmp2; /* the old effect will be "refreshed" */
1922  break;
1923  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
1924  if (!silent)
1926  "You can not cast %s while %s is in effect",
1927  spell_ob->name, tmp2->name_pl);
1928  return 0;
1929  }
1930  }
1931  FOR_INV_FINISH();
1932  if (force == NULL) {
1933  force = create_archetype(FORCE_NAME);
1934  force->subtype = FORCE_CHANGE_ABILITY;
1935  free_string(force->name);
1936  if (spell_ob->race)
1937  force->name = add_refcount(spell_ob->race);
1938  else
1939  force->name = add_refcount(spell_ob->name);
1940  free_string(force->name_pl);
1941  force->name_pl = add_refcount(spell_ob->name);
1942  } else {
1943  int duration;
1944 
1945  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1946  if (duration > force->duration) {
1947  force->duration = duration;
1949  "You recast the spell while in effect.");
1950 
1951  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
1952  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
1953  }
1954 
1955  } else {
1957  "Recasting the spell had no effect.");
1958  }
1959  return 1;
1960  }
1961  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
1962  if (op->type == PLAYER)
1963  store_spell_expiry(force);
1964  force->speed = 1.0;
1965  force->speed_left = -1.0;
1966  SET_FLAG(force, FLAG_APPLIED);
1967 
1968  /* Now start processing the effects. First, protections */
1969  for (i = 0; i < NROFATTACKS; i++) {
1970  if (spell_ob->resist[i]) {
1971  force->resist[i] = spell_ob->resist[i]+SP_level_dam_adjust(caster, spell_ob);
1972  if (force->resist[i] > 100)
1973  force->resist[i] = 100;
1974  }
1975  }
1976  if (spell_ob->stats.hp)
1977  force->stats.hp = spell_ob->stats.hp+SP_level_dam_adjust(caster, spell_ob);
1978 
1979  if (tmp->type == PLAYER) {
1980  /* Stat adjustment spells */
1981  for (i = 0; i < NUM_STATS; i++) {
1982  int8_t stat = get_attr_value(&spell_ob->stats, i), k, sm;
1983 
1984  if (stat) {
1985  sm = 0;
1986  for (k = 0; k < stat; k++)
1987  sm += rndm(1, 3);
1988 
1989  if ((get_attr_value(&tmp->stats, i)+sm) > (15+5*stat)) {
1990  sm = (15+5*stat)-get_attr_value(&tmp->stats, i);
1991  if (sm < 0)
1992  sm = 0;
1993  }
1994  set_attr_value(&force->stats, i, sm);
1995  if (!sm)
1997  no_gain_msgs[i]);
1998  }
1999  }
2000  }
2001 
2002  force->move_type = spell_ob->move_type;
2003 
2004  if (QUERY_FLAG(spell_ob, FLAG_SEE_IN_DARK))
2005  SET_FLAG(force, FLAG_SEE_IN_DARK);
2006 
2007  if (QUERY_FLAG(spell_ob, FLAG_XRAYS))
2008  SET_FLAG(force, FLAG_XRAYS);
2009 
2010  /* Haste/bonus speed */
2011  if (spell_ob->stats.exp) {
2012  if (op->speed > 0.5)
2013  force->stats.exp = (float)spell_ob->stats.exp/(op->speed+0.5);
2014  else
2015  force->stats.exp = spell_ob->stats.exp;
2016  }
2017 
2018  force->stats.wc = spell_ob->stats.wc;
2019  force->stats.ac = spell_ob->stats.ac;
2020  force->attacktype = spell_ob->attacktype;
2021 
2022  SET_FLAG(tmp, FLAG_NO_FIX_PLAYER); /* we don't want object_insert_in_ob() to call fix_object. */
2023  object_insert_in_ob(force, tmp);
2025  change_abil(tmp, force); /* Display any relevant messages, and call fix_object to update the player */
2026 
2027  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2028  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2029  }
2030 
2031  return 1;
2032 }
2033 
2050 int cast_bless(object *op, object *caster, object *spell_ob, int dir) {
2051  int i;
2052  const object *god = find_god(determine_god(op));
2053  object *force = NULL, *tmp;
2054 
2055  /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
2056  if (dir != 0) {
2057  tmp = find_target_for_friendly_spell(op, dir);
2058  } else {
2059  tmp = op;
2060  }
2061 
2062  /* If we've already got a force of this type, don't add a new one. */
2063  FOR_INV_PREPARE(tmp, tmp2)
2064  if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) {
2065  if (tmp2->name == spell_ob->name) {
2066  force = tmp2; /* the old effect will be "refreshed" */
2067  break;
2068  } else if (spell_ob->race && spell_ob->race == tmp2->name) {
2070  "You can not cast %s while %s is in effect",
2071  spell_ob->name, tmp2->name_pl);
2072  return 0;
2073  }
2074  }
2075  FOR_INV_FINISH();
2076  if (force == NULL) {
2077  force = create_archetype(FORCE_NAME);
2078  force->subtype = FORCE_CHANGE_ABILITY;
2079  free_string(force->name);
2080  if (spell_ob->race)
2081  force->name = add_refcount(spell_ob->race);
2082  else
2083  force->name = add_refcount(spell_ob->name);
2084  free_string(force->name_pl);
2085  force->name_pl = add_refcount(spell_ob->name);
2086  } else {
2087  int duration;
2088 
2089  duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2090  if (duration > force->duration) {
2091  force->duration = duration;
2093  "You recast the spell while in effect.");
2094  } else {
2096  "Recasting the spell had no effect.");
2097  }
2098  return 0;
2099  }
2100  force->duration = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob)*50;
2101  force->speed = 1.0;
2102  force->speed_left = -1.0;
2103 
2104  if (!god) {
2106  "Your blessing seems empty.");
2107  } else {
2108  /* Only give out good benefits, and put a max on it */
2109  const int16_t resist_max = spell_ob->resist[ATNR_GODPOWER];
2110  for (i = 0; i < NROFATTACKS; i++) {
2111  if (god->resist[i] > 0) {
2112  force->resist[i] = MIN(god->resist[i], resist_max);
2113  }
2114  }
2115  // Also grant appropriate amount of godpower resistance.
2116  force->resist[ATNR_GODPOWER] = spell_ob->resist[ATNR_GODPOWER];
2117 
2118  force->path_attuned |= god->path_attuned;
2119  if (spell_ob->attacktype) {
2120  force->attacktype |= god->attacktype|AT_PHYSICAL;
2121  if (god->slaying)
2122  force->slaying = add_string(god->slaying);
2123  }
2124  if (tmp != op) {
2126  "You bless %s.",
2127  tmp->name);
2129  "%s blessed you.",
2130  op->name);
2131  } else {
2133  "You are blessed by %s!",
2134  god->name);
2135  }
2136  }
2137  force->stats.wc = spell_ob->stats.wc;
2138  force->stats.ac = spell_ob->stats.ac;
2139 
2140  store_spell_expiry(force);
2141  object_insert_in_ob(force, tmp);
2142  SET_FLAG(force, FLAG_APPLIED);
2143  change_abil(tmp, force); /* To display any messages, will call fix_object() */
2144 
2145  if (spell_ob->other_arch != NULL && tmp->map != NULL) {
2146  object_insert_in_map_at(arch_to_object(spell_ob->other_arch), tmp->map, NULL, INS_ON_TOP, tmp->x, tmp->y);
2147  }
2148  return 1;
2149 }
2150 
2151 
2152 
2153 /*
2154  * Alchemy code by Mark Wedel
2155  *
2156  * This code adds a new spell, called alchemy. Alchemy will turn
2157  * objects to gold nuggets, the value of the gold nuggets being
2158  * from 5% to 40% of that of the item itself depending on casting level.
2159  * It uses the value of the object before charisma adjustments, because
2160  * the nuggets themselves will be will be adjusted by charisma when sold.
2161  *
2162  * Large nuggets are worth 25 gp each (base). You will always get
2163  * the maximum number of large nuggets you could get.
2164  * Small nuggets are worth 1 gp each (base). You will get from 0
2165  * to the max amount of small nuggets as you could get.
2166  *
2167  * For example, if an item is worth 110 gold, you will get
2168  * 4 large nuggets, and from 0-10 small nuggets.
2169  *
2170  * There is also a chance (1:30) that you will get nothing at all
2171  * for the object. There is also a maximum weight that will be
2172  * alchemied.
2173  */
2174 
2175 #define SMALL_NUGGET "smallnugget"
2176 #define LARGE_NUGGET "largenugget"
2177 
2192 static void alchemy_object(float value_adj, object *obj, int *small_nuggets, int *large_nuggets, int *weight) {
2193  uint64_t value = price_base(obj);
2194  // Don't reduce gems or money, since they don't get the x4 multiplier in price_base()
2195  // FIXME: If the x4 multiplier in price_base() gets changed, this should as well.
2196  if (obj->type != GEM && obj->type != MONEY)
2197  value /= 4;
2198  uint64_t small_value, large_value;
2200  /* Multiply the value of the object by value_adj, which should range
2201  * from 0.05 to 0.40. Set value to 0 instead if unpaid.
2202  */
2203  if (QUERY_FLAG(obj, FLAG_UNPAID))
2204  value = 0;
2205  else
2206  value *= value_adj;
2207 
2208  archetype *small_nugget_arch = try_find_archetype(SMALL_NUGGET);
2209  if (small_nugget_arch == NULL) {
2210  return;
2211  }
2212  small_value = price_base(&small_nugget_arch->clone);
2213  archetype *large_nugget_arch = try_find_archetype(LARGE_NUGGET);
2214  if (large_nugget_arch == NULL) {
2215  return;
2216  }
2217  large_value = price_base(&large_nugget_arch->clone);
2218 
2219  /* Give half of what value_adj says when we alchemy money (This should
2220  * hopefully make it so that it isn't worth it to alchemy money, sell
2221  * the nuggets, alchemy the gold from that, etc.
2222  */
2223  if (value && (obj->type == MONEY || obj->type == GEM))
2224  value /= 2;
2225 
2226  if ((obj->value > 0) && rndm(0, 29)) {
2227  int count;
2228 
2229  assert(large_value != 0 && small_value != 0);
2230  count = value/large_value;
2231  *large_nuggets += count;
2232  value -= (uint64_t)count*large_value;
2233  count = value/small_value;
2234  *small_nuggets += count;
2235  }
2236 
2237  /* Turn 25 small nuggets into 1 large nugget. If the value
2238  * of large nuggets is not evenly divisable by the small nugget
2239  * value, take off an extra small_nugget (Assuming small_nuggets!=0)
2240  */
2241  if (*small_nuggets*small_value >= large_value) {
2242  assert(small_value != 0);
2243  (*large_nuggets)++;
2244  *small_nuggets -= large_value/small_value;
2245  if (*small_nuggets && large_value%small_value)
2246  (*small_nuggets)--;
2247  }
2248 
2249  if (weight != NULL) {
2250  *weight += obj->weight;
2251  }
2252 
2253  object_remove(obj);
2255 }
2256 
2270 static void place_alchemy_objects(object *op, mapstruct *m, int small_nuggets, int large_nuggets, int x, int y) {
2271  object *tmp;
2272  int flag = 0;
2273 
2274  /* Put any nuggets below the player, but we can only pass this
2275  * flag if we are on the same space as the player
2276  */
2277  if (x == op->x && y == op->y && op->map == m)
2278  flag = INS_BELOW_ORIGINATOR;
2279 
2280  if (small_nuggets) {
2282  tmp-> nrof = small_nuggets;
2283  object_insert_in_map_at(tmp, m, op, flag, x, y);
2284  }
2285  if (large_nuggets) {
2287  tmp-> nrof = large_nuggets;
2288  object_insert_in_map_at(tmp, m, op, flag, x, y);
2289  }
2290 }
2291 
2306 int alchemy(object *op, object *caster, object *spell_ob) {
2307  int x, y, weight = 0, weight_max, large_nuggets, small_nuggets, mflags;
2308  int16_t nx, ny;
2309  float value_adj;
2310  mapstruct *mp;
2311 
2312  if (op->type != PLAYER)
2313  return 0;
2314 
2315  /* Put a maximum weight of items that can be alchemied. Limits the power
2316  * some, and also prevents people from alcheming every table/chair/clock
2317  * in sight
2318  */
2319  weight_max = spell_ob->duration+SP_level_duration_adjust(caster, spell_ob);
2320  weight_max *= 1000;
2321 
2322  /* Set value_adj to be a multiplier for how much of the original value
2323  * will be in the nuggets. Starts at 0.05, increasing by 0.01 per casting
2324  * level, maxing out at 0.40.
2325  */
2326  value_adj = (SP_level_dam_adjust(caster, spell_ob)/100.00)+0.05;
2327 
2328  if (value_adj > 0.40)
2329  value_adj = 0.40;
2330 
2331  for (y = op->y-1; y <= op->y+1; y++) {
2332  for (x = op->x-1; x <= op->x+1; x++) {
2333  nx = x;
2334  ny = y;
2335 
2336  mp = op->map;
2337 
2338  mflags = get_map_flags(mp, &mp, nx, ny, &nx, &ny);
2339 
2340  if (mflags&(P_OUT_OF_MAP|P_NO_MAGIC))
2341  continue;
2342 
2343  /* Treat alchemy a little differently - most spell effects
2344  * use fly as the movement type - for alchemy, consider it
2345  * ground level effect.
2346  */
2347  if (GET_MAP_MOVE_BLOCK(mp, nx, ny)&MOVE_WALK)
2348  continue;
2349 
2350  small_nuggets = 0;
2351  large_nuggets = 0;
2352 
2353  FOR_MAP_PREPARE(mp, nx, ny, tmp) {
2354  if (tmp->weight > 0 && !QUERY_FLAG(tmp, FLAG_NO_PICK)
2355  && !QUERY_FLAG(tmp, FLAG_ALIVE)
2356  // If a multitile monster has unalive pieces, then don't zap those.
2357  && (!tmp->head || !QUERY_FLAG(tmp->head, FLAG_ALIVE))
2358  && !QUERY_FLAG(tmp, FLAG_IS_CAULDRON)) {
2359  if (tmp->inv) {
2360  FOR_INV_PREPARE(tmp, tmp1)
2361  if (tmp1->weight > 0 && !QUERY_FLAG(tmp1, FLAG_NO_PICK)
2362  && !QUERY_FLAG(tmp1, FLAG_ALIVE)
2363  && !QUERY_FLAG(tmp1, FLAG_IS_CAULDRON))
2364  alchemy_object(value_adj, tmp1, &small_nuggets, &large_nuggets, &weight);
2365  FOR_INV_FINISH();
2366  }
2367  alchemy_object(value_adj, tmp, &small_nuggets, &large_nuggets, &weight);
2368 
2369  if (weight > weight_max) {
2370  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2371  return 1;
2372  }
2373  } /* is alchemable object */
2374  } FOR_MAP_FINISH(); /* process all objects on this space */
2375 
2376  /* Insert all the nuggets at one time. This probably saves time, but
2377  * it also prevents us from alcheming nuggets that were just created
2378  * with this spell.
2379  */
2380  place_alchemy_objects(op, mp, small_nuggets, large_nuggets, nx, ny);
2381  }
2382  }
2383 
2384  /* reset this so that if player standing on a big pile of stuff,
2385  * it is redrawn properly.
2386  */
2387  op->contr->socket->look_position = 0;
2388  return 1;
2389 }
2390 
2391 
2406 int remove_curse(object *op, object *caster, object *spell) {
2407  int success = 0, was_one = 0;
2408 
2409  FOR_INV_PREPARE(op, tmp)
2410  if (QUERY_FLAG(tmp, FLAG_APPLIED)
2412  || (QUERY_FLAG(tmp, FLAG_DAMNED) && QUERY_FLAG(spell, FLAG_DAMNED)))) {
2413  was_one++;
2414  if (tmp->level <= caster_level(caster, spell)) {
2415  success++;
2417  CLEAR_FLAG(tmp, FLAG_DAMNED);
2418 
2419  CLEAR_FLAG(tmp, FLAG_CURSED);
2421  tmp->value = 0; /* Still can't sell it */
2422  if (op->type == PLAYER)
2423  esrv_update_item(UPD_FLAGS, op, tmp);
2424  }
2425  }
2426  FOR_INV_FINISH();
2427 
2428  if (op->type == PLAYER) {
2429  if (success) {
2431  "You feel like some of your items are looser now.");
2432  } else {
2433  if (was_one)
2435  "You failed to remove the curse.");
2436  else
2438  "You are not using any cursed items.");
2439  }
2440  }
2441  return success;
2442 }
2443 
2454 int cast_item_curse_or_bless(object *op, object *spell_ob) {
2455  object *marked = find_marked_object(op);
2456  char name[HUGE_BUF];
2457 
2458  if (!marked) {
2460  "You need to mark an item first!");
2461  return 0;
2462  }
2463 
2464  if ((QUERY_FLAG(marked, FLAG_CURSED) && QUERY_FLAG(spell_ob, FLAG_CURSED))
2465  || (QUERY_FLAG(marked, FLAG_BLESSED) && QUERY_FLAG(spell_ob, FLAG_BLESSED))) {
2467  "The spell has no effect");
2468  return 0;
2469  }
2470 
2471  query_short_name(marked, name, HUGE_BUF);
2472  if (QUERY_FLAG(spell_ob, FLAG_CURSED)) {
2474  "Your %s emits a dark light for a few seconds.", name);
2475  SET_FLAG(marked, FLAG_CURSED);
2476  CLEAR_FLAG(marked, FLAG_KNOWN_CURSED);
2477  CLEAR_FLAG(marked, FLAG_IDENTIFIED);
2478  esrv_update_item(UPD_FLAGS, op, marked);
2479  return 1;
2480  }
2481 
2483  "Your %s glows blue for a few seconds.", name);
2484  SET_FLAG(marked, FLAG_BLESSED);
2485  SET_FLAG(marked, FLAG_KNOWN_BLESSED);
2486  SET_FLAG(marked, FLAG_STARTEQUIP);
2487  esrv_update_item(UPD_FLAGS, op, marked);
2488  return 1;
2489 }
2490 
2505 int cast_identify(object *op, object *caster, object *spell) {
2506  int success = 0, num_ident;
2507  char desc[MAX_BUF];
2508 
2509  num_ident = spell->stats.dam+SP_level_dam_adjust(caster, spell);
2510 
2511  if (num_ident < 1)
2512  num_ident = 1;
2513 
2514  FOR_INV_PREPARE(op, tmp)
2515  if (!tmp->invisible && !is_identified(tmp)) {
2516  tmp = identify(tmp);
2517  if (op->type == PLAYER) {
2519  "You have %s.",
2520  ob_describe(tmp, op, 1, desc, sizeof(desc)));
2521  if (tmp->msg) {
2523  "The item has a story:\n%s",
2524  tmp->msg);
2525  }
2526  }
2527  num_ident--;
2528  success = 1;
2529  if (!num_ident)
2530  break;
2531  }
2532  FOR_INV_FINISH();
2533  /* If all the power of the spell has been used up, don't go and identify
2534  * stuff on the floor. Only identify stuff on the floor if the spell
2535  * was not fully used.
2536  */
2537  if (num_ident) {
2538  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2539  if (!tmp->invisible && !is_identified(tmp)) {
2540  tmp = identify(tmp);
2541  if (op->type == PLAYER) {
2543  "On the ground is %s.",
2544  ob_describe(tmp, op, 1, desc, sizeof(desc)));
2545  if (tmp->msg) {
2547  "The item has a story:\n%s",
2548  tmp->msg);
2549  }
2551  }
2552  num_ident--;
2553  success = 1;
2554  if (!num_ident)
2555  break;
2556  }
2557  FOR_MAP_FINISH();
2558  }
2559  if (!success)
2561  "You can't reach anything unidentified.");
2562  else {
2563  spell_effect(spell, op->x, op->y, op->map, op);
2564  }
2565  return success;
2566 }
2567 
2580 int cast_detection(object *op, object *caster, object *spell) {
2581  object *tmp, *last, *detect;
2582  const object *god;
2583  int done_one, range, mflags, floor, level;
2584  int16_t x, y, nx, ny;
2585  mapstruct *m;
2586 
2587  bool spell_detect_magic = object_value_set(spell, "spell_detect_magic");
2588 
2589  /* We precompute some values here so that we don't have to keep
2590  * doing it over and over again.
2591  */
2592  god = find_god(determine_god(op));
2593  level = caster_level(caster, spell);
2594  range = spell->range+SP_level_range_adjust(caster, spell);
2595 
2596  for (x = op->x-range; x <= op->x+range; x++)
2597  for (y = op->y-range; y <= op->y+range; y++) {
2598  m = op->map;
2599  mflags = get_map_flags(m, &m, x, y, &nx, &ny);
2600  if (mflags&P_OUT_OF_MAP)
2601  continue;
2602 
2603  /* For most of the detections, we only detect objects above the
2604  * floor. But this is not true for show invisible.
2605  * Basically, we just go and find the top object and work
2606  * down - that is easier than working up.
2607  */
2608 
2609  last = GET_MAP_TOP(m, nx, ny);
2610  /* Shouldn't happen, but if there are no objects on a space, this
2611  * would happen.
2612  */
2613  if (!last)
2614  continue;
2615 
2616  done_one = 0;
2617  floor = 0;
2618  detect = NULL;
2619  tmp = last;
2621  /* show invisible */
2623  /* Might there be other objects that we can make visibile? */
2624  && (tmp->invisible && (QUERY_FLAG(tmp, FLAG_MONSTER) ||
2625  (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)) ||
2626  tmp->type == CF_HANDLE ||
2627  tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
2628  tmp->type == BUTTON || tmp->type == TELEPORTER ||
2629  tmp->type == GATE || tmp->type == LOCKED_DOOR ||
2630  tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
2631  tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
2632  tmp->type == TREASURE || tmp->type == BOOK ||
2633  tmp->type == HOLY_ALTAR))) {
2634  if (random_roll(0, level-1, op, PREFER_HIGH) > tmp->level) {
2635  tmp->invisible = 0;
2636  done_one = 1;
2637  }
2638  }
2639  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2640  floor = 1;
2641 
2642  /* All detections below this point don't descend beneath the floor,
2643  * so just continue on. We could be clever and look at the type of
2644  * detection to completely break out if we don't care about objects beneath
2645  * the floor, but once we get to the floor, not likely a very big issue anyways.
2646  */
2647  if (floor)
2648  continue;
2649 
2650  /* I had thought about making detect magic and detect curse
2651  * show the flash the magic item like it does for detect monster.
2652  * however, if the object is within sight, this would then make it
2653  * difficult to see what object is magical/cursed, so the
2654  * effect wouldn't be as apparent.
2655  */
2656 
2657  /* detect magic */
2658  if (spell_detect_magic
2659  && !QUERY_FLAG(tmp, FLAG_KNOWN_MAGICAL)
2660  && !QUERY_FLAG(tmp, FLAG_IDENTIFIED)
2661  && is_magical(tmp)) {
2663  /* make runes more visible */
2664  if (tmp->type == RUNE && tmp->attacktype&AT_MAGIC)
2665  tmp->stats.Cha /= 4;
2666  done_one = 1;
2667  }
2668  /* detect monster */
2670  && (QUERY_FLAG(tmp, FLAG_MONSTER) || (tmp->type == PLAYER && !QUERY_FLAG(tmp, FLAG_WIZ)))) {
2671  done_one = 2;
2672  if (!detect)
2673  detect = tmp;
2674  }
2675  /* Basically, if race is set in the spell, then the creatures race must
2676  * match that. if the spell race is set to GOD, then the gods opposing
2677  * race must match.
2678  */
2679  if (spell->race
2680  && QUERY_FLAG(tmp, FLAG_MONSTER)
2681  && tmp->race
2682  && ((!strcmp(spell->race, "GOD") && god && god->slaying && strstr(god->slaying, tmp->race)) || (strstr(spell->race, tmp->race)))) {
2683  done_one = 2;
2684  if (!detect)
2685  detect = tmp;
2686  }
2688  && !QUERY_FLAG(tmp, FLAG_KNOWN_CURSED)
2689  && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) {
2691  done_one = 1;
2692  }
2693  } FOR_OB_AND_BELOW_FINISH(); /* for stack of objects on this space */
2694 
2695  /* Code here puts an effect of the spell on the space, so you can see
2696  * where the magic is.
2697  */
2698  if (done_one) {
2699  object *detect_ob;
2700  int dx = nx, dy = ny;
2701 
2702  /* if this is set, we want to copy the face */
2703  if (done_one == 2 && detect) {
2704  /*
2705  * We can't simply copy the face to a single item, because
2706  * multipart objects need to have multipart glows.
2707  * So copy the initial item, erase some properties, and use that.
2708  */
2709 
2710  object *part;
2711  int flag;
2712 
2713  dx = HEAD(detect)->x;
2714  dy = HEAD(detect)->y;
2715 
2716  detect_ob = object_create_arch(HEAD(detect)->arch);
2717  for (part = detect_ob; part != NULL; part = part->more) {
2718  if (part->arch->reference_count > 0)
2719  part->arch->reference_count++;
2720  part->last_anim = 0;
2721  part->type = spell->other_arch->clone.type;
2722  for (flag = 0; flag < 4; flag++) {
2723  part->flags[flag] = spell->other_arch->clone.flags[flag];
2724  }
2725  part->stats.food = spell->other_arch->clone.stats.food;
2726  part->last_anim = 0;
2727  part->speed = spell->other_arch->clone.speed;
2728  part->speed_left = spell->other_arch->clone.speed_left;
2729  part->move_allow = spell->other_arch->clone.move_allow;
2730  part->move_block = spell->other_arch->clone.move_block;
2731  part->move_type = spell->other_arch->clone.move_type;
2732  part->glow_radius = spell->other_arch->clone.glow_radius;
2733  part->invisible = spell->other_arch->clone.invisible;
2734  part->weight = spell->other_arch->clone.weight;
2735  part->map_layer = spell->other_arch->clone.map_layer;
2736  FREE_AND_COPY(part->name, spell->other_arch->clone.name);
2737 
2738  /* by default, the detect_ob is already animated */
2739  if (!QUERY_FLAG(detect, FLAG_ANIMATE))
2740  CLEAR_FLAG(part, FLAG_ANIMATE);
2741  }
2742  object_update_speed(detect_ob);
2743  } else
2744  detect_ob = arch_to_object(spell->other_arch);
2745 
2746  object_insert_in_map_at(detect_ob, m, op, 0, dx, dy);
2747  }
2748  } /* for processing the surrounding spaces */
2749 
2750 
2751  /* Now process objects in the players inventory if detect curse or magic */
2752  if (QUERY_FLAG(spell, FLAG_KNOWN_CURSED) || spell_detect_magic) {
2753  done_one = 0;
2754  FOR_INV_PREPARE(op, tmp) {
2755  if (!tmp->invisible && !QUERY_FLAG(tmp, FLAG_IDENTIFIED)) {
2756  if (spell_detect_magic
2757  && is_magical(tmp)
2758  && !QUERY_FLAG(tmp, FLAG_KNOWN_MAGICAL)) {
2760  if (op->type == PLAYER)
2761  esrv_send_item(op, tmp);
2762  }
2764  && !QUERY_FLAG(tmp, FLAG_KNOWN_CURSED)
2765  && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) {
2767  if (op->type == PLAYER)
2768  esrv_send_item(op, tmp);
2769  }
2770  } /* if item is not identified */
2771  } FOR_INV_FINISH(); /* for the players inventory */
2772  } /* if detect magic/curse and object is a player */
2773  return 1;
2774 }
2775 
2783 static void charge_mana_effect(object *victim, int caster_level) {
2784  /* Prevent explosions for objects without mana. Without this check, doors
2785  * will explode, too.
2786  */
2787  if (victim->stats.maxsp <= 0)
2788  return;
2789 
2791  "You feel energy course through you.");
2792 
2793  if (victim->stats.sp >= victim->stats.maxsp*2) {
2794  object *tmp;
2795 
2797  "Your head explodes!");
2798 
2799  /* Explodes a fireball centered at player */
2801  tmp->dam_modifier = random_roll(1, caster_level, victim, PREFER_LOW)/5+1;
2802  tmp->stats.maxhp = random_roll(1, caster_level, victim, PREFER_LOW)/10+2;
2803  object_insert_in_map_at(tmp, victim->map, NULL, 0, victim->x, victim->y);
2804  victim->stats.sp = 2*victim->stats.maxsp;
2805  } else if (victim->stats.sp >= victim->stats.maxsp*1.88) {
2807  "You feel like your head is going to explode.");
2808  } else if (victim->stats.sp >= victim->stats.maxsp*1.66) {
2810  "You get a splitting headache!");
2811  } else if (victim->stats.sp >= victim->stats.maxsp*1.5) {
2813  "Chaos fills your world.");
2814  confuse_living(victim, victim, 99);
2815  } else if (victim->stats.sp >= victim->stats.maxsp*1.25) {
2817  "You start hearing voices.");
2818  }
2819 }
2820 
2838 int cast_transfer(object *op, object *caster, object *spell, int dir) {
2839  object *plyr = NULL;
2840  int16_t x, y;
2841  mapstruct *m;
2842  int mflags;
2843 
2844  m = op->map;
2845  x = op->x+freearr_x[dir];
2846  y = op->y+freearr_y[dir];
2847 
2848  mflags = get_map_flags(m, &m, x, y, &x, &y);
2849  if (!(mflags&P_OUT_OF_MAP) && mflags&P_IS_ALIVE) {
2850  FOR_MAP_PREPARE(m, x, y, tmp)
2851  plyr = tmp;
2852  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2853  break;
2854  FOR_MAP_FINISH();
2855  }
2856 
2857  /* If we did not find a player in the specified direction, transfer
2858  * to anyone on top of us. This is used for the rune of transference mostly.
2859  */
2860  if (plyr == NULL)
2861  FOR_MAP_PREPARE(op->map, op->x, op->y, tmp)
2862  plyr = tmp;
2863  if (plyr != op && QUERY_FLAG(plyr, FLAG_ALIVE))
2864  break;
2865  FOR_MAP_FINISH();
2866 
2867  if (!plyr) {
2869  "There is no one there.");
2870  return 0;
2871  }
2872 
2873  /* give sp */
2874  if (spell->stats.dam > 0) {
2875  plyr->stats.sp += spell->stats.dam+SP_level_dam_adjust(caster, spell);
2876  charge_mana_effect(plyr, caster_level(caster, spell));
2877  return 1;
2878  /* suck sp away. Can't suck sp from yourself */
2879  } else if (op != plyr) {
2880  /* old dragin magic used floats. easier to just use ints and divide by 100 */
2881 
2882  int rate = -spell->stats.dam+SP_level_dam_adjust(caster, spell), sucked;
2883 
2884  if (rate > 95)
2885  rate = 95;
2886 
2887  sucked = (plyr->stats.sp*rate)/100;
2888  plyr->stats.sp -= sucked;
2889  if (QUERY_FLAG(op, FLAG_ALIVE)) {
2890  /* Player doesn't get full credit */
2891  sucked = (sucked*rate)/100;
2892  op->stats.sp += sucked;
2893  if (sucked > 0) {
2894  charge_mana_effect(op, caster_level(caster, spell));
2895  }
2896  }
2897  return 1;
2898  }
2899  return 0;
2900 }
2901 
2911 void counterspell(object *op, int dir) {
2912  object *head;
2913  int mflags;
2914  mapstruct *m;
2915  int16_t sx, sy;
2916 
2917  sx = op->x+freearr_x[dir];
2918  sy = op->y+freearr_y[dir];
2919  m = op->map;
2920  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
2921  if (mflags&P_OUT_OF_MAP)
2922  return;
2923 
2924  FOR_MAP_PREPARE(m, sx, sy, tmp) {
2925  object *owner;
2926 
2927  /* Need to look at the head object - otherwise, if tmp
2928  * points to a monster, we don't have all the necessary
2929  * info for it.
2930  */
2931  head = HEAD(tmp);
2932 
2933  /* don't attack our own spells */
2934  owner = object_get_owner(tmp);
2935  if (owner != NULL && owner == object_get_owner(op))
2936  continue;
2937 
2938  /* Basically, if the object is magical and not counterspell,
2939  * we will more or less remove the object. Don't counterspell
2940  * monsters either.
2941  */
2942 
2943  if (head->attacktype&AT_MAGIC
2944  && !(head->attacktype&AT_COUNTERSPELL)
2945  && !QUERY_FLAG(head, FLAG_MONSTER)
2946  && (op->level > head->level)) {
2947  object_remove(head);
2948  object_free(head, 0);
2949  } else switch (head->type) {
2950  case SPELL_EFFECT:
2951  if ((op->level > head->level) && !op->stats.food && !op->speed_left) {
2952  object_remove(head);
2953  object_free(head, 0);
2954  }
2955  break;
2956 
2957  /* I really don't get this rune code that much - that
2958  * random chance seems really low.
2959  */
2960  case RUNE:
2961  if (rndm(0, 149) == 0) {
2962  head->stats.hp--; /* weaken the rune */
2963  if (!head->stats.hp) {
2964  object_remove(head);
2965  object_free(head, 0);
2966  }
2967  }
2968  break;
2969  }
2970  } FOR_MAP_FINISH();
2971 }
2972 
2987 int cast_consecrate(object *op, object *caster, object *spell) {
2988  char buf[MAX_BUF];
2989  const object *god = find_god(determine_god(op));
2990 
2991  if (!god) {
2993  "You can't consecrate anything if you don't worship a god!");
2994  return 0;
2995  }
2996 
2997  FOR_BELOW_PREPARE(op, tmp) {
2998  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
2999  break;
3000  if (tmp->type == HOLY_ALTAR) {
3001  if (tmp->level > caster_level(caster, spell)) {
3003  "You are not powerful enough to reconsecrate the %s",
3004  tmp->name);
3005  return 0;
3006  } else {
3007  /* If we got here, we are consecrating an altar */
3008  object *new_altar;
3009  size_t letter;
3010  archetype *altar_arch;
3011 
3012  snprintf(buf, MAX_BUF, "altar_");
3013  letter = strlen(buf);
3014  strncpy(buf+letter, god->name, MAX_BUF-letter);
3015  for (; letter < strlen(buf); letter++)
3016  buf[letter] = tolower(buf[letter]);
3017  altar_arch = try_find_archetype(buf);
3018  if (!altar_arch) {
3020  "You fail to consecrate the altar.");
3021  LOG(llevError, "cast_consecrate: can't find altar %s for god %s\n", buf, god->name);
3022  return 0;
3023  }
3024  new_altar = arch_to_object(altar_arch);
3025  new_altar->level = tmp->level;
3026  if (QUERY_FLAG(tmp, FLAG_IS_BUILDABLE))
3027  SET_FLAG(new_altar, FLAG_IS_BUILDABLE);
3028  object_insert_in_map_at(new_altar, tmp->map, tmp, INS_BELOW_ORIGINATOR, tmp->x, tmp->y);
3029  object_remove(tmp);
3031  "You consecrated the altar to %s!",
3032  god->name);
3033  return 1;
3034  }
3035  }
3036  } FOR_BELOW_FINISH();
3038  "You are not standing over an altar!");
3039  return 0;
3040 }
3041 
3065 int animate_weapon(object *op, object *caster, object *spell, int dir) {
3066  object *weapon, *tmp;
3067  char buf[MAX_BUF];
3068  int a, i;
3069  int16_t x, y;
3070  mapstruct *m;
3071  materialtype_t *mt;
3072 
3073  if (!spell->other_arch) {
3075  "Oops, program error!");
3076  LOG(llevError, "animate_weapon failed: spell %s missing other_arch!\n", spell->name);
3077  return 0;
3078  }
3079 
3080  /* exit if it's not a player using this spell. */
3081  if (op->type != PLAYER)
3082  return 0;
3083 
3084  /* if player already has a golem, abort */
3085  if (op->contr->ranges[range_golem] != NULL && op->contr->golem_count == op->contr->ranges[range_golem]->count) {
3087  return 0;
3088  }
3089 
3090  /* if no direction specified, pick one */
3091  if (!dir) {
3092  dir = object_find_free_spot(NULL, op->map, op->x, op->y, 1, 9);
3093  if ( dir == -1 ) {
3095  "There is something in the way.");
3096  return 0;
3097  }
3098  }
3099 
3100  m = op->map;
3101  x = op->x+freearr_x[dir];
3102  y = op->y+freearr_y[dir];
3103 
3104  /* if there's no place to put the golem, abort */
3105  if ((dir == -1)
3106  || (get_map_flags(m, &m, x, y, &x, &y)&P_OUT_OF_MAP)
3107  || ((spell->other_arch->clone.move_type&GET_MAP_MOVE_BLOCK(m, x, y)) == spell->other_arch->clone.move_type)) {
3109  "There is something in the way.");
3110  return 0;
3111  }
3112 
3113  /* Use the weapon marked by the player. */
3114  weapon = find_marked_object(op);
3115 
3116  if (!weapon) {
3118  "You must mark a weapon to use with this spell!");
3119  return 0;
3120  }
3121  if (spell->race && strcmp(weapon->arch->name, spell->race)) {
3123  "The spell fails to transform your weapon.");
3124  return 0;
3125  }
3126  if (weapon->type != WEAPON) {
3128  "You need to mark a weapon to animate it.");
3129  return 0;
3130  }
3131  if (QUERY_FLAG(weapon, FLAG_UNPAID)) {
3133  "You need to pay for the weapon to animate it.");
3134  return 0;
3135  }
3136  if (QUERY_FLAG(weapon, FLAG_APPLIED)) {
3137  char wn[MAX_BUF];
3138 
3139  query_name(weapon, wn, MAX_BUF);
3141  "You need to unequip %s before using it in this spell",
3142  wn);
3143  return 0;
3144  }
3145 
3146  if (weapon->nrof > 1) {
3147  tmp = object_split(weapon, 1, NULL, 0);
3148  esrv_update_item(UPD_NROF, op, weapon);
3149  weapon = tmp;
3150  }
3151 
3152  /* create the golem object */
3153  tmp = arch_to_object(spell->other_arch);
3154 
3155  /* if animated by a player, give the player control of the golem */
3156  CLEAR_FLAG(tmp, FLAG_MONSTER);
3157  SET_FLAG(tmp, FLAG_FRIENDLY);
3158  tmp->stats.exp = 0;
3159  add_friendly_object(tmp);
3160  tmp->type = GOLEM;
3161  object_set_owner(tmp, op);
3162  set_spell_skill(op, caster, spell, tmp);
3163  op->contr->ranges[range_golem] = tmp;
3164  op->contr->shoottype = range_golem;
3165  op->contr->golem_count = tmp->count;
3166 
3167  /* Give the weapon to the golem now. A bit of a hack to check the
3168  * removed flag - it should only be set if object_split() was
3169  * used above.
3170  */
3171  if (!QUERY_FLAG(weapon, FLAG_REMOVED))
3172  object_remove(weapon);
3173  object_insert_in_ob(weapon, tmp);
3174 
3175  /* To do everything necessary to let a golem use the weapon is a pain,
3176  * so instead, just set it as equipped (otherwise, we need to update
3177  * body_info, skills, etc)
3178  */
3179  SET_FLAG(tmp, FLAG_USE_WEAPON);
3180  SET_FLAG(weapon, FLAG_APPLIED);
3181  fix_object(tmp);
3182 
3183  /* There used to be 'odd' code that basically seemed to take the absolute
3184  * value of the weapon->magic an use that. IMO, that doesn't make sense -
3185  * if you're using a crappy weapon, it shouldn't be as good.
3186  */
3187 
3188  /* modify weapon's animated wc */
3189  tmp->stats.wc = tmp->stats.wc
3190  -SP_level_range_adjust(caster, spell)
3191  -5*weapon->stats.Dex
3192  -2*weapon->stats.Str
3193  -weapon->magic;
3194  if (tmp->stats.wc < -127)
3195  tmp->stats.wc = -127;
3196 
3197  /* Modify hit points for weapon */
3198  tmp->stats.maxhp = tmp->stats.maxhp
3199  +spell->duration
3201  +8*weapon->magic
3202  +12*weapon->stats.Con;
3203  if (tmp->stats.maxhp < 0)
3204  tmp->stats.maxhp = 10;
3205  tmp->stats.hp = tmp->stats.maxhp;
3206 
3207  /* Modify weapon's damage */
3208  tmp->stats.dam = spell->stats.dam
3209  +SP_level_dam_adjust(caster, spell)
3210  +weapon->stats.dam
3211  +weapon->magic
3212  +5*weapon->stats.Str;
3213  if (tmp->stats.dam < 0)
3214  tmp->stats.dam = 127;
3215 
3216  /* attacktype */
3217  if (!tmp->attacktype)
3218  tmp->attacktype = AT_PHYSICAL;
3219 
3220  mt = NULL;
3221  if (op->materialname != NULL)
3222  mt = name_to_material(op->materialname);
3223  if (mt != NULL) {
3224  for (i = 0; i < NROFATTACKS; i++)
3225  tmp->resist[i] = 50-(mt->save[i]*5);
3226  a = mt->save[0];
3227  } else {
3228  for (i = 0; i < NROFATTACKS; i++)
3229  tmp->resist[i] = 5;
3230  a = 10;
3231  }
3232  /* Set weapon's immunity */
3233  tmp->resist[ATNR_CONFUSION] = 100;
3234  tmp->resist[ATNR_POISON] = 100;
3235  tmp->resist[ATNR_SLOW] = 100;
3236  tmp->resist[ATNR_PARALYZE] = 100;
3237  tmp->resist[ATNR_TURN_UNDEAD] = 100;
3238  tmp->resist[ATNR_FEAR] = 100;
3239  tmp->resist[ATNR_DEPLETE] = 100;
3240  tmp->resist[ATNR_DEATH] = 100;
3241  tmp->resist[ATNR_BLIND] = 100;
3242 
3243  /* Improve weapon's armour value according to best save vs. physical of its material */
3244 
3245  if (a > 14)
3246  a = 14;
3247  tmp->resist[ATNR_PHYSICAL] = 100-(int)((100.0-(float)tmp->resist[ATNR_PHYSICAL])/(30.0-2.0*a));
3248 
3249  /* Determine golem's speed */
3250  tmp->speed = 0.4+0.1*SP_level_range_adjust(caster, spell);
3251 
3252  if (tmp->speed > 3.33)
3253  tmp->speed = 3.33;
3254 
3255  if (!spell->race) {
3256  snprintf(buf, sizeof(buf), "animated %s", weapon->name);
3257  if (tmp->name)
3258  free_string(tmp->name);
3259  tmp->name = add_string(buf);
3260 
3261  tmp->face = weapon->face;
3262  tmp->animation = weapon->animation;
3263  tmp->anim_speed = weapon->anim_speed;
3264  tmp->last_anim = weapon->last_anim;
3265  tmp->state = weapon->state;
3266  if (QUERY_FLAG(weapon, FLAG_ANIMATE)) {
3267  SET_FLAG(tmp, FLAG_ANIMATE);
3268  } else {
3269  CLEAR_FLAG(tmp, FLAG_ANIMATE);
3270  }
3271  object_update_speed(tmp);
3272  }
3273 
3274  /* make experience increase in proportion to the strength of the summoned creature. */
3275  tmp->stats.exp *= 1+(MAX(spell->stats.maxgrace, spell->stats.sp)/caster_level(caster, spell));
3276 
3277  tmp->speed_left = -1;
3278  tmp->direction = dir;
3279  object_insert_in_map_at(tmp, m, op, 0, x, y);
3280  return 1;
3281 }
3282 
3295 int cast_change_map_lightlevel(object *op, object *spell) {
3296  int success;
3297 
3298  if (!op->map)
3299  return 0; /* shouldnt happen */
3300 
3301  success = change_map_light(op->map, spell->stats.dam);
3302  if (!success) {
3303  if (spell->stats.dam < 0)
3305  "It can be no brighter here.");
3306  else
3308  "It can be no darker here.");
3309  }
3310  return success;
3311 }
3312 
3327 int create_aura(object *op, object *caster, object *spell) {
3328  int refresh = 0, i;
3329  object *new_aura;
3330 
3331  new_aura = arch_present_in_ob(spell->other_arch, op);
3332  if (new_aura)
3333  refresh = 1;
3334  else
3335  new_aura = arch_to_object(spell->other_arch);
3336 
3337  new_aura->duration = spell->duration+10*SP_level_duration_adjust(caster, spell);
3338  if (op->type == PLAYER)
3339  store_spell_expiry(new_aura);
3340 
3341  new_aura->stats.dam = spell->stats.dam+SP_level_dam_adjust(caster, spell);
3342 
3343  // If the range is zero, it's not an aura. Plain and simple. Minimum is one.
3344  // Also provides backward compatability on existing auras to be range 1
3345  new_aura->range = MAX(1, spell->range+SP_level_range_adjust(caster, spell));
3346 
3347  object_set_owner(new_aura, op);
3348  set_spell_skill(op, caster, spell, new_aura);
3349  new_aura->attacktype = spell->attacktype;
3350 
3351  new_aura->level = caster_level(caster, spell);
3352 
3353  /* Code below is so that auras can also provide resistances. For
3354  * example, fire shield both does damage to nearby enemies and also
3355  * provides some protection to fire. We need to use a different
3356  * FORCE object for this, as putting it in with the aura object
3357  * just puts too many meanings into that one object. Because
3358  * the duration of this force object is the same, we don't need
3359  * to set up spell expiry on it - this second object is really
3360  * an internal mechanic that should be invisible to the player.
3361  */
3362  for (i = 0; i < NROFATTACKS; i++) {
3363  if (spell->resist[i]) {
3364  int refresh1=1;
3365  object *force;
3366 
3367  force = object_present_in_ob_by_name(FORCE, spell->name, op);
3368  if (!force) {
3370  force->subtype = FORCE_CHANGE_ABILITY;
3371  free_string(force->name);
3372  force->name = add_refcount(spell->name);
3373  free_string(force->name_pl);
3374  force->name_pl = add_refcount(spell->name);
3375  refresh1=0;
3376  }
3377  force->duration = new_aura->duration;
3378  force->speed = new_aura->speed;
3379  memcpy(&force->resist, spell->resist, sizeof(spell->resist));
3380  SET_FLAG(force, FLAG_APPLIED);
3381 
3382  if (!refresh1)
3383  object_insert_in_ob(force, op);
3384  change_abil(op, new_aura);
3385  fix_object(op);
3386  break;
3387  }
3388  }
3389 
3390  if (refresh)
3392  "You recast the spell while in effect.");
3393  else
3394  object_insert_in_ob(new_aura, op);
3395  return 1;
3396 }
3397 
3413 int write_mark(object *op, object *spell, const char *msg) {
3414  char rune[HUGE_BUF];
3415  object *tmp;
3416 
3417  if (!msg || msg[0] == 0) {
3419  "Write what?");
3420  return 0;
3421  }
3422 
3423  if (strcasestr_local(msg, "endmsg")) {
3425  "Trying to cheat are we?");
3426  LOG(llevInfo, "write_rune: player %s tried to write bogus rune %s\n", op->name, msg);
3427  return 0;
3428  }
3429 
3430  if (!spell->other_arch)
3431  return 0;
3432  tmp = arch_to_object(spell->other_arch);
3433  strncpy(rune, msg, HUGE_BUF-2);
3434  rune[HUGE_BUF-2] = 0;
3435  strcat(rune, "\n");
3436  tmp->race = add_string(op->name); /*Save the owner of the rune*/
3437  object_set_msg(tmp, rune);
3438  object_insert_in_map_at(tmp, op->map, op, INS_BELOW_ORIGINATOR, op->x, op->y);
3439  return 1;
3440 }
SP_level_range_adjust
int SP_level_range_adjust(const object *caster, const object *spob)
Adjust the range of the spell based on level.
Definition: spell_util.cpp:338
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
Definition: object.h:70
object_value_set
bool object_value_set(const object *op, const char *const key)
Determine if an extra value is set.
Definition: object.cpp:4361
MSG_TYPE_SPELL_PERCEIVE_SELF
#define MSG_TYPE_SPELL_PERCEIVE_SELF
Perceive self messages.
Definition: newclient.h:641
object::name_pl
sstring name_pl
The plural name of the object.
Definition: object.h:323
GET_MAP_OB
#define GET_MAP_OB(M, X, Y)
Gets the bottom object on a map.
Definition: map.h:170
FORCE_CHANGE_ABILITY
#define FORCE_CHANGE_ABILITY
Definition: spells.h:145
player::bed_y
int16_t bed_y
x,y - coordinates of respawn (savebed).
Definition: player.h:111
living::exp
int64_t exp
Experience.
Definition: living.h:47
HAS_RANDOM_ITEMS
#define HAS_RANDOM_ITEMS(op)
This return TRUE if object has still randomitems which could be expanded.
Definition: define.h:184
UP_OBJ_FACE
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:533
write_mark
int write_mark(object *op, object *spell, const char *msg)
This writes a rune that contains the appropriate message.
Definition: spell_effect.cpp:3413
PLAYER
@ PLAYER
Definition: object.h:112
object_get_owner
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.cpp:789
ATNR_PARALYZE
#define ATNR_PARALYZE
Definition: attack.h:61
set_spell_skill
void set_spell_skill(object *op, object *caster, object *spob, object *dest)
Utility function to assign the correct skill when casting.
Definition: spell_util.cpp:94
LARGE_NUGGET
#define LARGE_NUGGET
Definition: spell_effect.cpp:2176
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:545
object_find_by_type_subtype
object * object_find_by_type_subtype(const object *who, int type, int subtype)
Find object in inventory.
Definition: object.cpp:4286
cast_polymorph
int cast_polymorph(object *op, object *caster, object *spell_ob, int dir)
Polymorph spell casting.
Definition: spell_effect.cpp:425
settings
struct Settings settings
Global settings.
Definition: init.cpp:139
CF_HANDLE
@ CF_HANDLE
Definition: object.h:213
SOUND_TYPE_ITEM
#define SOUND_TYPE_ITEM
Definition: newclient.h:339
INS_NO_WALK_ON
#define INS_NO_WALK_ON
Don't call check_walk_on against the originator.
Definition: object.h:582
friendly
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your and press< Return > You can also use say if you feel like typing a little extra Other NPCs may not speak to but display intelligence with their movement Some monsters can be friendly
Definition: survival-guide.txt:38
place_alchemy_objects
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.
Definition: spell_effect.cpp:2270
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:724
remove_friendly_object
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.cpp:52
cast_change_ability
int cast_change_ability(object *op, object *caster, object *spell_ob, int dir, int silent)
Cast some stat-improving spell.
Definition: spell_effect.cpp:1902
remove_curse
int remove_curse(object *op, object *caster, object *spell)
This function removes the cursed/damned status on equipped items.
Definition: spell_effect.cpp:2406
living::maxhp
int16_t maxhp
Max hit points.
Definition: living.h:41
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Find applied object in inventory.
Definition: object.cpp:4068
AT_POISON
#define AT_POISON
Definition: attack.h:86
object::weapontype
uint32_t weapontype
Type of weapon.
Definition: object.h:381
AT_MAGIC
#define AT_MAGIC
Definition: attack.h:77
CAN_PROBE
static bool CAN_PROBE(const object *ob)
Determine whether the given object can have an HP bar.
Definition: object.h:616
object::map_layer
uint8_t map_layer
What level to draw this on the map.
Definition: object.h:434
BOW
@ BOW
Definition: object.h:123
GET_MAP_TOP
#define GET_MAP_TOP(M, X, Y)
Gets the top object on a map.
Definition: map.h:172
llevError
@ llevError
Error, serious thing.
Definition: logger.h:11
FABS
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
mapstruct::difficulty
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:333
object::path_attuned
uint32_t path_attuned
Paths the object is attuned to.
Definition: object.h:353
WAND
@ WAND
Definition: object.h:225
unpaid_count::count
int count
Definition: shop.cpp:684
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
strcasestr_local
#define strcasestr_local
Definition: compat.h:28
FLAG_UNDEAD
#define FLAG_UNDEAD
Monster is undead.
Definition: define.h:270
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
find_archetype_by_object_type_name
archetype * find_archetype_by_object_type_name(int type, const char *name)
This function retrieves an archetype by type and name that appears during the game.
Definition: arch.cpp:64
FLAG_GENERATOR
#define FLAG_GENERATOR
Will generate type ob->stats.food.
Definition: define.h:248
esrv_map_scroll
void esrv_map_scroll(socket_struct *ns, int dx, int dy)
Definition: request.cpp:1753
object::inv
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
socket_struct::look_position
uint16_t look_position
Start of drawing of look window.
Definition: newserver.h:118
player::golem_count
uint32_t golem_count
To track the golem.
Definition: player.h:119
BUTTON
@ BUTTON
Definition: object.h:212
perceive_self
int perceive_self(object *op)
Living thing wants to know information.
Definition: spell_effect.cpp:1002
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Object was given to player at start.
Definition: define.h:268
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Makes sure the given map is loaded and swapped in.
Definition: map.cpp:1778
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
makes_invisible_to
int makes_invisible_to(object *pl, object *mon)
This checks to see if 'pl' is invisible to 'mon'.
Definition: spell_effect.cpp:756
archetypes_for_each
void archetypes_for_each(arch_op op)
Definition: assets.cpp:301
AssetsManager.h
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
magic_wall
int magic_wall(object *op, object *caster, int dir, object *spell_ob)
This creates magic walls.
Definition: spell_effect.cpp:1456
cast_change_map_lightlevel
int cast_change_map_lightlevel(object *op, object *spell)
This changes the light level for the entire map.
Definition: spell_effect.cpp:3295
ARCH_DEPLETION
#define ARCH_DEPLETION
Archetype for depletion.
Definition: object.h:590
map_find_by_archetype
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.cpp:3103
confuse_living
void confuse_living(object *op, object *hitter, int dam)
Confuse a living thing.
Definition: attack.cpp:2315
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.cpp:138
pick_up
bool pick_up(object *op, object *alt)
Try to pick up an item.
Definition: c_object.cpp:520
FLAG_SEE_IN_DARK
#define FLAG_SEE_IN_DARK
if set ob not effected by darkness
Definition: define.h:337
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
object::arch
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
cast_spell
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Main dispatch when someone casts a spell.
Definition: spell_util.cpp:1424
player::bed_x
int16_t bed_x
Definition: player.h:111
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.cpp:57
object::attack_movement
uint16_t attack_movement
What kind of attack movement.
Definition: object.h:401
FLAG_IS_BUILDABLE
#define FLAG_IS_BUILDABLE
Can build on item.
Definition: define.h:367
cast_wonder
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.cpp:968
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Constructs a loop iterating over all objects below an object.
Definition: define.h:698
object::range
int8_t range
Range of the spell.
Definition: object.h:417
object::speed
float speed
Frequency of object 'moves' relative to server tick rate.
Definition: object.h:337
GEM
@ GEM
Definition: object.h:172
artifactlist::items
std::vector< artifact * > items
Artifacts for this type.
Definition: artifact.h:28
food_value_choice
static int food_value_choice
Definition: spell_effect.cpp:594
object::invisible
int16_t invisible
How much longer the object will be invis.
Definition: object.h:370
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:433
living::Dex
int8_t Dex
Definition: living.h:36
object::x
int16_t x
Definition: object.h:335
player::transport
object * transport
Transport the player is in.
Definition: player.h:214
object::speed_left
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
give_artifact_abilities
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.cpp:230
PREFER_LOW
#define PREFER_LOW
Definition: define.h:558
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
WEAPON
@ WEAPON
Definition: object.h:124
object_find_first_free_spot
int object_find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
object_find_first_free_spot(archetype, mapstruct, x, y) works like object_find_free_spot(),...
Definition: object.cpp:3584
arch_present_in_ob
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.cpp:3207
object_set_owner
void object_set_owner(object *op, object *owner)
Sets the owner and sets the skill and exp pointers to owner's current skill and experience objects.
Definition: object.cpp:825
generate_treasure
object * generate_treasure(treasurelist *t, int difficulty)
Generate a treasure from a list generating a single item.
Definition: treasure.cpp:319
SMALL_NUGGET
#define SMALL_NUGGET
Definition: spell_effect.cpp:2175
artifact::item
object * item
Special values of the artifact.
Definition: artifact.h:15
ATNR_SLOW
#define ATNR_SLOW
Definition: attack.h:60
time
non standard information is not specified or uptime this means how long since the executable has been started A particular host may have been running a server for quite a long time
Definition: arch-handbook.txt:206
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
fix_generated_item
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.cpp:927
MIN
#define MIN(x, y)
Definition: compat.h:21
cast_consecrate
int cast_consecrate(object *op, object *caster, object *spell)
A spell to make an altar your god's.
Definition: spell_effect.cpp:2987
ATNR_GODPOWER
#define ATNR_GODPOWER
Definition: attack.h:69
TREASURE
@ TREASURE
Definition: object.h:115
MSG_TYPE_VICTIM_SPELL
#define MSG_TYPE_VICTIM_SPELL
Someone cast a bad spell on the player.
Definition: newclient.h:658
SP_level_duration_adjust
int SP_level_duration_adjust(const object *caster, const object *spob)
Adjust the duration of the spell based on level.
Definition: spell_util.cpp:312
object::direction
int8_t direction
Means the object is moving that way.
Definition: object.h:344
play_sound_map
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
Plays a sound on a map.
Definition: sounds.cpp:113
dimension_door
int dimension_door(object *op, object *caster, object *spob, int dir)
Teleport through some doors and space.
Definition: spell_effect.cpp:1609
object::count
tag_t count
Unique object number for this object.
Definition: object.h:307
FLAG_WIZCAST
#define FLAG_WIZCAST
The wizard can cast spells in no-magic area.
Definition: define.h:289
RUNE
@ RUNE
Definition: object.h:245
object_copy
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.cpp:1177
MAP_PLAYER_UNIQUE
#define MAP_PLAYER_UNIQUE
This map is player-specific.
Definition: map.h:92
player::savebed_map
char savebed_map[MAX_BUF]
Map where player will respawn after death.
Definition: player.h:110
tolower
#define tolower(C)
Simple macro to convert a letter to lowercase.
Definition: c_new.cpp:30
fix_object
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
FLAG_BLESSED
#define FLAG_BLESSED
Item has a blessing, opposite of cursed/damned.
Definition: define.h:369
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:248
polymorph_melt
static void polymorph_melt(object *who, object *op)
Destroys item from polymorph failure.
Definition: spell_effect.cpp:252
P_NO_MAGIC
#define P_NO_MAGIC
Spells (some) can't pass this object.
Definition: map.h:227
TRANSPORT
@ TRANSPORT
see doc/Developers/objects
Definition: object.h:113
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
player::hidden
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:147
UPD_NROF
#define UPD_NROF
Definition: newclient.h:325
SIGN
@ SIGN
Definition: object.h:216
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
food_choice
static archetype * food_choice
Definition: spell_effect.cpp:593
rndm
int rndm(int min, int max)
Returns a number between min and max.
Definition: utils.cpp:162
FLAG_BLOCKSVIEW
#define FLAG_BLOCKSVIEW
Object blocks view.
Definition: define.h:269
ATNR_TURN_UNDEAD
#define ATNR_TURN_UNDEAD
Definition: attack.h:62
range_golem
@ range_golem
Control golem.
Definition: player.h:34
apply_manual
int apply_manual(object *op, object *tmp, int aflag)
Main apply handler.
Definition: apply.cpp:597
FOR_OB_AND_ABOVE_FINISH
#define FOR_OB_AND_ABOVE_FINISH()
Finishes FOR_OB_AND_ABOVE_PREPARE().
Definition: define.h:737
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:355
no_gain_msgs
static const char *const no_gain_msgs[NUM_STATS]
This is used for the spells that gain stats.
Definition: spell_effect.cpp:1873
P_IS_ALIVE
#define P_IS_ALIVE
Something alive is on this space.
Definition: map.h:237
FLAG_APPLIED
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
object::level
int16_t level
Level of creature or object.
Definition: object.h:361
probe
int probe(object *op, object *caster, object *spell_ob, int dir, int level)
Try to get information about a living thing.
Definition: spell_effect.cpp:699
buf
StringBuffer * buf
Definition: readable.cpp:1565
getManager
AssetsManager * getManager()
Definition: assets.cpp:305
name_to_material
materialtype_t * name_to_material(const char *name)
Convert materialname to materialtype_t.
Definition: utils.cpp:248
object_insert_in_ob
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.cpp:2842
object::above
object * above
Pointer to the object stacked above this one.
Definition: object.h:296
HUGE_BUF
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
MSG_TYPE_VICTIM
#define MSG_TYPE_VICTIM
Something bad is happening to the player.
Definition: newclient.h:419
MAX
#define MAX(x, y)
Definition: compat.h:24
object::resist
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:351
FLAG_NO_PICK
#define FLAG_NO_PICK
Object can't be picked up.
Definition: define.h:239
MSG_TYPE_SPELL_TARGET
#define MSG_TYPE_SPELL_TARGET
Target of non attack spell.
Definition: newclient.h:642
ATNR_CONFUSION
#define ATNR_CONFUSION
Definition: attack.h:54
MSG_TYPE_SPELL_HEAL
#define MSG_TYPE_SPELL_HEAL
Healing related spells.
Definition: newclient.h:635
find_god
const object * find_god(const char *name)
Returns a god's object from its name.
Definition: holy.cpp:317
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:250
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Can't see what's underneath this object.
Definition: define.h:302
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Finishes FOR_BELOW_PREPARE().
Definition: define.h:705
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
FLAG_ALIVE
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
esrv_send_item
void esrv_send_item(object *pl, object *op)
Sends item's info to player.
Definition: main.cpp:354
food_each
static void food_each(archetype *arch)
Definition: spell_effect.cpp:595
MSG_TYPE_SPELL_SUCCESS
#define MSG_TYPE_SPELL_SUCCESS
Spell succeeded messages.
Definition: newclient.h:639
FOR_OB_AND_ABOVE_PREPARE
#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:733
store_spell_expiry
void store_spell_expiry(object *spell)
Stores in the spell when to warn player of expiration.
Definition: spell_util.cpp:1981
spell_effect
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.cpp:144
ATNR_BLIND
#define ATNR_BLIND
Definition: attack.h:71
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:424
polymorph
void polymorph(object *op, object *who, int level)
Handles polymorphing an object, living or not.
Definition: spell_effect.cpp:371
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
letter
**Media tags please refer to the protocol file in doc Developers protocol Quick for your pleasure an example[/b][i] This is an old letter
Definition: media-tags.txt:15
object_update
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.cpp:1419
object::contr
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
cast_invisible
int cast_invisible(object *op, object *caster, object *spell_ob)
Makes the player or character invisible.
Definition: spell_effect.cpp:803
PREFER_HIGH
#define PREFER_HIGH
Definition: define.h:557
FLAG_TEAR_DOWN
#define FLAG_TEAR_DOWN
at->faces[hp*animations/maxhp] at hit
Definition: define.h:279
charge_mana_effect
static void charge_mana_effect(object *victim, int caster_level)
Checks if victim has overcharged mana, and if so does some fireball.
Definition: spell_effect.cpp:2783
object::subtype
uint8_t subtype
Subtype of object.
Definition: object.h:349
add_refcount
sstring add_refcount(sstring str)
This will increase the refcount of the string str.
Definition: shstr.cpp:210
determine_god
const char * determine_god(object *op)
Determines if op worships a god.
Definition: gods.cpp:55
freearr_y
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
object::anim_speed
uint8_t anim_speed
Ticks between animation-frames.
Definition: object.h:429
object_present_in_ob_by_name
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Searches for any objects with a matching type & name variable in the inventory of the given object.
Definition: object.cpp:3188
alchemy_object
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.
Definition: spell_effect.cpp:2192
query_name
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:594
cast_word_of_recall
int cast_word_of_recall(object *op, object *caster, object *spell_ob)
Word of recall causes the player to return 'home'.
Definition: spell_effect.cpp:906
FLAG_KNOWN_BLESSED
#define FLAG_KNOWN_BLESSED
Item is known to be blessed.
Definition: define.h:370
GT_INVISIBLE
@ GT_INVISIBLE
Unused?
Definition: treasure.h:32
check_inv_recursive
object * check_inv_recursive(object *op, const object *trig)
Checks object and its inventory for specific item.
Definition: button.cpp:782
MOVE_WALK
#define MOVE_WALK
Object walks.
Definition: define.h:392
FLAG_KNOWN_CURSED
#define FLAG_KNOWN_CURSED
The object is known to be cursed.
Definition: define.h:320
levels
int64_t * levels
Number of levels for which we have experience.
Definition: exp.cpp:26
player::ranges
object * ranges[range_size]
Object for each range.
Definition: player.h:116
EXPLODING_FIREBALL
#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
archetype::clone
object clone
An object from which to do object_copy()
Definition: object.h:487
poison
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters as well as how often the character can attack this affects the prices when buying and selling items if this drops the player will start losing hit points wd Cleric or Dwarf sm Elf wd Fireborn ft Human ra Mage C Monk se Ninja hi Priest C Quetzalcoatl mw Swashbuckler si Thief st Viking ba Warrior or Wizard C Wraith C Class Prof Str Dex Con Wis Cha Int Pow Net Skills Enclosed are codes used for the skills above The ones in and fighting should all be pretty self explanatory For the other a brief description is for a more detailed look at the skills doc file Skill remove use magic items phys no fire cold Fireborns are supposed to be fire spirits They re closely in tune with magic and are powerful and learn magic easily Being fire they are immune to fire and poison
Definition: stats.txt:167
examine_monster
void examine_monster(object *op, object *tmp, int level)
Player examine a monster.
Definition: c_object.cpp:1616
price_base
uint64_t price_base(const object *obj)
Price an item based on its value or archetype value, type, identification/BUC status,...
Definition: item.cpp:1510
add_string
sstring add_string(const char *str)
This will add 'str' to the hash table.
Definition: shstr.cpp:124
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
Definition: define.h:748
HEAD
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:607
object::below
object * below
Pointer to the object stacked below this one.
Definition: object.h:295
change_map_light
int change_map_light(mapstruct *m, int change)
Used to change map light level (darkness) up or down.
Definition: map.cpp:2024
object::move_type
MoveType move_type
Type of movement this object uses.
Definition: object.h:436
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
query_short_name(object) is similar to query_name(), but doesn't contain any information about object...
Definition: item.cpp:518
set_attr_value
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.cpp:218
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:128
MSG_TYPE_ITEM
#define MSG_TYPE_ITEM
Item related information.
Definition: newclient.h:416
object::face
const Face * face
Face with colors.
Definition: object.h:341
FLAG_MAKE_INVIS
#define FLAG_MAKE_INVIS
(Item) gives invisibility when applied
Definition: define.h:328
change_resist_msg
const char *const change_resist_msg[NROFATTACKS]
These are the descriptions of the resistances displayed when a player puts on/takes off an item.
Definition: init.cpp:70
object::value
int32_t value
How much money it is worth (or contains)
Definition: object.h:360
is_identified
int is_identified(const object *op)
Return true if the item is identified, either because it is of a type that doesn't ever need identifi...
Definition: item.cpp:1360
ob_describe
char * ob_describe(const object *op, const object *observer, int use_media_tags, char *buf, size_t size)
Returns the description of an object, as seen by the given observer.
Definition: ob_methods.cpp:91
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:129
HOLE
@ HOLE
Definition: object.h:214
object_update_speed
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1334
object::last_anim
uint8_t last_anim
Last sequence used to draw face.
Definition: object.h:430
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Release the shared string if not NULL, and make it a reference to nv.
Definition: global.h:206
polymorph_living
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.cpp:162
player::tmp_invis
uint32_t tmp_invis
Will invis go away when we attack?
Definition: player.h:140
animate_weapon
int animate_weapon(object *op, object *caster, object *spell, int dir)
Generalization of staff_to_snake().
Definition: spell_effect.cpp:3065
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
INS_NO_MERGE
#define INS_NO_MERGE
Don't try to merge with other items.
Definition: object.h:580
FLAG_DAMNED
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:317
living::dam
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
object::magic
int8_t magic
Any magical bonuses to this item.
Definition: object.h:358
object::materialname
sstring materialname
Specific material name.
Definition: object.h:356
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:319
object_create_arch
object * object_create_arch(archetype *at)
Create a full object using the given archetype.
Definition: arch.cpp:296
spell
with a maximum of six This is not so if you are wearing plate you receive no benefit Armour is additive with all the supplementry forms of which means that it lasts until the next semi permanent spell effect is cast upon the character spell
Definition: tome-of-magic.txt:44
object_free
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1577
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Gets the blocking state of a square.
Definition: map.h:192
FOR_INV_FINISH
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:671
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Insert new object immediately below originator.
Definition: object.h:584
living::food
int32_t food
How much food in stomach.
Definition: living.h:48
GOLEM
@ GOLEM
Definition: object.h:150
caster_level
int caster_level(const object *caster, const object *spell)
This function returns the effective level the spell is being cast at.
Definition: spell_util.cpp:194
cast_detection
int cast_detection(object *op, object *caster, object *spell)
Detect magic or invisible items.
Definition: spell_effect.cpp:2580
cast_create_town_portal
int cast_create_town_portal(object *op, object *caster, object *spell)
This function cast the spell of town portal for op.
Definition: spell_effect.cpp:1241
tag_t
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:14
archetype
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:483
player::shoottype
rangetype shoottype
Which range-attack is being used by player.
Definition: player.h:112
ATNR_POISON
#define ATNR_POISON
Definition: attack.h:59
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:296
sproto.h
statname
const char *const statname[NUM_STATS]
Name of stats.
Definition: living.cpp:183
FLAG_NO_DROP
#define FLAG_NO_DROP
Object can't be dropped.
Definition: define.h:288
ATNR_DEATH
#define ATNR_DEATH
Definition: attack.h:66
living::sp
int16_t sp
Spell points.
Definition: living.h:42
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
Definition: stringbuffer.cpp:95
AssetsCollection::each
void each(std::function< void(T *)> op)
Apply a function to each asset.
Definition: AssetsCollection.h:158
FOR_OB_AND_BELOW_PREPARE
#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:744
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Spell related info.
Definition: newclient.h:415
BOOK
@ BOOK
Definition: object.h:119
GT_ENVIRONMENT
@ GT_ENVIRONMENT
?
Definition: treasure.h:31
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.cpp:42
object::race
sstring race
Human, goblin, dragon, etc.
Definition: object.h:326
cast_item_curse_or_bless
int cast_item_curse_or_bless(object *op, object *spell_ob)
This alters player's marked item's cursed or blessed status, based on the spell_ob's fields.
Definition: spell_effect.cpp:2454
object::facing
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
object::animation
const Animations * animation
Animation of this item, NULL if not animated.
Definition: object.h:428
RING
@ RING
Definition: object.h:190
materialtype_t::save
int8_t save[NROFATTACKS]
Save chances for the attacks.
Definition: material.h:36
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:246
weight
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your and press< Return > You can also use say if you feel like typing a little extra Other NPCs may not speak to but display intelligence with their movement Some monsters can be and may attack the nearest of your enemies Others can be in that they follow you around and help you in your quest to kill enemies and find treasure SPECIAL ITEMS There are many special items which can be found in of these the most important may be the signs all a player must do is apply the handle In the case of the player must move items over the button to hold it down Some of the larger buttons may need very large items to be moved onto before they can be activated Gates and locked but be for you could fall down into a pit full of ghosts or dragons and not be able to get back out Break away sometimes it may be worth a player s time to test the walls of a map for secret doors Fire such as missile weapons and spells you will notice them going up in smoke ! So be careful not to destroy valuable items Spellbooks sometimes a player can learn the other times they cannot There are many different types of books and scrolls out there Improve item have lower weight
Definition: survival-guide.txt:100
object_insert_in_map_at
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.cpp:2085
object::other_arch
struct archetype * other_arch
Pointer used for various things - mostly used for what this objects turns into or what this object cr...
Definition: object.h:425
mapstruct::last_reset_time
long last_reset_time
A timestamp of the last original map loading.
Definition: map.h:356
FLAG_MONSTER
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
P_OUT_OF_MAP
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:249
AssetsManager::archetypes
Archetypes * archetypes()
Get archetypes.
Definition: AssetsManager.h:44
EXIT_X
#define EXIT_X(xyz)
Definition: define.h:435
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
INS_ON_TOP
#define INS_ON_TOP
Always put object on top.
Definition: object.h:583
object_new
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it.
Definition: object.cpp:1258
describe_item
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Describes an item, in all its details.
Definition: item.cpp:958
create_archetype
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.cpp:276
object::weight
int32_t weight
Attributes of the object.
Definition: object.h:375
free_string
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:280
monster_check_apply_all
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.cpp:2012
cast_magic_storm
void cast_magic_storm(object *op, object *tmp, int lvl)
This is really used mostly for spell fumbles and the like.
Definition: spell_effect.cpp:49
living::wc
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
StringBuffer
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.cpp:25
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Release the shared string, and set it to NULL.
Definition: global.h:200
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Low flying object.
Definition: define.h:393
living::maxgrace
int16_t maxgrace
Maximum grace.
Definition: living.h:45
cast_transfer
int cast_transfer(object *op, object *caster, object *spell, int dir)
This spell transfers sp from the player to another person.
Definition: spell_effect.cpp:2838
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:717
EXIT
@ EXIT
Definition: object.h:186
FLAG_KNOWN_MAGICAL
#define FLAG_KNOWN_MAGICAL
The object is known to be magical.
Definition: define.h:319
change_abil
int change_abil(object *op, object *tmp)
Permanently alters an object's stats/flags based on another object.
Definition: living.cpp:394
sounds.h
FLAG_REMOVED
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
FLAG_WIZ
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
object::dam_modifier
uint8_t dam_modifier
How going up in level affects damage.
Definition: object.h:419
llevInfo
@ llevInfo
Information.
Definition: logger.h:12
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:266
object::slaying
sstring slaying
Which race to do double damage to.
Definition: object.h:327
object::glow_radius
int8_t glow_radius
indicates the glow radius of the object
Definition: object.h:374
AT_BLIND
#define AT_BLIND
Definition: attack.h:98
town_portal_find_force
static object * town_portal_find_force(object *op, object *spell)
Definition: spell_effect.cpp:1110
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
spells.h
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
SP_level_dam_adjust
int SP_level_dam_adjust(const object *caster, const object *spob)
Returns adjusted damage based on the caster.
Definition: spell_util.cpp:287
polymorph_item
static void polymorph_item(object *who, object *op, int level)
Changes an item to another item of similar type.
Definition: spell_effect.cpp:280
MSG_TYPE_SPELL_FAILURE
#define MSG_TYPE_SPELL_FAILURE
Spell failure messages.
Definition: newclient.h:637
is_dragon_pl
int is_dragon_pl(const object *op)
Checks if player is a dragon.
Definition: player.cpp:122
add_friendly_object
void add_friendly_object(object *op)
Add a new friendly object to the list of friendly objects.
Definition: friend.cpp:32
ATNR_DEPLETE
#define ATNR_DEPLETE
Definition: attack.h:65
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_.
Definition: map.cpp:300
ARCH_PORTAL_FAILED
#define ARCH_PORTAL_FAILED
Archetype for town portal failure.
Definition: object.h:592
living::maxsp
int16_t maxsp
Max spell points.
Definition: living.h:43
is_magical
int is_magical(const object *op)
Checks whether object is magical.
Definition: item.cpp:1239
mapstruct
This is a game-map.
Definition: map.h:315
counterspell
void counterspell(object *op, int dir)
Nullifies spell effects.
Definition: spell_effect.cpp:2911
floor
Magical Runes Runes are magical inscriptions on the dungeon floor
Definition: runes-guide.txt:3
living::Cha
int8_t Cha
Definition: living.h:36
cast_heal
int cast_heal(object *op, object *caster, object *spell, int dir)
Heals something.
Definition: spell_effect.cpp:1747
object::skill
sstring skill
Name of the skill this object uses/grants.
Definition: object.h:329
MSG_TYPE_SPELL_ERROR
#define MSG_TYPE_SPELL_ERROR
Spell failure messages.
Definition: newclient.h:640
shop.h
object_split
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.cpp:2622
cast_bless
int cast_bless(object *op, object *caster, object *spell_ob, int dir)
Improve statistics of some living object.
Definition: spell_effect.cpp:2050
object_find_free_spot
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.cpp:3544
cast_create_obj
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.cpp:494
object_set_msg
void object_set_msg(object *op, const char *msg)
Set the message field of an object.
Definition: object.cpp:4796
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.cpp:359
did_make_save
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.cpp:2293
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:220
unpaid_count::pl
object * pl
Definition: shop.cpp:683
cast_create_missile
int cast_create_missile(object *op, object *caster, object *spell, int dir, const char *stringarg)
Create a missile (nonmagic - magic +4).
Definition: spell_effect.cpp:493
archetype::reference_count
int reference_count
How many times this temporary archetype is used.
Definition: object.h:490
ATNR_MAGIC
#define ATNR_MAGIC
Definition: attack.h:50
FLAG_NO_FIX_PLAYER
#define FLAG_NO_FIX_PLAYER
fix_object() won't be called
Definition: define.h:277
hit_player
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.cpp:1907
EXIT_Y
#define EXIT_Y(xyz)
Definition: define.h:436
assets.h
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
map_path_unique
bool map_path_unique(const char *path)
Return true if the given map path leads to a unique map.
Definition: map.cpp:2714
ob_apply
method_ret ob_apply(object *op, object *applier, int aflags)
Apply an object by running an event hook or an object method.
Definition: ob_methods.cpp:44
town_portal_destroy_existing
static int town_portal_destroy_existing(object *op, object *spell)
Remove op's existing town portals.
Definition: spell_effect.cpp:1149
living::ac
int8_t ac
Armor Class, lower AC increases probability of not getting hit.
Definition: living.h:38
cast_create_food
int cast_create_food(object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
Create food.
Definition: spell_effect.cpp:627
object::duration
int16_t duration
Number of moves (see 'speed') spell lasts.
Definition: object.h:415
atnr_is_dragon_enabled
int atnr_is_dragon_enabled(int attacknr)
Determine if the attacktype represented by the specified attack-number is enabled for dragon players.
Definition: player.cpp:103
object_find_by_type_and_arch_name
object * object_find_by_type_and_arch_name(const object *who, int type, const char *name)
Find object in inventory by type and archetype name.
Definition: object.cpp:4262
arch_to_object
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.cpp:227
level
int level
Definition: readable.cpp:1563
player::count
uint32_t count
Any numbers typed before a command.
Definition: player.h:122
object::flags
ob_flags flags
Various flags.
Definition: object.h:427
FLAG_IS_USED_UP
#define FLAG_IS_USED_UP
When (–food<0) the object will exit.
Definition: define.h:260
FLAG_ANIMATE
#define FLAG_ANIMATE
The object looks at archetype for faces.
Definition: define.h:242
UPD_NAME
#define UPD_NAME
Definition: newclient.h:322
AT_COUNTERSPELL
#define AT_COUNTERSPELL
Definition: attack.h:95
AT_DISEASE
#define AT_DISEASE
Definition: attack.h:102
object::randomitems
struct treasurelist * randomitems
Items to be generated.
Definition: object.h:395
FOOD
@ FOOD
Definition: object.h:117
object_remove
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.cpp:1818
cure_disease
int cure_disease(object *sufferer, object *caster, sstring skill)
Do the cure disease stuff, from the spell "cure disease".
Definition: disease.cpp:685
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:270
a
Magical Runes Runes are magical inscriptions on the dungeon which cast a spell or detonate when something steps on them Flying objects don t detonate runes Beware ! Runes are invisible most of the time They are only visible occasionally ! There are several runes which are there are some special runes which may only be called with the invoke and people may apply it to read it Maybe useful for mazes ! This rune will not nor is it ordinarily invisible Partial Visibility of they ll be visible only part of the time They have a(your level/2) chance of being visible in any given round
ALTAR
@ ALTAR
Definition: object.h:127
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:236
AT_CONFUSION
#define AT_CONFUSION
Definition: attack.h:81
OB_TYPE_MOVE_BLOCK
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Basic macro to see if if ob1 can not move onto a space based on the 'type' move_block parameter Add c...
Definition: define.h:426
DRINK
@ DRINK
Definition: object.h:162
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Free inventory objects; if not set, drop inventory.
Definition: object.h:544
update_all_los
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.cpp:595
object::state
uint8_t state
How the object was last drawn (animation)
Definition: object.h:359
mapstruct::unique
uint32_t unique
If set, this is a per player unique map.
Definition: map.h:328
SP_WONDER
#define SP_WONDER
Definition: spells.h:83
archetype::name
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
object::nrof
uint32_t nrof
Number of objects.
Definition: object.h:342
FLAG_XRAYS
#define FLAG_XRAYS
X-ray vision.
Definition: define.h:300
player::socket
socket_struct * socket
Socket information for this player.
Definition: player.h:107
materialtype_t
One material type.
Definition: material.h:32
PETMOVE
#define PETMOVE
If the upper four bits of attack_movement are set to this number, the monster follows a player until ...
Definition: define.h:495
living::grace
int16_t grace
Grace.
Definition: living.h:44
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
object::move_allow
MoveType move_allow
What movement types explicitly allowed.
Definition: object.h:438
artifact
This is one artifact, ie one special item.
Definition: artifact.h:14
object::more
object * more
Pointer to the rest of a large body of objects.
Definition: object.h:303
get_attr_value
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.cpp:313
find_target_for_friendly_spell
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.cpp:813
cast_identify
int cast_identify(object *op, object *caster, object *spell)
Identifies objects in the players inventory/on the ground.
Definition: spell_effect.cpp:2505
freearr_x
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
FLAG_IS_CAULDRON
#define FLAG_IS_CAULDRON
container can make alchemical stuff
Definition: define.h:338
pets_control_golem
void pets_control_golem(object *op, int dir)
Makes the golem go in specified direction.
Definition: pets.cpp:643
player::invis_race
const char * invis_race
What race invisible to?
Definition: player.h:151
recharge
int recharge(object *op, object *caster, object *spell_ob)
Recharge wands.
Definition: spell_effect.cpp:84
SPELL
@ SPELL
Definition: object.h:219
Settings::create_home_portals
uint8_t create_home_portals
If 1, can create portals in unique maps (apartments)
Definition: global.h:312
object::attacktype
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:352
FLAG_CURSED
#define FLAG_CURSED
The object is cursed.
Definition: define.h:316
TELEPORTER
@ TELEPORTER
Definition: object.h:146
living.h
find_artifactlist
artifactlist * find_artifactlist(int type)
Finds the artifact list for a certain item type.
Definition: artifact.cpp:574
NDI_GREY
#define NDI_GREY
Definition: newclient.h:256
cast_earth_to_dust
int cast_earth_to_dust(object *op, object *caster, object *spell_ob)
Basically destroys earthwalls in the area.
Definition: spell_effect.cpp:855
NUM_STATS
@ NUM_STATS
Number of statistics.
Definition: living.h:18
MSG_TYPE_ITEM_INFO
#define MSG_TYPE_ITEM_INFO
Information related to items.
Definition: newclient.h:649
find_marked_object
object * find_marked_object(object *op)
Return the object the player has marked with the 'mark' command below.
Definition: c_object.cpp:1522
object::move_block
MoveType move_block
What movement types this blocks.
Definition: object.h:437
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:664
MAX_FOOD
static const int32_t MAX_FOOD
Definition: define.h:455
living::hp
int16_t hp
Hit Points.
Definition: living.h:40
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.cpp:287
FORCE
@ FORCE
Definition: object.h:229
alchemy
int alchemy(object *op, object *caster, object *spell_ob)
Change items to gold nuggets.
Definition: spell_effect.cpp:2306
HOLY_ALTAR
@ HOLY_ALTAR
Definition: object.h:166
TRAPDOOR
@ TRAPDOOR
Definition: object.h:215
create_aura
int create_aura(object *op, object *caster, object *spell)
Create an aura spell object and put it in the player's inventory.
Definition: spell_effect.cpp:3327
object.h
llevDebug
@ llevDebug
Only for debugging purposes.
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:142
SP_WORD_OF_RECALL
#define SP_WORD_OF_RECALL
Definition: spells.h:92
cast_cone
int cast_cone(object *op, object *caster, int dir, object *spell)
Casts a cone spell.
Definition: spell_attack.cpp:297
is_true_undead
int is_true_undead(object *op)
Is the object a true undead?
Definition: player.cpp:3993
P_BLOCKSVIEW
#define P_BLOCKSVIEW
This spot blocks the player's view.
Definition: map.h:226
GATE
@ GATE
Definition: object.h:211
FORCE_NAME
#define FORCE_NAME
Definition: spells.h:169
living::Con
int8_t Con
Definition: living.h:36
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Item is identifiable (e.g.
Definition: define.h:261
player_update_bg_music
void player_update_bg_music(object *player)
Definition: sounds.cpp:170
living::Str
int8_t Str
Definition: living.h:36
ATNR_FEAR
#define ATNR_FEAR
Definition: attack.h:63
identify
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1449