Crossfire Server, Branches 1.12  R18729
c_object.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_c_object_c =
3  * "$Id: c_object.c 12045 2009-07-09 23:07:04Z akirschbaum $";
4  */
5 /*
6  CrossFire, A Multiplayer game for X-windows
7 
8  Copyright (C) 2002-2007 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 author can be reached via e-mail to crossfire-devel@real-time.com
26 */
27 
34 #include <global.h>
35 #include <loader.h>
36 #include <skills.h>
37 #ifndef __CEXTRACT__
38 #include <sproto.h>
39 #endif
40 #include <living.h>
41 #include <math.h>
42 
43 static void set_pickup_mode(const object *op, int i);
44 
45 /*
46  * Object id parsing functions
47  */
48 
50 #define OBLINKMALLOC(p) if (!((p) = (objectlink *)malloc(sizeof(objectlink)))) \
51  fatal(OUT_OF_MEMORY);
52 
70 static object *find_best_apply_object_match(object *start, object *pl, const char *params, int aflag) {
71  object *tmp, *best = NULL;
72  int match_val = 0, tmpmatch;
73 
74  for (tmp = start; tmp; tmp = tmp->below) {
75  if (tmp->invisible)
76  continue;
77  if ((aflag == AP_APPLY) && (QUERY_FLAG(tmp, FLAG_APPLIED)))
78  continue;
79  if ((aflag == AP_UNAPPLY) && (!QUERY_FLAG(tmp, FLAG_APPLIED)))
80  continue;
81  if ((tmpmatch = item_matched_string(pl, tmp, params)) > match_val) {
82  match_val = tmpmatch;
83  best = tmp;
84  }
85  }
86  return best;
87 }
88 
99 static object *find_best_object_match(object *pl, const char *params) {
100  return find_best_apply_object_match(pl->inv, pl, params, AP_NULL);
101 }
102 
113 int command_uskill(object *pl, char *params) {
114  if (!params) {
116  "Usage: use_skill <skill name>", NULL);
117  return 0;
118  }
119  return use_skill(pl, params);
120 }
121 
132 int command_rskill(object *pl, char *params) {
133  object *skill;
134 
135  if (!params) {
137  "Usage: ready_skill <skill name>", NULL);
138  return 0;
139  }
140  skill = find_skill_by_name(pl, params);
141 
142  if (!skill) {
144  "You have no knowledge of the skill %s",
145  "You have no knowledge of the skill %s",
146  params);
147  return 0;
148  }
149  return change_skill(pl, skill, 0);
150 }
151 
152 
153 /* These functions (command_search, command_disarm) are really juse wrappers for
154  * things like 'use_skill ...'). In fact, they should really be obsoleted
155  * and replaced with those.
156  */
167 int command_search(object *op, char *params) {
168  return use_skill(op, skill_names[SK_FIND_TRAPS]);
169 }
170 
181 int command_disarm(object *op, char *params) {
183 }
184 
198 int command_throw(object *op, char *params) {
199  object *skop;
200 
202  if (skop)
203  return do_skill(op, op, skop, op->facing, params);
204  else {
206  "You have no knowledge of the skill throwing.", NULL);
207  }
208  return 0;
209 }
210 
221 int command_apply(object *op, char *params) {
222  if (!params) {
223  player_apply_below(op);
224  return 0;
225  } else {
226  int aflag = 0;
227  object *inv = op->inv;
228 
229  while (*params == ' ')
230  params++;
231  if (!strncmp(params, "-a ", 3)) {
232  aflag = AP_APPLY;
233  params += 3;
234  }
235  if (!strncmp(params, "-u ", 3)) {
236  aflag = AP_UNAPPLY;
237  params += 3;
238  }
239  if (!strncmp(params, "-b ", 3)) {
240  params += 3;
241  if (op->container)
242  inv = op->container->inv;
243  else {
244  inv = op;
245  while (inv->above)
246  inv = inv->above;
247  }
248  }
249  while (*params == ' ')
250  params++;
251 
252  inv = find_best_apply_object_match(inv, op, params, aflag);
253  if (inv) {
254  player_apply(op, inv, aflag, 0);
255  } else
257  "Could not find any match to the %s.",
258  "Could not find any match to the %s.",
259  params);
260  }
261  return 0;
262 }
263 
282 int sack_can_hold(const object *pl, const object *sack, const object *op, uint32 nrof) {
283  char name[MAX_BUF];
284  query_name(sack, name, MAX_BUF);
285 
286  if (!QUERY_FLAG(sack, FLAG_APPLIED)) {
288  "The %s is not active.",
289  "The %s is not active.",
290  name);
291  return 0;
292  }
293  if (sack == op) {
295  "You can't put the %s into itself.",
296  "You can't put the %s into itself.",
297  name);
298  return 0;
299  }
300  if (sack->race
301  && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type))) {
303  "You can put only %s into the %s.",
304  "You can put only %s into the %s.",
305  sack->race, name);
306  return 0;
307  }
308  if (op->type == SPECIAL_KEY && sack->slaying && op->slaying) {
310  "You can't want put the key into %s.",
311  "You can't want put the key into %s.",
312  name);
313  return 0;
314  }
315  if (sack->weight_limit && sack->carrying+(nrof ? nrof : 1)
316  *(op->weight+(op->type == CONTAINER ? (op->carrying*op->stats.Str) : 0))
317  *(100-sack->stats.Str)/100 > sack->weight_limit) {
319  "That won't fit in the %s!",
320  "That won't fit in the %s!",
321  name);
322  return 0;
323  }
324  /* All other checks pass, must be OK */
325  return 1;
326 }
327 
340 static void pick_up_object(object *pl, object *op, object *tmp, int nrof) {
341  /* buf needs to be big (more than 256 chars) because you can get
342  * very long item names.
343  */
344  char buf[HUGE_BUF], name[MAX_BUF];
345  object *env = tmp->env;
346  uint32 weight, effective_weight_limit;
347  int tmp_nrof = tmp->nrof ? tmp->nrof : 1;
348 
349  /* IF the player is flying & trying to take the item out of a container
350  * that is in his inventory, let him. tmp->env points to the container
351  * (sack, luggage, etc), tmp->env->env then points to the player (nested
352  * containers not allowed as of now)
353  */
354  if ((pl->move_type&MOVE_FLYING)
355  && !QUERY_FLAG(pl, FLAG_WIZ)
356  && get_player_container(tmp) != pl) {
358  "You are levitating, you can't reach the ground!", NULL);
359  return;
360  }
361  if (QUERY_FLAG(tmp, FLAG_NO_DROP))
362  return;
363 
364  if (QUERY_FLAG(tmp, FLAG_WAS_WIZ) && !QUERY_FLAG(pl, FLAG_WAS_WIZ)) {
366  "The object disappears in a puff of smoke! It must have been an illusion.",
367  NULL);
368  if (!QUERY_FLAG(tmp, FLAG_REMOVED))
369  remove_ob(tmp);
370  free_object(tmp);
371  return;
372  }
373 
374  if (nrof > tmp_nrof || nrof == 0)
375  nrof = tmp_nrof;
376 
377  /* Figure out how much weight this object will add to the player */
378  weight = tmp->weight*nrof;
379  if (tmp->inv)
380  weight += tmp->carrying*(100-tmp->stats.Str)/100;
381 
382  if (pl->stats.Str <= MAX_STAT)
383  effective_weight_limit = weight_limit[pl->stats.Str];
384  else
385  effective_weight_limit = weight_limit[MAX_STAT];
386 
387  if ((pl->weight+pl->carrying+weight) > effective_weight_limit) {
389  "That item is too heavy for you to pick up.", NULL);
390  return;
391  }
392 
394  SET_FLAG(tmp, FLAG_WAS_WIZ);
395 
396  if (nrof != tmp_nrof) {
397  char failure[MAX_BUF];
398 
399  tmp = get_split_ob(tmp, nrof, failure, sizeof(failure));
400  if (!tmp) {
402  failure, NULL);
403  return;
404  }
405  } else {
406  /* If the object is in a container, send a delete to the client.
407  * - we are moving all the items from the container to elsewhere,
408  * so it needs to be deleted.
409  */
410  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
411  remove_ob(tmp); /* Unlink it */
412  }
413  }
414  query_name(tmp, name, MAX_BUF);
415 
416  if (QUERY_FLAG(tmp, FLAG_UNPAID)) {
417  char *value = stringbuffer_finish(query_cost_string(tmp, pl, F_BUY|F_SHOP, NULL));
418  snprintf(buf, sizeof(buf), "%s will cost you %s.", name, value);
419  free(value);
420  } else
421  snprintf(buf, sizeof(buf), "You pick up the %s.", name);
422 
423  /* Now item is about to be picked. */
424  if (execute_event(tmp, EVENT_PICKUP, pl, op, NULL, SCRIPT_FIX_ALL) != 0)
425  return;
426 
428  buf, NULL);
429 
430  tmp = insert_ob_in_ob(tmp, op);
431 
432  /* All the stuff below deals with client/server code, and is only
433  * usable by players
434  */
435  if (pl->type != PLAYER)
436  return;
437 
438  /* Additional weight changes speed, etc */
439  fix_object(pl);
440 
441  /* These are needed to update the weight for the container we
442  * are putting the object in.
443  */
444  if (op != pl) {
445  esrv_update_item(UPD_WEIGHT, pl, op);
446  esrv_update_item(UPD_WEIGHT, pl, pl);
447  }
448 
449  /* Update the container the object was in */
450  if (env && env != pl && env != op)
451  esrv_update_item(UPD_WEIGHT, pl, env);
452 }
453 
462 void pick_up(object *op, object *alt) {
463 /* modified slightly to allow monsters use this -b.t. 5-31-95 */
464  object *tmp = NULL, *tmp1;
465  mapstruct *tmp_map = NULL;
466  int count;
467  tag_t tag;
468 
469  /* Decide which object to pick. */
470  if (alt) {
471  if (!can_pick(op, alt)) {
473  "You can't pick up the %s.",
474  "You can't pick up the %s.",
475  alt->name);
476  return;
477  }
478  tmp = alt;
479  } else {
480  if (op->below == NULL || !can_pick(op, op->below)) {
482  "There is nothing to pick up here.", NULL);
483  return;
484  }
485  tmp = op->below;
486  }
487 
488  /* it is possible that the object is a thrown object and is flying about.
489  * in that case, what we want to pick up is the payload. Objects
490  * that are thrown are encapsulated into a thrown object.
491  * stop_item() returns the payload (unlinked from map) and gets rid of the
492  * container object. If this object isn't picked up, we need to insert
493  * it back on the map.
494  * A bug here is that even attempting to pick up one of these objects will
495  * result in this logic being called even if player is unable to pick it
496  * up.
497  */
498 
499  tmp_map = tmp->map;
500  tmp1 = stop_item(tmp);
501  if (tmp1 == NULL)
502  return;
503 
504  /* If it is a thrown object, insert it back into the map here.
505  * makes life easier further along. Do no merge so pick up code
506  * behaves more sanely.
507  */
508  if (tmp1 != tmp) {
509  tmp = insert_ob_in_map(tmp1, tmp_map, op, INS_NO_MERGE);
510  }
511 
512  if (tmp == NULL) return;
513 
514  if (!can_pick(op, tmp)) return;
515 
516  /* Establish how many of the object we are picking up */
517  if (op->type == PLAYER) {
518  count = op->contr->count;
519  if (count == 0)
520  count = tmp->nrof;
521  } else
522  count = tmp->nrof;
523 
524  /* container is open, so use it */
525  if (op->container) {
526  alt = op->container;
527  if (alt != tmp->env && !sack_can_hold(op, alt, tmp, count)) return;
528  } else {
529  /* non container pickup. See if player has any
530  * active containers.
531  */
532  object *container=NULL;
533 
534  /* Look for any active containers that can hold this item.
535  * we cover two cases here - the perfect match case, where we
536  * break out of the loop, and the general case (have a container),
537  * Moved this into a single loop - reduces redundant code, is
538  * more efficient and easier to follow. MSW 2009-04-06
539  */
540  for (alt = op->inv; alt; alt = alt->below) {
541  if (alt->type == CONTAINER
542  && QUERY_FLAG(alt, FLAG_APPLIED)
543  && sack_can_hold(NULL, alt, tmp, count)) {
544  if (alt->race && alt->race == tmp->race) {
545  break; /* perfect match */
546  }
547  else if (!container) {
548  container = alt;
549  }
550  }
551  }
552  /* Note container could be null, but no reason to check for it */
553  if (!alt) alt=container;
554 
555  if (!alt)
556  alt = op; /* No free containers */
557  }
558  /* see if this object is already in this container. If so,
559  * move it to player inventory from this container.
560  */
561  if (tmp->env == alt) {
562  alt = op;
563  }
564 
565  /* Don't allow players to be put into containers. Instead,
566  * just put them in the players inventory.
567  */
568  if (tmp->type == CONTAINER && alt->type==CONTAINER) {
569  alt = op;
570  }
571 #ifdef PICKUP_DEBUG
572  LOG(llevDebug, "Pick_up(): %s picks %s (%d) and inserts it %s.\n", op->name, tmp->name, op->contr->count, alt->name);
573 #endif
574 
575  /* startequip items are not allowed to be put into containers
576  * Not sure why we have this limitation
577  */
578  if (op->type == PLAYER
579  && alt->type == CONTAINER
580  && QUERY_FLAG(tmp, FLAG_STARTEQUIP)) {
582  "This object cannot be put into containers!", NULL);
583  return;
584  }
585 
586  tag = tmp->count;
587  pick_up_object(op, alt, tmp, count);
588  if (op->type == PLAYER)
589  op->contr->count = 0;
590 }
591 
602 int command_take(object *op, char *params) {
603  object *tmp, *next;
604  int ival;
605  int missed = 0;
606 
607  if (op->container)
608  tmp = op->container->inv;
609  else {
610  tmp = op->above;
611  if (tmp)
612  while (tmp->above) {
613  tmp = tmp->above;
614  }
615  if (!tmp)
616  tmp = op->below;
617  }
618 
619  if (tmp == NULL) {
621  "Nothing to take!", NULL);
622  return 0;
623  }
624 
625  /* Makes processing easier */
626  if (params && *params == '\0')
627  params = NULL;
628 
629  while (tmp) {
630  next = tmp->below;
631 
632  if (tmp->invisible) {
633  tmp = next;
634  continue;
635  }
636  /* This following two if and else if could be merged into line
637  * but that probably will make it more difficult to read, and
638  * not make it any more efficient
639  */
640  if (params && (ival = item_matched_string(op, tmp, params)) > 0) {
641  if ((ival <= 2) && (!can_pick(op, tmp))) {
642  if (!QUERY_FLAG(tmp, FLAG_IS_FLOOR))/* don't count floor tiles */
643  missed++;
644  } else
645  pick_up(op, tmp);
646  } else if (can_pick(op, tmp) && !params) {
647  pick_up(op, tmp);
648  break;
649  }
650  tmp = next;
651  /* Might as well just skip over the player immediately -
652  * we know it can't be picked up
653  */
654  if (tmp == op)
655  tmp = tmp->below;
656  }
657  if (!params && !tmp) {
658  for (tmp = op->below; tmp != NULL; tmp = tmp->next)
659  if (!tmp->invisible) {
661  "You can't pick up a %s.",
662  "You can't pick up a %s.",
663  tmp->name ? tmp->name : "null");
664 
665  break;
666  }
667  if (!tmp)
669  "There is nothing to pick up.", NULL);
670  }
671  if (missed == 1)
673  "You were unable to take one of the items.", NULL);
674  else if (missed > 1)
676  "You were unable to take %d of the items.",
677  "You were unable to take %d of the items.",
678  missed);
679  return 0;
680 }
681 
700 void put_object_in_sack(object *op, object *sack, object *tmp, uint32 nrof) {
701  tag_t tmp_tag, tmp2_tag;
702  object *tmp2, *sack2, *orig = sack;
703  char name_sack[MAX_BUF], name_tmp[MAX_BUF];
704 
705  if (sack == tmp)
706  return; /* Can't put an object in itself */
707  query_name(sack, name_sack, MAX_BUF);
708  if (sack->type != CONTAINER && sack->type != TRANSPORT) {
710  "The %s is not a container.",
711  "The %s is not a container.",
712  name_sack);
713  return;
714  }
715  if (QUERY_FLAG(tmp, FLAG_STARTEQUIP)) {
716  query_name(tmp, name_tmp, MAX_BUF);
718  "You cannot put the %s in the %s.",
719  "You cannot put the %s in the %s.",
720  name_tmp, name_sack);
721  return;
722  }
723  if (tmp->type == CONTAINER) {
724  if (tmp->inv) {
725  if (tmp->slaying)
726  return;
727  /* Eneq(@csd.uu.se): If the object to be dropped is a container
728  * and does not require a key to be opened,
729  * we instead move the contents of that container into the active
730  * container, this is only done if the object has something in it.
731  * If object is container but need a key, just don't do anything
732  */
733  sack2 = tmp;
734  query_name(tmp, name_tmp, MAX_BUF);
736  "You move the items from %s into %s.",
737  "You move the items from %s into %s.",
738  name_tmp, name_sack);
739 
740  for (tmp2 = tmp->inv; tmp2; tmp2 = tmp) {
741  tmp = tmp2->below;
742  if ((sack->type == CONTAINER && sack_can_hold(op, op->container, tmp2, tmp2->nrof))
743  || (sack->type == TRANSPORT && transport_can_hold(sack, tmp2, tmp2->nrof))) {
744  put_object_in_sack(op, sack, tmp2, 0);
745  } else {
748  "Your %s fills up.",
749  "Your %s fills up.",
750  name_sack);
751  break;
752  }
753  }
754  esrv_update_item(UPD_WEIGHT, op, sack2);
755  return;
756  } else {
757  query_name(tmp, name_tmp, MAX_BUF);
759  "You can not put a %s into a %s",
760  "You can not put a %s into a %s",
761  name_tmp,
762  name_sack);
763  return;
764  }
765 
766  }
767 
768  /* Don't worry about this for containers - our caller should have
769  * already checked this.
770  */
771  if ((sack->type == CONTAINER) && !sack_can_hold(op, sack, tmp, (nrof ? nrof : tmp->nrof)))
772  return;
773 
774  if (QUERY_FLAG(tmp, FLAG_APPLIED)) {
775  if (apply_special(op, tmp, AP_UNAPPLY|AP_NO_MERGE))
776  return;
777  }
778 
779  /* we want to put some portion of the item into the container */
780  if (nrof && tmp->nrof != nrof) {
781  char failure[MAX_BUF];
782  object *tmp2 = tmp;
783 
784  tmp2_tag = tmp2->count;
785  tmp = get_split_ob(tmp, nrof, failure, sizeof(failure));
786 
787  if (!tmp) {
789  failure, NULL);
790  return;
791  }
792  } else
793  remove_ob(tmp);
794 
795  if (sack->nrof > 1) {
796  orig = get_split_ob(sack, sack->nrof-1, NULL, 0);
797  set_object_face_main(orig);
798  CLEAR_FLAG(orig, FLAG_APPLIED);
799  if (sack->env) {
800  insert_ob_in_ob(orig, sack->env);
801  } else {
802  insert_ob_in_map_at(orig, sack->map, NULL, 0, sack->x, sack->y);
803  orig->move_off = 0;
804  }
805  }
806 
807  query_name(tmp, name_tmp, MAX_BUF);
809  "You put the %s in %s.",
810  "You put the %s in %s.",
811  name_tmp, name_sack);
812  tmp_tag = tmp->count;
813  tmp2 = insert_ob_in_ob(tmp, sack);
814  if (!QUERY_FLAG(op, FLAG_NO_FIX_PLAYER))
815  fix_object(op); /* This is overkill, fix_player() is called somewhere */
816  /* in object.c */
817 
818  /* If a transport, need to update all the players in the transport
819  * the view of what is in it.
820  */
821  if (sack->type == TRANSPORT) {
822  for (tmp = sack->inv; tmp; tmp = tmp->below) {
823  if (tmp->type == PLAYER)
824  tmp->contr->socket.update_look = 1;
825  }
826  } else {
827  /* update the sacks weight */
828  esrv_update_item(UPD_WEIGHT, op, sack);
829  }
830 }
831 
847 object *drop_object(object *op, object *tmp, uint32 nrof) {
848  tag_t tmp_tag;
849 
850  if (QUERY_FLAG(tmp, FLAG_NO_DROP)) {
851  return NULL;
852  }
853 
854  if (QUERY_FLAG(tmp, FLAG_APPLIED)) {
855  if (apply_special(op, tmp, AP_UNAPPLY|AP_NO_MERGE))
856  return NULL; /* can't unapply it */
857  }
858 
859  /* Lauwenmark: Handle for plugin drop event */
860  if (execute_event(tmp, EVENT_DROP, op, NULL, NULL, SCRIPT_FIX_ALL) != 0)
861  return NULL;
862 
863  /* We are only dropping some of the items. We split the current objec
864  * off
865  */
866  if (nrof && tmp->nrof != nrof) {
867  char failure[MAX_BUF];
868 
869  tmp = get_split_ob(tmp, nrof, failure, sizeof(failure));
870  if (!tmp) {
872  failure, NULL);
873  return NULL;
874  }
875  } else
876  remove_ob(tmp);
877 
878  if (QUERY_FLAG(tmp, FLAG_STARTEQUIP)) {
879  char name[MAX_BUF];
880 
881  query_name(tmp, name, MAX_BUF);
883  "You drop the %s. The gods who lent it to you retrieves it.",
884  "You drop the %s. The gods who lent it to you retrieves it.",
885  name);
886  free_object(tmp);
887 
888  if (!QUERY_FLAG(op, FLAG_NO_FIX_PLAYER))
889  fix_object(op);
890 
891  return NULL;
892  }
893 
894  /* If SAVE_INTERVAL is commented out, we never want to save
895  * the player here.
896  */
897 #ifdef SAVE_INTERVAL
898  /* I'm not sure why there is a value check - since the save
899  * is done every SAVE_INTERVAL seconds, why care the value
900  * of what he is dropping?
901  */
902  if (op->type == PLAYER
903  && !QUERY_FLAG(tmp, FLAG_UNPAID)
904  && (tmp->nrof ? tmp->value*tmp->nrof : tmp->value > 2000)
905  && (op->contr->last_save_time+SAVE_INTERVAL) <= time(NULL)) {
906  save_player(op, 1);
907  op->contr->last_save_time = time(NULL);
908  }
909 #endif /* SAVE_INTERVAL */
910 
911 
912  tmp->x = op->x;
913  tmp->y = op->y;
914 
915  tmp_tag = tmp->count;
916  insert_ob_in_map(tmp, op->map, op, 0);
917  if (!was_destroyed(tmp, tmp_tag) && !QUERY_FLAG(tmp, FLAG_UNPAID) && tmp->type != MONEY && is_in_shop(op)) {
918  sell_item(tmp, op);
919  }
920 
921  /* Call this before we update the various windows/players. At least
922  * that we, we know the weight is correct.
923  */
924  if (!QUERY_FLAG(op, FLAG_NO_FIX_PLAYER)) {
925  fix_object(op); /* This is overkill, fix_player() is called somewhere */
926  /* in object.c */
927 
928  /* Need to update weight of player */
929  if (op->type == PLAYER)
930  esrv_update_item(UPD_WEIGHT, op, op);
931  }
932  return tmp;
933 }
934 
943 void drop(object *op, object *tmp) {
944  /* Hopeful fix for disappearing objects when dropping from a container -
945  * somehow, players get an invisible object in the container, and the
946  * old logic would skip over invisible objects - works fine for the
947  * playes inventory, but drop inventory wants to use the next value.
948  */
949  if (tmp->invisible) {
950  /* if the following is the case, it must be in an container. */
951  if (tmp->env && tmp->env->type != PLAYER) {
952  /* Just toss the object - probably shouldn't be hanging
953  * around anyways
954  */
955  remove_ob(tmp);
956  free_object(tmp);
957  return;
958  } else {
959  while (tmp != NULL && tmp->invisible)
960  tmp = tmp->below;
961  }
962  }
963 
964  if (tmp == NULL) {
966  "You don't have anything to drop.", NULL);
967  return;
968  }
969  if (QUERY_FLAG(tmp, FLAG_INV_LOCKED)) {
971  "This item is locked", NULL);
972  return;
973  }
974  if (QUERY_FLAG(tmp, FLAG_NO_DROP)) {
975  return;
976  }
977 
978  if (op->type == PLAYER) {
979  if (op->contr->last_used == tmp && op->contr->last_used_id == tmp->count) {
980  object *n = NULL;
981 
982  if (tmp->below != NULL)
983  n = tmp->below;
984  else if (tmp->above != NULL)
985  n = tmp->above;
986  op->contr->last_used = n;
987  if (n != NULL)
988  op->contr->last_used_id = n->count;
989  else
990  op->contr->last_used_id = 0;
991  }
992  };
993 
994  if (op->container) {
995  if (op->type == PLAYER) {
996  put_object_in_sack(op, op->container, tmp, op->contr->count);
997  } else {
998  put_object_in_sack(op, op->container, tmp, 0);
999  };
1000  } else {
1001  if (op->type == PLAYER) {
1002  drop_object(op, tmp, op->contr->count);
1003  } else {
1004  drop_object(op, tmp, 0);
1005  };
1006  }
1007  if (op->type == PLAYER)
1008  op->contr->count = 0;
1009 }
1010 
1021 int command_dropall(object *op, char *params) {
1022  object *curinv, *nextinv;
1023  int count = 0;
1024 
1025  if (op->inv == NULL) {
1026  draw_ext_info(NDI_UNIQUE, 0, op,
1028  "Nothing to drop!", NULL);
1029  return 0;
1030  }
1031 
1032  curinv = op->inv;
1033 
1034  if (op->contr)
1035  count = op->contr->count;
1036 
1037  /* Set this so we don't call it for _every_ object that
1038  * is dropped.
1039  */
1041 
1042  /*
1043  * This is the default. Drops everything not locked or considered
1044  * not something that should be dropped.
1045  * Care must be taken that the next item pointer is not to money as
1046  * the drop() routine will do unknown things to it when dropping
1047  * in a shop. --Tero.Pelander@utu.fi
1048  */
1049  if (params == NULL) {
1050  while (curinv != NULL) {
1051  nextinv = curinv->below;
1052  while (nextinv && nextinv->type == MONEY)
1053  nextinv = nextinv->below;
1054  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1055  && curinv->type != MONEY
1056  && curinv->type != FOOD
1057  && curinv->type != KEY
1058  && curinv->type != SPECIAL_KEY
1059  && curinv->type != GEM
1060  && !curinv->invisible
1061  && (curinv->type != CONTAINER || op->container != curinv)) {
1062  drop(op, curinv);
1063  if (op->contr)
1064  op->contr->count = count;
1065  }
1066  curinv = nextinv;
1067  }
1068  } else if (strcmp(params, "weapons") == 0) {
1069  while (curinv != NULL) {
1070  nextinv = curinv->below;
1071  while (nextinv && nextinv->type == MONEY)
1072  nextinv = nextinv->below;
1073  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1074  && ((curinv->type == WEAPON) || (curinv->type == BOW) || (curinv->type == ARROW))) {
1075  drop(op, curinv);
1076  if (op->contr)
1077  op->contr->count = count;
1078  }
1079  curinv = nextinv;
1080  }
1081  } else if (strcmp(params, "armor") == 0 || strcmp(params, "armour") == 0) {
1082  while (curinv != NULL) {
1083  nextinv = curinv->below;
1084  while (nextinv && nextinv->type == MONEY)
1085  nextinv = nextinv->below;
1086  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1087  && ((curinv->type == ARMOUR) || curinv->type == SHIELD || curinv->type == HELMET)) {
1088  drop(op, curinv);
1089  if (op->contr)
1090  op->contr->count = count;
1091  }
1092  curinv = nextinv;
1093  }
1094  } else if (strcmp(params, "food") == 0) {
1095  while (curinv != NULL) {
1096  nextinv = curinv->below;
1097  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED) && (curinv->type == FOOD || curinv->type == DRINK)) {
1098  drop(op, curinv);
1099  if (op->contr)
1100  op->contr->count = count;
1101  }
1102  curinv = nextinv;
1103  }
1104  } else if (strcmp(params, "flesh") == 0) {
1105  while (curinv != NULL) {
1106  nextinv = curinv->below;
1107  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED) && (curinv->type == FLESH)) {
1108  drop(op, curinv);
1109  if (op->contr)
1110  op->contr->count = count;
1111  }
1112  curinv = nextinv;
1113  }
1114  } else if (strcmp(params, "misc") == 0) {
1115  while (curinv != NULL) {
1116  nextinv = curinv->below;
1117  while (nextinv && nextinv->type == MONEY)
1118  nextinv = nextinv->below;
1119  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1120  && !QUERY_FLAG(curinv, FLAG_APPLIED)) {
1121  switch (curinv->type) {
1122  case HORN:
1123  case BOOK:
1124  case SPELLBOOK:
1125  case GIRDLE:
1126  case AMULET:
1127  case RING:
1128  case CLOAK:
1129  case BOOTS:
1130  case GLOVES:
1131  case BRACERS:
1132  case SCROLL:
1133  case ARMOUR_IMPROVER:
1134  case WEAPON_IMPROVER:
1135  case WAND:
1136  case ROD:
1137  case POTION:
1138  drop(op, curinv);
1139  curinv = nextinv;
1140  if (op->contr)
1141  op->contr->count = count;
1142  break;
1143 
1144  default:
1145  curinv = nextinv;
1146  break;
1147  }
1148  }
1149  curinv = nextinv;
1150  }
1151  }
1152  op->contr->socket.update_look = 1;
1154  /* call it now, once */
1155  fix_object(op);
1156  /* Need to update weight of player. Likewise, only do it once */
1157  if (op->type == PLAYER)
1158  esrv_update_item(UPD_WEIGHT, op, op);
1159 
1160  return 0;
1161 }
1162 
1173 int command_drop(object *op, char *params) {
1174  object *tmp, *next;
1175  int did_one = 0;
1176  int ival = 0;
1177  int missed = 0;
1178 
1179  if (!params) {
1181  "Drop what?", NULL);
1182  return 0;
1183  } else {
1184  for (tmp = op->inv; tmp; tmp = next) {
1185  next = tmp->below;
1186  if (QUERY_FLAG(tmp, FLAG_NO_DROP) || tmp->invisible)
1187  continue;
1188  if ((ival = item_matched_string(op, tmp, params)) > 0) {
1189  if ((QUERY_FLAG(tmp, FLAG_INV_LOCKED)) && ((ival == 1) || (ival == 2)))
1190  missed++;
1191  else
1192  drop(op, tmp);
1193  did_one = 1;
1194  }
1195  }
1196  if (!did_one)
1198  "Nothing to drop.", NULL);
1199  if (missed == 1)
1201  "One item couldn't be dropped because it was locked.", NULL);
1202  else if (missed > 1)
1204  "%d items couldn't be dropped because they were locked.",
1205  "%d items couldn't be dropped because they were locked.",
1206  missed);
1207  }
1208  if (op->type == PLAYER) {
1209  op->contr->count = 0;
1210  op->contr->socket.update_look = 1;
1211  }
1212  return 0;
1213 }
1214 
1223 static void empty_container(object *container, object *pl) {
1224  object *inv;
1225  object *next;
1226  int left = 0;
1227  char name[MAX_BUF];
1228 
1229  if (!container->inv)
1230  return;
1231 
1232  for (inv = container->inv; inv; inv = next) {
1233  next = inv->below;
1234  if (QUERY_FLAG(inv, FLAG_INV_LOCKED)) {
1235  /* you can have locked items in container. */
1236  left++;
1237  continue;
1238  }
1239  drop(pl, inv);
1240  if (inv->below == next)
1241  /* item couldn't be dropped for some reason. */
1242  left++;
1243  }
1244  esrv_update_item(UPD_WEIGHT, pl, container);
1245 
1246  query_name(container, name, sizeof(name));
1247  if (left)
1248  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "You empty the %s except %d items.", NULL, name, left);
1249  else
1250  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "You empty the %s.", NULL, name);
1251 }
1252 
1263 int command_empty(object *op, char *params) {
1264  object *inv;
1265  object *container;
1266 
1267  if (!params) {
1269  "Empty what?", NULL);
1270  return 0;
1271  }
1272 
1273  if (strcmp(params, "all") == 0) {
1274  for (inv = op->inv; inv; inv = inv->below)
1275  if (inv->type == CONTAINER)
1276  empty_container(inv, op);
1277  return 0;
1278  }
1279 
1280  container = find_best_object_match(op, params);
1281  if (!container) {
1283  "No such item.", NULL);
1284  return 0;
1285  }
1286  if (container->type != CONTAINER) {
1288  "This is not a container!", NULL);
1289  return 0;
1290  }
1291  empty_container(container, op);
1292 
1293  return 0;
1294 }
1295 
1306 int command_examine(object *op, char *params) {
1307  if (!params) {
1308  object *tmp = op->below;
1309 
1310  while (tmp && !LOOK_OBJ(tmp))
1311  tmp = tmp->below;
1312  if (tmp)
1313  examine(op, tmp);
1314  } else {
1315  object *tmp = find_best_object_match(op, params);
1316 
1317  if (tmp)
1318  examine(op, tmp);
1319  else
1321  "Could not find an object that matches %s",
1322  "Could not find an object that matches %s",
1323  params);
1324  }
1325  return 0;
1326 }
1327 
1339 object *find_marked_object(object *op) {
1340  object *tmp;
1341 
1342  if (!op || !op->contr || !op->contr->mark)
1343  return NULL;
1344 
1345  /* This may seem like overkill, but we need to make sure that they
1346  * player hasn't dropped the item. We use count on the off chance that
1347  * an item got reincarnated at some point.
1348  */
1349  for (tmp = op->inv; tmp; tmp = tmp->below) {
1350  if (tmp->invisible)
1351  continue;
1352  if (tmp == op->contr->mark) {
1353  if (tmp->count == op->contr->mark_count)
1354  return tmp;
1355  else {
1356  op->contr->mark = NULL;
1357  op->contr->mark_count = 0;
1358  return NULL;
1359  }
1360  }
1361  }
1362  return NULL;
1363 }
1364 
1376 int command_mark(object *op, char *params) {
1377  char name[MAX_BUF];
1378 
1379  if (!op->contr)
1380  return 1;
1381  if (!params) {
1382  object *mark = find_marked_object(op);
1383  if (!mark)
1385  "You have no marked object.", NULL);
1386  else {
1387  query_name(mark, name, MAX_BUF);
1389  "%s is marked.",
1390  "%s is marked.",
1391  name);
1392  }
1393  } else {
1394  object *mark1 = find_best_object_match(op, params);
1395 
1396  if (!mark1) {
1398  "Could not find an object that matches %s",
1399  "Could not find an object that matches %s",
1400  params);
1401  return 1;
1402  } else {
1403  op->contr->mark = mark1;
1404  op->contr->mark_count = mark1->count;
1405  query_name(mark1, name, MAX_BUF);
1407  "Marked item %s",
1408  "Marked item %s",
1409  name);
1410  return 0;
1411  }
1412  }
1413  return 0; /*shouldnt get here */
1414 }
1415 
1424 void examine_monster(object *op, object *tmp) {
1425  object *mon = tmp->head ? tmp->head : tmp;
1426 
1427  if (QUERY_FLAG(mon, FLAG_UNDEAD))
1429  "It is an undead force.", NULL);
1430  if (mon->level > op->level)
1432  "It is likely more powerful than you.", NULL);
1433  else if (mon->level < op->level)
1435  "It is likely less powerful than you.", NULL);
1436  else
1438  "It is probably as powerful as you.", NULL);
1439 
1440  if (mon->attacktype&AT_ACID)
1442  "You smell an acrid odor.", NULL);
1443 
1444  /* Anyone know why this used to use the clone value instead of the
1445  * maxhp field? This seems that it should give more accurate results.
1446  */
1447  switch ((mon->stats.hp+1)*4/(mon->stats.maxhp+1)) { /* From 1-4 */
1448  case 1:
1450  "It is in a bad shape.", NULL);
1451  break;
1452 
1453  case 2:
1455  "It is hurt.", NULL);
1456  break;
1457 
1458  case 3:
1460  "It is somewhat hurt.", NULL);
1461  break;
1462 
1463  case 4:
1465  "It is in excellent shape.", NULL);
1466  break;
1467  }
1468  if (present_in_ob(POISONING, mon) != NULL)
1470  "It looks very ill.", NULL);
1471 }
1472 
1481 void examine(object *op, object *tmp) {
1482  char buf[VERY_BIG_BUF];
1483  int in_shop;
1484  int i;
1485 
1486  buf[0] = '\0';
1487 
1488  if (tmp == NULL || tmp->type == CLOSE_CON)
1489  return;
1490 
1491  /* Put the description in buf. */
1492  ob_describe(tmp, op, buf, sizeof(buf));
1493 
1494  /* Send the player the description, prepending "That is" if singular
1495  * and "Those are" if plural.
1496  */
1497  if (tmp->nrof <= 1)
1499  "That is %s",
1500  "That is %s",
1501  buf);
1502  else
1504  "Those are %s",
1505  "Those are %s",
1506  buf);
1507  buf[0] = '\0';
1508 
1509  if (tmp->custom_name) {
1511  "You name it %s",
1512  "You name it %s",
1513  tmp->custom_name);
1514  }
1515 
1516  switch (tmp->type) {
1517  case SPELLBOOK:
1518  if (QUERY_FLAG(tmp, FLAG_IDENTIFIED) && tmp->inv) {
1519  char level[100];
1520 
1521  get_levelnumber(tmp->inv->level, level, 100);
1522  snprintf(buf, sizeof(buf), "%s is a %s level %s spell", tmp->inv->name, level, tmp->inv->skill);
1523  }
1524  break;
1525 
1526  case BOOK:
1527  if (tmp->msg != NULL)
1528  snprintf(buf, sizeof(buf), "Something is written in it.");
1529  break;
1530 
1531  case CONTAINER:
1532  if (tmp->race != NULL) {
1533  if (tmp->weight_limit && tmp->stats.Str < 100)
1534  snprintf(buf, sizeof(buf), "It can hold only %s and its weight limit is %.1f kg.", tmp->race, tmp->weight_limit/(10.0*(100-tmp->stats.Str)));
1535  else
1536  snprintf(buf, sizeof(buf), "It can hold only %s.", tmp->race);
1537  } else
1538  if (tmp->weight_limit && tmp->stats.Str < 100)
1539  snprintf(buf, sizeof(buf), "Its weight limit is %.1f kg.", tmp->weight_limit/(10.0*(100-tmp->stats.Str)));
1540  break;
1541 
1542  case WAND:
1543  if (QUERY_FLAG(tmp, FLAG_IDENTIFIED))
1544  snprintf(buf, sizeof(buf), "It has %d charges left.", tmp->stats.food);
1545  break;
1546  }
1547 
1548  if (buf[0] != '\0')
1550  buf, NULL);
1551 
1552  if (tmp->materialname != NULL && !tmp->msg) {
1554  "It is made of: %s.",
1555  "It is made of: %s.",
1556  tmp->materialname);
1557  }
1558  /* Where to wear this item */
1559  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
1560  if (tmp->body_info[i] < -1) {
1561  if (op->body_info[i])
1563  "It goes %s (%d)",
1564  "It goes %s (%d)",
1565  body_locations[i].use_name, -tmp->body_info[i]);
1566  else
1568  "It goes %s",
1569  "It goes %s",
1570  body_locations[i].nonuse_name);
1571  } else if (tmp->body_info[i]) {
1572  if (op->body_info[i])
1574  "It goes %s",
1575  "It goes %s",
1576  body_locations[i].use_name);
1577  else
1579  "It goes %s",
1580  "It goes %s",
1581  body_locations[i].nonuse_name);
1582  }
1583  }
1584 
1585  if (tmp->weight) {
1586  snprintf(buf, sizeof(buf), tmp->nrof > 1 ? "They weigh %3.3f kg." : "It weighs %3.3f kg.", tmp->weight*((float)(tmp->nrof ? tmp->nrof : 1)/1000.0));
1588  buf, NULL);
1589  }
1590 
1591  in_shop = is_in_shop(op);
1592 
1593  if (tmp->value && !QUERY_FLAG(tmp, FLAG_STARTEQUIP) && !QUERY_FLAG(tmp, FLAG_NO_PICK)) {
1594  char *value = stringbuffer_finish(query_cost_string(tmp, op, F_SELL|F_APPROX, NULL));
1595  snprintf(buf, sizeof(buf), "You reckon %s worth %s.", tmp->nrof > 1 ? "they are" : "it is", value);
1596  free(value);
1598  buf, NULL);
1599  if (in_shop) {
1600  if (QUERY_FLAG(tmp, FLAG_UNPAID)) {
1601  value = stringbuffer_finish(query_cost_string(tmp, op, F_BUY|F_SHOP, NULL));
1602  snprintf(buf, sizeof(buf), "%s would cost you %s.", tmp->nrof > 1 ? "They" : "It", value);
1603  free(value);
1604  } else {
1605  value = stringbuffer_finish(query_cost_string(tmp, op, F_SELL+F_SHOP, NULL));
1606  snprintf(buf, sizeof(buf), "You are offered %s for %s.", value, tmp->nrof > 1 ? "them" : "it");
1607  free(value);
1608  }
1610  buf, NULL);
1611  }
1612  }
1613 
1614  if (QUERY_FLAG(tmp, FLAG_MONSTER))
1615  examine_monster(op, tmp);
1616 
1617  /* Is this item buildable? */
1618  if (QUERY_FLAG(tmp, FLAG_IS_BUILDABLE))
1620  "This is a buildable item.", NULL);
1621 
1622  /* Does the object have a message? Don't show message for all object
1623  * types - especially if the first entry is a match
1624  */
1625  if (tmp->msg
1626  && tmp->type != EXIT
1627  && tmp->type != BOOK
1628  && tmp->type != CORPSE
1629  && !tmp->move_on
1630  && strncasecmp(tmp->msg, "@match", 6)) {
1631  /* This is just a hack so when identifying hte items, we print
1632  * out the extra message
1633  */
1634  if (need_identify(tmp) && QUERY_FLAG(tmp, FLAG_IDENTIFIED))
1636  "The object has a story:", NULL);
1637 
1639  tmp->msg, NULL);
1640  }
1642  " ", " "); /* Blank line */
1643 }
1644 
1653 void inventory(object *op, object *inv) {
1654  object *tmp;
1655  const char *in;
1656  int items = 0, length;
1657  char weight[MAX_BUF], name[MAX_BUF];
1658 
1659  if (inv == NULL && op == NULL) {
1661  "Inventory of what object?", NULL);
1662  return;
1663  }
1664  tmp = inv ? inv->inv : op->inv;
1665 
1666  while (tmp) {
1667  if ((!tmp->invisible && (inv == NULL || inv->type == CONTAINER || QUERY_FLAG(tmp, FLAG_APPLIED)))
1668  || (!op || QUERY_FLAG(op, FLAG_WIZ)))
1669  items++;
1670  tmp = tmp->below;
1671  }
1672  if (inv == NULL) { /* player's inventory */
1673  if (items == 0) {
1675  "You carry nothing.", NULL);
1676  return;
1677  } else {
1678  length = 28;
1679  in = "";
1681  "Inventory:", NULL);
1682  }
1683  } else {
1684  if (items == 0)
1685  return;
1686  else {
1687  length = 28;
1688  in = " ";
1689  }
1690  }
1691  for (tmp = inv ? inv->inv : op->inv; tmp; tmp = tmp->below) {
1692  if ((!op || !QUERY_FLAG(op, FLAG_WIZ))
1693  && (tmp->invisible || (inv && inv->type != CONTAINER && !QUERY_FLAG(tmp, FLAG_APPLIED))))
1694  continue;
1695  query_weight(tmp, weight, MAX_BUF);
1696  query_name(tmp, name, MAX_BUF);
1697  if ((!op || QUERY_FLAG(op, FLAG_WIZ)))
1699  "[fixed]%s- %-*.*s (%5d) %-8s",
1700  "%s- %-*.*s (%5d) %-8s",
1701  in, length, length, name, tmp->count, weight);
1702  else
1704  "[fixed]%s- %-*.*s %-8s",
1705  "%s- %-*.*s %-8s",
1706  in, length+8, length+8, name, weight);
1707  }
1708  if (!inv && op) {
1709  query_weight(op, weight, MAX_BUF);
1711  "[fixed]%-*s %-8s",
1712  "%-*s %-8s",
1713  41, "Total weight :", weight);
1714  }
1715 }
1716 
1723 static void display_new_pickup(const object *op) {
1724  int i = op->contr->mode;
1725 
1726  if (!(i&PU_NEWMODE))
1727  return;
1728 
1730  "%d NEWMODE",
1731  "%d NEWMODE",
1732  i&PU_NEWMODE ? 1 : 0);
1734  "%d DEBUG",
1735  "%d DEBUG",
1736  i&PU_DEBUG ? 1 : 0);
1738  "%d INHIBIT",
1739  "%d INHIBIT",
1740  i&PU_INHIBIT ? 1 : 0);
1742  "%d STOP",
1743  "%d STOP",
1744  i&PU_STOP ? 1 : 0);
1745 
1747  "%d <= x pickup weight/value RATIO (0==off)",
1748  "%d <= x pickup weight/value RATIO (0==off)",
1749  (i&PU_RATIO)*5);
1750 
1752  "%d FOOD",
1753  "%d FOOD",
1754  i&PU_FOOD ? 1 : 0);
1756  "%d DRINK",
1757  "%d DRINK",
1758  i&PU_DRINK ? 1 : 0);
1760  "%d VALUABLES",
1761  "%d VALUABLES",
1762  i&PU_VALUABLES ? 1 : 0);
1763 
1765  "%d BOW",
1766  "%d BOW",
1767  i&PU_BOW ? 1 : 0);
1769  "%d ARROW",
1770  "%d ARROW",
1771  i&PU_ARROW ? 1 : 0);
1772 
1774  "%d HELMET",
1775  "%d HELMET",
1776  i&PU_HELMET ? 1 : 0);
1778  "%d SHIELD",
1779  "%d SHIELD",
1780  i&PU_SHIELD ? 1 : 0);
1782  "%d ARMOUR",
1783  "%d ARMOUR",
1784  i&PU_ARMOUR ? 1 : 0);
1785 
1787  "%d BOOTS",
1788  "%d BOOTS",
1789  i&PU_BOOTS ? 1 : 0);
1791  "%d GLOVES",
1792  "%d GLOVES",
1793  i&PU_GLOVES ? 1 : 0);
1795  "%d CLOAK",
1796  "%d CLOAK",
1797  i&PU_CLOAK ? 1 : 0);
1799  "%d KEY",
1800  "%d KEY",
1801  i&PU_KEY ? 1 : 0);
1802 
1804  "%d MISSILEWEAPON",
1805  "%d MISSILEWEAPON",
1806  i&PU_MISSILEWEAPON ? 1 : 0);
1808  "%d ALLWEAPON",
1809  "%d ALLWEAPON",
1810  i&PU_ALLWEAPON ? 1 : 0);
1812  "%d MAGICAL",
1813  "%d MAGICAL",
1814  i&PU_MAGICAL ? 1 : 0);
1816  "%d POTION",
1817  "%d POTION",
1818  i&PU_POTION ? 1 : 0);
1819 
1821  "%d SPELLBOOK",
1822  "%d SPELLBOOK",
1823  i&PU_SPELLBOOK ? 1 : 0);
1825  "%d SKILLSCROLL",
1826  "%d SKILLSCROLL",
1827  i&PU_SKILLSCROLL ? 1 : 0);
1829  "%d READABLES",
1830  "%d READABLES",
1831  i&PU_READABLES ? 1 : 0);
1833  "%d MAGICDEVICE",
1834  "%d MAGICDEVICE",
1835  i&PU_MAGIC_DEVICE ? 1 : 0);
1836 
1838  "%d NOT CURSED",
1839  "%d NOT CURSED",
1840  i&PU_NOT_CURSED ? 1 : 0);
1841 
1843  "%d JEWELS",
1844  "%d JEWELS",
1845  i&PU_JEWELS ? 1 : 0);
1846 
1848  "%d FLESH",
1849  "%d FLESH",
1850  i&PU_FLESH ? 1 : 0);
1851 
1853  "", "");
1854 }
1855 
1867 int command_pickup(object *op, char *params) {
1868  uint32 i;
1869  static const char *names[] = {
1870  "debug", "inhibit", "stop", "food", "drink",
1871  "valuables", "bow", "arrow", "helmet", "shield",
1872  "armour", "boots", "gloves", "cloak", "key",
1873  "missile", "allweapon", "magical", "potion", "spellbook",
1874  "skillscroll", "readables", "magicdevice", "notcursed", "jewels",
1875  "flesh", NULL
1876  };
1877  static const uint32 modes[] = {
1882  };
1883 
1884  if (!params) {
1885  /* if the new mode is used, just print the settings */
1886  if (op->contr->mode&PU_NEWMODE) {
1887  display_new_pickup(op);
1888  return 1;
1889  }
1890  if (1)
1891  LOG(llevDebug, "command_pickup: !params\n");
1892  set_pickup_mode(op, (op->contr->mode > 6) ? 0 : op->contr->mode+1);
1893  return 0;
1894  }
1895 
1896  while (*params == ' ')
1897  params++;
1898 
1899  if (*params == '+' || *params == '-') {
1900  int mode;
1901 
1902  for (mode = 0; names[mode]; mode++) {
1903  if (!strcmp(names[mode], params+1)) {
1904  i = op->contr->mode;
1905  if (!(i&PU_NEWMODE))
1906  i = PU_NEWMODE;
1907  if (*params == '+')
1908  i = i|modes[mode];
1909  else
1910  i = i&~modes[mode];
1911  op->contr->mode = i;
1912  display_new_pickup(op);
1913  return 1;
1914  }
1915  }
1917  "Pickup: invalid item %s\n",
1918  "Pickup: invalid item %s\n",
1919  params);
1920  return 1;
1921  }
1922 
1923  if (sscanf(params, "%u", &i) != 1) {
1924  if (1)
1925  LOG(llevDebug, "command_pickup: params==NULL\n");
1927  "Usage: pickup <0-7> or <value_density> .", NULL);
1928  return 1;
1929  }
1930  set_pickup_mode(op, i);
1931  display_new_pickup(op);
1932 
1933  return 1;
1934 }
1935 
1944 static void set_pickup_mode(const object *op, int i) {
1945  switch (op->contr->mode = i) {
1946  case 0:
1948  "Mode: Don't pick up.", NULL);
1949  break;
1950 
1951  case 1:
1953  "Mode: Pick up one item.", NULL);
1954  break;
1955 
1956  case 2:
1958  "Mode: Pick up one item and stop.", NULL);
1959  break;
1960 
1961  case 3:
1963  "Mode: Stop before picking up.", NULL);
1964  break;
1965 
1966  case 4:
1968  "Mode: Pick up all items.", NULL);
1969  break;
1970 
1971  case 5:
1973  "Mode: Pick up all items and stop.", NULL);
1974  break;
1975 
1976  case 6:
1978  "Mode: Pick up all magic items.", NULL);
1979  break;
1980 
1981  case 7:
1983  "Mode: Pick up all coins and gems", NULL);
1984  break;
1985  }
1986 }
1987 
1998 int command_search_items(object *op, char *params) {
1999  if (settings.search_items == FALSE)
2000  return 1;
2001 
2002  if (params == NULL) {
2003  if (op->contr->search_str[0] == '\0') {
2005  "Example: search magic+1 "
2006  "Would automatically pick up all "
2007  "items containing the word 'magic+1'.",
2008  NULL);
2009  return 1;
2010  }
2011  op->contr->search_str[0] = '\0';
2013  "Search mode turned off.", NULL);
2014  fix_object(op);
2015  return 1;
2016  }
2017  if ((int)strlen(params) >= MAX_BUF) {
2019  "Search string too long.", NULL);
2020  return 1;
2021  }
2022  strcpy(op->contr->search_str, params);
2024  "Searching for '%s'.",
2025  "Searching for '%s'.",
2026  op->contr->search_str);
2027  fix_object(op);
2028  return 1;
2029 }
2030 
2047 int command_rename_item(object *op, char *params) {
2048  char buf[VERY_BIG_BUF], name[MAX_BUF];
2049  int itemnumber;
2050  object *item = NULL;
2051  object *tmp;
2052  char *closebrace;
2053  size_t counter;
2054  tag_t tag;
2055 
2056  if (params) {
2057  /* Let's skip white spaces */
2058  while (' ' == *params)
2059  params++;
2060 
2061  /* Checking the first part */
2062  if ((itemnumber = atoi(params)) != 0) {
2063  for (item = op->inv; item && ((item->count != itemnumber) || item->invisible); item = item->below)
2064  ;
2065  if (!item) {
2067  "Tried to rename an invalid item.", NULL);
2068  return 1;
2069  }
2070  while (isdigit(*params) || ' ' == *params)
2071  params++;
2072  } else if ('<' == *params) {
2073  /* Got old name, let's get it & find appropriate matching item */
2074  closebrace = strchr(params, '>');
2075  if (!closebrace) {
2077  "Syntax error!", NULL);
2078  return 1;
2079  }
2080  /* Sanity check for buffer overruns */
2081  if ((closebrace-params) > 127) {
2083  "Old name too long (up to 127 characters allowed)!", NULL);
2084  return 1;
2085  }
2086  /* Copy the old name */
2087  snprintf(buf, sizeof(buf), "%.*s", (int)(closebrace-(params+1)), params+1);
2088 
2089  /* Find best matching item */
2090  item = find_best_object_match(op, buf);
2091  if (!item) {
2093  "Could not find a matching item to rename.", NULL);
2094  return 1;
2095  }
2096 
2097  /* Now need to move pointer to just after > */
2098  params = closebrace+1;
2099  while (' ' == *params)
2100  params++;
2101  } else {
2102  /* Use marked item */
2103  item = find_marked_object(op);
2104  if (!item) {
2106  "No marked item to rename.", NULL);
2107  return 1;
2108  }
2109  }
2110 
2111  /* Now let's find the new name */
2112  if (!strncmp(params, "to ", 3)) {
2113  params += 3;
2114  while (' ' == *params)
2115  params++;
2116  if ('<' != *params) {
2118  "Syntax error, expecting < at start of new name!", NULL);
2119  return 1;
2120  }
2121  closebrace = strchr(params+1, '>');
2122  if (!closebrace) {
2124  "Syntax error, expecting > at end of new name!", NULL);
2125  return 1;
2126  }
2127 
2128  /* Sanity check for buffer overruns */
2129  if ((closebrace-params) > 127) {
2131  "New name too long (up to 127 characters allowed)!", NULL);
2132  return 1;
2133  }
2134 
2135  /* Copy the new name */
2136  snprintf(buf, sizeof(buf), "%.*s", (int)(closebrace-(params+1)), params+1);
2137 
2138  /* Let's check it for weird characters */
2139  for (counter = 0; counter < strlen(buf); counter++) {
2140  if (isalnum(buf[counter]))
2141  continue;
2142  if (' ' == buf[counter])
2143  continue;
2144  if ('\'' == buf[counter])
2145  continue;
2146  if ('+' == buf[counter])
2147  continue;
2148  if ('_' == buf[counter])
2149  continue;
2150  if ('-' == buf[counter])
2151  continue;
2152 
2153  /* If we come here, then the name contains an invalid character...
2154  * tell the player & exit
2155  */
2157  "Invalid new name!", NULL);
2158  return 1;
2159  }
2160  } else {
2161  /* If param contains something, then syntax error... */
2162  if (strlen(params)) {
2164  "Syntax error, expected 'to <' after old name!", NULL);
2165  return 1;
2166  }
2167  /* New name is empty */
2168  buf[0] = '\0';
2169  }
2170  } else {
2171  /* Last case: params==NULL */
2172  item = find_marked_object(op);
2173  if (!item) {
2175  "No marked item to rename.", NULL);
2176  return 1;
2177  }
2178  buf[0] = '\0';
2179  }
2180 
2181  /* Coming here, everything is fine... */
2182  if (!strlen(buf)) {
2183  /* Clear custom name */
2184  if (item->custom_name == NULL) {
2186  "This item has no custom name.", NULL);
2187  return 1;
2188  }
2189 
2191  query_base_name(item, item->nrof > 1 ? 1 : 0, name, MAX_BUF);
2193  "You stop calling your %s with weird names.",
2194  "You stop calling your %s with weird names.",
2195  name);
2196  } else {
2197  if (item->custom_name != NULL && strcmp(item->custom_name, buf) == 0) {
2198  query_base_name(item, item->nrof > 1 ? 1 : 0, name, MAX_BUF);
2200  "You keep calling your %s %s.",
2201  "You keep calling your %s %s.",
2202  name, buf);
2203  return 1;
2204  }
2205 
2206  /* Set custom name */
2207  FREE_AND_COPY(item->custom_name, buf);
2208 
2209  query_base_name(item, item->nrof > 1 ? 1 : 0, name, MAX_BUF);
2211  "Your %s will now be called %s.",
2212  "Your %s will now be called %s.",
2213  name, buf);
2214  }
2215 
2216  tag = item->count;
2217  tmp = merge_ob(item, NULL);
2218  if (tmp == NULL) {
2219  /* object was not merged - if it was, merge_ob handles updating for us. */
2220  esrv_update_item(UPD_NAME, op, item);
2221  }
2222 
2223  return 1;
2224 }
2225 
2234 int command_lock_item(object *op, char *params) {
2235  object *item;
2236  object *tmp;
2237  tag_t tag;
2238  char name[HUGE_BUF];
2239 
2240  if (!params || strlen(params) == 0) {
2242  "Lock what item?", "Lock what item?");
2243  return 1;
2244  }
2245 
2246  item = find_best_object_match(op, params);
2247  if (!item) {
2249  "Can't find any matching item.", "Can't find any matching item.");
2250  return 1;
2251  }
2252 
2253  query_short_name(item, name, HUGE_BUF);
2254  if (QUERY_FLAG(item, FLAG_INV_LOCKED)) {
2256  "Unlocked %s.", "Unlocked %s.", name);
2257  CLEAR_FLAG(item, FLAG_INV_LOCKED);
2258  } else {
2260  "Locked %s.", "Locked %s.", name);
2261  SET_FLAG(item, FLAG_INV_LOCKED);
2262  }
2263 
2264  tag = item->count;
2265  tmp = merge_ob(item, NULL);
2266  if (tmp == NULL) {
2267  /* object was not merged, if it was merge_ob handles updates for us */
2268  esrv_update_item(UPD_FLAGS, op, item);
2269  }
2270  return 1;
2271 }
2272 
2282 int command_use(object *op, char *params) {
2283  char *with, copy[MAX_BUF];
2284  object *first, *second, *add;
2285  archetype *arch;
2286  int count;
2287  sstring data;
2288 
2289  if (!op->type == PLAYER)
2290  return 1;
2291 
2292  snprintf(copy, sizeof(copy), "%s", params);
2293  with = strstr(copy, " with ");
2294  if (!with) {
2295  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "Syntax is use <item> with <item>.", NULL);
2296  return 1;
2297  }
2298 
2299  with[0] = '\0';
2300  with = with+strlen(" with ");
2301 
2302  first = find_best_object_match(op, copy);
2303  if (!first) {
2304  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "No match for %s.", NULL, copy);
2305  return 1;
2306  }
2307  second = find_best_object_match(op, with);
2308  if (!second) {
2309  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "No match for %s.", NULL, with);
2310  return 1;
2311  }
2312 
2313  snprintf(copy, sizeof(copy), "on_use_with_%s", first->arch->name);
2314  data = get_ob_key_value(second, copy);
2315  if (!data) {
2316  snprintf(copy, sizeof(copy), "on_use_with_%d_%d", first->type, first->subtype);
2317  data = get_ob_key_value(second, copy);
2318  if (!data) {
2319  snprintf(copy, sizeof(copy), "on_use_with_%d", first->type);
2320  data = get_ob_key_value(second, copy);
2321  if (!data) {
2322  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "Nothing happens.", NULL);
2323  return 1;
2324  }
2325  }
2326  }
2327 
2328  while (data != NULL) {
2329  if (strncmp(data, "add ", 4) == 0) {
2330  data += 4;
2331  if (isdigit(*data)) {
2332  count = atol(data);
2333  data = strchr(data, ' ')+1;
2334  } else
2335  count = 1;
2336  with = strchr(data, ' ');
2337  if (!with) {
2338  strncpy(copy, data, sizeof(copy));
2339  data = NULL;
2340  } else {
2341  *with = '\0';
2342  strncpy(copy, data, sizeof(copy));
2343  data += strlen(copy)+1;
2344  }
2345  arch = find_archetype(copy);
2346  if (!arch) {
2347  LOG(llevError, "Use: invalid archetype %s in %s.\n", copy, second->name);
2348  return 1;
2349  }
2350  add = object_create_arch(arch);
2351  add->nrof = count;
2352  insert_ob_in_ob(add, op);
2353  } else if (strncmp(data, "remove $", 8) == 0) {
2354  data += 8;
2355  if (*data == '1') {
2356  if (first)
2357  first = decrease_ob(first);
2358  data += 2;
2359  } else if (*data == '2') {
2360  if (second)
2361  second = decrease_ob(second);
2362  data += 2;
2363  } else {
2364  LOG(llevError, "Use: invalid use string %s in %s\n", data, second->name);
2365  return 1;
2366  }
2367  } else {
2368  LOG(llevError, "Use: invalid use string %s in %s\n", data, second->name);
2369  return 1;
2370  }
2371  }
2372 
2373  return 1;
2374 }
#define AP_UNAPPLY
Definition: define.h:1010
#define UPD_FLAGS
Definition: newclient.h:255
#define MSG_TYPE_SKILL_MISSING
Definition: newclient.h:501
#define FOOD
Definition: define.h:118
#define RING
Definition: define.h:232
int sack_can_hold(const object *pl, const object *sack, const object *op, uint32 nrof)
Definition: c_object.c:282
static object * find_best_object_match(object *pl, const char *params)
Definition: c_object.c:99
#define FLAG_NO_DROP
Definition: define.h:585
#define NUM_BODY_LOCATIONS
Definition: object.h:41
Definition: player.h:146
int apply_special(object *who, object *op, int aflags)
Definition: apply.c:1139
archetype * find_archetype(const char *name)
Definition: arch.c:700
#define FLAG_IS_FLOOR
Definition: define.h:599
#define FLAG_UNPAID
Definition: define.h:532
int is_in_shop(object *ob)
Definition: shop.c:1414
MoveType move_type
Definition: object.h:277
int change_skill(object *who, object *new_skill, int flag)
Definition: skill_util.c:301
#define FALSE
Definition: exp.c:42
const char * get_ob_key_value(const object *op, const char *const key)
Definition: object.c:3701
void pick_up(object *op, object *alt)
Definition: c_object.c:462
MoveType move_on
Definition: object.h:280
int command_apply(object *op, char *params)
Definition: c_object.c:221
const char * race
Definition: object.h:171
#define SET_FLAG(xyz, p)
Definition: define.h:510
object * present_in_ob(uint8 type, const object *op)
Definition: object.c:2806
#define CLOSE_CON
Definition: define.h:303
#define PU_DEBUG
Definition: define.h:396
#define F_SELL
Definition: define.h:776
#define WAND
Definition: define.h:291
void get_levelnumber(int i, char *buf, size_t size)
Definition: item.c:444
#define UPD_NAME
Definition: newclient.h:258
#define CORPSE
Definition: define.h:329
struct obj * container
Definition: object.h:149
#define PU_STOP
Definition: define.h:398
#define MONEY
Definition: define.h:148
#define PU_SHIELD
Definition: define.h:410
object * mon
Definition: comet_perf.c:74
object * insert_ob_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1761
#define FLAG_NO_FIX_PLAYER
Definition: define.h:573
#define LOOK_OBJ(ob)
Definition: object.h:344
int save_player(object *op, int flag)
Definition: login.c:223
void inventory(object *op, object *inv)
Definition: c_object.c:1653
#define PU_KEY
Definition: define.h:416
#define HUGE_BUF
Definition: define.h:83
int command_pickup(object *op, char *params)
Definition: c_object.c:1867
void esrv_update_item(int flags, object *pl, object *op)
Definition: standalone.c:200
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:448
int item_matched_string(object *pl, object *op, const char *name)
Definition: object.c:3901
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.c:732
socket_struct socket
Definition: player.h:148
sint16 invisible
Definition: object.h:211
#define POTION
Definition: define.h:117
void query_weight(const object *op, char *buf, size_t size)
Definition: item.c:424
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
int command_examine(object *op, char *params)
Definition: c_object.c:1306
#define SCROLL
Definition: define.h:293
const char * skill_names[NUM_SKILLS]
Definition: skill_util.c:65
uint32 mode
Definition: player.h:164
void examine_monster(object *op, object *tmp)
Definition: c_object.c:1424
uint8 subtype
Definition: object.h:190
#define SK_FIND_TRAPS
Definition: skills.h:62
struct obj * above
Definition: object.h:146
#define BOOTS
Definition: define.h:281
#define PU_FLESH
Definition: define.h:430
#define PU_FOOD
Definition: define.h:403
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.c:64
object * stop_item(object *op)
Definition: time.c:426
#define CLOAK
Definition: define.h:268
sint16 x
Definition: object.h:179
#define GIRDLE
Definition: define.h:295
uint8 search_items
Definition: global.h:355
static void pick_up_object(object *pl, object *op, object *tmp, int nrof)
Definition: c_object.c:340
#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 PU_NEWMODE
Definition: define.h:399
#define F_BUY
Definition: define.h:775
#define ARMOUR
Definition: define.h:128
#define SK_DISARM_TRAPS
Definition: skills.h:74
Definition: object.h:321
#define PU_MISSILEWEAPON
Definition: define.h:418
#define PLAYER
Definition: define.h:113
int command_take(object *op, char *params)
Definition: c_object.c:602
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:449
#define PU_CLOAK
Definition: define.h:415
#define FLAG_REMOVED
Definition: define.h:528
sint16 hp
Definition: living.h:81
int command_disarm(object *op, char *params)
Definition: c_object.c:181
#define SPECIAL_KEY
Definition: define.h:133
#define POISONING
Definition: define.h:287
#define AMULET
Definition: define.h:153
#define FLAG_UNDEAD
Definition: define.h:566
uint32 tag_t
Definition: object.h:40
int command_lock_item(object *op, char *params)
Definition: c_object.c:2234
void remove_ob(object *op)
Definition: object.c:1515
sint16 maxhp
Definition: living.h:82
int command_uskill(object *pl, char *params)
Definition: c_object.c:113
#define PU_BOOTS
Definition: define.h:413
object * last_used
Definition: player.h:208
void examine(object *op, object *tmp)
Definition: c_object.c:1481
sint32 weight_limit
Definition: object.h:217
#define TRANSPORT
Definition: define.h:114
#define SK_THROWING
Definition: skills.h:72
#define WEAPON_IMPROVER
Definition: define.h:308
object * get_player_container(object *op)
Definition: object.c:356
#define PU_SKILLSCROLL
Definition: define.h:424
const char * materialname
Definition: object.h:197
sint32 weight
Definition: object.h:216
StringBuffer * query_cost_string(const object *tmp, object *who, int flag, StringBuffer *buf)
Definition: shop.c:511
#define PU_ARROW
Definition: define.h:408
struct mapdef * map
Definition: object.h:155
char search_str[MAX_BUF]
Definition: player.h:243
#define KEY
Definition: define.h:136
uint32 last_used_id
Definition: player.h:209
#define HORN
Definition: define.h:147
#define FLAG_IDENTIFIED
Definition: define.h:557
#define MOVE_FLYING
Definition: define.h:703
#define F_SHOP
Definition: define.h:782
sint32 carrying
Definition: object.h:218
const char * name
Definition: object.h:167
#define PU_INHIBIT
Definition: define.h:397
struct obj * env
Definition: object.h:151
#define EVENT_PICKUP
Definition: plugin.h:66
#define PU_BOW
Definition: define.h:406
#define FLESH
Definition: define.h:234
#define AP_NULL
Definition: define.h:1008
struct obj * below
Definition: object.h:145
static void display_new_pickup(const object *op)
Definition: c_object.c:1723
#define PU_RATIO
Definition: define.h:401
uint32 nrof
Definition: object.h:184
MoveType move_off
Definition: object.h:281
int do_skill(object *op, object *part, object *skill, int dir, const char *string)
Definition: skill_util.c:373
sint8 facing
Definition: object.h:186
sint16 y
Definition: object.h:179
struct pl * contr
Definition: object.h:134
#define PU_DRINK
Definition: define.h:404
#define WEAPON
Definition: define.h:127
int can_pick(const object *who, const object *item)
Definition: object.c:3569
static void empty_container(object *container, object *pl)
Definition: c_object.c:1223
int command_rename_item(object *op, char *params)
Definition: c_object.c:2047
int command_search_items(object *op, char *params)
Definition: c_object.c:1998
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:283
int command_dropall(object *op, char *params)
Definition: c_object.c:1021
void player_apply_below(object *pl)
Definition: apply.c:619
uint32 count
Definition: player.h:163
#define MSG_TYPE_SKILL
Definition: newclient.h:329
static void set_pickup_mode(const object *op, int i)
Definition: c_object.c:1944
int command_drop(object *op, char *params)
Definition: c_object.c:1173
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
#define FLAG_WIZ
Definition: define.h:527
#define GEM
Definition: define.h:202
#define EXIT
Definition: define.h:228
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
#define MAX_BUF
Definition: define.h:81
#define GLOVES
Definition: define.h:282
char * ob_describe(const object *op, const object *observer, char *buf, size_t size)
Definition: ob_methods.c:102
#define PU_READABLES
Definition: define.h:425
object * object_create_arch(archetype *at)
Definition: arch.c:741
int command_rskill(object *pl, char *params)
Definition: c_object.c:132
int strncasecmp(const char *s1, const char *s2, int n)
Definition: porting.c:402
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
#define BOOK
Definition: define.h:120
#define BRACERS
Definition: define.h:286
const char * skill
Definition: object.h:174
#define EVENT_DROP
Definition: plugin.h:65
int command_use(object *op, char *params)
Definition: c_object.c:2282
object * drop_object(object *op, object *tmp, uint32 nrof)
Definition: c_object.c:847
struct obj * next
Definition: object.h:135
sint8 Str
Definition: living.h:78
#define F_APPROX
Definition: define.h:781
const char * sstring
Definition: global.h:84
int need_identify(const object *op)
Definition: item.c:1401
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
int set_object_face_main(object *op)
Definition: apply.c:160
#define decrease_ob(xyz)
Definition: global.h:276
int command_mark(object *op, char *params)
Definition: c_object.c:1376
uint32 attacktype
Definition: object.h:193
void sell_item(object *op, object *pl)
Definition: shop.c:1059
#define INS_NO_MERGE
Definition: object.h:394
#define CONTAINER
Definition: define.h:306
uint32 update_look
Definition: newserver.h:131
#define VERY_BIG_BUF
Definition: define.h:82
#define FREE_AND_COPY(sv, nv)
Definition: global.h:288
const char * custom_name
Definition: object.h:285
tag_t count
Definition: object.h:157
living stats
Definition: object.h:219
struct archt * arch
Definition: object.h:263
#define MSG_TYPE_COMMAND_INFO
Definition: newclient.h:444
#define FLAG_IS_BUILDABLE
Definition: define.h:672
struct Settings settings
Definition: init.c:48
#define ARMOUR_IMPROVER
Definition: define.h:307
int transport_can_hold(const object *transport, const object *op, int nrof)
Definition: apply.c:64
#define FLAG_APPLIED
Definition: define.h:531
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.c:551
#define PU_SPELLBOOK
Definition: define.h:423
int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: standalone.c:225
#define MSG_TYPE_COMMAND
Definition: newclient.h:326
const uint32 weight_limit[MAX_STAT+1]
Definition: living.c:143
const char * msg
Definition: object.h:175
#define FLAG_STARTEQUIP
Definition: define.h:564
#define PU_VALUABLES
Definition: define.h:405
#define BOW
Definition: define.h:126
#define PU_MAGICAL
Definition: define.h:420
int command_empty(object *op, char *params)
Definition: c_object.c:1263
#define DRINK
Definition: define.h:187
#define UPD_WEIGHT
Definition: newclient.h:256
#define PU_JEWELS
Definition: define.h:429
#define FLAG_MONSTER
Definition: define.h:541
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
#define HELMET
Definition: define.h:146
struct obj * head
Definition: object.h:154
static object * find_best_apply_object_match(object *start, object *pl, const char *params, int aflag)
Definition: c_object.c:70
#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 PU_GLOVES
Definition: define.h:414
int player_apply(object *pl, object *op, int aflag, int quiet)
Definition: apply.c:557
#define ARROW
Definition: define.h:125
object * mark
Definition: player.h:248
unsigned int uint32
Definition: global.h:58
#define ROD
Definition: define.h:115
#define FLAG_WAS_WIZ
Definition: define.h:530
#define was_destroyed(op, old_tag)
Definition: object.h:94
object * find_marked_object(object *op)
Definition: c_object.c:1339
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
#define PU_ARMOUR
Definition: define.h:411
#define MSG_TYPE_COMMAND_EXAMINE
Definition: newclient.h:450
void free_object(object *ob)
Definition: object.c:1238
Definition: map.h:346
int use_skill(object *op, const char *string)
Definition: skill_util.c:863
#define FLAG_NO_PICK
Definition: define.h:535
#define PU_POTION
Definition: define.h:421
uint32 mark_count
Definition: player.h:247
#define PU_HELMET
Definition: define.h:409
sint16 level
Definition: object.h:202
#define AT_ACID
Definition: attack.h:110
#define FLAG_INV_LOCKED
Definition: define.h:626
void fix_object(object *op)
Definition: living.c:900
#define PU_ALLWEAPON
Definition: define.h:419
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:447
uint8 real_wiz
Definition: global.h:359
#define PU_NOT_CURSED
Definition: define.h:428
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.c:207
sint32 value
Definition: object.h:201
void put_object_in_sack(object *op, object *sack, object *tmp, uint32 nrof)
Definition: c_object.c:700
#define MSG_TYPE_COMMAND_INVENTORY
Definition: newclient.h:451
const char * name
Definition: object.h:322
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:78
int command_throw(object *op, char *params)
Definition: c_object.c:198
uint8 type
Definition: object.h:189
#define MAX_STAT
Definition: define.h:78
int command_search(object *op, char *params)
Definition: c_object.c:167
#define PU_MAGIC_DEVICE
Definition: define.h:426
sint32 food
Definition: living.h:89
void drop(object *op, object *tmp)
Definition: c_object.c:943