Crossfire Server, Trunk
apply.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 #include "global.h"
20 
21 /* need math lib for double-precision and pow() in dragon_eat_flesh() */
22 #include <math.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "living.h"
27 #include "skills.h"
28 #include "sounds.h"
29 #include "spells.h"
30 #include "sproto.h"
31 #include "tod.h"
32 
33 static int apply_check_apply_restrictions(object *who, object *op, int aflags);
34 static int apply_check_personalized_blessings(object *who, const object *op);
35 static int apply_check_item_power(const object *who, const object *op, int aflags);
36 static int apply_check_owner(const object *who, const object *op, int aflags);
37 static void apply_update_ranged_skill(const object *who, object *op, int aflags);
38 
54 int transport_can_hold(const object *transport, const object *op, int nrof) {
55  return op->weight*nrof+transport->carrying <= transport->weight_limit;
56 }
57 
68 int should_director_abort(const object *op, const object *victim) {
69  int arch_flag, name_flag, race_flag;
70 
71  /* Never move doors, it messes things. */
72  if (victim->type == DOOR)
73  return 1;
74 
75  /* Get flags to determine what of arch, name, and race should be
76  * checked. This is stored in subtype, and is a bitmask, the LSB
77  * is the arch flag, the next is the name flag, and the last is
78  * the race flag. Also note, if subtype is set to zero, that also
79  * goes to defaults of all affecting it. Examples:
80  * subtype 1: only arch
81  * subtype 3: arch or name
82  * subtype 5: arch or race
83  * subtype 7: all three
84  */
85  if (op->subtype) {
86  arch_flag = op->subtype&1;
87  name_flag = op->subtype&2;
88  race_flag = op->subtype&4;
89  } else {
90  arch_flag = 1;
91  name_flag = 1;
92  race_flag = 1;
93  }
94  /* If the director has race set, only affect objects with a arch,
95  * name or race that matches.
96  */
97  if (op->race
98  && (!(victim->arch && arch_flag && victim->arch->name) || strcmp(op->race, victim->arch->name))
99  && (!(victim->name && name_flag) || strcmp(op->race, victim->name))
100  && (!(victim->race && race_flag) || strcmp(op->race, victim->race)))
101  return 1;
102 
103  /* If the director has slaying set, only affect objects where none
104  * of arch, name, or race match.
105  */
106  if (op->slaying
107  && ((victim->arch && arch_flag && victim->arch->name && !strcmp(op->slaying, victim->arch->name))
108  || (victim->name && name_flag && !strcmp(op->slaying, victim->name))
109  || (victim->race && race_flag && !strcmp(op->slaying, victim->race))))
110  return 1;
111 
112  return 0;
113 }
114 
122 void apply_handle_yield(object *tmp) {
123  const char *yield;
124 
125  yield = object_get_value(tmp, "on_use_yield");
126  if (yield != NULL) {
127  object *drop = create_archetype(yield);
128  if (tmp->env)
129  drop = object_insert_in_ob(drop, tmp->env);
130  else
132  }
133 }
134 
146 int set_object_face_main(object *op) {
147  const Face *newface = op->arch->clone.face;
148  sstring saved = object_get_value(op, "face_closed");
149 
150  if (op->more)
151  set_object_face_main(op->more);
152 
153  if (saved)
154  newface = try_find_face(saved, newface);
155  if (newface && op->face != newface) {
156  op->face = newface;
157  return TRUE;
158  }
159  return FALSE;
160 }
161 
173 static int set_object_face_other(object *op) {
174  sstring custom;
175  const Face *newface = NULL;
176  object *head = op->head ? op->head : op;
177 
178  if (op->more)
179  set_object_face_other(op->more);
180 
181  if (head->face && head->other_arch && head->other_arch->clone.face)
182  newface = head->other_arch->clone.face;
183 
184  if (op->face != op->arch->clone.face) {
185  /* object has a custom face, save it so it gets correctly restored later. */
186  object_set_value(op, "face_closed", op->face->name, 1);
187  }
188 
189  custom = object_get_value(head, "face_opened");
190  if (custom)
191  newface = try_find_face(custom, newface);
192  if (newface && op->face != newface) {
193  op->face = newface;
194  return TRUE;
195  }
196  return FALSE;
197 }
198 
222 int apply_container(object *op, object *sack, int aflags) {
223  char name_sack[MAX_BUF], name_tmp[MAX_BUF];
224  object *tmp = op->container;
225 
226  if (op->type != PLAYER)
227  return 0; /* This might change */
228 
229  if (sack == NULL || sack->type != CONTAINER) {
230  LOG(llevError, "apply_container: '%s' tried to apply %s, which is not a container\n", op->name, sack ? sack->name : "(null)");
231  return 0;
232  }
233 
234  if (sack->head)
235  sack = sack->head;
236 
237  query_name(sack, name_sack, MAX_BUF);
238 
239  if ( aflags == AP_APPLY || aflags == AP_UNAPPLY || aflags == AP_OPEN ) {
240  // What if the container isn't in the player's inventory?
241  if ( sack->env != op ) {
243  "Not in your inventory: %s",
244  name_sack);
245  return 0;
246  }
247  }
248  if ( aflags == AP_APPLY ) {
249  // What if the container is open? Make it just ready!
250  if ( op->container == sack ) {
251  op->container = NULL;
252  if (op->contr != NULL)
253  op->contr->socket->container_position = 0;
254  CLEAR_FLAG(sack, FLAG_APPLIED);
256  "You readied %s.",
257  name_sack);
258  SET_FLAG(sack, FLAG_APPLIED);
259  // FIXME: This is not flipping the face!
260  if (set_object_face_main(sack)) // change image to closed
262  else
263  esrv_update_item(UPD_FLAGS, op, sack);
264  return 0;
265  }
266  // What if the container is already applied? Do nothing!
267  if (QUERY_FLAG(sack, FLAG_APPLIED)) {
269  "Already readied %s.",
270  name_sack);
271  return 0;
272  }
273  // What if the container is closed? Same as no aflags.
274  aflags = AP_NULL;
275  }
276 
277  if ( aflags == AP_OPEN ) {
278  // What if the container is already open?
279  if ( op->container == sack ) {
281  "Already opened %s.",
282  name_sack);
283  return 0;
284  }
285  // Set the container as applied and then proceed as if no special flags
286  SET_FLAG(sack, FLAG_APPLIED);
287  aflags = AP_NULL;
288  }
289 
290  if ( aflags == AP_UNAPPLY ) {
291  // If not open, two cases:
292  if ( op->container != sack ) {
293  if (QUERY_FLAG(sack, FLAG_APPLIED)) {
294  CLEAR_FLAG(sack, FLAG_APPLIED);
296  "You closed %s.",
297  name_sack);
298  esrv_update_item(UPD_FLAGS, op, sack);
299  return 0;
300  }
301  else {
303  "Already closed %s.",
304  name_sack);
305  return 0;
306  }
307  }
308  // open; same as no special flags
309  aflags = AP_NULL;
310  }
311 
312  /* If we have a currently open container, then it needs
313  * to be closed in all cases if we are opening this one up.
314  * We then fall through if appropriate for opening the new
315  * container.
316  */
317  if (op->container && QUERY_FLAG(op->container, FLAG_APPLIED) &&
318  (QUERY_FLAG(sack, FLAG_APPLIED) || sack->env != op) )
319  {
320  tag_t tmp_tag = op->container->count;
321 
322  if (op->container->env != op) { /* if container is on the ground */
323  object *part = op->container->head ? op->container->head : op->container;
324  while (part) {
325  part->move_off = 0;
326  part = part->more;
327  }
328  }
329 
330  /* Query name before the close event, as the container could be destroyed. */
331  query_name(op->container, name_tmp, MAX_BUF);
332 
334  return 1;
335 
338  "You close %s.",
339  name_tmp);
340 
341  op->container = NULL;
342  if (op->contr != NULL)
343  op->contr->socket->container_position = 0;
344 
345  /* The container may have been destroyed by the event handler. */
346  if (!object_was_destroyed(tmp, tmp_tag)) {
350  else
352  }
353  if (tmp == sack)
354  return 1;
355  }
356 
357  /* If the player is trying to open it (which he must be doing
358  * if we got here), and it is locked, check to see if player
359  * has the equipment to open it.
360  */
361 
362  if (sack->slaying) { /* it's locked */
363  tmp = find_key(op, op, sack);
364  if (tmp) {
365  query_name(tmp, name_tmp, MAX_BUF);
368  "You unlock %s with %s.",
369  name_sack, name_tmp);
370  } else {
373  "You don't have the key to unlock %s.",
374  name_sack);
375  return 0;
376  }
377  }
378 
379  /* By the time we get here, we have made sure any other container
380  * has been closed and if this is a locked container, the player
381  * has the key to open it.
382  */
383 
384  /* There are really two cases - the sack is either on the ground,
385  * or the sack is part of the player's inventory. If on the ground,
386  * we assume that the player is opening it, since if it was being
387  * closed, that would have been taken care of above.
388  */
389 
390 
391  if (sack->env != op) {
392  /* Hypothetical case - the player is trying to open a sack
393  * that belongs to someone else. This normally should not
394  * happen, but a misbehaving client/player could
395  * try to do it, so let's handle it gracefully.
396  */
397  if (sack->env) {
399  "You can't open %s",
400  name_sack);
401  return 0;
402  }
403 
404  if (sack->nrof > 1) {
405  object *left = object_split(sack, sack->nrof-1, NULL, 0);
406 
407  object_insert_in_map_at(left, sack->map, NULL, INS_NO_MERGE, sack->x, sack->y);
408  /* recompute the name so it's nice */
409  query_name(sack, name_sack, MAX_BUF);
410  }
411 
412  /* set it so when the player walks off, we can unapply the sack */
413  {
414  object *part = sack->head ? sack->head : sack;
415  while (part) {
416  part->move_off = MOVE_ALL;
417  part = part->more;
418  }
419  }
420 
421  CLEAR_FLAG(sack, FLAG_APPLIED);
423  "You open %s.",
424  name_sack);
425  SET_FLAG(sack, FLAG_APPLIED);
426  op->container = sack;
427  if (op->contr != NULL)
428  op->contr->socket->container_position = 0;
429 
430  if (set_object_face_other(sack))
432  else
433  esrv_update_item(UPD_FLAGS, op, sack);
434  esrv_send_inventory(op, sack);
435  } else { /* sack is in players inventory */
436  if (QUERY_FLAG(sack, FLAG_APPLIED)) { /* readied sack becoming open */
437  CLEAR_FLAG(sack, FLAG_APPLIED);
439  "You open %s.",
440  name_sack);
441  SET_FLAG(sack, FLAG_APPLIED);
442  op->container = sack;
443  if (op->contr != NULL)
444  op->contr->socket->container_position = 0;
445 
446  if (set_object_face_other(sack))
448  else
449  esrv_update_item(UPD_FLAGS, op, sack);
450  esrv_send_inventory(op, sack);
451  } else {
452  object *left = NULL;
453 
454  if (sack->nrof > 1)
455  left = object_split(sack, sack->nrof-1, NULL, 1);
456 
457  CLEAR_FLAG(sack, FLAG_APPLIED);
459  "You readied %s.",
460  name_sack);
461  SET_FLAG(sack, FLAG_APPLIED);
462  esrv_update_item(UPD_FLAGS, op, sack);
463 
464  if (left) {
465  object_insert_in_ob(left, sack->env);
466  esrv_send_item(op, left);
467  }
468  }
469  }
470  return 1;
471 }
472 
484 void do_learn_spell(object *op, object *spell, int special_prayer) {
485  object *tmp;
486 
487  if (op->type != PLAYER) {
488  LOG(llevError, "BUG: do_learn_spell(): not a player\n");
489  return;
490  }
491 
492  /* Upgrade special prayers to normal prayers */
493  tmp = check_spell_known(op, spell->name);
494  if (tmp != NULL) {
495  if (special_prayer && !QUERY_FLAG(tmp, FLAG_STARTEQUIP)) {
496  LOG(llevError, "BUG: do_learn_spell(): spell already known, but not marked as startequip\n");
497  return;
498  }
499  return;
500  }
501 
502  play_sound_player_only(op->contr, SOUND_TYPE_SPELL, spell, 0, "learn");
503  tmp = object_new();
506 
507  if (special_prayer)
509 
511  "Type 'bind cast %s to store the spell in a key.",
512  spell->name);
513 
514  esrv_add_spells(op->contr, tmp);
515 }
516 
525 void do_forget_spell(object *op, const char *spell) {
526  object *spob;
527 
528  if (op->type != PLAYER) {
529  LOG(llevError, "BUG: do_forget_spell(): not a player\n");
530  return;
531  }
532  spob = check_spell_known(op, spell);
533  if (spob == NULL) {
534  LOG(llevError, "BUG: do_forget_spell(): spell not known\n");
535  return;
536  }
537 
539  "You lose knowledge of %s.",
540  spell);
541  player_unready_range_ob(op->contr, spob);
542  esrv_remove_spell(op->contr, spob);
543  object_remove(spob);
544  object_free(spob, 0);
545 }
546 
557 static int apply_check_race_restrictions(object *who, object *item) {
558  char buf[MAX_BUF];
559  sstring restriction;
560 
561  if (who->type != PLAYER || QUERY_FLAG(who, FLAG_WIZ))
562  return 1;
563 
564  restriction = object_get_value(item, "race_restriction");
565  if (!restriction)
566  return 1;
567 
568  snprintf(buf, sizeof(buf), ":%s:", who->race);
569  buf[sizeof(buf)-1] = '\0';
570 
571  if (strstr(restriction, buf) != NULL)
572  return 1;
573 
574  query_name(item, buf, sizeof(buf));
575  draw_ext_info_format(NDI_UNIQUE, 0, who, MSG_TYPE_APPLY, MSG_TYPE_APPLY_PROHIBITION, "Somehow you can't seem to use the %s.", buf);
576 
577  return 0;
578 }
579 
597 int apply_manual(object *op, object *tmp, int aflag) {
598  tmp = HEAD(tmp);
599 
601  if (op->type == PLAYER) {
603  "You should pay for it first.");
604  return METHOD_SILENT_ERROR;
605  }
606  return 0; /* monsters just skip unpaid items */
607  }
608 
610  return METHOD_SILENT_ERROR;
611 
612  if (op->contr)
613  play_sound_player_only(op->contr, SOUND_TYPE_ITEM, tmp, 0, "apply");
614 
615  return ob_apply(tmp, op, aflag);
616 }
617 
637 int apply_by_living(object *pl, object *op, int aflag, int quiet) {
638  int tmp;
639 
640  if (op->env == NULL && (pl->move_type&MOVE_FLYING)) {
641  /* player is flying and applying object not in inventory */
642  if (!QUERY_FLAG(pl, FLAG_WIZ) && !(op->move_type&MOVE_FLYING)) {
644  "But you are floating high above the ground!");
645  return 0;
646  }
647  }
648 
649  /* Check for PLAYER to avoid a DM to disappear in a puff of smoke if
650  * applied.
651  */
652  if (op->type != PLAYER
654  && !QUERY_FLAG(pl, FLAG_WAS_WIZ)) {
655  play_sound_map(SOUND_TYPE_ITEM, op, 0, "evaporate");
657  "The object disappears in a puff of smoke!");
659  "It must have been an illusion.");
660  object_remove(op);
661  object_free(op, 0);
662  return 1;
663  }
664 
665  tmp = apply_manual(pl, op, aflag);
666  if (!quiet) {
667  if (tmp == METHOD_UNHANDLED) {
668  char name[MAX_BUF];
669 
672  "I don't know how to apply the %s.",
673  name);
674  } else if (tmp == METHOD_ERROR)
676  "You must get it first!\n");
677  else if (tmp == METHOD_SILENT_ERROR)
678  return tmp;
679  }
680  if (tmp == METHOD_OK) {
681  if (op->anim_suffix != NULL)
682  apply_anim_suffix(pl, op->anim_suffix);
683  }
684  return tmp;
685 }
686 
695 void apply_by_living_below(object *pl) {
696  object *tmp;
697  int floors;
698 
699  if (pl->contr->transport && pl->contr->transport->type == TRANSPORT) {
700  ob_apply(pl->contr->transport, pl, 0);
701  return;
702  }
703 
704  /* If using a container, set the starting item to be the top
705  * item in the container. Otherwise, use the map.
706  */
707  tmp = pl->container != NULL ? pl->container->inv : pl->below;
708 
709  /* This is perhaps more complicated. However, I want to make sure that
710  * we don't use a corrupt pointer for the next object, so we get the
711  * next object in the stack before applying. This is can only be a
712  * problem if apply_by_living() has a bug in that it uses the object but
713  * does not return a proper value.
714  */
715  floors = 0;
718  floors++;
719  else if (floors > 0)
720  return; /* process only floor objects after first floor object */
721 
722  /* If it is visible, player can apply it. If it is applied by
723  * person moving on it, also activate. Added code to make it
724  * so that at least one of players movement types be that which
725  * the item needs.
726  */
727  if (!tmp->invisible || (tmp->move_on&pl->move_type)) {
728  if (apply_by_living(pl, tmp, 0, 1) == METHOD_OK)
729  return;
730  }
731  if (floors >= 2)
732  return; /* process at most two floor objects */
734 }
735 
751 static int unapply_special(object *who, object *op, int aflags) {
752  char name[MAX_BUF];
753 
754  if (op->type != LAMP)
757  switch (op->type) {
758  case WEAPON:
759  if (!(aflags&AP_NOPRINT))
761  "You unwield %s.",
762  name);
763  (void)change_abil(who, op);
765  who->current_weapon = NULL;
766  clear_skill(who);
767  break;
768 
769  case SKILL: /* allows objects to impart skills */
770  case SKILL_TOOL:
771  if (op != who->chosen_skill)
772  LOG(llevError, "BUG: unapply_special(): applied skill is not a chosen skill\n");
773  if (who->type == PLAYER) {
774  if (who->contr->shoottype == range_skill)
775  who->contr->shoottype = range_none;
776  if (!op->invisible) {
777  if (!(aflags&AP_NOPRINT))
779  "You stop using the %s.",
780  name);
781  } else {
782  if (!(aflags&AP_NOPRINT))
784  "You can no longer use the skill: %s.",
785  op->skill);
786  }
787  }
788  (void)change_abil(who, op);
789  who->chosen_skill = NULL;
791  break;
792 
793  case ARMOUR:
794  case HELMET:
795  case SHIELD:
796  case RING:
797  case BOOTS:
798  case GLOVES:
799  case AMULET:
800  case GIRDLE:
801  case BRACERS:
802  case CLOAK:
803  if (!(aflags&AP_NOPRINT))
805  "You unwear %s.",
806  name);
807  (void)change_abil(who, op);
808  break;
809 
810  case BOW:
811  case WAND:
812  case ROD:
813  clear_skill(who);
814  if (!(aflags&AP_NOPRINT))
816  "You unready %s.",
817  name);
818  if (who->type == PLAYER)
819  who->contr->shoottype = range_none;
820  else if (op->type == BOW)
822  else
824  break;
825 
826  case BUILDER:
827  if (!(aflags&AP_NOPRINT))
829  "You unready %s.",
830  name);
831  who->contr->shoottype = range_none;
832  who->contr->ranges[range_builder] = NULL;
833  break;
834 
835  default:
836  if (!(aflags&AP_NOPRINT))
838  "You unapply %s.",
839  name);
840  break;
841  }
842 
843  fix_object(who);
844 
845  if (!(aflags&AP_NO_MERGE)) {
846  object *tmp;
847 
848  tmp = object_merge(op, NULL);
849  if (who->type == PLAYER) {
850  if (tmp) { /* it was merged */
851  op = tmp;
852  }
854  }
855  }
856  return 0;
857 }
858 
878 static object *get_item_from_body_location(object *start, int loc) {
879  object *tmp;
880 
881  if (!start)
882  return NULL;
883 
884  tmp = start;
887  && tmp->body_info[loc]
888  && (!tmp->invisible || tmp->type == SKILL))
889  return tmp;
891  return NULL;
892 }
893 
915 static int unapply_for_ob(object *who, object *op, int aflags) {
916  int i;
917  object *tmp = NULL, *last;
918  char name[MAX_BUF];
919 
920  /* If we are applying a shield or weapon, unapply any equipped shield
921  * or weapons first - only allowed to use one weapon/shield at a time.
922  */
923  if (op->type == WEAPON || op->type == SHIELD) {
925  if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == op->type) {
926  if (!(aflags&AP_IGNORE_CURSE)
927  && !(aflags&AP_PRINT)
929  /* In this case, we want to try and remove a
930  * cursed item. While we know it won't work, we
931  * want unapply_special to at least generate the
932  * message.
933  */
934  if (!(aflags&AP_NOPRINT)) {
937  "No matter how hard you try, you just can't remove %s.",
938  name);
939  }
940  return 1;
941  }
942 
943  if (aflags&AP_PRINT) {
946  name);
947  } else
948  unapply_special(who, tmp, aflags);
949  }
950  } FOR_INV_FINISH();
951  }
952 
953  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
954  /* this used up a slot that we need to free */
955  if (op->body_info[i]) {
956  last = who->inv;
957 
958  /* We do a while loop - may need to remove several items
959  * in order to free up enough slots.
960  */
961  while (who->body_used[i]+op->body_info[i] < 0) {
962  tmp = get_item_from_body_location(last, i);
963  if (!tmp)
964  return 1;
965 
966  /* If just printing, we don't care about cursed status */
967  if ((aflags&AP_IGNORE_CURSE)
968  || (aflags&AP_PRINT)
970  if (aflags&AP_PRINT) {
973  name);
974  } else
975  unapply_special(who, tmp, aflags);
976  } else {
977  /* Cursed item that we can't unequip - tell the player.
978  * Note this could be annoying if this is just one of a
979  * few, so it may not be critical (eg, putting on a
980  * ring and you have one cursed ring.)
981  */
982  if (!(aflags&AP_NOPRINT)) {
985  "The %s just won't come off",
986  name);
987  }
988  }
989  last = tmp->below;
990  }
991  /* if we got here, this slot is freed up - otherwise, if it
992  * wasn't freed up, the return in the !tmp would have
993  * kicked in.
994  */
995  } /* if op is using this body location */
996  } /* for body locations */
997  return 0;
998 }
999 
1016 int apply_can_apply_object(const object *who, const object *op) {
1017  int i, retval = 0;
1018  object *tmp = NULL, *ws = NULL;
1019 
1020  /* Players have 2 'arm's, so they could in theory equip 2 shields or
1021  * 2 weapons, but we don't want to let them do that. So if they are
1022  * trying to equip a weapon or shield, see if they already have one
1023  * in place and store that way.
1024  */
1025  if (op->type == WEAPON || op->type == SHIELD) {
1027  if (tmp != NULL) {
1028  retval = CAN_APPLY_UNAPPLY;
1029  ws = tmp;
1030  }
1031  }
1032 
1033  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
1034  if (op->body_info[i]) {
1035  /* Item uses more slots than we have */
1036  if (FABS(op->body_info[i]) > who->body_info[i]) {
1037  /* Could return now for efficiently - rest of info
1038  * below isn't really needed.
1039  */
1040  retval |= CAN_APPLY_NEVER;
1041  } else if (who->body_used[i]+op->body_info[i] < 0) {
1042  /* in this case, equipping this would use more free
1043  * spots than we have.
1044  */
1045  object *tmp1;
1046 
1047  /* if we have an applied weapon/shield, and unapply
1048  * it would free enough slots to equip the new item,
1049  * then just set this can continue. We don't care
1050  * about the logic below - if you have shield equipped
1051  * and try to equip another shield, there is only one
1052  * choice. However, the check for the number of body
1053  * locations does take into the account cases where what
1054  * is being applied may be two handed for example.
1055  */
1056  if (ws) {
1057  if (who->body_used[i]-ws->body_info[i]+op->body_info[i] >= 0) {
1058  retval |= CAN_APPLY_UNAPPLY;
1059  continue;
1060  }
1061  }
1062 
1063  tmp1 = get_item_from_body_location(who->inv, i);
1064  if (!tmp1)
1065  retval |= CAN_APPLY_NEVER;
1066  else {
1067  /* need to unapply something. However, if this
1068  * something is different than we had found before,
1069  * it means they need to apply multiple objects
1070  */
1071  retval |= CAN_APPLY_UNAPPLY;
1072  if (!tmp)
1073  tmp = tmp1;
1074  else if (tmp != tmp1)
1075  retval |= CAN_APPLY_UNAPPLY_MULT;
1076  /* This object isn't using up all the slots, so
1077  * there must be another. If so, and if the new
1078  * item doesn't need all the slots, the player
1079  * then has a choice.
1080  */
1081  if (who->body_used[i]-tmp1->body_info[i] != who->body_info[i]
1082  && FABS(op->body_info[i]) < who->body_info[i])
1083  retval |= CAN_APPLY_UNAPPLY_CHOICE;
1084 
1085  /* Does unequipping 'tmp1' free up enough slots
1086  * for this to be equipped? If not, there must
1087  * be something else to unapply.
1088  */
1089  if (who->body_used[i]+op->body_info[i]-tmp1->body_info[i] < 0)
1090  retval |= CAN_APPLY_UNAPPLY_MULT;
1091  }
1092  } /* if not enough free slots */
1093  } /* if this object uses location i */
1094  } /* for i -> num_body_locations loop */
1095 
1096  /* Do checks for can_use_weapon/shield/armour. */
1098  retval |= CAN_APPLY_RESTRICTION;
1100  retval |= CAN_APPLY_RESTRICTION;
1102  retval |= CAN_APPLY_RESTRICTION;
1103 
1104  if (who->type != PLAYER) {
1105  if ((op->type == WAND || op->type == ROD)
1107  retval |= CAN_APPLY_RESTRICTION;
1108  if (op->type == BOW && !QUERY_FLAG(who, FLAG_USE_BOW))
1109  retval |= CAN_APPLY_RESTRICTION;
1110  if (op->type == RING && !QUERY_FLAG(who, FLAG_USE_RING))
1111  retval |= CAN_APPLY_RESTRICTION;
1112  }
1113  return retval;
1114 }
1115 
1131 int apply_check_weapon_power(const object *who, int improves) {
1132  return (who->level/5)+5 >= improves;
1133 }
1134 
1156 int apply_special(object *who, object *op, int aflags) {
1157  int basic_flag = aflags&AP_BASIC_FLAGS;
1158  object *tmp, *skop;
1159  char name_op[MAX_BUF];
1160 
1161  if (who == NULL) {
1162  LOG(llevError, "apply_special() from object without environment.\n");
1163  return 1;
1164  }
1165 
1166  if (op->env != who)
1167  return 1; /* op is not in inventory */
1168 
1169  /* trying to unequip op */
1170  if (QUERY_FLAG(op, FLAG_APPLIED)) {
1171  /* always apply, so no reason to unapply */
1172  if (basic_flag == AP_APPLY)
1173  return 0;
1174 
1175  if (!(aflags&AP_IGNORE_CURSE)
1177  if (!(aflags&AP_NOPRINT)) {
1178  query_name(op, name_op, MAX_BUF);
1180  "No matter how hard you try, you just can't remove %s.",
1181  name_op);
1182  }
1183  return 1;
1184  }
1185  return unapply_special(who, op, aflags);
1186  }
1187 
1188  if (basic_flag == AP_UNAPPLY)
1189  return 0;
1190 
1191  if (!apply_check_apply_restrictions(who, op, aflags))
1192  return 1;
1193 
1194  if (op->skill && op->type != SKILL && op->type != SKILL_TOOL) {
1195  skop = find_skill_by_name(who, op->skill);
1196  if (!skop) {
1197  if (!(aflags&AP_NOPRINT))
1199  "You need the %s skill to use this item!",
1200  op->skill);
1201  if (who->type == PLAYER)
1202  return 1;
1203 
1204  /* monsters do not care about missing skills */
1205  } else
1206  /* While experience will be credited properly, we want to
1207  * change the skill so that the dam and wc get updated
1208  */
1209  change_skill(who, skop, (aflags&AP_NOPRINT));
1210  } else
1211  skop = NULL;
1212 
1213  if (!apply_check_item_power(who, op, aflags))
1214  return 1;
1215 
1217  return 1;
1218 
1219  /* Ok. We are now at the state where we can apply the new object.
1220  * Note that we don't have the checks for can_use_...
1221  * below - that is already taken care of by apply_can_apply_object().
1222  */
1223 
1224  tmp = op->nrof <= 1 ? NULL : object_split(op, op->nrof-1, NULL, 0);
1225 
1226  switch (op->type) {
1227  case WEAPON:
1228  if (!apply_check_weapon_power(who, op->last_eat)) {
1229  if (!(aflags&AP_NOPRINT))
1231  "That weapon is too powerful for you to use. It would consume your soul!");
1232  if (tmp != NULL)
1234  return 1;
1235  }
1236 
1237  if (!apply_check_owner(who, op, aflags)) {
1238  if (tmp != NULL)
1240  return 1;
1241  }
1242 
1244 
1245  if (skop)
1246  change_skill(who, skop, 1);
1248 
1249  if (!(aflags&AP_NOPRINT)) {
1250  query_name(op, name_op, MAX_BUF);
1252  "You wield %s.",
1253  name_op);
1254  }
1255 
1256  (void)change_abil(who, op);
1257  break;
1258 
1259  case ARMOUR:
1260  case HELMET:
1261  case SHIELD:
1262  case BOOTS:
1263  case GLOVES:
1264  case GIRDLE:
1265  case BRACERS:
1266  case CLOAK:
1267  case RING:
1268  case AMULET:
1270  if (!(aflags&AP_NOPRINT)) {
1271  query_name(op, name_op, MAX_BUF);
1273  "You wear %s.",
1274  name_op);
1275  }
1276  (void)change_abil(who, op);
1277  break;
1278 
1279  /* this part is needed for skill-tools */
1280  case SKILL:
1281  case SKILL_TOOL:
1282  if (who->chosen_skill) {
1283  LOG(llevError, "BUG: apply_special(): can't apply two skills\n");
1284  return 1;
1285  }
1286 
1287  apply_update_ranged_skill(who, op, aflags);
1289  (void)change_abil(who, op);
1290  who->chosen_skill = op;
1292  break;
1293 
1294  case BOW:
1295  if (!apply_check_weapon_power(who, op->last_eat)) {
1296  if (!(aflags&AP_NOPRINT))
1298  "That weapon is too powerful for you to use. It would consume your soul!");
1299  if (tmp != NULL)
1301  return 1;
1302  }
1303 
1304  if (!apply_check_owner(who, op, aflags)) {
1305  if (tmp != NULL)
1307  return 1;
1308  }
1309  /*FALLTHROUGH*/
1310  case WAND:
1311  case ROD:
1312  /* check for skill, alter player status */
1314  if (skop)
1315  change_skill(who, skop, 0);
1316  if (!(aflags&AP_NOPRINT)) {
1317  query_name(op, name_op, MAX_BUF);
1319  "You ready %s.",
1320  name_op);
1321  }
1322  if (who->type == PLAYER) {
1323  if (op->type == BOW) {
1324  (void)change_abil(who, op);
1325  if (!(aflags&AP_NOPRINT)) {
1326  query_name(op, name_op, MAX_BUF);
1328  "You will now fire %s with %s.",
1329  op->race ? op->race : "nothing",
1330  name_op);
1331  }
1332  who->contr->shoottype = range_bow;
1333  } else
1334  who->contr->shoottype = range_misc;
1335  } else {
1336  if (op->type == BOW)
1338  else
1340  }
1341  break;
1342 
1343  case BUILDER:
1344  if (who->contr->ranges[range_builder])
1345  unapply_special(who, who->contr->ranges[range_builder], 0);
1346  who->contr->shoottype = range_builder;
1347  who->contr->ranges[range_builder] = op;
1348  if (!(aflags&AP_NOPRINT)) {
1349  query_name(op, name_op, MAX_BUF);
1351  "You ready your %s.",
1352  name_op);
1353  }
1354  break;
1355 
1356  default:
1357  query_name(op, name_op, MAX_BUF);
1359  "You apply %s.",
1360  name_op);
1361  break;
1362  } /* end of switch op->type */
1363 
1365 
1366  if (tmp != NULL)
1368 
1369  fix_object(who);
1370 
1371  /* We exclude spell casting objects. The fire code will set the
1372  * been applied flag when they are used - until that point,
1373  * you don't know anything about them.
1374  */
1375  if (who->type == PLAYER && op->type != WAND && op->type != ROD)
1377 
1379  if (who->type == PLAYER) {
1381  "Oops, it feels deadly cold!");
1383  }
1384  }
1385  if (who->type == PLAYER)
1387  return 0;
1388 }
1389 
1400 int apply_auto(object *op) {
1401  object *tmp;
1402 
1403  switch (op->type) {
1404  case SHOP_FLOOR:
1405  if (!HAS_RANDOM_ITEMS(op))
1406  return 0;
1407  do {
1408  int i;
1409 
1410  i = 10; /* let's give it 10 tries */
1411  while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5))) == NULL
1412  && --i)
1413  ;
1414  if (tmp == NULL)
1415  return 0;
1418  tmp = NULL;
1419  }
1420  } while (!tmp);
1423  if (is_magical(tmp)) {
1425  }
1426  object_insert_in_map_at(tmp, op->map, NULL, 0, op->x, op->y);
1428  identify(tmp);
1429  return 1;
1430  break;
1431 
1432  case TREASURE:
1434  return 0;
1435  while (op->stats.hp-- > 0)
1436  create_treasure(op->randomitems, op, (op->map ? GT_ENVIRONMENT : 0) | (QUERY_FLAG(op, FLAG_BLESSED) ? GT_ONLY_GOOD : 0), op->stats.exp ? (int)op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
1437 
1438  /* If we generated an object and put it in this object's
1439  * inventory, move it to the parent object as the current
1440  * object is about to disappear. An example of this item
1441  * is the random_ *stuff that is put inside other objects.
1442  */
1443  FOR_INV_PREPARE(op, tmp) {
1444  object_remove(tmp);
1445  if (op->env)
1446  object_insert_in_ob(tmp, op->env);
1447  else
1449  } FOR_INV_FINISH();
1450  object_remove(op);
1452  break;
1453  }
1454  return 0;
1455 }
1456 
1469 static void auto_apply_fix_inventory(mapstruct *m, object *tmp)
1470 {
1471  if (!tmp->inv)
1472  return;
1473  FOR_INV_PREPARE(tmp, invtmp) {
1474  if (invtmp->inv)
1475  auto_apply_fix_inventory(m,invtmp); // Recurse for containers in objects
1476  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
1477  apply_auto(invtmp);
1478  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
1479  while (invtmp->stats.hp-- > 0)
1480  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
1481  invtmp->randomitems = NULL;
1482  } else if (invtmp && invtmp->arch
1483  && invtmp->type != TREASURE
1484  && invtmp->type != SPELL
1485  && invtmp->type != CLASS
1486  && HAS_RANDOM_ITEMS(invtmp)) {
1487  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
1488  /* Need to clear this so that we never try to
1489  * create treasure again for this object
1490  */
1491  invtmp->randomitems = NULL;
1492  }
1493  } FOR_INV_FINISH();
1494  /* This is really temporary - the code at the
1495  * bottom will also set randomitems to null.
1496  * The problem is there are bunches of maps/players
1497  * already out there with items that have spells
1498  * which haven't had the randomitems set
1499  * to null yet.
1500  * MSW 2004-05-13
1501  *
1502  * And if it's a spellbook, it's better to set
1503  * randomitems to NULL too, else you get two spells
1504  * in the book ^_-
1505  * Ryo 2004-08-16
1506  */
1507  if (tmp->type == WAND
1508  || tmp->type == ROD
1509  || tmp->type == SCROLL
1510  || tmp->type == FIREWALL
1511  || tmp->type == POTION
1512  || tmp->type == ALTAR
1513  || tmp->type == SPELLBOOK)
1514  tmp->randomitems = NULL;
1515 }
1516 
1528  int x, y;
1529 
1530  if (m == NULL)
1531  return;
1532 
1533  for (x = 0; x < MAP_WIDTH(m); x++)
1534  for (y = 0; y < MAP_HEIGHT(m); y++)
1535  FOR_MAP_PREPARE(m, x, y, tmp) {
1536  if (tmp->inv) {
1538  }
1540  apply_auto(tmp);
1541  else if ((tmp->type == TREASURE || tmp->type == CONTAINER)
1542  && HAS_RANDOM_ITEMS(tmp)) {
1543  while (tmp->stats.hp-- > 0)
1544  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
1545  tmp->randomitems = NULL;
1546  } else if (tmp->type == TIMED_GATE) {
1547  object *head = HEAD(tmp);
1548 
1549  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
1550  tmp->speed = 0;
1552  }
1553  }
1554  /* This function can be called every time a map is loaded,
1555  * even when swapping back in. As such, we don't want to
1556  * create the treasure over and over again, so after we
1557  * generate the treasure, blank out randomitems so if it
1558  * is swapped in again, it won't make anything. This is a
1559  * problem for the above objects, because they have
1560  * counters which say how many times to make the treasure.
1561  */
1562  else if (tmp
1563  && tmp->arch
1564  && tmp->type != PLAYER
1565  && tmp->type != TREASURE
1566  && tmp->type != SPELL
1567  && tmp->type != PLAYER_CHANGER
1568  && tmp->type != CLASS
1569  && HAS_RANDOM_ITEMS(tmp)) {
1570  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
1571  tmp->randomitems = NULL;
1572  }
1573 
1574  if (QUERY_FLAG(tmp, FLAG_MONSTER))
1576  } FOR_MAP_FINISH();
1577 
1578  for (x = 0; x < MAP_WIDTH(m); x++)
1579  for (y = 0; y < MAP_HEIGHT(m); y++)
1580  FOR_MAP_PREPARE(m, x, y, tmp) {
1581  if (tmp->above
1582  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
1583  check_trigger(tmp, tmp->above);
1584  } FOR_MAP_FINISH();
1585 }
1586 
1601 void scroll_failure(object *op, int failure, int power) {
1602  if (abs(failure/4) > power)
1603  power = abs(failure/4); /* set minimum effect */
1604 
1605  if (failure <= -1 && failure > -15) {/* wonder */
1606  object *tmp;
1607 
1609  "Your spell warps!");
1611  cast_wonder(op, op, 0, tmp);
1612  if (op->stats.sp < 0)
1613  /* For some reason the sp can become negative here. */
1614  op->stats.sp = 0;
1616  return;
1617  }
1618 
1620  if (failure <= -35 && failure > -60) { /* confusion */
1622  "The magic recoils on you!");
1623  confuse_living(op, op, power);
1624  return;
1625  }
1626 
1627  if (failure <= -60 && failure > -70) {/* paralysis */
1629  "The magic recoils and paralyzes you!");
1630  paralyze_living(op, power);
1631  return;
1632  }
1633 
1634  if (failure <= -70 && failure > -80) {/* blind */
1636  "The magic recoils on you!");
1637  blind_living(op, op, power);
1638  return;
1639  }
1640 
1641  if (failure <= -80) {/* blast the immediate area */
1642  object *tmp;
1643 
1645  cast_magic_storm(op, tmp, power);
1647  "You unleash uncontrolled mana!");
1648  return;
1649  }
1650  }
1651  /* Either no spell failure on this server, or wrong values,
1652  * in any case let's punish.
1653  */
1655  "Your mana is drained!");
1656  op->stats.sp -= random_roll(0, power-1, op, PREFER_LOW);
1657  if (op->stats.sp < 0)
1658  op->stats.sp = 0;
1659 }
1660 
1672 void apply_changes_to_player(object *pl, object *change, int limit_stats) {
1673  int i, j;
1674  int excess_stat = 0; /* if the stat goes over the maximum
1675  * for the race, put the excess stat some
1676  * where else.
1677  */
1678 
1679  if (change->type != CLASS) return;
1680 
1681  /* the following code assigns stats up to the stat max
1682  * for the race, and if the stat max is exceeded,
1683  * tries to randomly reassign the excess stat
1684  */
1685  if (! (limit_stats & AC_PLAYER_STAT_NO_CHANGE)) {
1686  for (i = 0; i < NUM_STATS; i++) {
1687  int8_t stat = get_attr_value(&pl->contr->orig_stats, i);
1688  int race_bonus = get_attr_value(&pl->arch->clone.stats, i);
1689 
1690  stat += get_attr_value(&change->stats, i);
1691  if (limit_stats & AC_PLAYER_STAT_LIMIT) {
1692  if (stat > 20+race_bonus) {
1693  excess_stat++;
1694  stat = 20+race_bonus;
1695  } else if (stat < 1) {
1696  /* I didn't see any code here before to make sure minimum
1697  * stats were enforced - maybe it was just dumb
1698  * luck that one would not have a stat low enough that then
1699  * has a stat penalty for class that would bring it negative?
1700  * I imagine a negative stat would crash the server pretty
1701  * quickly - MSW, Sept 2010
1702  */
1703  excess_stat += stat;
1704  stat = 1;
1705  }
1706  }
1707  set_attr_value(&pl->contr->orig_stats, i, stat);
1708  }
1709 
1710  /* Maybe we should randomly deduct stats in this case?
1711  * It's will go away sometime soon in any case.
1712  */
1713  if (excess_stat < 0) excess_stat = 0;
1714 
1715  /* We don't put an explicit check for limit_stats here -
1716  * excess stat will never be 0 if limit_stats is not
1717  * true.
1718  */
1719  for (j = 0; excess_stat > 0 && j < 100; j++) {
1720  /* try 100 times to assign excess stats */
1721  int i = rndm(0, NUM_STATS-1);
1722  int stat = get_attr_value(&pl->contr->orig_stats, i);
1723  int race_bonus = get_attr_value(&pl->arch->clone.stats, i);
1724 
1725  if (i == CHARISMA) {
1726  continue; /* exclude cha from this */
1727  }
1728 
1729  if (stat < 20+race_bonus) {
1730  change_attr_value(&pl->contr->orig_stats, i, 1);
1731  excess_stat--;
1732  }
1733  }
1734  }
1735  /* Done with stat processing */
1736 
1737  /* insert the randomitems from the change's treasurelist into
1738  * the player ref: player.c
1739  */
1740  if (change->randomitems != NULL)
1741  give_initial_items(pl, change->randomitems);
1742 
1743 
1744  /* set up the face, for some races. */
1745 
1746  /* first, look for the force object banning changing the
1747  * face. Certain races never change face with class.
1748  */
1749  int has_noclassfacechange = (object_find_by_name(pl, "NOCLASSFACECHANGE") != NULL);
1750  const Animations *anim = NULL;
1751 
1752  if (change->anim_suffix) {
1753  char buf[MAX_BUF];
1754 
1755  snprintf(buf, MAX_BUF, "%s_%s", pl->animation->name, change->anim_suffix);
1757  if (anim) {
1758  pl->animation = anim;
1759  pl->anim_speed = -1;
1761  animate_object(pl, pl->facing);
1762  }
1763  }
1764  /* Check for anim == -1 so that we can override specific class faces for races.
1765  * This allows us to have custom class faces on the races that lack noclassfacechange
1766  *
1767  * Daniel Hawkins 2020-09-08
1768  */
1769  if ((!has_noclassfacechange) && anim == 0) {
1770  pl->animation = GET_ANIM(change);
1771  pl->face = change->face;
1772 
1773  if (QUERY_FLAG(change, FLAG_ANIMATE))
1775  else
1777  }
1778 
1779  /* Hard coding in class name is a horrible idea - lets
1780  * use the supported mechanism for this
1781  */
1782  if (object_present_in_ob_by_name(FORCE, "no weapon force", pl))
1784 
1785 }
1786 
1800 static int apply_check_apply_restrictions(object *who, object *op, int aflags) {
1801  int i;
1802 
1804  if (i == 0)
1805  return 1;
1806 
1807  /* Can't just apply this object. Lets see why not and what to do */
1808 
1809  if (i&CAN_APPLY_NEVER) {
1810  if (!(aflags&AP_NOPRINT)) {
1811  char name_op[MAX_BUF];
1812 
1813  query_name(op, name_op, MAX_BUF);
1815  "You don't have the body to use a %s",
1816  name_op);
1817  }
1818  return 0;
1819  }
1820 
1821  if (i&CAN_APPLY_RESTRICTION) {
1822  if (!(aflags&AP_NOPRINT)) {
1823  char name_op[MAX_BUF];
1824 
1825  query_name(op, name_op, MAX_BUF);
1827  "You have a prohibition against using a %s",
1828  name_op);
1829  }
1830  return 0;
1831  }
1832 
1833  if (who->type != PLAYER) {
1834  /* Some error, so don't try to equip something more */
1835  return !unapply_for_ob(who, op, aflags);
1836  }
1837 
1838  if (who->contr->unapply == unapply_never
1839  || (i&CAN_APPLY_UNAPPLY_CHOICE && who->contr->unapply == unapply_nochoice)) {
1840  if (!(aflags&AP_NOPRINT))
1842  "You need to unapply some item(s):");
1844  return 0;
1845  }
1846 
1847  if (who->contr->unapply == unapply_always
1848  || !(i&CAN_APPLY_UNAPPLY_CHOICE)) {
1849  return !unapply_for_ob(who, op, aflags);
1850  }
1851 
1852  return 1;
1853 }
1854 
1867 static int apply_check_item_power(const object *who, const object *op, int aflags) {
1868  if (who->type != PLAYER)
1869  return 1;
1870 
1871  if (op->item_power == 0
1872  || op->item_power+who->contr->item_power <= settings.item_power_factor*who->level)
1873  return 1;
1874 
1875  if (!(aflags&AP_NOPRINT))
1877  "Equipping that combined with other items would consume your soul!");
1878  return 0;
1879 }
1880 
1895 static int apply_check_personalized_blessings(object *who, const object *op) {
1896  const char *owner;
1897  const char *will;
1898  long item_will;
1899  long margin;
1900  const char *msg;
1901  int random_effect;
1902  int damage_percentile;
1903 
1905  return 1;
1906  }
1907 
1908  owner = object_get_value(op, "item_owner");
1909  if (owner == NULL || strcmp(owner, who->name) == 0)
1910  return 1;
1911 
1912  will = object_get_value(op, "item_willpower");
1913  item_will = will != NULL ? atol(will) : 0;
1914  if (item_will > who->stats.exp) {
1916  "This %s refuses to serve you - it keeps evading your hand !",
1917  op->name);
1918  return 0;
1919  }
1920 
1921  margin = item_will != 0 ? who->stats.exp/item_will : who->stats.exp;
1922  random_effect = random_roll(0, 100, who, 1)-margin*20;
1923  if (random_effect > 80) {
1924  msg = "You don't know why, but you have the feeling that the %s is angry at you !";
1925  damage_percentile = 60;
1926  } else if (random_effect > 60) {
1927  msg = "The %s seems to look at you nastily !";
1928  damage_percentile = 45;
1929  } else if (random_effect > 40) {
1930  msg = "You have the strange feeling that the %s is annoyed...";
1931  damage_percentile = 30;
1932  } else if (random_effect > 20) {
1933  msg = "The %s seems tired, or bored, in a way. Very strange !";
1934  damage_percentile = 15;
1935  } else if (random_effect > 0) {
1936  msg = "You hear the %s sighing !";
1937  damage_percentile = 0;
1938  } else {
1939  msg = NULL;
1940  damage_percentile = 0;
1941  }
1942  if (msg != NULL)
1944  msg, op->name);
1945  if (damage_percentile > 0) {
1946  int weapon_bite = (who->stats.hp*damage_percentile)/100;
1947  if (weapon_bite < 1)
1948  weapon_bite = 1;
1949  who->stats.hp -= weapon_bite;
1951  "You get a nasty bite in the hand !");
1952  }
1953 
1954  return 1;
1955 }
1956 
1971 static int apply_check_owner(const object *who, const object *op, int aflags) {
1972  const char *quotepos;
1973 
1974  if (op->level == 0)
1975  return 1;
1976 
1977  quotepos = strstr(op->name, "'");
1978  if (quotepos == NULL || strncmp(op->name, who->name, quotepos-op->name) == 0)
1979  return 1;
1980 
1981  if (!(aflags&AP_NOPRINT))
1983  "The weapon does not recognize you as its owner.");
1984  return 0;
1985 }
1986 
1997 static void apply_update_ranged_skill(const object *who, object *op, int aflags) {
1998  if (who->type != PLAYER) {
1999  return;
2000  }
2001 
2002  who->contr->shoottype = range_skill;
2003  who->contr->ranges[range_skill] = op;
2004  if (op->invisible) {
2005  if (!(aflags&AP_NOPRINT))
2007  "Readied skill: %s.",
2008  op->skill ? op->skill : op->name);
2009  } else {
2010  if (!(aflags&AP_NOPRINT)) {
2011  char name_op[MAX_BUF];
2012 
2013  query_name(op, name_op, MAX_BUF);
2015  "You ready %s.",
2016  name_op);
2018  "You can now use the skill: %s.",
2019  op->skill);
2020  }
2021  }
2022 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:70
paralyze_living
void paralyze_living(object *op, int dam)
Definition: attack.cpp:2397
CLASS
@ CLASS
Definition: object.h:143
FLAG_USE_BOW
#define FLAG_USE_BOW
Definition: define.h:293
HAS_RANDOM_ITEMS
#define HAS_RANDOM_ITEMS(op)
Definition: define.h:184
unapply_special
static int unapply_special(object *who, object *op, int aflags)
Definition: apply.cpp:751
PLAYER
@ PLAYER
Definition: object.h:112
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:536
UPD_FACE
#define UPD_FACE
Definition: newclient.h:306
settings
struct Settings settings
Definition: init.cpp:139
SOUND_TYPE_ITEM
#define SOUND_TYPE_ITEM
Definition: newclient.h:324
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
object_find_by_type_applied
object * object_find_by_type_applied(const object *who, int type)
Definition: object.cpp:4074
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:15
AP_APPLY
#define AP_APPLY
Definition: define.h:574
BOW
@ BOW
Definition: object.h:123
BRACERS
@ BRACERS
Definition: object.h:222
llevError
@ llevError
Definition: logger.h:11
FABS
#define FABS(x)
Definition: define.h:22
MOVE_ALL
#define MOVE_ALL
Definition: define.h:398
AP_NO_MERGE
#define AP_NO_MERGE
Definition: define.h:581
WAND
@ WAND
Definition: object.h:225
range_bow
@ range_bow
Definition: player.h:31
FLAG_USE_RING
#define FLAG_USE_RING
Definition: define.h:297
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
GLOVES
@ GLOVES
Definition: object.h:218
GIRDLE
@ GIRDLE
Definition: object.h:228
diamondslots.x
x
Definition: diamondslots.py:15
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
CAN_APPLY_NEVER
#define CAN_APPLY_NEVER
Definition: define.h:630
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
apply_special
int apply_special(object *who, object *op, int aflags)
Definition: apply.cpp:1156
confuse_living
void confuse_living(object *op, object *hitter, int dam)
Definition: attack.cpp:2310
clear_skill
void clear_skill(object *who)
Definition: skill_util.cpp:398
apply_check_apply_restrictions
static int apply_check_apply_restrictions(object *who, object *op, int aflags)
Definition: apply.cpp:1800
object_merge
object * object_merge(object *op, object *top)
Definition: object.cpp:2046
FALSE
#define FALSE
Definition: compat.h:14
esrv_send_inventory
void esrv_send_inventory(object *pl, object *op)
Definition: item.cpp:316
apply_check_owner
static int apply_check_owner(const object *who, const object *op, int aflags)
Definition: apply.cpp:1971
apply_check_race_restrictions
static int apply_check_race_restrictions(object *who, object *item)
Definition: apply.cpp:557
set_object_face_other
static int set_object_face_other(object *op)
Definition: apply.cpp:173
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:305
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:188
METHOD_OK
#define METHOD_OK
Definition: ob_methods.h:15
CAN_APPLY_RESTRICTION
#define CAN_APPLY_RESTRICTION
Definition: define.h:631
object::x
int16_t x
Definition: object.h:335
ARMOUR
@ ARMOUR
Definition: object.h:125
PREFER_LOW
#define PREFER_LOW
Definition: define.h:564
object::map
struct mapstruct * map
Definition: object.h:305
object::anim_suffix
sstring anim_suffix
Definition: object.h:324
WEAPON
@ WEAPON
Definition: object.h:124
TIMED_GATE
@ TIMED_GATE
Definition: object.h:133
MSG_TYPE_APPLY_CURSED
#define MSG_TYPE_APPLY_CURSED
Definition: newclient.h:594
apply_by_living
int apply_by_living(object *pl, object *op, int aflag, int quiet)
Definition: apply.cpp:637
LOOSE_MANA
#define LOOSE_MANA
Definition: spells.h:162
GT_ONLY_GOOD
@ GT_ONLY_GOOD
Definition: treasure.h:34
range_none
@ range_none
Definition: player.h:30
apply_changes_to_player
void apply_changes_to_player(object *pl, object *change, int limit_stats)
Definition: apply.cpp:1672
unapply_for_ob
static int unapply_for_ob(object *who, object *op, int aflags)
Definition: apply.cpp:915
CHARISMA
@ CHARISMA
Definition: living.h:15
AMULET
@ AMULET
Definition: object.h:144
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
Settings::spell_failure_effects
uint8_t spell_failure_effects
Definition: global.h:269
play_sound_player_only
void play_sound_player_only(player *pl, int8_t sound_type, object *emitter, int dir, const char *action)
Definition: sounds.cpp:51
TREASURE
@ TREASURE
Definition: object.h:115
SKILL
@ SKILL
Definition: object.h:148
play_sound_map
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
Definition: sounds.cpp:113
Ice.tmp
int tmp
Definition: Ice.py:207
change_skill
int change_skill(object *who, object *new_skill, int flag)
Definition: skill_util.cpp:359
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
GET_ANIM
#define GET_ANIM(ob)
Definition: global.h:164
fix_object
void fix_object(object *op)
Definition: living.cpp:1125
FLAG_BLESSED
#define FLAG_BLESSED
Definition: define.h:369
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:233
TRANSPORT
@ TRANSPORT
Definition: object.h:113
UPD_NROF
#define UPD_NROF
Definition: newclient.h:310
unapply_always
@ unapply_always
Definition: player.h:78
scroll_failure
void scroll_failure(object *op, int failure, int power)
Definition: apply.cpp:1601
skills.h
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:137
esrv_add_spells
void esrv_add_spells(player *pl, object *spell)
Definition: request.cpp:1909
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4337
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:263
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
events_execute_object_event
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:292
apply_check_personalized_blessings
static int apply_check_personalized_blessings(object *who, const object *op)
Definition: apply.cpp:1895
auto_apply_fix_inventory
static void auto_apply_fix_inventory(mapstruct *m, object *tmp)
Definition: apply.cpp:1469
buf
StringBuffer * buf
Definition: readable.cpp:1552
do_learn_spell
void do_learn_spell(object *op, object *spell, int special_prayer)
Definition: apply.cpp:484
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2848
MSG_TYPE_VICTIM
#define MSG_TYPE_VICTIM
Definition: newclient.h:404
MAX
#define MAX(x, y)
Definition: compat.h:24
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
cast_magic_storm
void cast_magic_storm(object *op, object *tmp, int lvl)
Definition: spell_effect.cpp:49
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
range_builder
@ range_builder
Definition: player.h:36
esrv_send_item
void esrv_send_item(object *pl, object *op)
Definition: main.cpp:354
METHOD_UNHANDLED
#define METHOD_UNHANDLED
Definition: ob_methods.h:16
FLAG_IS_A_TEMPLATE
#define FLAG_IS_A_TEMPLATE
Definition: define.h:366
object::carrying
int32_t carrying
Definition: object.h:377
AP_NULL
#define AP_NULL
Definition: define.h:573
object::y
int16_t y
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:425
autojail.who
who
Definition: autojail.py:3
CLOAK
@ CLOAK
Definition: object.h:209
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1555
give_initial_items
void give_initial_items(object *pl, treasurelist *items)
Definition: player.cpp:784
AP_PRINT
#define AP_PRINT
Definition: define.h:583
object_find_by_name
object * object_find_by_name(const object *who, const char *name)
Definition: object.cpp:3947
esrv_remove_spell
void esrv_remove_spell(player *pl, object *spell)
Definition: request.cpp:1772
apply_handle_yield
void apply_handle_yield(object *tmp)
Definition: apply.cpp:122
HELMET
@ HELMET
Definition: object.h:141
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
drop
void drop(object *op, object *tmp)
Definition: c_object.cpp:1168
blind_living
void blind_living(object *op, object *hitter, int dam)
Definition: attack.cpp:2353
object_present_in_ob_by_name
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
Definition: object.cpp:3194
MSG_TYPE_APPLY_SUCCESS
#define MSG_TYPE_APPLY_SUCCESS
Definition: newclient.h:592
SPELL_WONDER
#define SPELL_WONDER
Definition: spells.h:163
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:592
FLAG_USE_RANGE
#define FLAG_USE_RANGE
Definition: define.h:292
POTION
@ POTION
Definition: object.h:116
FLAG_KNOWN_CURSED
#define FLAG_KNOWN_CURSED
Definition: define.h:320
BUILDER
@ BUILDER
Definition: object.h:251
archetype::clone
object clone
Definition: object.h:478
apply_by_living_below
void apply_by_living_below(object *pl)
Definition: apply.cpp:695
object::weight_limit
int32_t weight_limit
Definition: object.h:376
apply_anim_suffix
void apply_anim_suffix(object *who, const char *suffix)
Definition: anim.cpp:150
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:754
HEAD
#define HEAD(op)
Definition: object.h:598
ROD
@ ROD
Definition: object.h:114
CONTAINER
@ CONTAINER
Definition: object.h:236
set_attr_value
void set_attr_value(living *stats, int attr, int8_t value)
Definition: living.cpp:218
object::face
const Face * face
Definition: object.h:341
apply_check_item_power
static int apply_check_item_power(const object *who, const object *op, int aflags)
Definition: apply.cpp:1867
SCRIPT_FIX_ALL
#define SCRIPT_FIX_ALL
Definition: global.h:388
AP_IGNORE_CURSE
#define AP_IGNORE_CURSE
Definition: define.h:582
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
MOVE_FLYING
#define MOVE_FLYING
Definition: define.h:395
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1344
object::type
uint8_t type
Definition: object.h:348
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:571
FLAG_DAMNED
#define FLAG_DAMNED
Definition: define.h:317
apply_manual
int apply_manual(object *op, object *tmp, int aflag)
Definition: apply.cpp:597
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:304
FLAG_USE_SHIELD
#define FLAG_USE_SHIELD
Definition: define.h:237
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)
Definition: object.cpp:1587
do_forget_spell
void do_forget_spell(object *op, const char *spell)
Definition: apply.cpp:525
LAMP
@ LAMP
Definition: object.h:206
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:575
tag_t
uint32_t tag_t
Definition: object.h:14
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
Definition: define.h:296
sproto.h
IS_SHIELD
#define IS_SHIELD(op)
Definition: define.h:170
find_key
object * find_key(object *pl, object *container, object *door)
Definition: player.cpp:2468
AC_PLAYER_STAT_NO_CHANGE
#define AC_PLAYER_STAT_NO_CHANGE
Definition: define.h:597
MSG_TYPE_VICTIM_WAS_HIT
#define MSG_TYPE_VICTIM_WAS_HIT
Definition: newclient.h:640
animate.anim
string anim
Definition: animate.py:20
FOR_OB_AND_BELOW_PREPARE
#define FOR_OB_AND_BELOW_PREPARE(op_)
Definition: define.h:750
CAN_APPLY_UNAPPLY_MULT
#define CAN_APPLY_UNAPPLY_MULT
Definition: define.h:634
GT_ENVIRONMENT
@ GT_ENVIRONMENT
Definition: treasure.h:31
SOUND_TYPE_SPELL
#define SOUND_TYPE_SPELL
Definition: newclient.h:323
RING
@ RING
Definition: object.h:190
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.cpp:2095
object::other_arch
struct archetype * other_arch
Definition: object.h:423
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
find_skill_by_name
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.cpp:211
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:74
should_director_abort
int should_director_abort(const object *op, const object *victim)
Definition: apply.cpp:68
MAX_BUF
#define MAX_BUF
Definition: define.h:35
object_new
object * object_new(void)
Definition: object.cpp:1268
Settings::personalized_blessings
uint8_t personalized_blessings
Definition: global.h:312
object::head
object * head
Definition: object.h:304
apply_container
int apply_container(object *op, object *sack, int aflags)
Definition: apply.cpp:222
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
IS_WEAPON
#define IS_WEAPON(op)
Definition: define.h:163
monster_check_apply_all
void monster_check_apply_all(object *monster)
Definition: monster.cpp:2001
apply_check_weapon_power
int apply_check_weapon_power(const object *who, int improves)
Definition: apply.cpp:1131
try_find_animation
Animations * try_find_animation(const char *name)
Definition: assets.cpp:278
apply_auto
int apply_auto(object *op)
Definition: apply.cpp:1400
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
FLAG_KNOWN_MAGICAL
#define FLAG_KNOWN_MAGICAL
Definition: define.h:319
change_abil
int change_abil(object *op, object *tmp)
Definition: living.cpp:394
MSG_TYPE_APPLY_BADBODY
#define MSG_TYPE_APPLY_BADBODY
Definition: newclient.h:596
range_misc
@ range_misc
Definition: player.h:33
FLAG_READY_SKILL
#define FLAG_READY_SKILL
Definition: define.h:333
FLAG_READY_BOW
#define FLAG_READY_BOW
Definition: define.h:299
sounds.h
check_trigger
int check_trigger(object *op, object *cause)
Definition: button.cpp:518
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:251
object::slaying
sstring slaying
Definition: object.h:327
CAN_APPLY_UNAPPLY
#define CAN_APPLY_UNAPPLY
Definition: define.h:633
spells.h
object::name
sstring name
Definition: object.h:319
AP_OPEN
#define AP_OPEN
Definition: define.h:576
IS_ARMOR
#define IS_ARMOR(op)
Definition: define.h:166
unapply_nochoice
@ unapply_nochoice
Definition: player.h:76
FLAG_USE_ARMOUR
#define FLAG_USE_ARMOUR
Definition: define.h:295
item
Definition: item.py:1
reputation.victim
victim
Definition: reputation.py:14
apply_can_apply_object
int apply_can_apply_object(const object *who, const object *op)
Definition: apply.cpp:1016
is_magical
int is_magical(const object *op)
Definition: item.cpp:1231
FIREWALL
@ FIREWALL
Definition: object.h:173
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:167
change_attr_value
void change_attr_value(living *stats, int attr, int8_t value)
Definition: living.cpp:264
mapstruct
Definition: map.h:314
object::env
object * env
Definition: object.h:301
check_spell_known
object * check_spell_known(object *op, const char *name)
Definition: spell_util.cpp:394
AC_PLAYER_STAT_LIMIT
#define AC_PLAYER_STAT_LIMIT
Definition: define.h:596
sstring
const typedef char * sstring
Definition: sstring.h:2
give.op
op
Definition: give.py:33
FLAG_AUTO_APPLY
#define FLAG_AUTO_APPLY
Definition: define.h:250
animate_object
void animate_object(object *op, int dir)
Definition: anim.cpp:44
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.cpp:2628
set_object_face_main
int set_object_face_main(object *op)
Definition: apply.cpp:146
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.cpp:359
SKILL_TOOL
@ SKILL_TOOL
Definition: object.h:194
CAN_APPLY_UNAPPLY_CHOICE
#define CAN_APPLY_UNAPPLY_CHOICE
Definition: define.h:635
diamondslots.y
y
Definition: diamondslots.py:16
FLAG_BEEN_APPLIED
#define FLAG_BEEN_APPLIED
Definition: define.h:323
get_item_from_body_location
static object * get_item_from_body_location(object *start, int loc)
Definition: apply.cpp:878
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.cpp:42
ob_apply
method_ret ob_apply(object *op, object *applier, int aflags)
Definition: ob_methods.cpp:44
AP_NOPRINT
#define AP_NOPRINT
Definition: define.h:585
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:76
cast_wonder
int cast_wonder(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.cpp:968
MSG_TYPE_APPLY_FAILURE
#define MSG_TYPE_APPLY_FAILURE
Definition: newclient.h:593
apply_auto_fix
void apply_auto_fix(mapstruct *m)
Definition: apply.cpp:1527
object::body_info
int8_t body_info[NUM_BODY_LOCATIONS]
Definition: object.h:382
FLAG_ANIMATE
#define FLAG_ANIMATE
Definition: define.h:242
Face
Definition: face.h:14
UPD_NAME
#define UPD_NAME
Definition: newclient.h:307
object::randomitems
struct treasurelist * randomitems
Definition: object.h:395
object_remove
void object_remove(object *op)
Definition: object.cpp:1828
ALTAR
@ ALTAR
Definition: object.h:127
DOOR
@ DOOR
Definition: object.h:131
transport_can_hold
int transport_can_hold(const object *transport, const object *op, int nrof)
Definition: apply.cpp:54
EVENT_CLOSE
#define EVENT_CLOSE
Definition: events.h:24
object::move_off
MoveType move_off
Definition: object.h:438
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
try_find_face
const Face * try_find_face(const char *name, const Face *error)
Definition: assets.cpp:286
AP_BASIC_FLAGS
#define AP_BASIC_FLAGS
Definition: define.h:578
Settings::item_power_factor
float item_power_factor
Definition: global.h:303
FLAG_READY_RANGE
#define FLAG_READY_RANGE
Definition: define.h:298
METHOD_ERROR
#define METHOD_ERROR
Definition: ob_methods.h:17
generate_treasure
object * generate_treasure(treasurelist *t, int difficulty)
Definition: treasure.cpp:295
SCROLL
@ SCROLL
Definition: object.h:226
FLAG_IS_LINKED
#define FLAG_IS_LINKED
Definition: define.h:315
object::nrof
uint32_t nrof
Definition: object.h:342
rndm
int rndm(int min, int max)
Definition: utils.cpp:162
Animations
Definition: face.h:25
MSG_TYPE_APPLY_PROHIBITION
#define MSG_TYPE_APPLY_PROHIBITION
Definition: newclient.h:597
object::stats
living stats
Definition: object.h:378
unapply_never
@ unapply_never
Definition: player.h:77
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.cpp:4490
object::more
object * more
Definition: object.h:303
get_attr_value
int8_t get_attr_value(const living *stats, int attr)
Definition: living.cpp:313
AP_UNAPPLY
#define AP_UNAPPLY
Definition: define.h:575
range_skill
@ range_skill
Definition: player.h:35
apply_update_ranged_skill
static void apply_update_ranged_skill(const object *who, object *op, int aflags)
Definition: apply.cpp:1997
tod.h
BOOTS
@ BOOTS
Definition: object.h:217
TRUE
#define TRUE
Definition: compat.h:11
SPELL
@ SPELL
Definition: object.h:219
FLAG_READY_WEAPON
#define FLAG_READY_WEAPON
Definition: define.h:334
player_unready_range_ob
void player_unready_range_ob(player *pl, object *ob)
Definition: player.cpp:4457
SHIELD
@ SHIELD
Definition: object.h:140
MSG_TYPE_APPLY
#define MSG_TYPE_APPLY
Definition: newclient.h:397
FLAG_CURSED
#define FLAG_CURSED
Definition: define.h:316
MSG_TYPE_APPLY_ERROR
#define MSG_TYPE_APPLY_ERROR
Definition: newclient.h:590
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
living.h
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
NUM_STATS
@ NUM_STATS
Definition: living.h:18
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
FORCE
@ FORCE
Definition: object.h:229
METHOD_SILENT_ERROR
#define METHOD_SILENT_ERROR
Definition: ob_methods.h:18
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Definition: define.h:302
banquet.floors
list floors
Definition: banquet.py:29
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
identify
object * identify(object *op)
Definition: item.cpp:1425
MSG_TYPE_APPLY_UNAPPLY
#define MSG_TYPE_APPLY_UNAPPLY
Definition: newclient.h:591