Crossfire Server, Branches 1.12  R18729
apply.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_apply_c =
3  * "$Id: apply.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 /*
6  CrossFire, A Multiplayer game for X-windows
7 
8  Copyright (C) 2006 Mark Wedel & Crossfire Development Team
9  Copyright (C) 1992 Frank Tore Johansen
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 
25  The authors can be reached via e-mail to crossfire-devel@real-time.com
26 */
27 
33 #include <global.h>
34 #include <living.h>
35 #include <spells.h>
36 #include <skills.h>
37 #include <tod.h>
38 
39 #ifndef __CEXTRACT__
40 #include <sproto.h>
41 #endif
42 
43 /* Want this regardless of rplay. */
44 #include <sounds.h>
45 
46 /* need math lib for double-precision and pow() in dragon_eat_flesh() */
47 #include <math.h>
48 
64 int transport_can_hold(const object *transport, const object *op, int nrof) {
65  if ((op->weight*nrof+transport->carrying) > transport->weight_limit)
66  return 0;
67  else
68  return 1;
69 }
70 
81 int should_director_abort(object *op, object *victim) {
82  int arch_flag, name_flag, race_flag;
83  /* Get flags to determine what of arch, name, and race should be
84  * checked. This is stored in subtype, and is a bitmask, the LSB
85  * is the arch flag, the next is the name flag, and the last is
86  * the race flag. Also note, if subtype is set to zero, that also
87  * goes to defaults of all affecting it. Examples:
88  * subtype 1: only arch
89  * subtype 3: arch or name
90  * subtype 5: arch or race
91  * subtype 7: all three
92  */
93  if (op->subtype) {
94  arch_flag = (op->subtype&1);
95  name_flag = (op->subtype&2);
96  race_flag = (op->subtype&4);
97  } else {
98  arch_flag = 1;
99  name_flag = 1;
100  race_flag = 1;
101  }
102  /* If the director has race set, only affect objects with a arch,
103  * name or race that matches.
104  */
105  if ((op->race)
106  && ((!(victim->arch && arch_flag && victim->arch->name) || strcmp(op->race, victim->arch->name)))
107  && ((!(victim->name && name_flag) || strcmp(op->race, victim->name)))
108  && ((!(victim->race && race_flag) || strcmp(op->race, victim->race)))) {
109  return 1;
110  }
111 
112  /* If the director has slaying set, only affect objects where none
113  * of arch, name, or race match.
114  */
115  if ((op->slaying)
116  && (((victim->arch && arch_flag && victim->arch->name && !strcmp(op->slaying, victim->arch->name)))
117  || ((victim->name && name_flag && !strcmp(op->slaying, victim->name)))
118  || ((victim->race && race_flag && !strcmp(op->slaying, victim->race))))) {
119  return 1;
120  }
121  return 0;
122 }
123 
131 void handle_apply_yield(object *tmp) {
132  const char *yield;
133 
134  yield = get_ob_key_value(tmp, "on_use_yield");
135  if (yield != NULL) {
136  object *drop = create_archetype(yield);
137  if (tmp->env) {
138  drop = insert_ob_in_ob(drop, tmp->env);
139  } else {
140  drop->x = tmp->x;
141  drop->y = tmp->y;
142  insert_ob_in_map(drop, tmp->map, tmp, INS_BELOW_ORIGINATOR);
143  }
144  }
145 }
146 
147 int check_weapon_power(const object *who, int improvs);
148 
160 int set_object_face_main(object *op) {
161  int newface = op->arch->clone.face->number;
162  sstring saved = get_ob_key_value(op, "face_closed");
163 
164  if (saved) {
165  newface = find_face(saved, newface);
166  }
167  if (newface && op->face != &new_faces[newface]) {
168  op->face = &new_faces[newface];
169  return TRUE;
170  }
171  return FALSE;
172 }
173 
185 static int set_object_face_other(object *op) {
186  sstring custom;
187  int newface = 0;
188 
189  if (op->face && op->other_arch && op->other_arch->clone.face)
190  newface = op->other_arch->clone.face->number;
191 
192  if (op->face != op->arch->clone.face) {
193  /* object has a custom face, save it so it gets correctly restored later. */
194  set_ob_key_value(op, "face_closed", op->face->name, 1);
195  }
196 
197  custom = get_ob_key_value(op, "face_opened");
198  if (custom) {
199  newface = find_face(custom, newface);
200  }
201 
202  if (newface && op->face->number != newface) {
203  op->face = &new_faces[newface];
204  return TRUE;
205  }
206  return FALSE;
207 }
208 
230 int apply_container(object *op, object *sack) {
231  char name_sack[MAX_BUF], name_tmp[MAX_BUF];
232  object *tmp = op->container;
233 
234  if (op->type != PLAYER)
235  return 0; /* This might change */
236 
237  if (sack == NULL || sack->type != CONTAINER) {
238  LOG(llevError, "apply_container: %s is not container!\n", sack ? sack->name : "NULL");
239  return 0;
240  }
241 
242  /* If we have a currently open container, then it needs
243  * to be closed in all cases if we are opening this one up.
244  * We then fall through if appropriate for openening the new
245  * container.
246  */
247  if (op->container && QUERY_FLAG(sack, FLAG_APPLIED)) {
248  if (op->container->env != op) { /* if container is on the ground */
249  op->container->move_off = 0;
250  }
251  /* Lauwenmark: Handle for plugin close event */
252  if (execute_event(tmp, EVENT_CLOSE, op, NULL, NULL, SCRIPT_FIX_ALL) != 0)
253  return 1;
254 
255  query_name(op->container, name_tmp, MAX_BUF);
258  "You close %s.",
259  "You close %s.",
260  name_tmp);
262  op->container = NULL;
263  if (set_object_face_main(tmp)) {
265  } else {
266  esrv_update_item(UPD_FLAGS, op, tmp);
267  }
268  if (tmp == sack)
269  return 1;
270  }
271 
272  query_name(sack, name_sack, MAX_BUF);
273 
274  /* If the player is trying to open it (which he must be doing
275  * if we got here), and it is locked, check to see if player
276  * has the equipment to open it.
277  */
278 
279  if (sack->slaying) { /* it's locked */
280  tmp = find_key(op, op, sack);
281  if (tmp) {
282  query_name(tmp, name_tmp, MAX_BUF);
285  "You unlock %s with %s.",
286  "You unlock %s with %s.",
287  name_sack, name_tmp);
288  } else {
291  "You don't have the key to unlock %s.",
292  "You don't have the key to unlock %s.",
293  name_sack);
294  return 0;
295  }
296  }
297 
298  /* By the time we get here, we have made sure any other container
299  * has been closed and if this is a locked container, the player
300  * has the key to open it.
301  */
302 
303  /* There are really two cases - the sack is either on the ground,
304  * or the sack is part of the player's inventory. If on the ground,
305  * we assume that the player is opening it, since if it was being
306  * closed, that would have been taken care of above.
307  */
308 
309 
310  if (sack->env != op) {
311  /* Hypothetical case - the player is trying to open a sack
312  * that belongs to someone else. This normally should not
313  * happen, but a misbehaving client/player could
314  * try to do it, so let's handle it gracefully.
315  */
316  if (sack->env) {
318  "You can't open %s",
319  "You can't open %s",
320  name_sack);
321  return 0;
322  }
323 
324  if (sack->nrof > 1) {
325  object *left = get_split_ob(sack, sack->nrof-1, NULL, 0);
326 
327  insert_ob_in_map_at(left, sack->map, NULL, INS_NO_MERGE, sack->x, sack->y);
328  /* recompute the name so it's nice */
329  query_name(sack, name_sack, MAX_BUF);
330  }
331 
332  /* set it so when the player walks off, we can unapply the sack */
333  sack->move_off = MOVE_ALL; /* trying force closing it */
334 
335  CLEAR_FLAG(sack, FLAG_APPLIED);
337  "You open %s.",
338  "You open %s.",
339  name_sack);
340  SET_FLAG(sack, FLAG_APPLIED);
341  op->container = sack;
342  if (set_object_face_other(sack)) {
344  } else {
345  esrv_update_item(UPD_FLAGS, op, sack);
346  }
347  esrv_send_inventory(op, sack);
348  } else { /* sack is in players inventory */
349  if (QUERY_FLAG(sack, FLAG_APPLIED)) { /* readied sack becoming open */
350  CLEAR_FLAG(sack, FLAG_APPLIED);
352  "You open %s.",
353  "You open %s.",
354  name_sack);
355  SET_FLAG(sack, FLAG_APPLIED);
356  op->container = sack;
357  if (set_object_face_other(sack)) {
359  } else {
360  esrv_update_item(UPD_FLAGS, op, sack);
361  }
362  esrv_send_inventory(op, sack);
363  } else {
364  object *left = NULL;
365 
366  if (sack->nrof > 1) {
367  left = get_split_ob(sack, sack->nrof-1, NULL, 1);
368  }
369 
370  CLEAR_FLAG(sack, FLAG_APPLIED);
372  "You readied %s.",
373  "You readied %s.",
374  name_sack);
375  SET_FLAG(sack, FLAG_APPLIED);
376  esrv_update_item(UPD_FLAGS, op, sack);
377 
378  if (left) {
379  insert_ob_in_ob(left, sack->env);
380  esrv_send_item(op, left);
381  }
382  }
383  }
384  return 1;
385 }
386 
398 void do_learn_spell(object *op, object *spell, int special_prayer) {
399  object *tmp;
400 
401  if (op->type != PLAYER) {
402  LOG(llevError, "BUG: do_learn_spell(): not a player\n");
403  return;
404  }
405 
406  /* Upgrade special prayers to normal prayers */
407  if ((tmp = check_spell_known(op, spell->name)) != NULL) {
408  if (special_prayer && !QUERY_FLAG(tmp, FLAG_STARTEQUIP)) {
409  LOG(llevError, "BUG: do_learn_spell(): spell already known, but not marked as startequip\n");
410  return;
411  }
412  return;
413  }
414 
415  play_sound_player_only(op->contr, SOUND_TYPE_SPELL, spell, 0, "learn");
416  tmp = get_object();
417  copy_object(spell, tmp);
418  insert_ob_in_ob(tmp, op);
419 
420  if (special_prayer) {
422  }
423 
425  "Type 'bind cast %s to store the spell in a key.",
426  "Type 'bind cast %s to store the spell in a key.",
427  spell->name);
428 
429  esrv_add_spells(op->contr, tmp);
430 }
431 
440 void do_forget_spell(object *op, const char *spell) {
441  object *spob;
442 
443  if (op->type != PLAYER) {
444  LOG(llevError, "BUG: do_forget_spell(): not a player\n");
445  return;
446  }
447  if ((spob = check_spell_known(op, spell)) == NULL) {
448  LOG(llevError, "BUG: do_forget_spell(): spell not known\n");
449  return;
450  }
451 
453  "You lose knowledge of %s.",
454  "You lose knowledge of %s.",
455  spell);
456  player_unready_range_ob(op->contr, spob);
457  esrv_remove_spell(op->contr, spob);
458  remove_ob(spob);
459  free_object(spob);
460 }
461 
472 static int check_race_restrictions(object *who, object *item) {
473  char buf[MAX_BUF];
474  sstring restriction;
475 
476  if (who->type != PLAYER || QUERY_FLAG(who, FLAG_WIZ))
477  return 1;
478 
479  restriction = get_ob_key_value(item, "race_restriction");
480  if (!restriction)
481  return 1;
482 
483  snprintf(buf, sizeof(buf), ":%s:", who->race);
484  buf[sizeof(buf)-1] = '\0';
485 
486  if (strstr(restriction, buf) != NULL)
487  return 1;
488 
489  query_name(item, buf, sizeof(buf));
490  draw_ext_info_format(NDI_UNIQUE, 0, who, MSG_TYPE_APPLY, MSG_TYPE_APPLY_PROHIBITION, "Somehow you can't seem to use the %s.", NULL, buf);
491 
492  return 0;
493 }
494 
512 int manual_apply(object *op, object *tmp, int aflag) {
513  if (tmp->head)
514  tmp = tmp->head;
515 
516  if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_APPLIED)) {
517  if (op->type == PLAYER) {
519  "You should pay for it first.", NULL);
520  return METHOD_SILENT_ERROR;
521  }
522  return 0; /* monsters just skip unpaid items */
523  }
524 
525  if (!check_race_restrictions(op, tmp))
526  return METHOD_SILENT_ERROR;
527 
528  /* Lauwenmark: Handle for plugin apply event */
529  if (execute_event(tmp, EVENT_APPLY, op, NULL, NULL, SCRIPT_FIX_ALL) != 0)
530  return METHOD_OK;
531 
532  if (op->contr)
533  play_sound_player_only(op->contr, SOUND_TYPE_ITEM, tmp, 0, "apply");
534 
535  return ob_apply(tmp, op, aflag);
536 }
537 
557 int player_apply(object *pl, object *op, int aflag, int quiet) {
558  int tmp;
559 
560  if (op->env == NULL && (pl->move_type&MOVE_FLYING)) {
561  /* player is flying and applying object not in inventory */
562  if (!QUERY_FLAG(pl, FLAG_WIZ) && !(op->move_type&MOVE_FLYING)) {
564  "But you are floating high above the ground!", NULL);
565  return 0;
566  }
567  }
568 
569  /* Check for PLAYER to avoid a DM to disappear in a puff of smoke if
570  * applied.
571  */
572  if (op->type != PLAYER
573  && QUERY_FLAG(op, FLAG_WAS_WIZ)
574  && !QUERY_FLAG(pl, FLAG_WAS_WIZ)) {
575  play_sound_map(SOUND_TYPE_ITEM, op, 0, "evaporate");
577  "The object disappears in a puff of smoke!", NULL);
579  "It must have been an illusion.", NULL);
580  remove_ob(op);
581  free_object(op);
582  return 1;
583  }
584 
585  pl->contr->last_used = op;
586  pl->contr->last_used_id = op->count;
587 
588  tmp = manual_apply(pl, op, aflag);
589  if (!quiet) {
590  if (tmp == METHOD_UNHANDLED) {
591  char name[MAX_BUF];
592 
593  query_name(op, name, MAX_BUF);
595  "I don't know how to apply the %s.",
596  "I don't know how to apply the %s.",
597  name);
598  } else if (tmp == METHOD_ERROR)
600  "You must get it first!\n", NULL);
601  else if (tmp == METHOD_SILENT_ERROR)
602  return tmp;
603  }
604  if (tmp == METHOD_OK) {
605  if (op->anim_suffix != NULL)
607  }
608  return tmp;
609 }
610 
619 void player_apply_below(object *pl) {
620  object *tmp, *next;
621  int floors;
622 
623  if (pl->contr->transport && pl->contr->transport->type == TRANSPORT) {
624  ob_apply(pl->contr->transport, pl, 0);
625  return;
626  }
627 
628  /* If using a container, set the starting item to be the top
629  * item in the container. Otherwise, use the map.
630  */
631  tmp = (pl->container != NULL) ? pl->container->inv : pl->below;
632 
633  /* This is perhaps more complicated. However, I want to make sure that
634  * we don't use a corrupt pointer for the next object, so we get the
635  * next object in the stack before applying. This is can only be a
636  * problem if player_apply() has a bug in that it uses the object but
637  * does not return a proper value.
638  */
639  for (floors = 0; tmp != NULL; tmp = next) {
640  next = tmp->below;
641  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
642  floors++;
643  else if (floors > 0)
644  return; /* process only floor objects after first floor object */
645 
646  /* If it is visible, player can apply it. If it is applied by
647  * person moving on it, also activate. Added code to make it
648  * so that at least one of players movement types be that which
649  * the item needs.
650  */
651  if (!tmp->invisible || (tmp->move_on&pl->move_type)) {
652  if (player_apply(pl, tmp, 0, 1) == METHOD_OK)
653  return;
654  }
655  if (floors >= 2)
656  return; /* process at most two floor objects */
657  }
658 }
659 
675 static int unapply_special(object *who, object *op, int aflags) {
676  char name[MAX_BUF];
677 
678  if (op->type != LAMP)
680  query_name(op, name, MAX_BUF);
681  switch (op->type) {
682  case WEAPON:
683  if (!(aflags&AP_NOPRINT))
685  "You unwield %s.",
686  "You unwield %s.",
687  name);
688  (void)change_abil(who, op);
689  if (QUERY_FLAG(who, FLAG_READY_WEAPON))
691  who->current_weapon = NULL;
692  clear_skill(who);
693  break;
694 
695  case SKILL: /* allows objects to impart skills */
696  case SKILL_TOOL:
697  if (op != who->chosen_skill) {
698  LOG(llevError, "BUG: apply_special(): applied skill is not a chosen skill\n");
699  }
700  if (who->type == PLAYER) {
701  if (who->contr->shoottype == range_skill)
702  who->contr->shoottype = range_none;
703  if (!op->invisible) {
704  if (!(aflags&AP_NOPRINT))
706  "You stop using the %s.",
707  "You stop using the %s.",
708  name);
709  } else {
710  if (!(aflags&AP_NOPRINT))
712  "You can no longer use the skill: %s.",
713  "You can no longer use the skill: %s.",
714  op->skill);
715  }
716  }
717  (void)change_abil(who, op);
718  who->chosen_skill = NULL;
720  break;
721 
722  case ARMOUR:
723  case HELMET:
724  case SHIELD:
725  case RING:
726  case BOOTS:
727  case GLOVES:
728  case AMULET:
729  case GIRDLE:
730  case BRACERS:
731  case CLOAK:
732  if (!(aflags&AP_NOPRINT))
734  "You unwear %s.",
735  "You unwear %s.",
736  name);
737  (void)change_abil(who, op);
738  break;
739 
740  case BOW:
741  case WAND:
742  case ROD:
743  case HORN:
744  clear_skill(who);
745  if (!(aflags&AP_NOPRINT))
747  "You unready %s.",
748  "You unready %s.",
749  name);
750  if (who->type == PLAYER) {
751  who->contr->shoottype = range_none;
752  } else {
753  if (op->type == BOW)
755  else
757  }
758  break;
759 
760  case BUILDER:
761  if (!(aflags&AP_NOPRINT))
763  "You unready %s.",
764  "You unready %s.",
765  name);
766  who->contr->shoottype = range_none;
767  who->contr->ranges[range_builder] = NULL;
768  break;
769 
770  default:
771  if (!(aflags&AP_NOPRINT))
773  "You unapply %s.",
774  "You unapply %s.",
775  name);
776  break;
777  }
778 
779  fix_object(who);
780 
781  if (!(aflags&AP_NO_MERGE)) {
782  object *tmp;
783 
784  tmp = merge_ob(op, NULL);
785  if (who->type == PLAYER) {
786  if (tmp) { /* it was merged */
787  op = tmp;
788  }
789  esrv_update_item(UPD_FLAGS, who, op);
790  }
791  }
792  return 0;
793 }
794 
814 static object *get_item_from_body_location(object *start, int loc) {
815  object *tmp;
816 
817  if (!start)
818  return NULL;
819 
820  for (tmp = start; tmp; tmp = tmp->below)
821  if (QUERY_FLAG(tmp, FLAG_APPLIED)
822  && tmp->body_info[loc]
823  && (!tmp->invisible || tmp->type == SKILL))
824  return tmp;
825 
826  return NULL;
827 }
828 
850 static int unapply_for_ob(object *who, object *op, int aflags) {
851  int i;
852  object *tmp = NULL, *last;
853  char name[MAX_BUF];
854 
855  /* If we are applying a shield or weapon, unapply any equipped shield
856  * or weapons first - only allowed to use one weapon/shield at a time.
857  */
858  if (op->type == WEAPON || op->type == SHIELD) {
859  for (tmp = who->inv; tmp; tmp = tmp->below) {
860  if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == op->type) {
861  if ((aflags&AP_IGNORE_CURSE)
862  || (aflags&AP_PRINT)
863  || (!QUERY_FLAG(tmp, FLAG_CURSED) && !QUERY_FLAG(tmp, FLAG_DAMNED))) {
864  if (aflags&AP_PRINT) {
865  query_name(tmp, name, MAX_BUF);
867  name, NULL);
868  } else
869  unapply_special(who, tmp, aflags);
870  } else {
871  /* In this case, we want to try and remove a
872  * cursed item. While we know it won't work, we
873  * want unapply_special to at least generate the
874  * message.
875  */
876  if (!(aflags&AP_NOPRINT)) {
877  query_name(tmp, name, MAX_BUF);
879  "No matter how hard you try, you just can't remove %s.",
880  "No matter how hard you try, you just can't remove %s.",
881  name);
882  }
883  return 1;
884  }
885 
886  }
887  }
888  }
889 
890  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
891  /* this used up a slot that we need to free */
892  if (op->body_info[i]) {
893  last = who->inv;
894 
895  /* We do a while loop - may need to remove several items
896  * in order to free up enough slots.
897  */
898  while ((who->body_used[i]+op->body_info[i]) < 0) {
899  tmp = get_item_from_body_location(last, i);
900  if (!tmp) {
901  return 1;
902  }
903 
904  /* If just printing, we don't care about cursed status */
905  if ((aflags&AP_IGNORE_CURSE)
906  || (aflags&AP_PRINT)
907  || (!(QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)))) {
908  if (aflags&AP_PRINT) {
909  query_name(tmp, name, MAX_BUF);
911  name, NULL);
912  } else
913  unapply_special(who, tmp, aflags);
914  } else {
915  /* Cursed item that we can't unequip - tell the player.
916  * Note this could be annoying if this is just one of a
917  * few, so it may not be critical (eg, putting on a
918  * ring and you have one cursed ring.)
919  */
920  if (!(aflags&AP_NOPRINT)) {
921  query_name(tmp, name, MAX_BUF);
923  "The %s just won't come off",
924  "The %s just won't come off",
925  name);
926  }
927  }
928  last = tmp->below;
929  }
930  /* if we got here, this slot is freed up - otherwise, if it
931  * wasn't freed up, the return in the !tmp would have
932  * kicked in.
933  */
934  } /* if op is using this body location */
935  } /* for body lcoations */
936  return 0;
937 }
938 
955 int can_apply_object(object *who, object *op) {
956  int i, retval = 0;
957  object *tmp = NULL, *ws = NULL;
958 
959  /* Players have 2 'arm's, so they could in theory equip 2 shields or
960  * 2 weapons, but we don't want to let them do that. So if they are
961  * trying to equip a weapon or shield, see if they already have one
962  * in place and store that way.
963  */
964  if (op->type == WEAPON || op->type == SHIELD) {
965  for (tmp = who->inv; tmp && !ws; tmp = tmp->below) {
966  if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == op->type) {
967  retval = CAN_APPLY_UNAPPLY;
968  ws = tmp;
969  }
970  }
971  }
972 
973  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
974  if (op->body_info[i]) {
975  /* Item uses more slots than we have */
976  if (FABS(op->body_info[i]) > who->body_info[i]) {
977  /* Could return now for efficiently - rest of info
978  * below isn't really needed.
979  */
980  retval |= CAN_APPLY_NEVER;
981  } else if ((who->body_used[i]+op->body_info[i]) < 0) {
982  /* in this case, equipping this would use more free
983  * spots than we have.
984  */
985  object *tmp1;
986 
987  /* if we have an applied weapon/shield, and unapply
988  * it would free enough slots to equip the new item,
989  * then just set this can continue. We don't care
990  * about the logic below - if you have shield equipped
991  * and try to equip another shield, there is only one
992  * choice. However, the check for the number of body
993  * locations does take into the account cases where what
994  * is being applied may be two handed for example.
995  */
996  if (ws) {
997  if ((who->body_used[i]-ws->body_info[i]+op->body_info[i]) >= 0) {
998  retval |= CAN_APPLY_UNAPPLY;
999  continue;
1000  }
1001  }
1002 
1003  tmp1 = get_item_from_body_location(who->inv, i);
1004  if (!tmp1) {
1005  retval |= CAN_APPLY_NEVER;
1006  } else {
1007  /* need to unapply something. However, if this
1008  * something is different than we had found before,
1009  * it means they need to apply multiple objects
1010  */
1011  retval |= CAN_APPLY_UNAPPLY;
1012  if (!tmp)
1013  tmp = tmp1;
1014  else if (tmp != tmp1) {
1015  retval |= CAN_APPLY_UNAPPLY_MULT;
1016  }
1017  /* This object isn't using up all the slots, so
1018  * there must be another. If so, and if the new
1019  * item doesn't need all the slots, the player
1020  * then has a choice.
1021  */
1022  if (((who->body_used[i]-tmp1->body_info[i]) != who->body_info[i])
1023  && (FABS(op->body_info[i]) < who->body_info[i]))
1024  retval |= CAN_APPLY_UNAPPLY_CHOICE;
1025 
1026  /* Does unequipping 'tmp1' free up enough slots
1027  * for this to be equipped? If not, there must
1028  * be something else to unapply.
1029  */
1030  if ((who->body_used[i]+op->body_info[i]-tmp1->body_info[i]) < 0)
1031  retval |= CAN_APPLY_UNAPPLY_MULT;
1032  }
1033  } /* if not enough free slots */
1034  } /* if this object uses location i */
1035  } /* for i -> num_body_locations loop */
1036 
1037  /* Do checks for can_use_weapon/shield/armour. */
1038  if (IS_WEAPON(op) && !QUERY_FLAG(who, FLAG_USE_WEAPON))
1039  retval |= CAN_APPLY_RESTRICTION;
1040  if (IS_SHIELD(op) && !QUERY_FLAG(who, FLAG_USE_SHIELD))
1041  retval |= CAN_APPLY_RESTRICTION;
1042  if (IS_ARMOR(op) && !QUERY_FLAG(who, FLAG_USE_ARMOUR))
1043  retval |= CAN_APPLY_RESTRICTION;
1044 
1045  if (who->type != PLAYER) {
1046  if ((op->type == WAND || op->type == HORN || op->type == ROD)
1047  && !QUERY_FLAG(who, FLAG_USE_RANGE))
1048  retval |= CAN_APPLY_RESTRICTION;
1049  if (op->type == BOW && !QUERY_FLAG(who, FLAG_USE_BOW))
1050  retval |= CAN_APPLY_RESTRICTION;
1051  if (op->type == RING && !QUERY_FLAG(who, FLAG_USE_RING))
1052  retval |= CAN_APPLY_RESTRICTION;
1053  if (op->type == BOW && !QUERY_FLAG(who, FLAG_USE_BOW))
1054  retval |= CAN_APPLY_RESTRICTION;
1055  }
1056  return retval;
1057 }
1058 
1076 int check_weapon_power(const object *who, int improvs) {
1077  /* Old code is below (commented out). Basically, since weapons
1078  * are the only object players really have any control to improve,
1079  * it's a bit harsh to require high level in some combat skill,
1080  * so we just use overall level.
1081  */
1082 #if 1
1083  if (((who->level/5)+5) >= improvs)
1084  return 1;
1085  else
1086  return 0;
1087 
1088 #else
1089  int level = 0;
1090 
1091  /* The skill system hands out wc and dam bonuses to fighters
1092  * more generously than the old system (see fix_object). Thus
1093  * we need to curtail the power of player enchanted weapons.
1094  * I changed this to 1 improvement per "fighter" level/5 -b.t.
1095  * Note: Nothing should break by allowing this ratio to be
1096  * different or using normal level - it is just a matter of play
1097  * balance.
1098  */
1099  if (who->type == PLAYER) {
1100  object *wc_obj = NULL;
1101 
1102  for (wc_obj = who->inv; wc_obj; wc_obj = wc_obj->below)
1103  if (wc_obj->type == SKILL && IS_COMBAT_SKILL(wc_obj->subtype)
1104  && wc_obj->level > level)
1105  level = wc_obj->level;
1106 
1107  if (!level) {
1108  LOG(llevError, "Error: Player: %s lacks wc experience object\n", who->name);
1109  level = who->level;
1110  }
1111  } else
1112  level = who->level;
1113 
1114  return (improvs <= ((level/5)+5));
1115 #endif
1116 }
1117 
1139 int apply_special(object *who, object *op, int aflags) {
1140  int basic_flag = aflags&AP_BASIC_FLAGS;
1141  object *tmp, *skop = NULL;
1142  int i;
1143  char name_op[MAX_BUF];
1144 
1145  if (who == NULL) {
1146  LOG(llevError, "apply_special() from object without environment.\n");
1147  return 1;
1148  }
1149 
1150  query_name(op, name_op, MAX_BUF);
1151 
1152  if (op->env != who)
1153  return 1; /* op is not in inventory */
1154 
1155  /* trying to unequip op */
1156  if (QUERY_FLAG(op, FLAG_APPLIED)) {
1157  /* always apply, so no reason to unapply */
1158  if (basic_flag == AP_APPLY)
1159  return 0;
1160 
1161  if (!(aflags&AP_IGNORE_CURSE)
1162  && (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))) {
1163  if (!(aflags&AP_NOPRINT))
1165  "No matter how hard you try, you just can't remove %s.",
1166  "No matter how hard you try, you just can't remove %s.",
1167  name_op);
1168  return 1;
1169  }
1170  return unapply_special(who, op, aflags);
1171  }
1172 
1173  if (basic_flag == AP_UNAPPLY)
1174  return 0;
1175 
1176  i = can_apply_object(who, op);
1177 
1178  /* Can't just apply this object. Lets see what not and what to do */
1179  if (i) {
1180  if (i&CAN_APPLY_NEVER) {
1181  if (!(aflags&AP_NOPRINT))
1183  "You don't have the body to use a %s",
1184  "You don't have the body to use a %s",
1185  name_op);
1186  return 1;
1187  } else if (i&CAN_APPLY_RESTRICTION) {
1188  if (!(aflags&AP_NOPRINT))
1190  "You have a prohibition against using a %s",
1191  "You have a prohibition against using a %s",
1192  name_op);
1193  return 1;
1194  }
1195  if (who->type != PLAYER) {
1196  /* Some error, so don't try to equip something more */
1197  if (unapply_for_ob(who, op, aflags))
1198  return 1;
1199  } else {
1200  if (who->contr->unapply == unapply_never
1202  if (!(aflags&AP_NOPRINT))
1204  "You need to unapply some item(s):", NULL);
1205  unapply_for_ob(who, op, AP_PRINT);
1206  return 1;
1207  } else if (who->contr->unapply == unapply_always
1208  || !(i&CAN_APPLY_UNAPPLY_CHOICE)) {
1209  i = unapply_for_ob(who, op, aflags);
1210  if (i)
1211  return 1;
1212  }
1213  }
1214  }
1215  if (op->skill && op->type != SKILL && op->type != SKILL_TOOL) {
1216  skop = find_skill_by_name(who, op->skill);
1217  if (!skop) {
1218  if (!(aflags&AP_NOPRINT))
1220  "You need the %s skill to use this item!",
1221  "You need the %s skill to use this item!",
1222  op->skill);
1223  return 1;
1224  } else {
1225  /* While experience will be credited properly, we want to
1226  * change the skill so that the dam and wc get updated
1227  */
1228  change_skill(who, skop, (aflags&AP_NOPRINT));
1229  }
1230  }
1231 
1232  if (who->type == PLAYER
1233  && op->item_power
1234  && (op->item_power+who->contr->item_power) > (settings.item_power_factor*who->level)) {
1235  if (!(aflags&AP_NOPRINT))
1237  "Equipping that combined with other items would consume your soul!", NULL);
1238  return 1;
1239  }
1240 
1241  /* If personalized blessings are activated, the weapon can bite
1242  * the wielder if he/she is not the one who initially blessed it.
1243  * Chances of being hurt depend on the experience amount
1244  * ("willpower") the object has, compared to the experience
1245  * amount of the wielder.
1246  */
1248  const char *owner = get_ob_key_value(op, "item_owner");
1249  if ((owner != NULL) && (strcmp(owner, who->name))) {
1250  const char *will = get_ob_key_value(op, "item_willpower");
1251  long item_will = 0;
1252  long margin = 0;
1253  const char *msg = NULL;
1254  int random_effect = 0;
1255  int damage_percentile = 0;
1256 
1257  if (will != NULL)
1258  item_will = atol(will);
1259  if (item_will > who->stats.exp) {
1261  "This %s refuses to serve you - it keeps evading your hand !",
1262  "This %s refuses to serve you - it keeps evading your hand !",
1263  op->name);
1264  return 1;
1265  }
1266  if (item_will != 0)
1267  margin = who->stats.exp/item_will;
1268  else
1269  margin = who->stats.exp;
1270  random_effect = (random_roll(0, 100, who, 1)-(margin*20));
1271  if (random_effect > 80) {
1272  msg = "You don't know why, but you have the feeling that the %s is angry at you !";
1273  damage_percentile = 60;
1274  } else if (random_effect > 60) {
1275  msg = "The %s seems to look at you nastily !";
1276  damage_percentile = 45;
1277  } else if (random_effect > 40) {
1278  msg = "You have the strange feeling that the %s is annoyed...";
1279  damage_percentile = 30;
1280  } else if (random_effect > 20) {
1281  msg = "The %s seems tired, or bored, in a way. Very strange !";
1282  damage_percentile = 15;
1283  } else if (random_effect > 0) {
1284  msg = "You hear the %s sighing !";
1285  damage_percentile = 0;
1286  }
1287  if (msg != NULL)
1289  msg, msg, op->name);
1290  if (damage_percentile > 0) {
1291  int weapon_bite = (who->stats.hp*damage_percentile)/100;
1292  if (weapon_bite < 1)
1293  weapon_bite = 1;
1294  who->stats.hp -= weapon_bite;
1296  "You get a nasty bite in the hand !",
1297  "You get a nasty bite in the hand !");
1298  }
1299  }
1300  }
1301 
1302  /* Ok. We are now at the state where we can apply the new object.
1303  * Note that we don't have the checks for can_use_...
1304  * below - that is already taken care of by can_apply_object.
1305  */
1306 
1307  if (op->nrof > 1)
1308  tmp = get_split_ob(op, op->nrof-1, NULL, 0);
1309  else
1310  tmp = NULL;
1311 
1312  switch (op->type) {
1313  case WEAPON: {
1314  int ownerlen = 0;
1315  char *quotepos = NULL;
1316 
1317  if (!check_weapon_power(who, op->last_eat)) {
1318  if (!(aflags&AP_NOPRINT))
1321  "That weapon is too powerful for you to use. It would consume your soul!",
1322  NULL);
1323 
1324  if (tmp != NULL)
1325  (void)insert_ob_in_ob(tmp, who);
1326  return 1;
1327  }
1328  /* BUG? It seems the value of quotepos is never used. */
1329  if ((quotepos = strstr(op->name, "'")) != NULL) {
1330  ownerlen = (strstr(op->name, "'")-op->name);
1331  if (op->level && (strncmp(op->name, who->name, ownerlen))) {
1332  /* if the weapon does not have the name as the
1333  * character, can't use it. (Ragnarok's sword
1334  * attempted to be used by Foo: won't work) */
1335  if (!(aflags&AP_NOPRINT))
1337  "The weapon does not recognize you as its owner.", NULL);
1338  if (tmp != NULL)
1339  (void)insert_ob_in_ob(tmp, who);
1340  return 1;
1341  }
1342  }
1343  SET_FLAG(op, FLAG_APPLIED);
1344 
1345  if (skop)
1346  change_skill(who, skop, 1);
1347  if (!QUERY_FLAG(who, FLAG_READY_WEAPON))
1349 
1350  if (!(aflags&AP_NOPRINT))
1352  "You wield %s.", "You wield %s.",
1353  name_op);
1354 
1355  (void)change_abil(who, op);
1356  break;
1357  }
1358 
1359  case ARMOUR:
1360  case HELMET:
1361  case SHIELD:
1362  case BOOTS:
1363  case GLOVES:
1364  case GIRDLE:
1365  case BRACERS:
1366  case CLOAK:
1367  case RING:
1368  case AMULET:
1369  SET_FLAG(op, FLAG_APPLIED);
1370  if (!(aflags&AP_NOPRINT))
1372  "You wear %s.",
1373  "You wear %s.",
1374  name_op);
1375  (void)change_abil(who, op);
1376  break;
1377 
1378  /* this part is needed for skill-tools */
1379  case SKILL:
1380  case SKILL_TOOL:
1381  if (who->chosen_skill) {
1382  LOG(llevError, "BUG: apply_special(): can't apply two skills\n");
1383  return 1;
1384  }
1385 
1386  if (who->type == PLAYER) {
1387  who->contr->shoottype = range_skill;
1388  who->contr->ranges[range_skill] = op;
1389  if (!op->invisible) {
1390  if (!(aflags&AP_NOPRINT)) {
1392  "You ready %s.",
1393  "You ready %s.",
1394  name_op);
1396  "You can now use the skill: %s.",
1397  "You can now use the skill: %s.",
1398  op->skill);
1399  }
1400  } else {
1401  if (!(aflags&AP_NOPRINT))
1403  "Readied skill: %s.",
1404  "Readied skill: %s.",
1405  op->skill ? op->skill : op->name);
1406  }
1407  }
1408  SET_FLAG(op, FLAG_APPLIED);
1409  (void)change_abil(who, op);
1410  who->chosen_skill = op;
1411  SET_FLAG(who, FLAG_READY_SKILL);
1412  break;
1413 
1414  case BOW:
1415  if (!check_weapon_power(who, op->last_eat)) {
1416  if (!(aflags&AP_NOPRINT)) {
1418  "That item is too powerful for you to use.",
1419  NULL);
1421  "It would consume your soul!.", NULL);
1422  }
1423  if (tmp != NULL)
1424  (void)insert_ob_in_ob(tmp, who);
1425  return 1;
1426  }
1427  if (op->level && (strncmp(op->name, who->name, strlen(who->name)))) {
1428  if (!(aflags&AP_NOPRINT)) {
1430  "The weapon does not recognize you as its owner.", NULL);
1431  }
1432  if (tmp != NULL)
1433  (void)insert_ob_in_ob(tmp, who);
1434  return 1;
1435  }
1436  /*FALLTHROUGH*/
1437  case WAND:
1438  case ROD:
1439  case HORN:
1440  /* check for skill, alter player status */
1441  SET_FLAG(op, FLAG_APPLIED);
1442  if (skop)
1443  change_skill(who, skop, 0);
1444  if (!(aflags&AP_NOPRINT))
1446  "You ready %s.",
1447  "You ready %s.",
1448  name_op);
1449  if (who->type == PLAYER) {
1450  if (op->type == BOW) {
1451  (void)change_abil(who, op);
1452  if (!(aflags&AP_NOPRINT))
1454  "You will now fire %s with %s.",
1455  "You will now fire %s with %s.",
1456  op->race ? op->race : "nothing",
1457  name_op);
1458  who->contr->shoottype = range_bow;
1459  } else {
1460  who->contr->shoottype = range_misc;
1461  }
1462  } else {
1463  if (op->type == BOW)
1464  SET_FLAG(who, FLAG_READY_BOW);
1465  else
1466  SET_FLAG(who, FLAG_READY_RANGE);
1467  }
1468  break;
1469 
1470  case BUILDER:
1471  if (who->contr->ranges[range_builder])
1472  unapply_special(who, who->contr->ranges[range_builder], 0);
1473  who->contr->shoottype = range_builder;
1474  who->contr->ranges[range_builder] = op;
1475  if (!(aflags&AP_NOPRINT))
1477  "You ready your %s.",
1478  "You ready your %s.",
1479  name_op);
1480  break;
1481 
1482  default:
1484  "You apply %s.",
1485  "You apply %s.",
1486  name_op);
1487  } /* end of switch op->type */
1488 
1489  SET_FLAG(op, FLAG_APPLIED);
1490 
1491  if (tmp != NULL)
1492  tmp = insert_ob_in_ob(tmp, who);
1493 
1494  fix_object(who);
1495 
1496  /* We exclude spell casting objects. The fire code will set the
1497  * been applied flag when they are used - until that point,
1498  * you don't know anything about them.
1499  */
1500  if (who->type == PLAYER && op->type != WAND && op->type != HORN && op->type != ROD)
1502 
1503  if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)) {
1504  if (who->type == PLAYER) {
1506  "Oops, it feels deadly cold!", NULL);
1508  }
1509  }
1510  if (who->type == PLAYER) {
1512  }
1513  return 0;
1514 }
1515 
1526 int auto_apply(object *op) {
1527  object *tmp = NULL, *tmp2;
1528  int i;
1529 
1530  switch (op->type) {
1531  case SHOP_FLOOR:
1532  if (!HAS_RANDOM_ITEMS(op))
1533  return 0;
1534  do {
1535  i = 10; /* let's give it 10 tries */
1536  while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? (int)op->stats.exp : MAX(op->map->difficulty, 5))) == NULL
1537  && --i)
1538  ;
1539  if (tmp == NULL)
1540  return 0;
1541  if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {
1542  free_object(tmp);
1543  tmp = NULL;
1544  }
1545  } while (!tmp);
1546  tmp->x = op->x;
1547  tmp->y = op->y;
1548  SET_FLAG(tmp, FLAG_UNPAID);
1549  insert_ob_in_map(tmp, op->map, NULL, 0);
1551  identify(tmp);
1552  break;
1553 
1554  case TREASURE:
1555  if (QUERY_FLAG(op, FLAG_IS_A_TEMPLATE))
1556  return 0;
1557  while ((op->stats.hp--) > 0)
1558  create_treasure(op->randomitems, op, op->map ? GT_ENVIRONMENT : 0, op->stats.exp ? (int)op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
1559 
1560  /* If we generated an object and put it in this object's
1561  * inventory, move it to the parent object as the current
1562  * object is about to disappear. An example of this item
1563  * is the random_ *stuff that is put inside other objects.
1564  */
1565  for (tmp = op->inv; tmp; tmp = tmp2) {
1566  tmp2 = tmp->below;
1567  remove_ob(tmp);
1568  if (op->env)
1569  insert_ob_in_ob(tmp, op->env);
1570  else
1571  free_object(tmp);
1572  }
1573  remove_ob(op);
1574  free_object(op);
1575  break;
1576  }
1577  return tmp ? 1 : 0;
1578 }
1579 
1591  object *tmp, *above = NULL;
1592  int x, y;
1593 
1594  if (m == NULL)
1595  return;
1596 
1597  for (x = 0; x < MAP_WIDTH(m); x++)
1598  for (y = 0; y < MAP_HEIGHT(m); y++)
1599  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL; tmp = above) {
1600  above = tmp->above;
1601 
1602  if (tmp->inv) {
1603  object *invtmp, *invnext;
1604 
1605  for (invtmp = tmp->inv; invtmp != NULL; invtmp = invnext) {
1606  invnext = invtmp->below;
1607 
1608  if (QUERY_FLAG(invtmp, FLAG_AUTO_APPLY))
1609  auto_apply(invtmp);
1610  else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS(invtmp)) {
1611  while ((invtmp->stats.hp--) > 0)
1612  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
1613  invtmp->randomitems = NULL;
1614  } else if (invtmp && invtmp->arch
1615  && invtmp->type != TREASURE
1616  && invtmp->type != SPELL
1617  && invtmp->type != CLASS
1618  && HAS_RANDOM_ITEMS(invtmp)) {
1619  create_treasure(invtmp->randomitems, invtmp, 0, m->difficulty, 0);
1620  /* Need to clear this so that we never try to
1621  * create treasure again for this object
1622  */
1623  invtmp->randomitems = NULL;
1624  }
1625  }
1626  /* This is really temporary - the code at the
1627  * bottom will also set randomitems to null.
1628  * The problem is there are bunches of maps/players
1629  * already out there with items that have spells
1630  * which haven't had the randomitems set
1631  * to null yet.
1632  * MSW 2004-05-13
1633  *
1634  * And if it's a spellbook, it's better to set
1635  * randomitems to NULL too, else you get two spells
1636  * in the book ^_-
1637  * Ryo 2004-08-16
1638  */
1639  if (tmp->type == WAND
1640  || tmp->type == ROD
1641  || tmp->type == SCROLL
1642  || tmp->type == HORN
1643  || tmp->type == FIREWALL
1644  || tmp->type == POTION
1645  || tmp->type == ALTAR
1646  || tmp->type == SPELLBOOK)
1647  tmp->randomitems = NULL;
1648  }
1649 
1650  if (QUERY_FLAG(tmp, FLAG_AUTO_APPLY))
1651  auto_apply(tmp);
1652  else if ((tmp->type == TREASURE || (tmp->type == CONTAINER))
1653  && HAS_RANDOM_ITEMS(tmp)) {
1654  while ((tmp->stats.hp--) > 0)
1655  create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
1656  tmp->randomitems = NULL;
1657  } else if (tmp->type == TIMED_GATE) {
1658  object *head = tmp->head != NULL ? tmp->head : tmp;
1659 
1660  if (QUERY_FLAG(head, FLAG_IS_LINKED)) {
1661  tmp->speed = 0;
1662  update_ob_speed(tmp);
1663  }
1664  }
1665  /* This function can be called everytime a map is loaded,
1666  * even when swapping back in. As such, we don't want to
1667  * create the treasure over and ove again, so after we
1668  * generate the treasure, blank out randomitems so if it
1669  * is swapped in again, it won't make anything. This is a
1670  * problem for the above objects, because they have
1671  * counters which say how many times to make the treasure.
1672  */
1673  else if (tmp
1674  && tmp->arch
1675  && tmp->type != PLAYER
1676  && tmp->type != TREASURE
1677  && tmp->type != SPELL
1678  && tmp->type != PLAYER_CHANGER
1679  && tmp->type != CLASS
1680  && HAS_RANDOM_ITEMS(tmp)) {
1681  create_treasure(tmp->randomitems, tmp, GT_APPLY, m->difficulty, 0);
1682  tmp->randomitems = NULL;
1683  }
1684  }
1685 
1686  for (x = 0; x < MAP_WIDTH(m); x++)
1687  for (y = 0; y < MAP_HEIGHT(m); y++)
1688  for (tmp = GET_MAP_OB(m, x, y); tmp != NULL; tmp = tmp->above)
1689  if (tmp->above
1690  && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
1691  check_trigger(tmp, tmp->above);
1692 }
1693 
1708 void scroll_failure(object *op, int failure, int power) {
1709  if (abs(failure/4) > power)
1710  power = abs(failure/4); /* set minimum effect */
1711 
1712  if (failure <= -1 && failure > -15) {/* wonder */
1713  object *tmp;
1714 
1716  "Your spell warps!", NULL);
1718  cast_wonder(op, op, 0, tmp);
1719  if (op->stats.sp < 0)
1720  /* For some reason the sp can become negative here. */
1721  op->stats.sp = 0;
1722  free_object(tmp);
1723  return;
1724  }
1725 
1727  if (failure <= -35 && failure > -60) { /* confusion */
1729  "The magic recoils on you!", NULL);
1730  confuse_living(op, op, power);
1731  return;
1732  }
1733 
1734  if (failure <= -60 && failure > -70) {/* paralysis */
1736  "The magic recoils and paralyzes you!", NULL);
1737  paralyze_living(op, op, power);
1738  return;
1739  }
1740 
1741  if (failure <= -70 && failure > -80) {/* blind */
1743  "The magic recoils on you!", NULL);
1744  blind_living(op, op, power);
1745  return;
1746  }
1747 
1748  if (failure <= -80) {/* blast the immediate area */
1749  object *tmp;
1750 
1752  cast_magic_storm(op, tmp, power);
1754  "You unlease uncontrolled mana!", NULL);
1755  free_object(tmp);
1756  return;
1757  }
1758  }
1759  /* Either no spell failure on this server, or wrong values,
1760  * in any case let's punish.
1761  */
1763  "Your mana is drained!", NULL);
1764  op->stats.sp -= random_roll(0, power-1, op, PREFER_LOW);
1765  if (op->stats.sp < 0)
1766  op->stats.sp = 0;
1767 }
1768 
1776 void apply_changes_to_player(object *pl, object *change) {
1777  int excess_stat = 0; /* if the stat goes over the maximum
1778  * for the race, put the excess stat some
1779  * where else.
1780  */
1781 
1782  switch (change->type) {
1783  case CLASS: {
1784  living *stats = &(pl->contr->orig_stats);
1785  living *ns = &(change->stats);
1786  object *walk;
1787  int flag_change_face = 1;
1788 
1789  /* the following code assigns stats up to the stat max
1790  * for the race, and if the stat max is exceeded,
1791  * tries to randomly reassign the excess stat
1792  */
1793  int i, j;
1794  for (i = 0; i < NUM_STATS; i++) {
1795  sint8 stat = get_attr_value(stats, i);
1796  int race_bonus = get_attr_value(&(pl->arch->clone.stats), i);
1797 
1798  stat += get_attr_value(ns, i);
1799  if (stat > 20+race_bonus) {
1800  excess_stat++;
1801  stat = 20+race_bonus;
1802  }
1803  set_attr_value(stats, i, stat);
1804  }
1805 
1806  for (j = 0; excess_stat > 0 && j < 100; j++) {
1807  /* try 100 times to assign excess stats */
1808  int i = rndm(0, 6);
1809  int stat = get_attr_value(stats, i);
1810  int race_bonus = get_attr_value(&(pl->arch->clone.stats), i);
1811 
1812  if (i == CHA)
1813  continue; /* exclude cha from this */
1814  if (stat < 20+race_bonus) {
1815  change_attr_value(stats, i, 1);
1816  excess_stat--;
1817  }
1818  }
1819 
1820  /* insert the randomitems from the change's treasurelist into
1821  * the player ref: player.c
1822  */
1823  if (change->randomitems != NULL)
1824  give_initial_items(pl, change->randomitems);
1825 
1826 
1827  /* set up the face, for some races. */
1828 
1829  /* first, look for the force object banning changing the
1830  * face. Certain races never change face with class.
1831  */
1832  for (walk = pl->inv; walk != NULL; walk = walk->below)
1833  if (!strcmp(walk->name, "NOCLASSFACECHANGE"))
1834  flag_change_face = 0;
1835 
1836  if (flag_change_face) {
1837  pl->animation_id = GET_ANIM_ID(change);
1838  pl->face = change->face;
1839 
1840  if (QUERY_FLAG(change, FLAG_ANIMATE))
1841  SET_FLAG(pl, FLAG_ANIMATE);
1842  else
1843  CLEAR_FLAG(pl, FLAG_ANIMATE);
1844  }
1845 
1846  if (change->anim_suffix) {
1847  char buf[MAX_BUF];
1848  int anim;
1849 
1850  snprintf(buf, MAX_BUF, "%s_%s", animations[pl->animation_id].name, change->anim_suffix);
1851  anim = try_find_animation(buf);
1852  if (anim) {
1853  pl->animation_id = anim;
1854  pl->anim_speed = -1;
1855  CLEAR_FLAG(pl, FLAG_ANIMATE);
1856  animate_object(pl, pl->facing);
1857  }
1858  }
1859 
1860  /* check the special case of can't use weapons */
1861  /*if(QUERY_FLAG(change, FLAG_USE_WEAPON))
1862  * CLEAR_FLAG(pl, FLAG_USE_WEAPON);
1863  */
1864  if (!strcmp(change->name, "monk"))
1866 
1867  break;
1868  }
1869  }
1870 }
1871 
1872 void legacy_apply_container(object *op, object *sack) {
1873  apply_container(op, sack);
1874 }
#define AP_UNAPPLY
Definition: define.h:1010
#define UPD_FLAGS
Definition: newclient.h:255
#define MSG_TYPE_APPLY_PROHIBITION
Definition: newclient.h:523
#define RING
Definition: define.h:232
signed char sint8
Definition: global.h:80
#define NUM_BODY_LOCATIONS
Definition: object.h:41
Definition: player.h:146
#define FLAG_DAMNED
Definition: define.h:614
#define FLAG_IS_FLOOR
Definition: define.h:599
#define FLAG_UNPAID
Definition: define.h:532
#define FLAG_IS_LINKED
Definition: define.h:612
MoveType move_type
Definition: object.h:277
#define INS_BELOW_ORIGINATOR
Definition: object.h:398
int change_skill(object *who, object *new_skill, int flag)
Definition: skill_util.c:301
void legacy_apply_container(object *op, object *sack)
Definition: apply.c:1872
#define FALSE
Definition: exp.c:42
const char * get_ob_key_value(const object *op, const char *const key)
Definition: object.c:3701
MoveType move_on
Definition: object.h:280
#define CAN_APPLY_UNAPPLY_CHOICE
Definition: define.h:1059
object * check_spell_known(object *op, const char *name)
Definition: spell_util.c:408
const char * race
Definition: object.h:171
void esrv_send_item(object *pl, object *op)
Definition: standalone.c:197
#define SET_FLAG(xyz, p)
Definition: define.h:510
#define FABS(x)
Definition: define.h:61
#define MSG_TYPE_APPLY_FAILURE
Definition: newclient.h:519
New_Face * new_faces
Definition: image.c:38
#define WAND
Definition: define.h:291
const char * name
Definition: face.h:55
#define FLAG_USE_ARMOUR
Definition: define.h:592
void apply_changes_to_player(object *pl, object *change)
Definition: apply.c:1776
struct obj * container
Definition: object.h:149
void do_forget_spell(object *op, const char *spell)
Definition: apply.c:440
#define METHOD_ERROR
Definition: ob_methods.h:44
object * insert_ob_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1761
sint8 get_attr_value(const living *stats, int attr)
Definition: living.c:377
#define FLAG_READY_RANGE
Definition: define.h:595
void esrv_update_item(int flags, object *pl, object *op)
Definition: standalone.c:200
struct treasureliststruct * randomitems
Definition: object.h:236
#define MAP_HEIGHT(m)
Definition: map.h:99
object clone
Definition: object.h:326
#define CAN_APPLY_NEVER
Definition: define.h:1054
sint16 invisible
Definition: object.h:211
#define PREFER_LOW
Definition: define.h:909
#define POTION
Definition: define.h:117
rangetype shoottype
Definition: player.h:153
object * merge_ob(object *op, object *top)
Definition: object.c:1724
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
const char * slaying
Definition: object.h:172
#define IS_WEAPON(op)
Definition: define.h:449
void esrv_send_inventory(object *pl, object *op)
Definition: item.c:307
#define SCROLL
Definition: define.h:293
object * ranges[range_size]
Definition: player.h:157
#define MSG_TYPE_VICTIM_WAS_HIT
Definition: newclient.h:567
uint8 subtype
Definition: object.h:190
#define FLAG_USE_WEAPON
Definition: define.h:593
sint64 exp
Definition: living.h:88
#define SPELL_WONDER
Definition: spells.h:190
void blind_living(object *op, object *hitter, int dam)
Definition: attack.c:2276
struct obj * above
Definition: object.h:146
#define BOOTS
Definition: define.h:281
void player_apply_below(object *pl)
Definition: apply.c:619
Definition: living.h:77
#define CLOAK
Definition: define.h:268
int should_director_abort(object *op, object *victim)
Definition: apply.c:81
sint16 x
Definition: object.h:179
#define GIRDLE
Definition: define.h:295
method_ret ob_apply(object *op, object *applier, int aflags)
Definition: ob_methods.c:59
void scroll_failure(object *op, int failure, int power)
Definition: apply.c:1708
int set_object_face_main(object *op)
Definition: apply.c:160
sint16 sp
Definition: living.h:83
void change_attr_value(living *stats, int attr, sint8 value)
Definition: living.c:336
#define SCRIPT_FIX_ALL
Definition: global.h:450
#define AP_APPLY
Definition: define.h:1009
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
#define FLAG_USE_SHIELD
Definition: define.h:533
struct archt * other_arch
Definition: object.h:264
#define ARMOUR
Definition: define.h:128
#define FLAG_USE_RING
Definition: define.h:594
#define MSG_TYPE_APPLY_UNAPPLY
Definition: newclient.h:517
#define PLAYER
Definition: define.h:113
void esrv_add_spells(player *pl, object *spell)
Definition: request.c:1812
sint16 hp
Definition: living.h:81
#define MSG_TYPE_APPLY_BADBODY
Definition: newclient.h:522
int manual_apply(object *op, object *tmp, int aflag)
Definition: apply.c:512
#define SOUND_TYPE_ITEM
Definition: sounds.h:37
#define NDI_NAVY
Definition: newclient.h:197
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.c:499
#define LOOSE_MANA
Definition: spells.h:189
#define CAN_APPLY_UNAPPLY_MULT
Definition: define.h:1058
#define MOVE_ALL
Definition: define.h:706
void paralyze_living(object *op, object *hitter, int dam)
Definition: attack.c:2324
int rndm(int min, int max)
Definition: utils.c:174
#define AMULET
Definition: define.h:153
uint16 number
Definition: face.h:43
void handle_apply_yield(object *tmp)
Definition: apply.c:131
#define FLAG_READY_SKILL
Definition: define.h:630
struct obj * chosen_skill
Definition: object.h:237
int change_abil(object *op, object *tmp)
Definition: living.c:443
const char * name
Definition: face.h:48
#define CAN_APPLY_UNAPPLY
Definition: define.h:1057
void remove_ob(object *op)
Definition: object.c:1515
object * last_used
Definition: player.h:208
int apply_special(object *who, object *op, int aflags)
Definition: apply.c:1139
#define SHOP_FLOOR
Definition: define.h:230
void confuse_living(object *op, object *hitter, int dam)
Definition: attack.c:2237
#define AP_IGNORE_CURSE
Definition: define.h:1016
sint32 weight_limit
Definition: object.h:217
#define TRANSPORT
Definition: define.h:114
#define CAN_APPLY_RESTRICTION
Definition: define.h:1055
uint8 spell_failure_effects
Definition: global.h:357
object * create_archetype(const char *name)
Definition: arch.c:625
unapplymode unapply
Definition: player.h:162
static object * get_item_from_body_location(object *start, int loc)
Definition: apply.c:814
#define MSG_TYPE_VICTIM
Definition: newclient.h:336
sint32 weight
Definition: object.h:216
#define METHOD_OK
Definition: ob_methods.h:42
#define AP_PRINT
Definition: define.h:1017
sint16 item_power
Definition: player.h:171
struct mapdef * map
Definition: object.h:155
uint32 last_used_id
Definition: player.h:209
void set_attr_value(living *stats, int attr, sint8 value)
Definition: living.c:296
#define HORN
Definition: define.h:147
#define EVENT_CLOSE
Definition: plugin.h:72
object * transport
Definition: player.h:249
#define MOVE_FLYING
Definition: define.h:703
void identify(object *op)
Definition: item.c:1447
void fix_auto_apply(mapstruct *m)
Definition: apply.c:1590
sint32 carrying
Definition: object.h:218
const char * name
Definition: object.h:167
living orig_stats
Definition: player.h:203
struct obj * env
Definition: object.h:151
#define SPELL
Definition: define.h:283
struct obj * below
Definition: object.h:145
uint16 difficulty
Definition: map.h:364
#define FLAG_IS_A_TEMPLATE
Definition: define.h:671
#define TRUE
Definition: exp.c:41
struct obj * current_weapon
Definition: object.h:221
uint32 nrof
Definition: object.h:184
int can_apply_object(object *who, object *op)
Definition: apply.c:955
#define AP_NOPRINT
Definition: define.h:1020
MoveType move_off
Definition: object.h:281
EXTERN Animations * animations
Definition: global.h:241
int transport_can_hold(const object *transport, const object *op, int nrof)
Definition: apply.c:64
sint8 facing
Definition: object.h:186
sint16 y
Definition: object.h:179
struct pl * contr
Definition: object.h:134
sint8 item_power
Definition: object.h:213
#define WEAPON
Definition: define.h:127
int try_find_animation(const char *name)
Definition: anim.c:161
void player_unready_range_ob(player *pl, object *ob)
Definition: player.c:4221
void play_sound_map(sint8 sound_type, object *emitter, int dir, const char *action)
Definition: sounds.c:90
#define CHA
Definition: living.h:45
void cast_magic_storm(object *op, object *tmp, int lvl)
Definition: spell_effect.c:55
#define UPD_NROF
Definition: newclient.h:261
#define TRIGGER_PEDESTAL
Definition: define.h:144
#define MAX(x, y)
Definition: define.h:70
float speed
Definition: object.h:181
int cast_wonder(object *op, object *caster, int dir, object *spell_ob)
Definition: spell_effect.c:997
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
static int unapply_for_ob(object *who, object *op, int aflags)
Definition: apply.c:850
#define MSG_TYPE_APPLY
Definition: newclient.h:330
#define TRIGGER_BUTTON
Definition: define.h:142
#define FLAG_WIZ
Definition: define.h:527
#define FLAG_BEEN_APPLIED
Definition: define.h:620
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
#define MAX_BUF
Definition: define.h:81
#define METHOD_UNHANDLED
Definition: ob_methods.h:43
void give_initial_items(object *pl, treasurelist *items)
Definition: player.c:688
#define GLOVES
Definition: define.h:282
#define IS_SHIELD(op)
Definition: define.h:456
object * get_object(void)
Definition: object.c:921
void drop(object *op, object *tmp)
Definition: c_object.c:943
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
#define BUILDER
Definition: define.h:334
int check_weapon_power(const object *who, int improvs)
Definition: apply.c:1076
#define BRACERS
Definition: define.h:286
const char * skill
Definition: object.h:174
sint32 last_eat
Definition: object.h:207
#define CLASS
Definition: define.h:149
#define FLAG_READY_WEAPON
Definition: define.h:631
#define LAMP
Definition: define.h:263
#define TIMED_GATE
Definition: define.h:138
static int unapply_special(object *who, object *op, int aflags)
Definition: apply.c:675
void animate_object(object *op, int dir)
Definition: anim.c:186
#define FLAG_KNOWN_CURSED
Definition: define.h:617
#define MSG_TYPE_APPLY_CURSED
Definition: newclient.h:520
const char * sstring
Definition: global.h:84
#define AP_BASIC_FLAGS
Definition: define.h:1012
#define FLAG_CURSED
Definition: define.h:613
sint8 body_info[NUM_BODY_LOCATIONS]
Definition: object.h:223
#define SHIELD
Definition: define.h:145
#define AP_NO_MERGE
Definition: define.h:1015
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
sint8 body_used[NUM_BODY_LOCATIONS]
Definition: object.h:224
#define FLAG_ANIMATE
Definition: define.h:538
#define FLAG_AUTO_APPLY
Definition: define.h:546
#define MSG_TYPE_APPLY_SUCCESS
Definition: newclient.h:518
#define ALTAR
Definition: define.h:130
#define NUM_STATS
Definition: living.h:48
#define INS_NO_MERGE
Definition: object.h:394
#define CONTAINER
Definition: define.h:306
int set_ob_key_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:3826
#define FIREWALL
Definition: define.h:204
int apply_container(object *op, object *sack)
Definition: apply.c:230
tag_t count
Definition: object.h:157
#define EVENT_APPLY
Definition: plugin.h:62
living stats
Definition: object.h:219
struct archt * arch
Definition: object.h:263
#define MAP_WIDTH(m)
Definition: map.h:97
void clear_skill(object *who)
Definition: skill_util.c:340
#define SKILL
Definition: define.h:157
struct Settings settings
Definition: init.c:48
void esrv_remove_spell(player *pl, object *spell)
Definition: request.c:1725
#define METHOD_SILENT_ERROR
Definition: ob_methods.h:45
#define FLAG_APPLIED
Definition: define.h:531
int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: standalone.c:225
const char * anim_suffix
Definition: object.h:169
#define MSG_TYPE_APPLY_ERROR
Definition: newclient.h:516
uint16 animation_id
Definition: object.h:267
#define FLAG_STARTEQUIP
Definition: define.h:564
int auto_apply(object *op)
Definition: apply.c:1526
void update_ob_speed(object *op)
Definition: object.c:1008
#define GET_ANIM_ID(ob)
Definition: global.h:249
#define BOW
Definition: define.h:126
#define UPD_WEIGHT
Definition: newclient.h:256
void play_sound_player_only(player *pl, sint8 sound_type, object *emitter, int dir, const char *action)
Definition: sounds.c:40
#define GET_MAP_OB(M, X, Y)
Definition: map.h:193
#define TREASURE
Definition: define.h:116
uint8 anim_speed
Definition: object.h:268
uint8 personalized_blessings
Definition: global.h:401
void do_learn_spell(object *op, object *spell, int special_prayer)
Definition: apply.c:398
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
#define HELMET
Definition: define.h:146
void apply_anim_suffix(object *who, sstring suffix)
Definition: anim.c:289
int player_apply(object *pl, object *op, int aflag, int quiet)
Definition: apply.c:557
struct obj * head
Definition: object.h:154
#define FLAG_READY_BOW
Definition: define.h:596
#define SPELLBOOK
Definition: define.h:266
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
object * get_split_ob(object *orig_ob, uint32 nr, char *err, size_t size)
Definition: object.c:2313
#define FLAG_USE_RANGE
Definition: define.h:589
#define ROD
Definition: define.h:115
#define FLAG_WAS_WIZ
Definition: define.h:530
#define IS_ARMOR(op)
Definition: define.h:452
#define SKILL_TOOL
Definition: define.h:236
int check_trigger(object *op, object *cause)
Definition: button.c:525
object * find_key(object *pl, object *container, object *door)
Definition: player.c:2278
void copy_object(object *op2, object *op)
Definition: object.c:758
#define UPD_FACE
Definition: newclient.h:257
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
object * generate_treasure(treasurelist *t, int difficulty)
Definition: treasure.c:524
void free_object(object *ob)
Definition: object.c:1238
#define IS_COMBAT_SKILL(num)
Definition: skills.h:116
Definition: map.h:346
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:51
New_Face * face
Definition: object.h:183
static int set_object_face_other(object *op)
Definition: apply.c:185
sint16 level
Definition: object.h:202
void fix_object(object *op)
Definition: living.c:900
unsigned find_face(const char *name, unsigned error)
Definition: image.c:324
#define SOUND_TYPE_SPELL
Definition: sounds.h:36
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.c:207
#define PLAYER_CHANGER
Definition: define.h:194
float item_power_factor
Definition: global.h:392
const char * name
Definition: object.h:322
#define FLAG_USE_BOW
Definition: define.h:590
#define HAS_RANDOM_ITEMS(op)
Definition: define.h:470
uint8 type
Definition: object.h:189
static int check_race_restrictions(object *who, object *item)
Definition: apply.c:472