Crossfire Server  1.75.0
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
131  object_insert_in_map_at(drop, tmp->map, tmp, INS_BELOW_ORIGINATOR, tmp->x, tmp->y);
132  }
133 }
134 
146 void do_learn_spell(object *op, object *spell, int special_prayer) {
147  object *tmp;
148 
149  if (op->type != PLAYER) {
150  LOG(llevError, "BUG: do_learn_spell(): not a player\n");
151  return;
152  }
153 
154  /* Upgrade special prayers to normal prayers */
155  tmp = check_spell_known(op, spell->name);
156  if (tmp != NULL) {
157  if (special_prayer && !QUERY_FLAG(tmp, FLAG_STARTEQUIP)) {
158  LOG(llevError, "BUG: do_learn_spell(): spell already known, but not marked as startequip\n");
159  return;
160  }
161  return;
162  }
163 
164  play_sound_player_only(op->contr, SOUND_TYPE_SPELL, spell, 0, "learn");
165  tmp = object_new();
166  object_copy(spell, tmp);
167  object_insert_in_ob(tmp, op);
168 
169  if (special_prayer)
171 
173  "Type 'bind cast %s to store the spell in a key.",
174  spell->name);
175 
176  esrv_add_spells(op->contr, tmp);
177 }
178 
187 void do_forget_spell(object *op, const char *spell) {
188  object *spob;
189 
190  if (op->type != PLAYER) {
191  LOG(llevError, "BUG: do_forget_spell(): not a player\n");
192  return;
193  }
194  spob = check_spell_known(op, spell);
195  if (spob == NULL) {
196  LOG(llevError, "BUG: do_forget_spell(): spell not known\n");
197  return;
198  }
199 
201  "You lose knowledge of %s.",
202  spell);
203  player_unready_range_ob(op->contr, spob);
204  esrv_remove_spell(op->contr, spob);
205  object_remove(spob);
206  object_free(spob, 0);
207 }
208 
219 static int apply_check_race_restrictions(object *who, object *item) {
220  char buf[MAX_BUF];
221  sstring restriction;
222 
223  if (who->type != PLAYER || QUERY_FLAG(who, FLAG_WIZ))
224  return 1;
225 
226  restriction = object_get_value(item, "race_restriction");
227  if (!restriction)
228  return 1;
229 
230  snprintf(buf, sizeof(buf), ":%s:", who->race);
231  buf[sizeof(buf)-1] = '\0';
232 
233  if (strstr(restriction, buf) != NULL)
234  return 1;
235 
236  query_name(item, buf, sizeof(buf));
237  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);
238 
239  return 0;
240 }
241 
259 int apply_manual(object *op, object *tmp, int aflag) {
260  tmp = HEAD(tmp);
261 
262  if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_APPLIED)) {
263  if (op->type == PLAYER) {
265  "You should pay for it first.");
266  return METHOD_SILENT_ERROR;
267  }
268  return 0; /* monsters just skip unpaid items */
269  }
270 
271  if (!apply_check_race_restrictions(op, tmp))
272  return METHOD_SILENT_ERROR;
273 
274  if (op->contr)
275  play_sound_player_only(op->contr, SOUND_TYPE_ITEM, tmp, 0, "apply");
276 
277  return ob_apply(tmp, op, aflag);
278 }
279 
299 int apply_by_living(object *pl, object *op, int aflag, int quiet) {
300  int tmp;
301 
302  if (op->env == NULL && (pl->move_type&MOVE_FLYING)) {
303  /* player is flying and applying object not in inventory */
304  if (!QUERY_FLAG(pl, FLAG_WIZ) && !(op->move_type&MOVE_FLYING)) {
306  "But you are floating high above the ground!");
307  return 0;
308  }
309  }
310 
311  /* Check for PLAYER to avoid a DM to disappear in a puff of smoke if
312  * applied.
313  */
314  if (op->type != PLAYER
315  && QUERY_FLAG(op, FLAG_WAS_WIZ)
316  && !QUERY_FLAG(pl, FLAG_WAS_WIZ)) {
317  play_sound_map(SOUND_TYPE_ITEM, op, 0, "evaporate");
319  "The object disappears in a puff of smoke!");
321  "It must have been an illusion.");
322  object_remove(op);
323  object_free(op, 0);
324  return 1;
325  }
326 
327  tmp = apply_manual(pl, op, aflag);
328  if (!quiet) {
329  if (tmp == METHOD_UNHANDLED) {
330  char name[MAX_BUF];
331 
332  query_name(op, name, MAX_BUF);
334  "I don't know how to apply the %s.",
335  name);
336  } else if (tmp == METHOD_ERROR)
338  "You must get it first!\n");
339  else if (tmp == METHOD_SILENT_ERROR)
340  return tmp;
341  }
342  if (tmp == METHOD_OK) {
343  if (op->anim_suffix != NULL)
345  }
346  return tmp;
347 }
348 
357 void apply_by_living_below(object *pl) {
358  object *tmp;
359  int floors;
360 
361  if (pl->contr->transport && pl->contr->transport->type == TRANSPORT) {
362  ob_apply(pl->contr->transport, pl, 0);
363  return;
364  }
365 
366  /* If using a container, set the starting item to be the top
367  * item in the container. Otherwise, use the map.
368  */
369  tmp = pl->container != NULL ? pl->container->inv : pl->below;
370 
371  /* This is perhaps more complicated. However, I want to make sure that
372  * we don't use a corrupt pointer for the next object, so we get the
373  * next object in the stack before applying. This is can only be a
374  * problem if apply_by_living() has a bug in that it uses the object but
375  * does not return a proper value.
376  */
377  floors = 0;
379  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
380  floors++;
381  else if (floors > 0)
382  return; /* process only floor objects after first floor object */
383 
384  /* If it is visible, player can apply it. If it is applied by
385  * person moving on it, also activate. Added code to make it
386  * so that at least one of players movement types be that which
387  * the item needs.
388  */
389  if (!tmp->invisible || (tmp->move_on&pl->move_type)) {
390  if (apply_by_living(pl, tmp, 0, 1) == METHOD_OK)
391  return;
392  }
393  if (floors >= 2)
394  return; /* process at most two floor objects */
396 }
397 
413 static int unapply_special(object *who, object *op, int aflags) {
414  char name[MAX_BUF];
415 
416  if (op->type != LAMP)
418  query_name(op, name, MAX_BUF);
419  switch (op->type) {
420  case WEAPON:
421  if (!(aflags&AP_NOPRINT))
423  "You unwield %s.",
424  name);
425  (void)change_abil(who, op);
427  who->current_weapon = NULL;
428  clear_skill(who);
429  break;
430 
431  case SKILL: /* allows objects to impart skills */
432  case SKILL_TOOL:
433  if (op != who->chosen_skill)
434  LOG(llevError, "BUG: unapply_special(): applied skill is not a chosen skill\n");
435  if (who->type == PLAYER) {
436  if (who->contr->shoottype == range_skill)
437  who->contr->shoottype = range_none;
438  if (!op->invisible) {
439  if (!(aflags&AP_NOPRINT))
441  "You stop using the %s.",
442  name);
443  } else {
444  if (!(aflags&AP_NOPRINT))
446  "You can no longer use the skill: %s.",
447  op->skill);
448  }
449  }
450  (void)change_abil(who, op);
451  who->chosen_skill = NULL;
453  break;
454 
455  case ARMOUR:
456  case HELMET:
457  case SHIELD:
458  case RING:
459  case BOOTS:
460  case GLOVES:
461  case AMULET:
462  case GIRDLE:
463  case BRACERS:
464  case CLOAK:
465  if (!(aflags&AP_NOPRINT))
467  "You unwear %s.",
468  name);
469  (void)change_abil(who, op);
470  break;
471 
472  case BOW:
473  case WAND:
474  case ROD:
475  clear_skill(who);
476  if (!(aflags&AP_NOPRINT))
478  "You unready %s.",
479  name);
480  if (who->type == PLAYER)
481  who->contr->shoottype = range_none;
482  else if (op->type == BOW)
484  else
486  break;
487 
488  case BUILDER:
489  if (!(aflags&AP_NOPRINT))
491  "You unready %s.",
492  name);
493  who->contr->shoottype = range_none;
494  who->contr->ranges[range_builder] = NULL;
495  break;
496 
497  default:
498  if (!(aflags&AP_NOPRINT))
500  "You unapply %s.",
501  name);
502  break;
503  }
504 
505  fix_object(who);
506 
507  if (!(aflags&AP_NO_MERGE)) {
508  object *tmp;
509 
510  tmp = object_merge(op, NULL);
511  if (who->type == PLAYER) {
512  if (tmp) { /* it was merged */
513  op = tmp;
514  }
515  esrv_update_item(UPD_FLAGS, who, op);
516  }
517  }
518  return 0;
519 }
520 
540 static object *get_item_from_body_location(object *start, int loc) {
541  object *tmp;
542 
543  if (!start)
544  return NULL;
545 
546  tmp = start;
548  if (QUERY_FLAG(tmp, FLAG_APPLIED)
549  && tmp->body_info[loc]
550  && (!tmp->invisible || tmp->type == SKILL))
551  return tmp;
553  return NULL;
554 }
555 
577 static int unapply_for_ob(object *who, object *op, int aflags) {
578  int i;
579  object *tmp = NULL, *last;
580  char name[MAX_BUF];
581 
582  /* If we are applying a shield or weapon, unapply any equipped shield
583  * or weapons first - only allowed to use one weapon/shield at a time.
584  */
585  if (op->type == WEAPON || op->type == SHIELD) {
586  FOR_INV_PREPARE(who, tmp) {
587  if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == op->type) {
588  if (!(aflags&AP_IGNORE_CURSE)
589  && !(aflags&AP_PRINT)
590  && (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) {
591  /* In this case, we want to try and remove a
592  * cursed item. While we know it won't work, we
593  * want unapply_special to at least generate the
594  * message.
595  */
596  if (!(aflags&AP_NOPRINT)) {
597  query_name(tmp, name, MAX_BUF);
599  "No matter how hard you try, you just can't remove %s.",
600  name);
601  }
602  return 1;
603  }
604 
605  if (aflags&AP_PRINT) {
606  query_name(tmp, name, MAX_BUF);
608  name);
609  } else
610  unapply_special(who, tmp, aflags);
611  }
612  } FOR_INV_FINISH();
613  }
614 
615  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
616  /* this used up a slot that we need to free */
617  if (op->body_info[i]) {
618  last = who->inv;
619 
620  /* We do a while loop - may need to remove several items
621  * in order to free up enough slots.
622  */
623  while (who->body_used[i]+op->body_info[i] < 0) {
624  tmp = get_item_from_body_location(last, i);
625  if (!tmp)
626  return 1;
627 
628  /* If just printing, we don't care about cursed status */
629  if ((aflags&AP_IGNORE_CURSE)
630  || (aflags&AP_PRINT)
631  || (!(QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)))) {
632  if (aflags&AP_PRINT) {
633  query_name(tmp, name, MAX_BUF);
635  name);
636  } else
637  unapply_special(who, tmp, aflags);
638  } else {
639  /* Cursed item that we can't unequip - tell the player.
640  * Note this could be annoying if this is just one of a
641  * few, so it may not be critical (eg, putting on a
642  * ring and you have one cursed ring.)
643  */
644  if (!(aflags&AP_NOPRINT)) {
645  query_name(tmp, name, MAX_BUF);
647  "The %s just won't come off",
648  name);
649  }
650  }
651  last = tmp->below;
652  }
653  /* if we got here, this slot is freed up - otherwise, if it
654  * wasn't freed up, the return in the !tmp would have
655  * kicked in.
656  */
657  } /* if op is using this body location */
658  } /* for body locations */
659  return 0;
660 }
661 
678 int apply_can_apply_object(const object *who, const object *op) {
679  int i, retval = 0;
680  object *tmp = NULL, *ws = NULL;
681 
682  /* Players have 2 'arm's, so they could in theory equip 2 shields or
683  * 2 weapons, but we don't want to let them do that. So if they are
684  * trying to equip a weapon or shield, see if they already have one
685  * in place and store that way.
686  */
687  if (op->type == WEAPON || op->type == SHIELD) {
688  tmp = object_find_by_type_applied(who, op->type);
689  if (tmp != NULL) {
690  retval = CAN_APPLY_UNAPPLY;
691  ws = tmp;
692  }
693  }
694 
695  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
696  if (op->body_info[i]) {
697  /* Item uses more slots than we have */
698  if (FABS(op->body_info[i]) > who->body_info[i]) {
699  /* Could return now for efficiently - rest of info
700  * below isn't really needed.
701  */
702  retval |= CAN_APPLY_NEVER;
703  } else if (who->body_used[i]+op->body_info[i] < 0) {
704  /* in this case, equipping this would use more free
705  * spots than we have.
706  */
707  object *tmp1;
708 
709  /* if we have an applied weapon/shield, and unapply
710  * it would free enough slots to equip the new item,
711  * then just set this can continue. We don't care
712  * about the logic below - if you have shield equipped
713  * and try to equip another shield, there is only one
714  * choice. However, the check for the number of body
715  * locations does take into the account cases where what
716  * is being applied may be two handed for example.
717  */
718  if (ws) {
719  if (who->body_used[i]-ws->body_info[i]+op->body_info[i] >= 0) {
720  retval |= CAN_APPLY_UNAPPLY;
721  continue;
722  }
723  }
724 
725  tmp1 = get_item_from_body_location(who->inv, i);
726  if (!tmp1)
727  retval |= CAN_APPLY_NEVER;
728  else {
729  /* need to unapply something. However, if this
730  * something is different than we had found before,
731  * it means they need to apply multiple objects
732  */
733  retval |= CAN_APPLY_UNAPPLY;
734  if (!tmp)
735  tmp = tmp1;
736  else if (tmp != tmp1)
737  retval |= CAN_APPLY_UNAPPLY_MULT;
738  /* This object isn't using up all the slots, so
739  * there must be another. If so, and if the new
740  * item doesn't need all the slots, the player
741  * then has a choice.
742  */
743  if (who->body_used[i]-tmp1->body_info[i] != who->body_info[i]
744  && FABS(op->body_info[i]) < who->body_info[i])
745  retval |= CAN_APPLY_UNAPPLY_CHOICE;
746 
747  /* Does unequipping 'tmp1' free up enough slots
748  * for this to be equipped? If not, there must
749  * be something else to unapply.
750  */
751  if (who->body_used[i]+op->body_info[i]-tmp1->body_info[i] < 0)
752  retval |= CAN_APPLY_UNAPPLY_MULT;
753  }
754  } /* if not enough free slots */
755  } /* if this object uses location i */
756  } /* for i -> num_body_locations loop */
757 
758  /* Do checks for can_use_weapon/shield/armour. */
759  if (IS_WEAPON(op) && !QUERY_FLAG(who, FLAG_USE_WEAPON))
760  retval |= CAN_APPLY_RESTRICTION;
761  if (IS_SHIELD(op) && !QUERY_FLAG(who, FLAG_USE_SHIELD))
762  retval |= CAN_APPLY_RESTRICTION;
763  if (IS_ARMOR(op) && !QUERY_FLAG(who, FLAG_USE_ARMOUR))
764  retval |= CAN_APPLY_RESTRICTION;
765 
766  if (who->type != PLAYER) {
767  if ((op->type == WAND || op->type == ROD)
768  && !QUERY_FLAG(who, FLAG_USE_RANGE))
769  retval |= CAN_APPLY_RESTRICTION;
770  if (op->type == BOW && !QUERY_FLAG(who, FLAG_USE_BOW))
771  retval |= CAN_APPLY_RESTRICTION;
772  if (op->type == RING && !QUERY_FLAG(who, FLAG_USE_RING))
773  retval |= CAN_APPLY_RESTRICTION;
774  }
775  return retval;
776 }
777 
793 int apply_check_weapon_power(const object *who, int improves) {
794  return (who->level/5)+5 >= improves;
795 }
796 
818 int apply_special(object *who, object *op, int aflags) {
819  int basic_flag = aflags&AP_BASIC_FLAGS;
820  object *tmp, *skop;
821  char name_op[MAX_BUF];
822 
823  if (who == NULL) {
824  LOG(llevError, "apply_special() from object without environment.\n");
825  return 1;
826  }
827 
828  if (op->env != who)
829  return 1; /* op is not in inventory */
830 
831  /* trying to unequip op */
832  if (QUERY_FLAG(op, FLAG_APPLIED)) {
833  /* always apply, so no reason to unapply */
834  if (basic_flag == AP_APPLY)
835  return 0;
836 
837  if (!(aflags&AP_IGNORE_CURSE)
838  && (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))) {
839  if (!(aflags&AP_NOPRINT)) {
840  query_name(op, name_op, MAX_BUF);
842  "No matter how hard you try, you just can't remove %s.",
843  name_op);
844  }
845  return 1;
846  }
847  return unapply_special(who, op, aflags);
848  }
849 
850  if (basic_flag == AP_UNAPPLY)
851  return 0;
852 
853  if (!apply_check_apply_restrictions(who, op, aflags))
854  return 1;
855 
856  if (op->skill && op->type != SKILL && op->type != SKILL_TOOL) {
857  skop = find_skill_by_name(who, op->skill);
858  if (!skop) {
859  if (!(aflags&AP_NOPRINT))
861  "You need the %s skill to use this item!",
862  op->skill);
863  if (who->type == PLAYER)
864  return 1;
865 
866  /* monsters do not care about missing skills */
867  } else
868  /* While experience will be credited properly, we want to
869  * change the skill so that the dam and wc get updated
870  */
871  change_skill(who, skop, (aflags&AP_NOPRINT));
872  } else
873  skop = NULL;
874 
875  if (!apply_check_item_power(who, op, aflags))
876  return 1;
877 
879  return 1;
880 
881  /* Ok. We are now at the state where we can apply the new object.
882  * Note that we don't have the checks for can_use_...
883  * below - that is already taken care of by apply_can_apply_object().
884  */
885 
886  tmp = op->nrof <= 1 ? NULL : object_split(op, op->nrof-1, NULL, 0);
887 
888  switch (op->type) {
889  case WEAPON:
890  if (!apply_check_weapon_power(who, op->last_eat)) {
891  if (!(aflags&AP_NOPRINT))
893  "That weapon is too powerful for you to use. It would consume your soul!");
894  if (tmp != NULL)
895  (void)object_insert_in_ob(tmp, who);
896  return 1;
897  }
898 
899  if (!apply_check_owner(who, op, aflags)) {
900  if (tmp != NULL)
901  (void)object_insert_in_ob(tmp, who);
902  return 1;
903  }
904 
905  SET_FLAG(op, FLAG_APPLIED);
906 
907  if (skop)
908  change_skill(who, skop, 1);
910 
911  if (!(aflags&AP_NOPRINT)) {
912  query_name(op, name_op, MAX_BUF);
914  "You wield %s.",
915  name_op);
916  }
917 
918  (void)change_abil(who, op);
919  break;
920 
921  case ARMOUR:
922  case HELMET:
923  case SHIELD:
924  case BOOTS:
925  case GLOVES:
926  case GIRDLE:
927  case BRACERS:
928  case CLOAK:
929  case RING:
930  case AMULET:
931  SET_FLAG(op, FLAG_APPLIED);
932  if (!(aflags&AP_NOPRINT)) {
933  query_name(op, name_op, MAX_BUF);
935  "You wear %s.",
936  name_op);
937  }
938  (void)change_abil(who, op);
939  break;
940 
941  /* this part is needed for skill-tools */
942  case SKILL:
943  case SKILL_TOOL:
944  if (who->chosen_skill) {
945  LOG(llevError, "BUG: apply_special(): can't apply two skills\n");
946  return 1;
947  }
948 
949  apply_update_ranged_skill(who, op, aflags);
950  SET_FLAG(op, FLAG_APPLIED);
951  (void)change_abil(who, op);
952  who->chosen_skill = op;
954  break;
955 
956  case BOW:
957  if (!apply_check_weapon_power(who, op->last_eat)) {
958  if (!(aflags&AP_NOPRINT))
960  "That weapon is too powerful for you to use. It would consume your soul!");
961  if (tmp != NULL)
962  (void)object_insert_in_ob(tmp, who);
963  return 1;
964  }
965 
966  if (!apply_check_owner(who, op, aflags)) {
967  if (tmp != NULL)
968  (void)object_insert_in_ob(tmp, who);
969  return 1;
970  }
971  /*FALLTHROUGH*/
972  case WAND:
973  case ROD:
974  /* check for skill, alter player status */
975  SET_FLAG(op, FLAG_APPLIED);
976  if (skop)
977  change_skill(who, skop, 0);
978  if (!(aflags&AP_NOPRINT)) {
979  query_name(op, name_op, MAX_BUF);
981  "You ready %s.",
982  name_op);
983  }
984  if (who->type == PLAYER) {
985  if (op->type == BOW) {
986  (void)change_abil(who, op);
987  if (!(aflags&AP_NOPRINT)) {
988  query_name(op, name_op, MAX_BUF);
990  "You will now fire %s with %s.",
991  op->race ? op->race : "nothing",
992  name_op);
993  }
994  who->contr->shoottype = range_bow;
995  } else
996  who->contr->shoottype = range_misc;
997  } else {
998  if (op->type == BOW)
999  SET_FLAG(who, FLAG_READY_BOW);
1000  else
1001  SET_FLAG(who, FLAG_READY_RANGE);
1002  }
1003  break;
1004 
1005  case BUILDER:
1006  if (who->contr->ranges[range_builder])
1007  unapply_special(who, who->contr->ranges[range_builder], 0);
1008  who->contr->shoottype = range_builder;
1009  who->contr->ranges[range_builder] = op;
1010  if (!(aflags&AP_NOPRINT)) {
1011  query_name(op, name_op, MAX_BUF);
1013  "You ready your %s.",
1014  name_op);
1015  }
1016  break;
1017 
1018  default:
1019  query_name(op, name_op, MAX_BUF);
1021  "You apply %s.",
1022  name_op);
1023  break;
1024  } /* end of switch op->type */
1025 
1026  SET_FLAG(op, FLAG_APPLIED);
1027 
1028  if (tmp != NULL)
1029  tmp = object_insert_in_ob(tmp, who);
1030 
1031  fix_object(who);
1032 
1033  /* We exclude spell casting objects. The fire code will set the
1034  * been applied flag when they are used - until that point,
1035  * you don't know anything about them.
1036  */
1037  if (who->type == PLAYER && op->type != WAND && op->type != ROD)
1039 
1040  if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)) {
1041  if (who->type == PLAYER) {
1043  "Oops, it feels deadly cold!");
1045  }
1046  }
1047  if (who->type == PLAYER)
1049  return 0;
1050 }
1051 
1062 int apply_auto(object *op) {
1063  switch (op->type) {
1064  case SHOP_FLOOR:
1065  if (!HAS_RANDOM_ITEMS(op))
1066  return 0;
1067  {
1068  int difficulty = op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5);
1069  // create all treasures, inserting it into the shop floor
1070  create_treasure(op->randomitems, op, GT_ONLY_GOOD, difficulty, 0);
1071  }
1072  FOR_INV_PREPARE(op, tmp) {
1073  SET_FLAG(tmp, FLAG_UNPAID);
1074  identify(tmp);
1075  // then drop it on the floor
1076  object_remove(tmp);
1077  object_insert_in_map_at(tmp, op->map, op, INS_NO_WALK_ON, op->x, op->y);
1078  } FOR_INV_FINISH();
1079  op->randomitems = NULL;
1081  return 1;
1082  break;
1083 
1084  case TREASURE:
1085  if (QUERY_FLAG(op, FLAG_IS_A_TEMPLATE))
1086  return 0;
1087  while (op->stats.hp-- > 0)
1088  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);
1089 
1090  /* If we generated an object and put it in this object's
1091  * inventory, move it to the parent object as the current
1092  * object is about to disappear. An example of this item
1093  * is the random_ *stuff that is put inside other objects.
1094  */
1095  FOR_INV_PREPARE(op, tmp) {
1096  object_remove(tmp);
1097  if (op->env)
1098  object_insert_in_ob(tmp, op->env);
1099  else
1101  } FOR_INV_FINISH();
1102  object_remove(op);
1104  break;
1105  }
1106  return 0;
1107 }
1108 
1121 static void auto_apply_fix_inventory(mapstruct *m, object *tmp)
1122 {
1123  if (!tmp->inv)
1124  return;
1125  FOR_INV_PREPARE(tmp, invtmp) {
1126  if (invtmp->inv)
1127  auto_apply_fix_inventory(m,invtmp); // Recurse for containers in objects
1128  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
1129  apply_auto(invtmp);
1130  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
1131  while (invtmp->stats.hp-- > 0)
1132  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
1133  invtmp->randomitems = NULL;
1134  } else if (invtmp && invtmp->arch
1135  && invtmp->type != TREASURE
1136  && invtmp->type != SPELL
1137  && invtmp->type != CLASS
1138  && HAS_RANDOM_ITEMS(invtmp)) {
1139  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
1140  /* Need to clear this so that we never try to
1141  * create treasure again for this object
1142  */
1143  invtmp->randomitems = NULL;
1144  }
1145  } FOR_INV_FINISH();
1146  /* This is really temporary - the code at the
1147  * bottom will also set randomitems to null.
1148  * The problem is there are bunches of maps/players
1149  * already out there with items that have spells
1150  * which haven't had the randomitems set
1151  * to null yet.
1152  * MSW 2004-05-13
1153  *
1154  * And if it's a spellbook, it's better to set
1155  * randomitems to NULL too, else you get two spells
1156  * in the book ^_-
1157  * Ryo 2004-08-16
1158  */
1159  if (tmp->type == WAND
1160  || tmp->type == ROD
1161  || tmp->type == SCROLL
1162  || tmp->type == FIREWALL
1163  || tmp->type == POTION
1164  || tmp->type == ALTAR
1165  || tmp->type == SPELLBOOK)
1166  tmp->randomitems = NULL;
1167 }
1168 
1180  int x, y;
1181 
1182  if (m == NULL)
1183  return;
1184 
1185  for (x = 0; x < MAP_WIDTH(m); x++)
1186  for (y = 0; y < MAP_HEIGHT(m); y++)
1187  FOR_MAP_PREPARE(m, x, y, tmp) {
1188  if (tmp->inv) {
1189  auto_apply_fix_inventory(m, tmp);
1190  }
1191 
1192  if (QUERY_FLAG(tmp, FLAG_AUTO_APPLY))
1193  apply_auto(tmp);
1194  else if ((tmp->type == TREASURE || tmp->type == CONTAINER)
1195  && HAS_RANDOM_ITEMS(tmp)) {
1196  while (tmp->stats.hp-- > 0)
1197  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
1198  tmp->randomitems = NULL;
1199  } else if (tmp->type == TIMED_GATE) {
1200  object *head = HEAD(tmp);
1201 
1202  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
1203  tmp->speed = 0;
1204  object_update_speed(tmp);
1205  }
1206  }
1207  /* This function can be called every time a map is loaded,
1208  * even when swapping back in. As such, we don't want to
1209  * create the treasure over and over again, so after we
1210  * generate the treasure, blank out randomitems so if it
1211  * is swapped in again, it won't make anything. This is a
1212  * problem for the above objects, because they have
1213  * counters which say how many times to make the treasure.
1214  */
1215  else if (tmp
1216  && tmp->arch
1217  && tmp->type != PLAYER
1218  && tmp->type != TREASURE
1219  && tmp->type != SPELL
1220  && tmp->type != PLAYER_CHANGER
1221  && tmp->type != CLASS
1222  && HAS_RANDOM_ITEMS(tmp)) {
1223  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
1224  tmp->randomitems = NULL;
1225  }
1226 
1227  if (QUERY_FLAG(tmp, FLAG_MONSTER))
1229  } FOR_MAP_FINISH();
1230 
1231  for (x = 0; x < MAP_WIDTH(m); x++)
1232  for (y = 0; y < MAP_HEIGHT(m); y++)
1233  FOR_MAP_PREPARE(m, x, y, tmp) {
1234  if (tmp->above
1235  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
1236  check_trigger(tmp, tmp->above);
1237  } FOR_MAP_FINISH();
1238 }
1239 
1254 void scroll_failure(object *op, int failure, int power) {
1255  if (abs(failure/4) > power)
1256  power = abs(failure/4); /* set minimum effect */
1257 
1258  if (failure <= -1 && failure > -15) {/* wonder */
1259  object *tmp;
1260 
1262  "Your spell warps!");
1264  cast_wonder(op, op, 0, tmp);
1265  if (op->stats.sp < 0)
1266  /* For some reason the sp can become negative here. */
1267  op->stats.sp = 0;
1269  return;
1270  }
1271 
1273  if (failure <= -35 && failure > -60) { /* confusion */
1275  "The magic recoils on you!");
1276  confuse_living(op, op, power);
1277  return;
1278  }
1279 
1280  if (failure <= -60 && failure > -70) {/* paralysis */
1282  "The magic recoils and paralyzes you!");
1283  paralyze_living(op, power);
1284  return;
1285  }
1286 
1287  if (failure <= -70 && failure > -80) {/* blind */
1289  "The magic recoils on you!");
1290  blind_living(op, op, power);
1291  return;
1292  }
1293 
1294  if (failure <= -80) {/* blast the immediate area */
1295  object *tmp;
1296 
1298  cast_magic_storm(op, tmp, power);
1300  "You unleash uncontrolled mana!");
1301  return;
1302  }
1303  }
1304  /* Either no spell failure on this server, or wrong values,
1305  * in any case let's punish.
1306  */
1308  "Your mana is drained!");
1309  op->stats.sp -= random_roll(0, power-1, op, PREFER_LOW);
1310  if (op->stats.sp < 0)
1311  op->stats.sp = 0;
1312 }
1313 
1325 void apply_changes_to_player(object *pl, object *change, int limit_stats) {
1326  int i, j;
1327  int excess_stat = 0; /* if the stat goes over the maximum
1328  * for the race, put the excess stat some
1329  * where else.
1330  */
1331 
1332  if (change->type != CLASS) return;
1333 
1334  /* the following code assigns stats up to the stat max
1335  * for the race, and if the stat max is exceeded,
1336  * tries to randomly reassign the excess stat
1337  */
1338  if (! (limit_stats & AC_PLAYER_STAT_NO_CHANGE)) {
1339  for (i = 0; i < NUM_STATS; i++) {
1340  int8_t stat = get_attr_value(&pl->contr->orig_stats, i);
1341  int race_bonus = get_attr_value(&pl->arch->clone.stats, i);
1342 
1343  stat += get_attr_value(&change->stats, i);
1344  if (limit_stats & AC_PLAYER_STAT_LIMIT) {
1345  if (stat > 20+race_bonus) {
1346  excess_stat++;
1347  stat = 20+race_bonus;
1348  } else if (stat < 1) {
1349  /* I didn't see any code here before to make sure minimum
1350  * stats were enforced - maybe it was just dumb
1351  * luck that one would not have a stat low enough that then
1352  * has a stat penalty for class that would bring it negative?
1353  * I imagine a negative stat would crash the server pretty
1354  * quickly - MSW, Sept 2010
1355  */
1356  excess_stat += stat;
1357  stat = 1;
1358  }
1359  }
1360  set_attr_value(&pl->contr->orig_stats, i, stat);
1361  }
1362 
1363  /* Maybe we should randomly deduct stats in this case?
1364  * It's will go away sometime soon in any case.
1365  */
1366  if (excess_stat < 0) excess_stat = 0;
1367 
1368  /* We don't put an explicit check for limit_stats here -
1369  * excess stat will never be 0 if limit_stats is not
1370  * true.
1371  */
1372  for (j = 0; excess_stat > 0 && j < 100; j++) {
1373  /* try 100 times to assign excess stats */
1374  int i = rndm(0, NUM_STATS-1);
1375  int stat = get_attr_value(&pl->contr->orig_stats, i);
1376  int race_bonus = get_attr_value(&pl->arch->clone.stats, i);
1377 
1378  if (i == CHARISMA) {
1379  continue; /* exclude cha from this */
1380  }
1381 
1382  if (stat < 20+race_bonus) {
1383  change_attr_value(&pl->contr->orig_stats, i, 1);
1384  excess_stat--;
1385  }
1386  }
1387  }
1388  /* Done with stat processing */
1389 
1390  /* insert the randomitems from the change's treasurelist into
1391  * the player ref: player.c
1392  */
1393  if (change->randomitems != NULL)
1394  give_initial_items(pl, change->randomitems);
1395 
1396 
1397  /* set up the face, for some races. */
1398 
1399  /* first, look for the force object banning changing the
1400  * face. Certain races never change face with class.
1401  */
1402  int has_noclassfacechange = (object_find_by_name(pl, "NOCLASSFACECHANGE") != NULL);
1403  const Animations *anim = NULL;
1404 
1405  if (change->anim_suffix) {
1406  char buf[MAX_BUF];
1407 
1408  snprintf(buf, MAX_BUF, "%s_%s", pl->animation->name, change->anim_suffix);
1409  anim = try_find_animation(buf);
1410  if (anim) {
1411  pl->animation = anim;
1412  pl->anim_speed = -1;
1413  CLEAR_FLAG(pl, FLAG_ANIMATE);
1414  animate_object(pl, pl->facing);
1415  }
1416  }
1417  /* Check for anim == -1 so that we can override specific class faces for races.
1418  * This allows us to have custom class faces on the races that lack noclassfacechange
1419  *
1420  * Neila Hawkins 2020-09-08
1421  */
1422  if ((!has_noclassfacechange) && anim == 0) {
1423  pl->animation = GET_ANIM(change);
1424  pl->face = change->face;
1425 
1426  if (QUERY_FLAG(change, FLAG_ANIMATE))
1427  SET_FLAG(pl, FLAG_ANIMATE);
1428  else
1429  CLEAR_FLAG(pl, FLAG_ANIMATE);
1430  }
1431 
1432  /* Hard coding in class name is a horrible idea - lets
1433  * use the supported mechanism for this
1434  */
1435  if (object_present_in_ob_by_name(FORCE, "no weapon force", pl))
1437 
1438 }
1439 
1453 static int apply_check_apply_restrictions(object *who, object *op, int aflags) {
1454  int i;
1455 
1456  i = apply_can_apply_object(who, op);
1457  if (i == 0)
1458  return 1;
1459 
1460  /* Can't just apply this object. Lets see why not and what to do */
1461 
1462  if (i&CAN_APPLY_NEVER) {
1463  if (!(aflags&AP_NOPRINT)) {
1464  char name_op[MAX_BUF];
1465 
1466  query_name(op, name_op, MAX_BUF);
1468  "You don't have the body to use a %s",
1469  name_op);
1470  }
1471  return 0;
1472  }
1473 
1474  if (i&CAN_APPLY_RESTRICTION) {
1475  if (!(aflags&AP_NOPRINT)) {
1476  char name_op[MAX_BUF];
1477 
1478  query_name(op, name_op, MAX_BUF);
1480  "You have a prohibition against using a %s",
1481  name_op);
1482  }
1483  return 0;
1484  }
1485 
1486  if (who->type != PLAYER) {
1487  /* Some error, so don't try to equip something more */
1488  return !unapply_for_ob(who, op, aflags);
1489  }
1490 
1491  if (who->contr->unapply == unapply_never
1493  if (!(aflags&AP_NOPRINT))
1495  "You need to unapply some item(s):");
1496  unapply_for_ob(who, op, AP_PRINT);
1497  return 0;
1498  }
1499 
1500  if (who->contr->unapply == unapply_always
1501  || !(i&CAN_APPLY_UNAPPLY_CHOICE)) {
1502  return !unapply_for_ob(who, op, aflags);
1503  }
1504 
1505  return 1;
1506 }
1507 
1520 static int apply_check_item_power(const object *who, const object *op, int aflags) {
1521  if (who->type != PLAYER)
1522  return 1;
1523 
1524  if (op->item_power == 0
1526  return 1;
1527 
1528  if (!(aflags&AP_NOPRINT))
1530  "Equipping that combined with other items would consume your soul!");
1531  return 0;
1532 }
1533 
1548 static int apply_check_personalized_blessings(object *who, const object *op) {
1549  const char *owner;
1550  const char *will;
1551  long item_will;
1552  long margin;
1553  const char *msg;
1554  int random_effect;
1555  int damage_percentile;
1556 
1558  return 1;
1559  }
1560 
1561  owner = object_get_value(op, "item_owner");
1562  if (owner == NULL || strcmp(owner, who->name) == 0)
1563  return 1;
1564 
1565  will = object_get_value(op, "item_willpower");
1566  item_will = will != NULL ? atol(will) : 0;
1567  if (item_will > who->stats.exp) {
1569  "This %s refuses to serve you - it keeps evading your hand !",
1570  op->name);
1571  return 0;
1572  }
1573 
1574  margin = item_will != 0 ? who->stats.exp/item_will : who->stats.exp;
1575  random_effect = random_roll(0, 100, who, 1)-margin*20;
1576  if (random_effect > 80) {
1577  msg = "You don't know why, but you have the feeling that the %s is angry at you !";
1578  damage_percentile = 60;
1579  } else if (random_effect > 60) {
1580  msg = "The %s seems to look at you nastily !";
1581  damage_percentile = 45;
1582  } else if (random_effect > 40) {
1583  msg = "You have the strange feeling that the %s is annoyed...";
1584  damage_percentile = 30;
1585  } else if (random_effect > 20) {
1586  msg = "The %s seems tired, or bored, in a way. Very strange !";
1587  damage_percentile = 15;
1588  } else if (random_effect > 0) {
1589  msg = "You hear the %s sighing !";
1590  damage_percentile = 0;
1591  } else {
1592  msg = NULL;
1593  damage_percentile = 0;
1594  }
1595  if (msg != NULL)
1597  msg, op->name);
1598  if (damage_percentile > 0) {
1599  int weapon_bite = (who->stats.hp*damage_percentile)/100;
1600  if (weapon_bite < 1)
1601  weapon_bite = 1;
1602  who->stats.hp -= weapon_bite;
1604  "You get a nasty bite in the hand !");
1605  }
1606 
1607  return 1;
1608 }
1609 
1624 static int apply_check_owner(const object *who, const object *op, int aflags) {
1625  const char *quotepos;
1626 
1627  if (op->level == 0)
1628  return 1;
1629 
1630  quotepos = strstr(op->name, "'");
1631  if (quotepos == NULL || strncmp(op->name, who->name, quotepos-op->name) == 0)
1632  return 1;
1633 
1634  if (!(aflags&AP_NOPRINT))
1636  "The weapon does not recognize you as its owner.");
1637  return 0;
1638 }
1639 
1650 static void apply_update_ranged_skill(const object *who, object *op, int aflags) {
1651  if (who->type != PLAYER) {
1652  return;
1653  }
1654 
1655  who->contr->shoottype = range_skill;
1656  who->contr->ranges[range_skill] = op;
1657  if (op->invisible) {
1658  if (!(aflags&AP_NOPRINT))
1660  "Readied skill: %s.",
1661  op->skill ? op->skill : op->name);
1662  } else {
1663  if (!(aflags&AP_NOPRINT)) {
1664  char name_op[MAX_BUF];
1665 
1666  query_name(op, name_op, MAX_BUF);
1668  "You ready %s.",
1669  name_op);
1671  "You can now use the skill: %s.",
1672  op->skill);
1673  }
1674  }
1675 }
Error, serious thing.
Definition: logger.h:11
#define AP_UNAPPLY
Item is to be remvoed.
Definition: define.h:596
Use skill.
Definition: player.h:35
Will unapply whatever is necessary - this goes beyond no choice - if there are multiple ojbect of the...
Definition: player.h:78
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:15
Sound-related defines.
object * ranges[range_size]
Object for each range.
Definition: player.h:118
living orig_stats
Permanent real stats of player.
Definition: player.h:169
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:305
#define FLAG_UNPAID
Object hasn&#39;t been paid for yet.
Definition: define.h:223
#define FLAG_IS_LINKED
The object is linked with other objects.
Definition: define.h:303
see doc/Developers/objects
Definition: object.h:113
#define INS_BELOW_ORIGINATOR
Insert new object immediately below originator.
Definition: object.h:586
int change_skill(object *who, object *new_skill, int flag)
This changes the object&#39;s skill to new_skill.
Definition: skill_util.cpp:357
Spell-related defines: spellpath, subtypes, ...
See Ring.
Definition: object.h:190
int8_t item_power
Power rating of the object.
Definition: object.h:372
#define CAN_APPLY_UNAPPLY_CHOICE
Definition: define.h:658
This represents one animation.
Definition: face.h:25
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
static int apply_check_apply_restrictions(object *who, object *op, int aflags)
Checks for general apply restrictions (no body, prohibited by god, conflicts with other items...
Definition: apply.cpp:1453
object * check_spell_known(object *op, const char *name)
Checks to see if player knows the spell.
Definition: spell_util.cpp:394
#define MSG_TYPE_APPLY_PROHIBITION
Class/god prohibiiton on obj.
Definition: newclient.h:644
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
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.cpp:44
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
See Bracers.
Definition: object.h:222
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
int rndm(int min, int max)
Returns a number between min and max.
Definition: utils.cpp:162
See Scroll.
Definition: object.h:226
#define MSG_TYPE_APPLY_FAILURE
Apply OK, but no/bad result.
Definition: newclient.h:640
Defines for the ingame clock, ticks management and weather system.
#define MSG_TYPE_APPLY_BADBODY
Don&#39;t have body to use object.
Definition: newclient.h:643
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:283
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
See Cloak.
Definition: object.h:209
int apply_can_apply_object(const object *who, const object *op)
Checks to see if &#39;who&#39; can apply object &#39;op&#39;.
Definition: apply.cpp:678
#define METHOD_ERROR
Definition: ob_methods.h:17
#define FLAG_IS_FLOOR
Can&#39;t see what&#39;s underneath this object.
Definition: define.h:290
static void auto_apply_fix_inventory(mapstruct *m, object *tmp)
Go through one object on a map and process any special treasure creation or such for anything in it&#39;s...
Definition: apply.cpp:1121
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
#define GET_ANIM(ob)
Definition: global.h:166
No range selected.
Definition: player.h:30
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
Number of statistics.
Definition: living.h:18
void apply_changes_to_player(object *pl, object *change, int limit_stats)
Applies (race) changes to a player.
Definition: apply.cpp:1325
object * below
Pointer to the object stacked below this one.
Definition: object.h:295
#define FLAG_READY_RANGE
(Monster) has a range attack readied...
Definition: define.h:286
object * object_find_by_name(const object *who, const char *name)
Finds an object in inventory name.
Definition: object.cpp:3941
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.cpp:359
See Spellbook.
Definition: object.h:208
sstring slaying
Which race to do double damage to.
Definition: object.h:327
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:78
#define AC_PLAYER_STAT_LIMIT
Limit stats to racial maximum.
Definition: define.h:619
#define CAN_APPLY_NEVER
Definition: define.h:653
#define PREFER_LOW
Definition: define.h:585
See Weapon.
Definition: object.h:124
See Helmet.
Definition: object.h:141
#define IS_WEAPON(op)
Definition: define.h:163
Object for applying character class modifications to someone.
Definition: object.h:143
See Rod.
Definition: object.h:114
int16_t y
Position in the map for this object.
Definition: object.h:335
object * object_find_by_type_applied(const object *who, int type)
Find applied object in inventory.
Definition: object.cpp:4068
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:284
#define FLAG_BLESSED
Item has a blessing, opposite of cursed/damned.
Definition: define.h:365
#define SPELL_WONDER
Definition: spells.h:163
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:547
void blind_living(object *op, object *hitter, int dam)
Blind a living thing.
Definition: attack.cpp:2358
void scroll_failure(object *op, int failure, int power)
op made some mistake with a scroll, this takes care of punishment.
Definition: apply.cpp:1254
See Button Trigger.
Definition: object.h:137
Misc items.
Definition: player.h:33
#define TRUE
Definition: compat.h:11
See Girdle.
Definition: object.h:228
MoveType move_on
Move types affected moving on to this space.
Definition: object.h:439
See Amulet.
Definition: object.h:144
object * chosen_skill
The skill chosen to use.
Definition: object.h:396
#define MAX(x, y)
Definition: compat.h:24
int16_t x
Definition: object.h:335
Global type definitions and header inclusions.
See Boots.
Definition: object.h:217
#define AP_APPLY
Item is to be applied.
Definition: define.h:595
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
static int apply_check_race_restrictions(object *who, object *item)
Checks if an item is restricted to a race.
Definition: apply.cpp:219
Will not unapply objects automatically.
Definition: player.h:77
#define FLAG_USE_RING
(Monster) can use rings, boots, gauntlets, etc
Definition: define.h:285
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.cpp:308
uint8_t anim_speed
Ticks between animation-frames.
Definition: object.h:429
See Wand & Staff.
Definition: object.h:225
static int unapply_for_ob(object *who, object *op, int aflags)
Remove equipment so an object can be applied.
Definition: apply.cpp:577
#define MSG_TYPE_APPLY
Applying objects.
Definition: newclient.h:425
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
Definition: define.h:777
void esrv_add_spells(player *pl, object *spell)
This tells the client to add the spell *spell, if spell is NULL, then add all spells in the player&#39;s ...
Definition: request.cpp:1994
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
int transport_can_hold(const object *transport, const object *op, int nrof)
Can transport hold object op? This is a pretty trivial function, but in the future, possible transport may have more restrictions or weight reduction like containers.
Definition: apply.cpp:54
int apply_check_weapon_power(const object *who, int improves)
This checks to see of the player (who) is sufficient level to use a weapon with improves improvements...
Definition: apply.cpp:793
int32_t weight
Attributes of the object.
Definition: object.h:375
object * transport
Transport the player is in.
Definition: player.h:216
#define SOUND_TYPE_ITEM
Definition: newclient.h:351
#define NDI_NAVY
Definition: newclient.h:248
#define LOOSE_MANA
Definition: spells.h:162
rangetype shoottype
Which range-attack is being used by player.
Definition: player.h:114
#define CAN_APPLY_UNAPPLY_MULT
Definition: define.h:657
static int apply_check_owner(const object *who, const object *op, int aflags)
Checks that the item&#39;s owner matches the applier.
Definition: apply.cpp:1624
Allows the use of a skill.
Definition: object.h:194
int change_abil(object *op, object *tmp)
Permanently alters an object&#39;s stats/flags based on another object.
Definition: living.cpp:394
Generic item builder, see subtypes below.
Definition: object.h:251
#define FLAG_READY_SKILL
(Monster or Player) has a skill readied
Definition: define.h:321
int16_t level
Level of creature or object.
Definition: object.h:361
#define CAN_APPLY_UNAPPLY
Definition: define.h:656
int apply_manual(object *op, object *tmp, int aflag)
Main apply handler.
Definition: apply.cpp:259
int16_t sp
Spell points.
Definition: living.h:42
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1577
See Shooting Weapon.
Definition: object.h:123
void confuse_living(object *op, object *hitter, int dam)
Confuse a living thing.
Definition: attack.cpp:2315
#define AP_IGNORE_CURSE
Apply/unapply regardless of cursed/damned status.
Definition: define.h:603
#define MSG_TYPE_VICTIM
Something bad is happening to the player.
Definition: newclient.h:433
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.cpp:287
#define CAN_APPLY_RESTRICTION
Definition: define.h:654
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1446
int check_trigger(object *op, object *cause)
Definition: button.cpp:518
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
See Treasure.
Definition: object.h:115
int32_t carrying
How much weight this object contains.
Definition: object.h:377
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
#define METHOD_OK
Definition: ob_methods.h:15
object * env
Pointer to the object which is the environment.
Definition: object.h:301
#define SET_FLAG(xyz, p)
Definition: define.h:384
#define AP_PRINT
Print what to do, don&#39;t actually do it Note this is supported in all the functions.
Definition: define.h:604
#define QUERY_FLAG(xyz, p)
Definition: define.h:386
int should_director_abort(const object *op, const object *victim)
Check if op should abort moving victim because of it&#39;s race or slaying.
Definition: apply.cpp:68
#define FLAG_USE_SHIELD
Can this creature use a shield?
Definition: define.h:224
#define FLAG_USE_RANGE
(Monster) can apply and use range items
Definition: define.h:280
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.cpp:2001
sstring anim_suffix
Used to determine combined animations.
Definition: object.h:324
Map builder.
Definition: player.h:36
#define MSG_TYPE_APPLY_ERROR
Definition: newclient.h:637
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:594
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1545
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:700
#define MOVE_FLYING
Combo of fly_low and fly_high.
Definition: define.h:401
sstring race
Human, goblin, dragon, etc.
Definition: object.h:326
This is a game-map.
Definition: map.h:320
const Animations * animation
Animation of this item, NULL if not animated.
Definition: object.h:428
int apply_special(object *who, object *op, int aflags)
Apply an object.
Definition: apply.cpp:818
#define MSG_TYPE_VICTIM_WAS_HIT
Player was hit by something.
Definition: newclient.h:688
#define INS_NO_WALK_ON
Don&#39;t call check_walk_on against the originator.
Definition: object.h:584
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.cpp:4331
#define FLAG_IS_A_TEMPLATE
Object has no ingame life until instantiated.
Definition: define.h:362
const Face * face
Face with colors.
Definition: object.h:341
#define AP_NOPRINT
Don&#39;t print messages - caller will do that may be some that still print.
Definition: define.h:607
#define UPD_FLAGS
Definition: newclient.h:331
void paralyze_living(object *op, int dam)
Paralyze a living thing.
Definition: attack.cpp:2402
See Potion.
Definition: object.h:116
struct Settings settings
Global settings.
Definition: init.cpp:139
void apply_auto_fix(mapstruct *m)
Go through the entire map (only the first time when an original map is loaded) and performs special a...
Definition: apply.cpp:1179
void player_unready_range_ob(player *pl, object *ob)
Unready an object for a player.
Definition: player.cpp:4475
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
void cast_magic_storm(object *op, object *tmp, int lvl)
This is really used mostly for spell fumbles and the like.
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.cpp:42
#define UPD_WEIGHT
Definition: newclient.h:332
unapplymode unapply
Method for auto unapply.
Definition: player.h:123
See Spell.
Definition: object.h:219
int cast_wonder(object *op, object *caster, int dir, object *spell_ob)
wonder is really just a spell that will likely cast another spell.
int apply_auto(object *op)
Map was just loaded, handle op&#39;s initialization.
Definition: apply.cpp:1062
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:609
#define MSG_TYPE_APPLY_UNAPPLY
Unapply an object.
Definition: newclient.h:638
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:218
#define FLAG_BEEN_APPLIED
Object was ever applied, for identification purposes.
Definition: define.h:311
living stats
Str, Con, Dex, etc.
Definition: object.h:378
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
#define METHOD_UNHANDLED
Definition: ob_methods.h:16
void give_initial_items(object *pl, treasurelist *items)
Gives a new player her initial items.
Definition: player.cpp:792
#define IS_SHIELD(op)
Definition: define.h:170
See Door.
Definition: object.h:131
int16_t invisible
How much longer the object will be invis.
Definition: object.h:370
See Magic Wall.
Definition: object.h:173
void drop(object *op, object *tmp)
Drop an item, either on the floor or in a container.
Definition: c_object.cpp:1120
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
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
Skill-related defines, including subtypes.
Lamp.
Definition: object.h:206
See Container.
Definition: object.h:236
#define FLAG_READY_WEAPON
(Monster or Player) has a weapon readied
Definition: define.h:322
See Player Changer.
Definition: object.h:167
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
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:753
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
#define FLAG_KNOWN_CURSED
The object is known to be cursed.
Definition: define.h:308
static int unapply_special(object *who, object *op, int aflags)
Unapplies specified item.
Definition: apply.cpp:413
#define AP_BASIC_FLAGS
Definition: define.h:599
object * object_merge(object *op, object *top)
This function goes through all objects below and including top, and merges op to the first matching o...
Definition: object.cpp:2036
#define FLAG_CURSED
The object is cursed.
Definition: define.h:304
See Player.
Definition: object.h:112
#define AP_NO_MERGE
Don&#39;t try to merge object after (un)applying it.
Definition: define.h:602
See Shield.
Definition: object.h:140
struct treasurelist * randomitems
Items to be generated.
Definition: object.h:395
int8_t body_info[NUM_BODY_LOCATIONS]
Body info as loaded from the file.
Definition: object.h:382
#define FLAG_ANIMATE
The object looks at archetype for faces.
Definition: define.h:229
#define FLAG_AUTO_APPLY
Will be applied when created.
Definition: define.h:237
See Altar.
Definition: object.h:127
static event_registration m
Definition: citylife.cpp:424
object * container
Current container being used.
Definition: object.h:299
void do_forget_spell(object *op, const char *spell)
Erases spell from player&#39;s inventory.
Definition: apply.cpp:187
void play_sound_player_only(player *pl, int8_t sound_type, object *emitter, int dir, const char *action)
Plays a sound for specified player only.
Definition: sounds.cpp:51
#define UPD_NROF
Definition: newclient.h:337
Also see SKILL_TOOL (74) below.
Definition: object.h:148
Animations * try_find_animation(const char *name)
Definition: assets.cpp:282
MoveType move_type
Type of movement this object uses.
Definition: object.h:436
sstring name
The name of the object, obviously...
Definition: object.h:319
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.cpp:313
See Shop Floor.
Definition: object.h:188
#define MAP_WIDTH(m)
Map width.
Definition: map.h:76
uint32_t nrof
Number of objects.
Definition: object.h:342
void clear_skill(object *who)
This function just clears the chosen_skill and range_skill values in the player.
Definition: skill_util.cpp:396
static int apply_check_item_power(const object *who, const object *op, int aflags)
Checks for item power restrictions when applying an item.
Definition: apply.cpp:1520
#define AC_PLAYER_STAT_NO_CHANGE
Do not make any stat adjustments.
Definition: define.h:620
static void apply_update_ranged_skill(const object *who, object *op, int aflags)
Updates ranged skill information.
Definition: apply.cpp:1650
void esrv_remove_spell(player *pl, object *spell)
Definition: request.cpp:1857
#define CLEAR_FLAG(xyz, p)
Definition: define.h:385
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
#define METHOD_SILENT_ERROR
Player was warned she can&#39;t use the item for now.
Definition: ob_methods.h:18
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:222
void change_attr_value(living *stats, int attr, int8_t value)
Like set_attr_value(), but instead the value (which can be negative) is added to the specified stat...
Definition: living.cpp:264
See Timed Gate.
Definition: object.h:133
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1334
#define UPD_NAME
Definition: newclient.h:334
#define MSG_TYPE_APPLY_SUCCESS
Was able to apply object.
Definition: newclient.h:639
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
void do_learn_spell(object *op, object *spell, int special_prayer)
Actually makes op learn spell.
Definition: apply.cpp:146
#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:773
#define FLAG_STARTEQUIP
Object was given to player at start.
Definition: define.h:255
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
Bow.
Definition: player.h:31
sstring name
Name of the animation sequence.
Definition: face.h:26
Don&#39;t generate bad/cursed items.
Definition: treasure.h:34
int apply_by_living(object *pl, object *op, int aflag, int quiet)
Living thing is applying an object.
Definition: apply.cpp:299
#define MSG_TYPE_APPLY_CURSED
Applied a cursed object (BAD)
Definition: newclient.h:641
int64_t exp
Experience.
Definition: living.h:47
sstring skill
Name of the skill this object uses/grants.
Definition: object.h:329
#define FLAG_MONSTER
Will attack players.
Definition: define.h:232
Will unapply objects when there no choice to unapply.
Definition: player.h:76
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:270
void apply_by_living_below(object *pl)
Attempt to apply the object &#39;below&#39; the player.
Definition: apply.cpp:357
See Gloves.
Definition: object.h:218
#define FLAG_READY_BOW
not implemented yet
Definition: define.h:287
#define FLAG_WAS_WIZ
Player was once a wiz.
Definition: define.h:221
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:746
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
StringBuffer * buf
Definition: readable.cpp:1563
#define IS_ARMOR(op)
Definition: define.h:166
object * current_weapon
Pointer to the weapon currently used.
Definition: object.h:380
Structure containing object statistics.
uint8_t subtype
Subtype of object.
Definition: object.h:349
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:338
int32_t weight_limit
Weight-limit of object.
Definition: object.h:376
int16_t item_power
Total item power of objects equipped.
Definition: player.h:132
const char * sstring
Definition: sstring.h:2
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 * 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
static object * get_item_from_body_location(object *start, int loc)
Returns the object that is using body location &#39;loc&#39;.
Definition: apply.cpp:540
See Breastplate Armor.
Definition: object.h:125
uint8_t spell_failure_effects
Nasty backlash to spell failures.
Definition: global.h:270
#define SOUND_TYPE_SPELL
Definition: newclient.h:350
void apply_handle_yield(object *tmp)
This checks whether the object has a "on_use_yield" field, and if so generated and drops matching ite...
Definition: apply.cpp:122
object * find_skill_by_name(object *who, const char *name)
This returns the skill pointer of the given name (the one that accumulates exp, has the level...
Definition: skill_util.cpp:209
float item_power_factor
See note in setings file.
Definition: global.h:304
object clone
An object from which to do object_copy()
Definition: object.h:487
#define FLAG_USE_BOW
(Monster) can apply and fire bows
Definition: define.h:281
#define HAS_RANDOM_ITEMS(op)
This return TRUE if object has still randomitems which could be expanded.
Definition: define.h:184
static int apply_check_personalized_blessings(object *who, const object *op)
If personalized blessings are activated, the weapon can bite the wielder if he/she is not the one who...
Definition: apply.cpp:1548
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:693
int8_t body_used[NUM_BODY_LOCATIONS]
Calculated value based on items equipped.
Definition: object.h:383
void apply_anim_suffix(object *who, const char *suffix)
Applies a compound animation to an object.
Definition: anim.cpp:150
uint8_t personalized_blessings
If 1, blessed weapons get an owner and a willpower value.
Definition: global.h:313
int16_t hp
Hit Points.
Definition: living.h:40
int32_t last_eat
How long since we last ate.
Definition: object.h:366
Definition: object.h:229