Crossfire Server, Trunk
c_object.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
19 #include "global.h"
20 
21 #include <ctype.h>
22 #include <math.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "living.h"
27 #include "loader.h"
28 #include "shop.h"
29 #include "skills.h"
30 #include "sproto.h"
31 
33 static const char *pickup_names[] = {
34  "debug", "inhibit", "stop", "food", "drink",
35  "valuables", "bow", "arrow", "helmet", "shield",
36  "armour", "boots", "gloves", "cloak", "key",
37  "missile", "melee", "magical", "potion", "spellbook",
38  "skillscroll", "readables", "magicdevice", "notcursed", "jewels",
39  "flesh", "container", "cursed", NULL
40 };
41 
43 static const uint32_t pickup_modes[] = {
48 };
49 
58 static int get_pickup_mode_index(const char *name) {
59  int best = -1;
60  size_t len = strlen(name);
61  for (size_t mode = 0; pickup_names[mode]; mode++) {
62  if (!strcmp(pickup_names[mode], name)) {
63  return mode;
64  }
65  if (len < strlen(pickup_names[mode]) && strncmp(name, pickup_names[mode], len) == 0) {
66  if (best != -2) {
67  if (best != -1) {
68  best = -2;
69  } else {
70  best = mode;
71  }
72  }
73  }
74  }
75  return best != -2 ? best : -1;
76 }
77 
78 static void set_pickup_mode(const object *op, int i);
79 
80 /*
81  * Object id parsing functions
82  */
83 
101 static object *find_best_apply_object_match(object *start, object *pl, const char *params, int aflag) {
102  object *tmp, *best = NULL;
103  int match_val = 0, tmpmatch;
104 
105  tmp = start;
107  if (!player_can_find(pl, tmp))
108  continue;
109  if (aflag == AP_APPLY && QUERY_FLAG(tmp, FLAG_APPLIED))
110  continue;
111  if (aflag == AP_UNAPPLY && !QUERY_FLAG(tmp, FLAG_APPLIED))
112  continue;
113  tmpmatch = object_matches_string(pl, tmp, params);
114  if (tmpmatch > match_val) {
115  match_val = tmpmatch;
116  best = tmp;
117  }
119  return best;
120 }
121 
132 static object *find_best_object_match(object *pl, const char *params) {
134 }
135 
144 void command_uskill(object *pl, const char *params) {
145  if (*params == '\0') {
147  "Usage: use_skill <skill name>");
148  return;
149  }
150  use_skill(pl, params);
151 }
152 
161 void command_rskill(object *pl, const char *params) {
162  object *skill;
163 
164  if (*params == '\0') {
166  "Usage: ready_skill <skill name>");
167  return;
168  }
169  skill = find_skill_by_name(pl, params);
170 
171  if (!skill) {
173  "You have no knowledge of the skill %s",
174  params);
175  return;
176  }
177  change_skill(pl, skill, 0);
178 }
179 
188 static void do_skill_by_number(object *op, int skill_subtype, const char *params,
189  const char *missing_message) {
190  object *skop = find_skill_by_number(op, skill_subtype);
191  if (skop) {
192  do_skill(op, op, skop, op->facing, *params == '\0' ? NULL : params);
193  return;
194  }
195 
197  missing_message);
198 }
199 
200 /* These functions (command_search, command_disarm) are really juse wrappers for
201  * things like 'use_skill ...'). In fact, they should really be obsoleted
202  * and replaced with those.
203  */
212 void command_search(object *op, const char *params) {
213  do_skill_by_number(op, SK_FIND_TRAPS, params, "You don't know how to search for unusual things.");
214 }
215 
224 void command_disarm(object *op, const char *params) {
225  do_skill_by_number(op, SK_DISARM_TRAPS, params, "You don't know how to disarm traps.");
226 }
227 
239 void command_throw(object *op, const char *params) {
240  do_skill_by_number(op, SK_THROWING, params, "You have no knowledge of the skill throwing.");
241 }
242 
251 void command_apply(object *op, const char *params) {
252  int aflag = 0;
253  object *inv = op->inv;
254  object *item;
255 
256  if (*params == '\0') {
258  return;
259  }
260 
261  while (*params == ' ')
262  params++;
263  if (!strncmp(params, "-a ", 3)) {
264  aflag = AP_APPLY;
265  params += 3;
266  }
267  if (!strncmp(params, "-u ", 3)) {
268  aflag = AP_UNAPPLY;
269  params += 3;
270  }
271  if (!strncmp(params, "-o ", 3)) {
272  aflag = AP_OPEN;
273  params += 3;
274  }
275  if (!strncmp(params, "-b ", 3)) {
276  params += 3;
277  if (op->container)
278  inv = op->container->inv;
279  else {
280  inv = op;
281  while (inv->above)
282  inv = inv->above;
283  }
284  }
285  while (*params == ' ')
286  params++;
287 
289  if (item == NULL)
291  if (item) {
292  apply_by_living(op, item, aflag, 0);
293  } else
295  "Could not find any match to the %s.",
296  params);
297 }
298 
317 int sack_can_hold(const object *pl, const object *sack, const object *op, uint32_t nrof) {
318  char name[MAX_BUF];
319  query_name(sack, name, MAX_BUF);
320 
321  if (!QUERY_FLAG(sack, FLAG_APPLIED)) {
323  "The %s is not active.",
324  name);
325  return 0;
326  }
327  if (sack == op) {
329  "You can't put the %s into itself.",
330  name);
331  return 0;
332  }
333  if (sack->race
334  && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type))) {
336  "You can put only %s into the %s.",
337  sack->race, name);
338  return 0;
339  }
340  if (op->type == SPECIAL_KEY && sack->slaying && op->slaying) {
342  "You can't put the key into %s.",
343  name);
344  return 0;
345  }
346  if (sack->weight_limit) {
347  int32_t new_weight;
348 
349  new_weight = sack->carrying+(nrof ? nrof : 1)
350  /* Most non-containers should have op->carrying == 0. Icecubes, however, will not,
351  * and we need to handle those.
352  * Neila Hawkins 2021-01-21
353  */
354  *(op->weight+(op->type == CONTAINER ? op->carrying*op->stats.Str : op->carrying))
355  *(100-sack->stats.Str)/100;
356  if (new_weight > sack->weight_limit) {
358  "That won't fit in the %s!",
359  name);
360  return 0;
361  }
362  }
363  /* All other checks pass, must be OK */
364  return 1;
365 }
366 
379 static void pick_up_object(object *pl, object *op, object *tmp, int nrof) {
380  /* buf needs to be big (more than 256 chars) because you can get
381  * very long item names.
382  */
383  char buf[HUGE_BUF], name[MAX_BUF];
384  object *env = tmp->env;
385  uint32_t weight, effective_weight_limit;
386  const int tmp_nrof = NROF(tmp);
387  tag_t tag;
388  mapstruct* map = tmp->map;
389  int16_t x = tmp->x, y = tmp->y;
390 
391  /* IF the player is flying & trying to take the item out of a container
392  * that is in his inventory, let him. tmp->env points to the container
393  * (sack, luggage, etc), tmp->env->env then points to the player (nested
394  * containers not allowed as of now)
395  */
396  if ((pl->move_type&MOVE_FLYING)
397  && !QUERY_FLAG(pl, FLAG_WIZ)
400  "You are levitating, you can't reach the ground!");
401  return;
402  }
404  return;
405 
408  "The object disappears in a puff of smoke! It must have been an illusion.");
409  if (!QUERY_FLAG(tmp, FLAG_REMOVED))
412  return;
413  }
414 
415  if (nrof > tmp_nrof || nrof == 0)
416  nrof = tmp_nrof;
417 
418  /* Figure out how much weight this object will add to the player */
419  weight = tmp->weight*nrof;
420  if (tmp->inv)
421  weight += tmp->carrying*(100-tmp->stats.Str)/100;
422 
423  effective_weight_limit = get_weight_limit(MIN(pl->stats.Str, settings.max_stat));
424 
425  if (pl->weight+pl->carrying+weight > effective_weight_limit) {
427  "That item is too heavy for you to pick up.");
428  return;
429  }
430 
433 
434  if (nrof != tmp_nrof) {
435  char failure[MAX_BUF];
436 
437  tmp = object_split(tmp, nrof, failure, sizeof(failure));
438  if (!tmp) {
440  failure);
441  return;
442  }
443  } else {
444  /* If the object is in a container, send a delete to the client.
445  * - we are moving all the items from the container to elsewhere,
446  * so it needs to be deleted.
447  */
448  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
449  object_remove(tmp); /* Unlink it */
450  }
451  }
453 
454  if (QUERY_FLAG(tmp, FLAG_UNPAID)) {
455  char *value = cost_str(shop_price_buy(tmp, pl));
456  if (op == pl) {
457  snprintf(buf, sizeof(buf), "%s will cost you %s.", name, value);
458  } else {
459  snprintf(buf, sizeof(buf), "%s will cost you %s. You place it in your %s.", name, value, op->name);
460  }
461  free(value);
462  } else {
463  if (op == pl) {
464  snprintf(buf, sizeof(buf), "You pick up the %s.", name);
465  } else {
466  snprintf(buf, sizeof(buf), "You pick up the %s and put it in your %s.", name, op->name);
467  }
468  }
469 
470  /* Now item is about to be picked. */
471  tag = tmp->count;
473  /* put item back, if it still exists */
474  if (tmp->count == tag && !QUERY_FLAG(tmp, FLAG_FREED)) {
475  if (env != NULL) {
477  } else {
478  object_insert_in_map_at(tmp, map, NULL, 0, x, y);
479  }
480  }
481  return;
482  }
483 
485  buf);
486 
488 
489  /* All the stuff below deals with client/server code, and is only
490  * usable by players
491  */
492  if (pl->type != PLAYER)
493  return;
494 
495  /* Additional weight changes speed, etc */
496  fix_object(pl);
497 
498  /* These are needed to update the weight for the container we
499  * are putting the object in.
500  */
501  if (op != pl) {
504  }
505 
506  /* Update the container the object was in */
507  if (env && env != pl && env != op)
509 }
510 
519 void pick_up(object *op, object *alt) {
520 /* modified slightly to allow monsters use this -b.t. 5-31-95 */
521  object *tmp = NULL, *tmp1;
522  mapstruct *tmp_map = NULL;
523  int count;
524 
525  /* Decide which object to pick. */
526  if (alt) {
527  if (!object_can_pick(op, alt)) {
529  "You can't pick up the %s.",
530  alt->name);
531  return;
532  }
533  tmp = alt;
534  } else {
535  if (op->below == NULL || !object_can_pick(op, op->below)) {
537  "There is nothing to pick up here.");
538  return;
539  }
540  tmp = op->below;
541  }
542 
543  /* it is possible that the object is a thrown object and is flying about.
544  * in that case, what we want to pick up is the payload. Objects
545  * that are thrown are encapsulated into a thrown object.
546  * stop_item() returns the payload (unlinked from map) and gets rid of the
547  * container object. If this object isn't picked up, we need to insert
548  * it back on the map.
549  * A bug here is that even attempting to pick up one of these objects will
550  * result in this logic being called even if player is unable to pick it
551  * up.
552  */
553 
554  tmp_map = tmp->map;
555  tmp1 = stop_item(tmp);
556  if (tmp1 == NULL)
557  return;
558 
559  /* If it is a thrown object, insert it back into the map here.
560  * makes life easier further along. Do no merge so pick up code
561  * behaves more sanely.
562  */
563  if (tmp1 != tmp) {
564  tmp = object_insert_in_map(tmp1, tmp_map, op, INS_NO_MERGE);
565  }
566 
567  if (tmp == NULL)
568  return;
569 
570  if (!object_can_pick(op, tmp))
571  return;
572 
573  /* Establish how many of the object we are picking up */
574  if (op->type == PLAYER) {
575  count = op->contr->count;
576  if (count == 0)
577  count = tmp->nrof;
578  } else
579  count = tmp->nrof;
580 
581  /* container is open, so use it */
582  if (op->container) {
583  alt = op->container;
584  if (alt != tmp->env && !sack_can_hold(op, alt, tmp, count))
585  return;
586  } else {
587  /* non container pickup. See if player has any
588  * active containers.
589  */
590  object *container = NULL;
591 
592  /* Look for any active containers that can hold this item.
593  * we cover two cases here - the perfect match case, where we
594  * break out of the loop, and the general case (have a container),
595  * Moved this into a single loop - reduces redundant code, is
596  * more efficient and easier to follow. MSW 2009-04-06
597  */
598  alt = op->inv;
600  if (alt->type == CONTAINER
601  && QUERY_FLAG(alt, FLAG_APPLIED)
602  && sack_can_hold(NULL, alt, tmp, count)) {
603  if (alt->race && alt->race == tmp->race) {
604  break; /* perfect match */
605  } else if (!container) {
606  container = alt;
607  }
608  }
610  /* Note container could be null, but no reason to check for it */
611  if (!alt)
612  alt = container;
613 
614  if (!alt)
615  alt = op; /* No free containers */
616  }
617  /* see if this object is already in this container. If so,
618  * move it to player inventory from this container.
619  */
620  if (tmp->env == alt) {
621  alt = op;
622  }
623 
624  /* Don't allow players to be put into containers. Instead,
625  * just put them in the players inventory.
626  */
627  if ((tmp->type == CONTAINER || tmp->type == MIMIC) && alt->type==CONTAINER) {
628  alt = op;
629  }
630 #ifdef PICKUP_DEBUG
631  LOG(llevDebug, "Pick_up(): %s picks %s (%d) and inserts it %s.\n", op->name, tmp->name, op->contr->count, alt->name);
632 #endif
633 
634  /* startequip items are not allowed to be put into containers
635  * Not sure why we have this limitation
636  */
637  if (op->type == PLAYER
638  && alt->type == CONTAINER
641  "This object cannot be put into containers!");
642  return;
643  }
644 
645  pick_up_object(op, alt, tmp, count);
646  if (op->type == PLAYER)
647  op->contr->count = 0;
648 }
649 
656 int object_matches_pickup_mode(const object *item, int mode) {
657  switch(mode) {
658  case PU_FOOD:
659  return item->type == FOOD;
660  case PU_DRINK:
661  return item->type == DRINK || (item->type == POISON && !QUERY_FLAG(item, FLAG_KNOWN_CURSED));
662  case PU_FLESH:
663  return item->type == FLESH;
664  case PU_POTION:
665  return item->type == POTION;
666  case PU_SPELLBOOK:
667  return item->type == SPELLBOOK;
668  case PU_SKILLSCROLL:
669  return item->type == SKILLSCROLL;
670  case PU_READABLES:
671  return item->type == BOOK || item->type == SCROLL;
672  case PU_MAGIC_DEVICE:
673  return item->type == WAND || item->type == ROD || item->type == WEAPON_IMPROVER || item->type == ARMOUR_IMPROVER || item->type == SKILL_TOOL;
674  case PU_MAGICAL:
676  case PU_VALUABLES:
677  return item->type == MONEY || item->type == GEM;
678  case PU_JEWELS:
679  return item->type == RING || item->type == AMULET;
680  case PU_BOW:
681  return item->type == BOW;
682  case PU_ARROW:
683  return item->type == ARROW;
684  case PU_ARMOUR:
685  return item->type == ARMOUR;
686  case PU_HELMET:
687  return item->type == HELMET;
688  case PU_SHIELD:
689  return item->type == SHIELD;
690  case PU_BOOTS:
691  return item->type == BOOTS;
692  case PU_GLOVES:
693  return item->type == GLOVES;
694  case PU_CLOAK:
695  return item->type == CLOAK;
696  case PU_MISSILEWEAPON:
697  return item->type == WEAPON && QUERY_FLAG(item, FLAG_IS_THROWN);
698  case PU_MELEEWEAPON:
699  return item->type == WEAPON;
700  case PU_KEY:
701  return item->type == KEY || item->type == SPECIAL_KEY;
702  case PU_CONTAINER:
703  return item->type == CONTAINER;
704  case PU_CURSED:
706  }
707  return 0;
708 }
709 
712  union {
713  struct {
717  };
718  char name[MAX_BUF];
720  };
721  int missed;
722 };
723 
731 typedef int (*item_matcher)(object *who, matcher_params *params, object *item);
732 
740 static int matcher_all(object *who, matcher_params *params, object *item) {
741  (void)who;
742  (void)params;
743  (void)item;
744  return 1;
745 }
746 
754 static int matcher_number(object *who, matcher_params *params, object *item) {
755  if (params->item_must_be_pickable == 0 || object_can_pick(who, item)) {
756  params->item_number++;
757  }
758  if (params->item_to_pick == params->item_number) {
759  /* Since we don't always increase item_number, multiple items may have the same index,
760  including unpickable ones, so to avoid failure messages just ensure no other item can be picked. */
761  params->item_to_pick = 0;
762  return 1;
763  }
764  return 0;
765 }
766 
774 static int matcher_name(object *who, matcher_params *params, object *item) {
775  int ival = object_matches_string(who, item, params->name);
776  if (ival > 0) {
777  if (ival <= 2 && !object_can_pick(who, item)) {
778  if (!QUERY_FLAG(item, FLAG_IS_FLOOR))/* don't count floor tiles */
779  params->missed++;
780  return 0;
781  }
782  return 1;
783  }
784  return 0;
785 }
786 
794 static int matcher_pickup_type(object *who, matcher_params *params, object *item) {
795  (void)who;
796  return object_matches_pickup_mode(item, params->pickup_type);
797 }
798 
806 static item_matcher make_matcher(object *who, const char *params, matcher_params *mp) {
807  memset(mp, 0, sizeof(*mp));
808  if (params[0] == '\0') {
809  mp->item_to_pick = 1;
810  mp->item_must_be_pickable = 1;
811  return &matcher_number;
812  }
813  if (params[0] == '#') {
814  mp->item_to_pick = atoi(params + 1);
815  if (mp->item_to_pick == 0) {
817  return NULL;
818  }
819  return &matcher_number;
820  }
821  if (params[0] == '*') {
822  if (params[1] == '\0') {
823  return &matcher_all;
824  }
825  int idx = get_pickup_mode_index(params + 1);
826  if (idx == -1) {
828  return NULL;
829  }
830  mp->pickup_type = pickup_modes[idx];
831  return &matcher_pickup_type;
832  }
833  strncpy(mp->name, params, sizeof(mp->name) - 1);
834  return &matcher_name;
835 }
836 
845 void command_take(object *op, const char *params) {
846  object *tmp;
847  int did_one = 0;
848 
849  if (op->container)
850  tmp = op->container->inv;
851  else {
852  tmp = op->above;
853  if (tmp)
854  while (tmp->above) {
855  tmp = tmp->above;
856  }
857  if (!tmp)
858  tmp = op->below;
859  }
860 
861  if (tmp == NULL) {
863  "Nothing to take!");
864  return;
865  }
866 
867  matcher_params mp;
868  item_matcher matcher = make_matcher(op, params, &mp);
869  if (!matcher) {
870  return; // Player already informed of failure.
871  }
872 
874 
876  if (tmp->invisible) {
877  continue;
878  }
879  if ((*matcher)(op, &mp, tmp)) {
880  pick_up(op, tmp);
881  did_one = 1;
882  }
884 
885  /* Nothing picked up, check if unable to pick or nothing to pick. */
886  if (params[0] == '\0' && !did_one) {
887  int found = 0;
889  if (!tmp->invisible) {
891  "You can't pick up a %s.",
892  tmp->name ? tmp->name : "null");
893  found = 1;
894  break;
895  }
897  if (!found)
899  "There is nothing to pick up.");
900  }
901 
902  if (mp.missed == 1)
904  "You were unable to take one of the items.");
905  else if (mp.missed > 1)
907  "You were unable to take %d of the items.",
908  mp.missed);
909 
910  /* Now update player and send information. */
912  fix_object(op);
913  if (op->type == PLAYER) {
914  op->contr->count = 0;
916  }
917 }
918 
937 void put_object_in_sack(object *op, object *sack, object *tmp, uint32_t nrof) {
938  object *sack2, *orig = sack;
939  char name_sack[MAX_BUF], name_tmp[MAX_BUF];
940 
941  if (sack == tmp)
942  return; /* Can't put an object in itself */
943  query_name(sack, name_sack, MAX_BUF);
944  if (sack->type != CONTAINER && sack->type != TRANSPORT) {
946  "The %s is not a container.",
947  name_sack);
948  return;
949  }
951  query_name(tmp, name_tmp, MAX_BUF);
953  "You cannot put the %s in the %s.",
954  name_tmp, name_sack);
955  return;
956  }
957  if (tmp->type == CONTAINER) {
958  if (tmp->inv) {
959  if (tmp->slaying)
960  return;
961  /* Eneq(@csd.uu.se): If the object to be dropped is a container
962  * and does not require a key to be opened,
963  * we instead move the contents of that container into the active
964  * container, this is only done if the object has something in it.
965  * If object is container but need a key, just don't do anything
966  */
967  sack2 = tmp;
968  query_name(tmp, name_tmp, MAX_BUF);
970  "You move the items from %s into %s.",
971  name_tmp, name_sack);
972 
973  FOR_INV_PREPARE(tmp, tmp2) {
974  if ((sack->type == CONTAINER && sack_can_hold(op, op->container, tmp2, tmp2->nrof))
975  || (sack->type == TRANSPORT && transport_can_hold(sack, tmp2, tmp2->nrof))) {
976  put_object_in_sack(op, sack, tmp2, 0);
977  } else {
980  "Your %s fills up.",
981  name_sack);
982  break;
983  }
984  } FOR_INV_FINISH();
985  esrv_update_item(UPD_WEIGHT, op, sack2);
986  return;
987  } else {
988  query_name(tmp, name_tmp, MAX_BUF);
990  "You can not put a %s into a %s",
991  name_tmp,
992  name_sack);
993  return;
994  }
995  }
996 
997  /* Don't worry about this for containers - our caller should have
998  * already checked this.
999  */
1000  if (sack->type == CONTAINER && !sack_can_hold(op, sack, tmp, nrof ? nrof : tmp->nrof))
1001  return;
1002 
1003  if (QUERY_FLAG(tmp, FLAG_APPLIED)) {
1005  return;
1006  }
1007 
1008  /* we want to put some portion of the item into the container */
1009  if (nrof && tmp->nrof != nrof) {
1010  char failure[MAX_BUF];
1011 
1012  tmp = object_split(tmp, nrof, failure, sizeof(failure));
1013 
1014  if (!tmp) {
1016  failure);
1017  return;
1018  }
1019  } else
1020  object_remove(tmp);
1021 
1022  if (sack->nrof > 1) {
1023  orig = object_split(sack, sack->nrof-1, NULL, 0);
1024  set_object_face_main(orig);
1025  CLEAR_FLAG(orig, FLAG_APPLIED);
1026  if (sack->env) {
1027  object_insert_in_ob(orig, sack->env);
1028  } else {
1029  object_insert_in_map_at(orig, sack->map, NULL, 0, sack->x, sack->y);
1030  orig->move_off = 0;
1031  }
1032  }
1033 
1034  query_name(tmp, name_tmp, MAX_BUF);
1036  "You put the %s in %s.",
1037  name_tmp, name_sack);
1038 
1039  object_insert_in_ob(tmp, sack);
1041  fix_object(op); /* This is overkill, fix_player() is called somewhere */
1042  /* in object.c */
1043 
1044  /* If a transport, need to update all the players in the transport
1045  * the view of what is in it.
1046  */
1047  if (sack->type == TRANSPORT) {
1048  FOR_INV_PREPARE(sack, tmp)
1049  if (tmp->type == PLAYER)
1050  tmp->contr->socket->update_look = 1;
1051  FOR_INV_FINISH();
1052  } else {
1053  /* update the sacks weight */
1054  esrv_update_item(UPD_WEIGHT, op, sack);
1055  }
1056 }
1057 
1073 object *drop_object(object *op, object *tmp, uint32_t nrof) {
1074  tag_t tmp_tag;
1075 
1076  if (QUERY_FLAG(tmp, FLAG_NO_DROP)) {
1077  return NULL;
1078  }
1079 
1080  if (QUERY_FLAG(tmp, FLAG_APPLIED)) {
1082  return NULL; /* can't unapply it */
1083  }
1084 
1085  if (events_execute_object_event(tmp, EVENT_DROP, op, NULL, NULL, SCRIPT_FIX_ALL) != 0)
1086  return NULL;
1087 
1088  /* ensure the plugin didn't destroy the object */
1089  if (QUERY_FLAG(tmp, FLAG_REMOVED))
1090  return NULL;
1091 
1092  /* We are only dropping some of the items. We split the current objec
1093  * off
1094  */
1095  if (nrof && tmp->nrof != nrof) {
1096  char failure[MAX_BUF];
1097 
1098  tmp = object_split(tmp, nrof, failure, sizeof(failure));
1099  if (!tmp) {
1101  failure);
1102  return NULL;
1103  }
1104  } else
1105  object_remove(tmp);
1106 
1107  if (QUERY_FLAG(tmp, FLAG_STARTEQUIP)) {
1108  char name[MAX_BUF];
1109 
1112  "You drop the %s. The gods who lent it to you retrieve it.",
1113  name);
1115 
1117  fix_object(op);
1118 
1119  return NULL;
1120  }
1121 
1122  /* If SAVE_INTERVAL is commented out, we never want to save
1123  * the player here.
1124  */
1125 #ifdef SAVE_INTERVAL
1126  /* I'm not sure why there is a value check - since the save
1127  * is done every SAVE_INTERVAL seconds, why care the value
1128  * of what he is dropping?
1129  */
1130  if (op->type == PLAYER
1131  && !QUERY_FLAG(tmp, FLAG_UNPAID)
1132  && (tmp->nrof ? tmp->value*tmp->nrof : tmp->value > 2000)
1133  && op->contr->last_save_time+SAVE_INTERVAL <= time(NULL)) {
1134  save_player(op, 1);
1135  op->contr->last_save_time = time(NULL);
1136  }
1137 #endif /* SAVE_INTERVAL */
1138 
1139 
1140  tmp_tag = tmp->count;
1142  if (!object_was_destroyed(tmp, tmp_tag) && !QUERY_FLAG(tmp, FLAG_UNPAID) && tmp->type != MONEY && shop_contains(op)) {
1143  sell_item(tmp, op);
1144  }
1145 
1146  /* Call this before we update the various windows/players. At least
1147  * that we, we know the weight is correct.
1148  */
1149  if (!QUERY_FLAG(op, FLAG_NO_FIX_PLAYER)) {
1150  fix_object(op); /* This is overkill, fix_player() is called somewhere */
1151  /* in object.c */
1152 
1153  /* Need to update weight of player */
1154  if (op->type == PLAYER)
1156  }
1157  return tmp;
1158 }
1159 
1168 void drop(object *op, object *tmp) {
1169  /* Hopeful fix for disappearing objects when dropping from a container -
1170  * somehow, players get an invisible object in the container, and the
1171  * old logic would skip over invisible objects - works fine for the
1172  * playes inventory, but drop inventory wants to use the next value.
1173  */
1174  if (tmp->invisible) {
1175  /* if the following is the case, it must be in an container. */
1176  if (tmp->env && tmp->env->type != PLAYER) {
1177  /* Just toss the object - probably shouldn't be hanging
1178  * around anyways
1179  */
1180  object_remove(tmp);
1182  return;
1183  } else {
1185  if (!tmp->invisible)
1186  break;
1188  }
1189  }
1190 
1191  if (tmp == NULL) {
1193  "You don't have anything to drop.");
1194  return;
1195  }
1196  if (QUERY_FLAG(tmp, FLAG_INV_LOCKED)) {
1198  "This item is locked");
1199  return;
1200  }
1201  if (QUERY_FLAG(tmp, FLAG_NO_DROP)) {
1202  return;
1203  }
1204 
1205  if (op->container) {
1206  if (op->type == PLAYER) {
1207  put_object_in_sack(op, op->container, tmp, op->contr->count);
1208  } else {
1209  put_object_in_sack(op, op->container, tmp, 0);
1210  };
1211  } else {
1212  if (op->type == PLAYER) {
1213  drop_object(op, tmp, op->contr->count);
1214  } else {
1215  drop_object(op, tmp, 0);
1216  };
1217  }
1218  if (op->type == PLAYER)
1219  op->contr->count = 0;
1220 }
1221 
1230 void command_dropall(object *op, const char *params) {
1231  int count = 0;
1232 
1233  if (op->inv == NULL) {
1236  "Nothing to drop!");
1237  return;
1238  }
1239 
1240  if (op->contr)
1241  count = op->contr->count;
1242 
1243  /* Set this so we don't call it for _every_ object that
1244  * is dropped.
1245  */
1247 
1248  /*
1249  * This is the default. Drops everything not locked or considered
1250  * not something that should be dropped.
1251  * Care must be taken that the next item pointer is not to money as
1252  * the drop() routine will do unknown things to it when dropping
1253  * in a shop. --Tero.Pelander@utu.fi
1254  */
1255  if (*params == '\0') {
1256  FOR_INV_PREPARE(op, curinv) {
1257  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1258  && curinv->type != MONEY
1259  && curinv->type != FOOD
1260  && curinv->type != KEY
1261  && curinv->type != SPECIAL_KEY
1262  && curinv->type != GEM
1263  && !curinv->invisible
1264  && (curinv->type != CONTAINER || op->container != curinv)) {
1265  drop(op, curinv);
1266  if (op->contr)
1267  op->contr->count = count;
1268  }
1269  } FOR_INV_FINISH();
1270  } else if (strcmp(params, "weapons") == 0) {
1271  FOR_INV_PREPARE(op, curinv) {
1272  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1273  && (curinv->type == WEAPON || curinv->type == BOW || curinv->type == ARROW)) {
1274  drop(op, curinv);
1275  if (op->contr)
1276  op->contr->count = count;
1277  }
1278  } FOR_INV_FINISH();
1279  } else if (strcmp(params, "armor") == 0 || strcmp(params, "armour") == 0) {
1280  FOR_INV_PREPARE(op, curinv) {
1281  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1282  && (curinv->type == ARMOUR || curinv->type == SHIELD || curinv->type == HELMET)) {
1283  drop(op, curinv);
1284  if (op->contr)
1285  op->contr->count = count;
1286  }
1287  } FOR_INV_FINISH();
1288  } else if (strcmp(params, "food") == 0) {
1289  FOR_INV_PREPARE(op, curinv) {
1290  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1291  && (curinv->type == FOOD || curinv->type == DRINK)) {
1292  drop(op, curinv);
1293  if (op->contr)
1294  op->contr->count = count;
1295  }
1296  } FOR_INV_FINISH();
1297  } else if (strcmp(params, "flesh") == 0) {
1298  FOR_INV_PREPARE(op, curinv) {
1299  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1300  && (curinv->type == FLESH)) {
1301  drop(op, curinv);
1302  if (op->contr)
1303  op->contr->count = count;
1304  }
1305  } FOR_INV_FINISH();
1306  } else if (strcmp(params, "misc") == 0) {
1307  FOR_INV_PREPARE(op, curinv) {
1308  if (!QUERY_FLAG(curinv, FLAG_INV_LOCKED)
1309  && !QUERY_FLAG(curinv, FLAG_APPLIED)) {
1310  switch (curinv->type) {
1311  case BOOK:
1312  case SPELLBOOK:
1313  case GIRDLE:
1314  case AMULET:
1315  case RING:
1316  case CLOAK:
1317  case BOOTS:
1318  case GLOVES:
1319  case BRACERS:
1320  case SCROLL:
1321  case ARMOUR_IMPROVER:
1322  case WEAPON_IMPROVER:
1323  case WAND:
1324  case ROD:
1325  case POTION:
1326  drop(op, curinv);
1327  if (op->contr)
1328  op->contr->count = count;
1329  break;
1330 
1331  default:
1332  break;
1333  }
1334  }
1335  } FOR_INV_FINISH();
1336  }
1337  op->contr->socket->update_look = 1;
1339  /* call it now, once */
1340  fix_object(op);
1341  /* Need to update weight of player. Likewise, only do it once */
1342  if (op->type == PLAYER)
1344 }
1345 
1354 void command_drop(object *op, const char *params) {
1355  int did_one = 0;
1356  int missed = 0;
1357 
1358  if (*params == '\0') {
1360  "Drop what?");
1361  return;
1362  }
1363 
1364  matcher_params mp;
1365  item_matcher matcher = make_matcher(op, params, &mp);
1366  if (!matcher) {
1367  return;
1368  }
1369 
1371 
1372  FOR_INV_PREPARE(op, tmp) {
1373  if (QUERY_FLAG(tmp, FLAG_NO_DROP) || tmp->invisible)
1374  continue;
1375  if ((*matcher)(op, &mp, tmp)) {
1376  if (QUERY_FLAG(tmp, FLAG_INV_LOCKED)) {
1377  missed++;
1378  } else {
1379  drop(op, tmp);
1380  }
1381  did_one = 1;
1382  }
1383  } FOR_INV_FINISH();
1384  if (!did_one)
1386  "Nothing to drop.");
1387  if (missed == 1)
1389  "One item couldn't be dropped because it was locked.");
1390  else if (missed > 1)
1392  "%d items couldn't be dropped because they were locked.",
1393  missed);
1394 
1395  /* Now update player and send information. */
1397  fix_object(op);
1398  if (op->type == PLAYER) {
1399  op->contr->count = 0;
1401  }
1402 }
1403 
1412 static void empty_container(object *container, object *pl) {
1413  int left = 0;
1414  char name[MAX_BUF];
1415 
1416  if (!container->inv)
1417  return;
1418 
1419  FOR_INV_PREPARE(container, inv) {
1420  object *next;
1421 
1422  if (QUERY_FLAG(inv, FLAG_INV_LOCKED)) {
1423  /* you can have locked items in container. */
1424  left++;
1425  continue;
1426  }
1427  next = inv->below;
1428  drop(pl, inv);
1429  if (inv->below == next)
1430  /* item couldn't be dropped for some reason. */
1431  left++;
1432  } FOR_INV_FINISH();
1433  esrv_update_item(UPD_WEIGHT, pl, container);
1434 
1435  query_name(container, name, sizeof(name));
1436  if (left)
1437  draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "You empty the %s except %d items.", name, left);
1438  else
1440 }
1441 
1450 void command_empty(object *op, const char *params) {
1451  object *container;
1452 
1453  if (*params == '\0') {
1455  "Empty what?");
1456  return;
1457  }
1458 
1459  if (strcmp(params, "all") == 0) {
1461  if (inv->type == CONTAINER)
1463  FOR_INV_FINISH();
1464  return;
1465  }
1466 
1467  container = find_best_object_match(op, params);
1468  if (!container) {
1470  "No such item.");
1471  return;
1472  }
1473  if (container->type != CONTAINER) {
1475  "This is not a container!");
1476  return;
1477  }
1478  empty_container(container, op);
1479 }
1480 
1489 void command_examine(object *op, const char *params) {
1490  if (*params == '\0') {
1492  if (LOOK_OBJ(tmp)) {
1493  examine(op, tmp);
1494  break;
1495  }
1496  FOR_BELOW_FINISH();
1497  } else {
1498  object *tmp = find_best_object_match(op, params);
1499 
1500  if (tmp)
1501  examine(op, tmp);
1502  else
1504  "Could not find an object that matches %s",
1505  params);
1506  }
1507 }
1508 
1520 object *find_marked_object(object *op) {
1521  if (!op || !op->contr || !op->contr->mark)
1522  return NULL;
1523 
1524  /* This may seem like overkill, but we need to make sure that they
1525  * player hasn't dropped the item. We use count on the off chance that
1526  * an item got reincarnated at some point.
1527  */
1528  /*
1529  FOR_INV_PREPARE(op, tmp) {
1530  if (tmp->invisible)
1531  continue;
1532  if (tmp == op->contr->mark) {
1533  if (tmp->count == op->contr->mark_count)
1534  return tmp;
1535  else {
1536  op->contr->mark = NULL;
1537  op->contr->mark_count = 0;
1538  return NULL;
1539  }
1540  }
1541  } FOR_INV_FINISH();
1542  */
1543  /* Try a different way of doing this
1544  * We check the environment of the marked object
1545  * to make sure it is still in the player's inventory.
1546  * In addition, we ensure there is the correct tag for that item.
1547  *
1548  * Neila Hawkins 2018-10-23
1549  */
1550  if (op->contr->mark->env == op && op->contr->mark->count == op->contr->mark_count)
1551  return op->contr->mark;
1552  // Otherwise reset the mark, since it is no longer valid.
1553  op->contr->mark = NULL;
1554  op->contr->mark_count = 0;
1555  return NULL;
1556 }
1557 
1567 void command_mark(object *op, const char *params) {
1568  char name[MAX_BUF];
1569 
1570  if (!op->contr)
1571  return;
1572  if (*params == '\0') {
1573  object *mark = find_marked_object(op);
1574  if (!mark)
1576  "You have no marked object.");
1577  else {
1578  query_name(mark, name, MAX_BUF);
1580  "%s is marked.",
1581  name);
1582  }
1583  } else {
1584  object *mark1 = find_best_object_match(op, params);
1585 
1586  if (!mark1) {
1588  "Could not find an object that matches %s",
1589  params);
1590  return;
1591  } else {
1592  op->contr->mark = mark1;
1593  op->contr->mark_count = mark1->count;
1594  query_name(mark1, name, MAX_BUF);
1596  "Marked item %s",
1597  name);
1598  return;
1599  }
1600  }
1601  /*shouldnt get here */
1602 }
1603 
1614 void examine_monster(object *op, object *tmp, int level) {
1615  object *mon = HEAD(tmp), *probe;
1616 
1617  if (QUERY_FLAG(mon, FLAG_UNDEAD))
1619  "It is an undead force.");
1620  if (mon->level > op->level)
1622  "It is likely more powerful than you.");
1623  else if (mon->level < op->level)
1625  "It is likely less powerful than you.");
1626  else
1628  "It is probably as powerful as you.");
1629 
1630  if (mon->attacktype&AT_ACID)
1632  "You smell an acrid odor.");
1633 
1634  /* Anyone know why this used to use the clone value instead of the
1635  * maxhp field? This seems that it should give more accurate results.
1636  */
1637  switch ((mon->stats.hp+1)*4/(mon->stats.maxhp+1)) {
1638  /* From 0-4+, since hp can be higher than maxhp if defined in map. */
1639  case 0:
1641  "It is critically wounded.");
1642  break;
1643 
1644  case 1:
1646  "It is in a bad shape.");
1647  break;
1648 
1649  case 2:
1651  "It is hurt.");
1652  break;
1653 
1654  case 3:
1656  "It is somewhat hurt.");
1657  break;
1658 
1659  default:
1661  "It is in excellent shape.");
1662  break;
1663  }
1664  if (object_present_in_ob(POISONING, mon) != NULL)
1666  "It looks very ill.");
1667 
1668  if (level < 10)
1669  return;
1671 
1672  if (level < 15)
1673  return;
1674 
1675  probe = object_find_by_type_and_name(mon, FORCE, "probe_force");
1676  if (probe != NULL && probe->level > level)
1677  return;
1678 
1679  if (probe == NULL) {
1681  free_string(probe->name);
1682  probe->name = add_string("probe_force");
1686  fix_object(mon);
1687  }
1688  probe->level = level;
1689  if (level / 10 > probe->duration)
1690  probe->duration = level / 10;
1691 }
1692 
1694  EX_ID_ABORT, // Not safe to continue
1695  EX_ID_NO_SKILL, // Player lacks the requisite skill(s)
1696  EX_ID_FAILED // Player has the skill but failed their ID roll
1697 };
1698 
1711  /* We will look for magic status, cursed status and then try to do a full skill-based ID, in that order */
1712  int exp = 0;
1713  object *skill = find_skill_by_number(op, SK_DET_MAGIC);
1714  if (skill && (object_can_pick(op, tmp))) {
1715  exp = detect_magic_on_item(op, tmp, skill);
1716  if (exp) {
1717  change_exp(op, exp, skill->skill, SK_SUBTRACT_SKILL_EXP);
1719  "You discover mystic forces on %s", tmp->nrof <= 1?"that item":"those items" );
1720  }
1721  }
1722 
1724  /* Cauldrons are a special case of item where it should be possible to detect a curse */
1725  if (skill && (object_can_pick(op, tmp) || QUERY_FLAG(tmp, FLAG_IS_CAULDRON))) {
1726  exp = detect_curse_on_item(op, tmp, skill);
1727  if (exp) {
1728  change_exp(op, exp, skill->skill, SK_SUBTRACT_SKILL_EXP);
1730  "You have a bad feeling about %s", tmp->nrof <= 1?"that item":"those items" );
1731  }
1732  }
1733 
1734  const typedata *tmptype = get_typedata(tmp->type);
1735  if (!tmptype) {
1736  LOG(llevError, "Attempted to examine item %d with type %d, which is invalid\n", tmp->count, tmp->type);
1737  return EX_ID_ABORT;
1738  }
1739 
1740  bool have_skill = false;
1742  skill = find_skill_by_number(op, tmptype->identifyskill);
1743  if (skill) {
1744  /* identify_object_with_skill() may merge tmp with another
1745  * object, so once that happens, we really can not do
1746  * any further processing with tmp. It would be possible
1747  * to modify identify_object_with_skill() to return
1748  * the merged object, but it is currently set to return
1749  * exp, so it would have to do it via modifying the
1750  * passed in value, but many other consumers would
1751  * need to be modified for that.
1752  */
1753  exp = identify_object_with_skill(tmp, op, skill, 1);
1754  if (exp) {
1755  change_exp(op, exp, skill->skill, SK_SUBTRACT_SKILL_EXP);
1756  return EX_ID_ABORT;
1757  }
1758  }
1759 
1760  /* The primary id skill didn't work, let's try the secondary one */
1761  skill = find_skill_by_number(op, tmptype->identifyskill2);
1762  if (skill) {
1763  /* if we've reached here, then the first skill will have been attempted
1764  * and failed; this will have set FLAG_NO_SKILL_IDENT we want to clear
1765  * that now, and try with the secondary ID skill, if it fails, then the
1766  * flag will be reset anyway, if it succeeds, it won't matter.*/
1768  exp = identify_object_with_skill(tmp, op, skill, 1);
1769  if (exp) {
1770  change_exp(op, exp, skill->skill, SK_SUBTRACT_SKILL_EXP);
1771  return EX_ID_ABORT;
1772  }
1773  }
1774  }
1775  return have_skill ? EX_ID_FAILED : EX_ID_NO_SKILL;
1776 }
1777 
1786 void examine_weight_and_material(object *op, object *tmp) {
1787  bool pl = tmp->nrof > 1;
1788  float weight = (tmp->nrof ? tmp->nrof : 1) * ((float)tmp->weight/1000.0);
1789 
1790  if (tmp->materialname && weight) {
1792  "%s made of %s and %s %3.3f kg.",
1793  pl ? "They are" : "It is", tmp->materialname,
1794  pl ? "weigh" : "weighs", weight);
1795  } else if (tmp->materialname) {
1797  "%s made of %s.", pl ? "They are" : "It is", tmp->materialname);
1798  } else if (weight) {
1800  "%s %3.3f kg.", pl ? "They weigh" : "it weighs", weight);
1801  }
1802 }
1803 
1812 void examine_wand_charge_level(object *op, object *tmp) {
1813  if (!is_identified(tmp)) return;
1814  const char *desc;
1815  if (tmp->stats.food <= 0) {
1816  desc = "It is completely depleted.";
1817  } else if (tmp->stats.food <= 2) {
1818  desc = "It is nearly depleted.";
1819  } else if (tmp->stats.food <= 4) {
1820  desc = "It is very low on power.";
1821  } else if (tmp->stats.food <= 8) {
1822  desc = "It is low on power.";
1823  } else if (tmp->stats.food <= 16) {
1824  desc = "It is well charged.";
1825  } else if (tmp->stats.food <= 32) {
1826  desc = "It is fully charged.";
1827  } else {
1828  desc = "It is overflowing with power.";
1829  }
1831 }
1832 
1841 void examine_rod_charge_level(object *op, object *tmp) {
1842  if (!is_identified(tmp)) return;
1843  if (!tmp->inv) // rod has no spell
1844  return;
1845  const int castings = tmp->stats.hp/SP_level_spellpoint_cost(tmp, tmp->inv, SPELL_HIGHEST);
1846  const char *desc;
1847  /* Rods get less precise information than wands/staves as part of balancing
1848  out their reusability -- in particular, you can't tell if a rod is *almost*
1849  out of shots or *completely* out of shots without trying it. */
1850  if (castings <= 1) {
1851  desc = "It is nearly depleted.";
1852  } else if (castings <= 3) {
1853  desc = "It hums with power.";
1854  } else {
1855  desc = "It crackles with power.";
1856  }
1858 }
1859 
1873 bool examine_fluff(object *op, object *tmp, bool output) {
1874  /* No message for stuff the player hasn't IDed. */
1876  return false;
1877  }
1878 
1879  // We use stringbuffer throughout this function so that we can use
1880  // trim_whitespace to conveniently strip trailing newlines, ensuring that
1881  // the output of examine is contiguous.
1882  // TODO: It might be better to strip the newlines in object_set_msg
1883  // and append them at print time, rather than ensuring that the msg
1884  // is newline-terminated and stripping off the newlines when we don't
1885  // want them; C string handling makes the latter a lot less convenient.
1886  if (tmp->msg && strncasecmp(tmp->msg, "@match", 6)) {
1887  if (!output) return true;
1889  stringbuffer_append_string(sb, tmp->msg);
1891  char *const msg = stringbuffer_finish(sb);
1893  free(msg);
1894  }
1895 
1896  switch (tmp->type) {
1897  /* Stuff with embedded skills. */
1898  case SKILLSCROLL:
1899  case SKILL_TOOL:
1900  {
1901  // Embedded skills are stored as an archetype name and don't get reified
1902  // until the player actually reads/equips the object, so we need to turn
1903  // the name into an actual archetype and then read the msg out of that.
1904  if (!tmp->skill) break; // Blank skill scroll, somehow.
1905  archetype *skill = get_archetype_by_skill_name(tmp->skill, SKILL);
1906  if (!skill) {
1907  if (!output) break; // Still need to check for lore later.
1908  // Skill name doesn't correspond to any actual skill.
1910  "Unfortunately, it is damaged beyond %s.",
1911  (tmp->type == SKILLSCROLL) ? "comprehension" : "repair");
1912  break;
1913  }
1914  if (skill->clone.msg) {
1915  if (!output) return true;
1917  "%s lets you %s a skill:",
1918  tmp->nrof > 1 ? "These objects" : "This object",
1919  (tmp->type == SKILLSCROLL) ? "learn" : "use");
1920 
1922  stringbuffer_append_string(sb, skill->clone.msg);
1924  char *const fluff = stringbuffer_finish(sb);
1925  // SPELL_INFO is not a perfect match here, but it should display in the
1926  // same manner as the spell descriptions below and there's no SKILL_INFO
1927  // message type.
1929  free(fluff);
1930  }
1931  break;
1932  }
1933 
1934  /* Stuff with embedded spells. */
1935  case SPELLBOOK:
1936  case SCROLL:
1937  case WAND:
1938  case ROD:
1939  case POTION:
1940  {
1941  if (tmp->inv && tmp->inv->msg) {
1942  if (!output) return true;
1944  "%s holds%s a spell:",
1945  tmp->nrof > 1 ? "These objects" : "This object",
1946  tmp->type == SPELLBOOK ? " knowledge of" : "");
1947 
1949  stringbuffer_append_string(sb, tmp->inv->msg);
1951  char *const fluff = stringbuffer_finish(sb);
1953  free(fluff);
1954  }
1955  }
1956  }
1957 
1958  if (tmp->lore) {
1959  if (!output) return true;
1961  "%s a story:", tmp->nrof > 1 ? "These objects have" : "This object has");
1963  stringbuffer_append_string(sb, tmp->lore);
1965  char *const msg = stringbuffer_finish(sb);
1967  free(msg);
1968  }
1969 
1970  // If we get this far in output=false mode, we didn't hit any of the earlier
1971  // escape hatches and thus have nothing to output. In normal use we'll hit
1972  // this regardless and assume we output something.
1973  return output;
1974 }
1975 
1985 void examine(object *op, object *tmp) {
1986  if (tmp == NULL || tmp->type == CLOSE_CON)
1987  return;
1988 
1989  /* If the player has examined this twice in a row, do a more detailed
1990  examine. last_examined shouldn't get set unless we already know that
1991  examine_fluff() will do something interesting. */
1992  if (op->contr->last_examined == tmp->count) {
1993  op->contr->last_examined = 0;
1995  "You examine the %s more closely.", tmp->nrof > 1 ? tmp->name_pl : tmp->name);
1996  examine_fluff(op, tmp, true);
1998  " "); /* Blank line */
1999  return;
2000  }
2001 
2002  int i;
2003  char prefix[MAX_BUF] = "";
2004  char buf[VERY_BIG_BUF] = "";
2005  if (is_identified(tmp)) {
2006  snprintf(prefix, MAX_BUF, "%s:", tmp->nrof<=1 ? "That is" : "Those are");
2007  } else {
2008  switch(examine_autoidentify(op, tmp)) {
2009  case EX_ID_NO_SKILL:
2010  snprintf(prefix, MAX_BUF, "You lack the skill to understand %s:",
2011  tmp->nrof<=1 ? "that fully; it is" : "those fully; they are");
2012  break;
2013  case EX_ID_FAILED:
2014  snprintf(prefix, MAX_BUF, "You fail to understand %s:",
2015  tmp->nrof<=1 ? "that fully; it is" : "those fully; they are");
2016  break;
2017  case EX_ID_ABORT:
2018  default:
2019  /* Item may have been merged with something else, not safe to proceed. */
2020  return;
2021  }
2022  }
2023 
2024  /* now we need to get the rest of the object description */
2025  ob_describe(tmp, op, 1, buf, sizeof(buf));
2026 
2028  "%s %s", prefix, buf);
2029  buf[0] = '\0';
2031  if (custom_name) {
2033  "You name it %s",
2034  custom_name);
2035  }
2036 
2037  switch (tmp->type) {
2038  case WAND:
2040  break;
2041 
2042  case ROD:
2044  break;
2045 
2046  case BOOK:
2047  if (tmp->msg != NULL)
2048  snprintf(buf, sizeof(buf), "Something is written in it.");
2049  break;
2050 
2051  case CONTAINER:
2052  if (tmp->race != NULL) {
2053  if (tmp->weight_limit && tmp->stats.Str < 100)
2054  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)));
2055  else
2056  snprintf(buf, sizeof(buf), "It can hold only %s.", tmp->race);
2057  } else
2058  if (tmp->weight_limit && tmp->stats.Str < 100)
2059  snprintf(buf, sizeof(buf), "Its weight limit is %.1f kg.", tmp->weight_limit/(10.0*(100-tmp->stats.Str)));
2060  break;
2061  }
2062 
2063  if (buf[0] != '\0')
2065  buf);
2066 
2068 
2069  /* Where to wear this item */
2070  for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
2071  if (tmp->body_info[i]) {
2072  if (op->body_info[i]) {
2073  if (tmp->body_info[i] < -1) {
2075  "%s %s (%d).", tmp->nrof > 1 ? "They go" : "It goes",
2076  body_locations[i].use_name, -tmp->body_info[i]);
2077  } else {
2079  "%s %s.", tmp->nrof > 1 ? "They go" : "It goes",
2081  }
2082  } else {
2084  "%s %s.", tmp->nrof > 1 ? "They go" : "It goes",
2086  }
2087  }
2088  }
2089 
2090  int in_shop = shop_contains(op);
2091 
2092  if (tmp->value && !QUERY_FLAG(tmp, FLAG_STARTEQUIP) && !QUERY_FLAG(tmp, FLAG_NO_PICK)) {
2093  char *value = cost_approx_str(tmp, op);
2094  snprintf(buf, sizeof(buf), "You reckon %s worth %s.", tmp->nrof > 1 ? "they are" : "it is", value);
2095  free(value);
2097  buf);
2098  if (in_shop) {
2099  if (QUERY_FLAG(tmp, FLAG_UNPAID)) {
2101  snprintf(buf, sizeof(buf), "%s would cost you %s.", tmp->nrof > 1 ? "They" : "It", value);
2102  free(value);
2103  } else {
2105  snprintf(buf, sizeof(buf), "You are offered %s for %s.", value, tmp->nrof > 1 ? "them" : "it");
2106  free(value);
2107  }
2109  buf);
2110  }
2111  }
2112 
2113  if (QUERY_FLAG(tmp, FLAG_MONSTER))
2114  examine_monster(op, tmp, 0);
2115 
2116  /* Is this item buildable? */
2118  int conn;
2119  bool has_link = false;
2120  if (QUERY_FLAG(tmp, FLAG_IS_LINKED) && (conn = get_button_value(tmp))) {
2121  FOR_INV_PREPARE(op, tmp_inv) {
2122  if (tmp_inv->type == FORCE && tmp_inv->slaying != NULL
2123  && strcmp(tmp_inv->slaying, op->map->path) == 0
2124  && tmp_inv->msg != NULL
2125  && tmp_inv->path_attuned == (uint32_t) conn) {
2126 
2127  has_link = true;
2130  "This is a buildable item, connected with: %s",
2131  tmp_inv->msg);
2132  break;
2133  }
2134  } FOR_INV_FINISH();
2135  }
2136  if (!has_link) {
2138  "This is a buildable item.");
2139  }
2140  }
2141 
2142  /* Does it have fluff text? */
2143  if (examine_fluff(op, tmp, false)) {
2144  op->contr->last_examined = tmp->count;
2146  "Examine again for more details.");
2147  } else {
2148  op->contr->last_examined = 0;
2149  }
2150 
2152  " "); /* Blank line */
2153 
2154  if (is_identified(tmp)) {
2156  }
2157 }
2158 
2167 void inventory(object *op, object *inv) {
2168  const char *in;
2169  int items = 0, length;
2170  char weight[MAX_BUF], name[MAX_BUF];
2171 
2172  if (inv == NULL && op == NULL) {
2174  "Inventory of what object?");
2175  return;
2176  }
2177  FOR_INV_PREPARE(inv ? inv : op, tmp)
2178  if ((!tmp->invisible && (inv == NULL || inv->type == CONTAINER || QUERY_FLAG(tmp, FLAG_APPLIED)))
2179  || !op || QUERY_FLAG(op, FLAG_WIZ))
2180  items++;
2181  FOR_INV_FINISH();
2182  if (inv == NULL) { /* player's inventory */
2183  if (items == 0) {
2185  "You carry nothing.");
2186  return;
2187  } else {
2188  length = 28;
2189  in = "";
2191  "Inventory:");
2192  }
2193  } else {
2194  if (items == 0)
2195  return;
2196  else {
2197  length = 28;
2198  in = " ";
2199  }
2200  }
2201  FOR_INV_PREPARE(inv ? inv : op, tmp) {
2202  if ((!op || !QUERY_FLAG(op, FLAG_WIZ))
2203  && (tmp->invisible || (inv && inv->type != CONTAINER && !QUERY_FLAG(tmp, FLAG_APPLIED))))
2204  continue;
2205  query_weight(tmp, weight, MAX_BUF);
2207  if (!op || QUERY_FLAG(op, FLAG_WIZ))
2209  "[fixed]%s- %-*.*s (%5d) %-8s",
2210  in, length, length, name, tmp->count, weight);
2211  else
2213  "[fixed]%s- %-*.*s %-8s",
2214  in, length+8, length+8, name, weight);
2215  } FOR_INV_FINISH();
2216  if (!inv && op) {
2217  query_weight(op, weight, MAX_BUF);
2219  "[fixed]%-*s %-8s",
2220  41, "Total weight :", weight);
2221  }
2222 }
2223 
2232 static void display_new_pickup(const object *op, int old) {
2233  int i = op->contr->mode;
2234 
2235  esrv_send_pickup(op->contr);
2236 
2237  if (!(i&PU_NEWMODE) || !(i&PU_DEBUG)) {
2238  if ((old & PU_INHIBIT) != (op->contr->mode & PU_INHIBIT)) {
2240  "Pickup is now %s.", (old & PU_INHIBIT) ? "active" : "inhibited");
2241  }
2242  return;
2243  }
2244 
2246  "%d NEWMODE",
2247  i&PU_NEWMODE ? 1 : 0);
2249  "%d DEBUG",
2250  i&PU_DEBUG ? 1 : 0);
2252  "%d INHIBIT",
2253  i&PU_INHIBIT ? 1 : 0);
2255  "%d STOP",
2256  i&PU_STOP ? 1 : 0);
2257 
2259  "%d <= x pickup weight/value RATIO (0==off)",
2260  (i&PU_RATIO)*5);
2261 
2263  "%d FOOD",
2264  i&PU_FOOD ? 1 : 0);
2266  "%d DRINK",
2267  i&PU_DRINK ? 1 : 0);
2269  "%d VALUABLES",
2270  i&PU_VALUABLES ? 1 : 0);
2271 
2273  "%d BOW",
2274  i&PU_BOW ? 1 : 0);
2276  "%d ARROW",
2277  i&PU_ARROW ? 1 : 0);
2278 
2280  "%d HELMET",
2281  i&PU_HELMET ? 1 : 0);
2283  "%d SHIELD",
2284  i&PU_SHIELD ? 1 : 0);
2286  "%d ARMOUR",
2287  i&PU_ARMOUR ? 1 : 0);
2288 
2290  "%d BOOTS",
2291  i&PU_BOOTS ? 1 : 0);
2293  "%d GLOVES",
2294  i&PU_GLOVES ? 1 : 0);
2296  "%d CLOAK",
2297  i&PU_CLOAK ? 1 : 0);
2299  "%d KEY",
2300  i&PU_KEY ? 1 : 0);
2301 
2303  "%d MISSILEWEAPON",
2304  i&PU_MISSILEWEAPON ? 1 : 0);
2306  "%d MELEEWEAPON",
2307  i&PU_MELEEWEAPON ? 1 : 0);
2309  "%d MAGICAL",
2310  i&PU_MAGICAL ? 1 : 0);
2312  "%d POTION",
2313  i&PU_POTION ? 1 : 0);
2314 
2316  "%d SPELLBOOK",
2317  i&PU_SPELLBOOK ? 1 : 0);
2319  "%d SKILLSCROLL",
2320  i&PU_SKILLSCROLL ? 1 : 0);
2322  "%d READABLES",
2323  i&PU_READABLES ? 1 : 0);
2325  "%d MAGICDEVICE",
2326  i&PU_MAGIC_DEVICE ? 1 : 0);
2327 
2329  "%d NOT CURSED",
2330  i&PU_NOT_CURSED ? 1 : 0);
2331 
2333  "%d JEWELS",
2334  i&PU_JEWELS ? 1 : 0);
2335 
2337  "%d FLESH",
2338  i&PU_FLESH ? 1 : 0);
2339 
2341  "%d CONTAINER",
2342  i&PU_CONTAINER ? 1 : 0);
2343 
2345  "%d CURSED",
2346  i&PU_CURSED ? 1 : 0);
2347 
2349  "");
2350 }
2351 
2361 void command_pickup(object *op, const char *params) {
2362  uint32_t i;
2363 
2364  if (*params == '\0') {
2365  /* if the new mode is used, just print the settings */
2366  if (op->contr->mode&PU_NEWMODE) {
2367  display_new_pickup(op, op->contr->mode);
2368  return;
2369  }
2370  if (1)
2371  LOG(llevDebug, "command_pickup: !params\n");
2372  set_pickup_mode(op, op->contr->mode > 6 ? 0 : op->contr->mode+1);
2373  return;
2374  }
2375 
2376  while (*params == ' ')
2377  params++;
2378 
2379  if (*params == '+' || *params == '-' || *params == '!') {
2380  int index = get_pickup_mode_index(params + 1);
2381 
2382  if (index != -1) {
2383  int old = op->contr->mode;
2384  i = op->contr->mode;
2385  if (!(i&PU_NEWMODE))
2386  i = PU_NEWMODE;
2387  if (*params == '+')
2388  i = i|pickup_modes[index];
2389  else if (*params == '-')
2390  i = i&~pickup_modes[index];
2391  else {
2392  if (i&pickup_modes[index])
2393  i = i&~pickup_modes[index];
2394  else
2395  i = i|pickup_modes[index];
2396  }
2397  op->contr->mode = i;
2398  display_new_pickup(op, old);
2399  return;
2400  }
2402  "Pickup: invalid item %s\n",
2403  params);
2404  return;
2405  }
2406 
2407  if (sscanf(params, "%u", &i) != 1) {
2408  if (1)
2409  LOG(llevDebug, "command_pickup: params==NULL\n");
2411  "Usage: pickup <0-7> or <value_density> .");
2412  return;
2413  }
2414  set_pickup_mode(op, i);
2415  display_new_pickup(op, op->contr->mode);
2416 }
2417 
2426 static void set_pickup_mode(const object *op, int i) {
2427  op->contr->mode = i;
2428  switch (op->contr->mode) {
2429  case 0:
2431  "Mode: Don't pick up.");
2432  break;
2433 
2434  case 1:
2436  "Mode: Pick up one item.");
2437  break;
2438 
2439  case 2:
2441  "Mode: Pick up one item and stop.");
2442  break;
2443 
2444  case 3:
2446  "Mode: Stop before picking up.");
2447  break;
2448 
2449  case 4:
2451  "Mode: Pick up all items.");
2452  break;
2453 
2454  case 5:
2456  "Mode: Pick up all items and stop.");
2457  break;
2458 
2459  case 6:
2461  "Mode: Pick up all magic items.");
2462  break;
2463 
2464  case 7:
2466  "Mode: Pick up all coins and gems");
2467  break;
2468  }
2469 }
2470 
2479 void command_search_items(object *op, const char *params) {
2480  if (settings.search_items == FALSE)
2481  return;
2482 
2483  if (!params || *params == '\0') {
2484  if (op->contr->search_str[0] == '\0') {
2486  "Example: search magic+1 "
2487  "Would automatically pick up all "
2488  "items containing the word 'magic+1'.");
2489  return;
2490  }
2491  op->contr->search_str[0] = '\0';
2493  "Search mode turned off.");
2494  fix_object(op);
2495  return;
2496  }
2497  if ((int)strlen(params) >= MAX_BUF) {
2499  "Search string too long.");
2500  return;
2501  }
2502  strcpy(op->contr->search_str, params);
2504  "Searching for '%s'.",
2505  op->contr->search_str);
2506  fix_object(op);
2507 }
2508 
2524 void command_rename_item(object *op, const char *params) {
2525  char buf[VERY_BIG_BUF], name[MAX_BUF];
2526  tag_t itemnumber;
2527  object *item = NULL;
2528  object *tmp;
2529  const char *closebrace;
2530  size_t counter;
2531 
2532  if (*params != '\0') {
2533  /* Let's skip white spaces */
2534  while (' ' == *params)
2535  params++;
2536 
2537  /* Checking the first part */
2538  itemnumber = atoi(params);
2539  if (itemnumber != 0) {
2541  if (inv->count == itemnumber && !inv->invisible) {
2542  item = inv;
2543  break;
2544  }
2545  FOR_INV_FINISH();
2546  if (!item) {
2548  "Tried to rename an invalid item.");
2549  return;
2550  }
2551  while (isdigit(*params) || ' ' == *params)
2552  params++;
2553  } else if ('<' == *params) {
2554  /* Got old name, let's get it & find appropriate matching item */
2555  closebrace = strchr(params, '>');
2556  if (!closebrace) {
2558  "Syntax error!");
2559  return;
2560  }
2561  /* Sanity check for buffer overruns */
2562  if (closebrace-params > 127) {
2564  "Old name too long (up to 127 characters allowed)!");
2565  return;
2566  }
2567  /* Copy the old name */
2568  snprintf(buf, sizeof(buf), "%.*s", (int)(closebrace-(params+1)), params+1);
2569 
2570  /* Find best matching item */
2572  if (!item) {
2574  "Could not find a matching item to rename.");
2575  return;
2576  }
2577 
2578  /* Now need to move pointer to just after > */
2579  params = closebrace+1;
2580  while (' ' == *params)
2581  params++;
2582  } else {
2583  /* Use marked item */
2585  if (!item) {
2587  "No marked item to rename.");
2588  return;
2589  }
2590  }
2591 
2592  /* Now let's find the new name */
2593  if (!strncmp(params, "to ", 3)) {
2594  params += 3;
2595  while (' ' == *params)
2596  params++;
2597  if ('<' != *params) {
2599  "Syntax error, expecting < at start of new name!");
2600  return;
2601  }
2602  closebrace = strchr(params+1, '>');
2603  if (!closebrace) {
2605  "Syntax error, expecting > at end of new name!");
2606  return;
2607  }
2608 
2609  /* Sanity check for buffer overruns */
2610  if (closebrace-params > 127) {
2612  "New name too long (up to 127 characters allowed)!");
2613  return;
2614  }
2615 
2616  /* Copy the new name */
2617  snprintf(buf, sizeof(buf), "%.*s", (int)(closebrace-(params+1)), params+1);
2618 
2619  /* Let's check it for weird characters */
2620  for (counter = 0; counter < strlen(buf); counter++) {
2621  if (isalnum(buf[counter]))
2622  continue;
2623  if (' ' == buf[counter])
2624  continue;
2625  if ('\'' == buf[counter])
2626  continue;
2627  if ('+' == buf[counter])
2628  continue;
2629  if ('_' == buf[counter])
2630  continue;
2631  if ('-' == buf[counter])
2632  continue;
2633 
2634  /* If we come here, then the name contains an invalid character...
2635  * tell the player & exit
2636  */
2638  "Invalid new name!");
2639  return;
2640  }
2641  } else {
2642  /* If param contains something, then syntax error... */
2643  if (strlen(params)) {
2645  "Syntax error, expected 'to <' after old name!");
2646  return;
2647  }
2648  /* New name is empty */
2649  buf[0] = '\0';
2650  }
2651  } else {
2652  /* Last case: *params=='\0' */
2654  if (!item) {
2656  "No marked item to rename.");
2657  return;
2658  }
2659  buf[0] = '\0';
2660  }
2661 
2662  /* Coming here, everything is fine... */
2663  if (!strlen(buf)) {
2664  /* Clear custom name */
2665  if (object_get_value(item, CUSTOM_NAME_FIELD) == NULL) {
2667  "This item has no custom name.");
2668  return;
2669  }
2670 
2672  query_base_name(item, item->nrof > 1 ? 1 : 0, name, MAX_BUF);
2674  "You stop calling your %s with weird names.",
2675  name);
2676  } else {
2678  if (custom_name != NULL && strcmp(custom_name, buf) == 0) {
2679  query_base_name(item, item->nrof > 1 ? 1 : 0, name, MAX_BUF);
2681  "You keep calling your %s %s.",
2682  name, buf);
2683  return;
2684  }
2685 
2686  /* Set custom name */
2688 
2689  query_base_name(item, item->nrof > 1 ? 1 : 0, name, MAX_BUF);
2691  "Your %s will now be called %s.",
2692  name, buf);
2693  }
2694 
2695  tmp = object_merge(item, NULL);
2696  if (tmp == NULL) {
2697  /* object was not merged - if it was, object_merge() handles updating for us. */
2699  }
2700 }
2701 
2710 void command_lock_item(object *op, const char *params) {
2711  object *item;
2712  object *tmp;
2713  char name[HUGE_BUF];
2714 
2715  if (*params == '\0' || strlen(params) == 0) {
2717  "Lock what item?");
2718  return;
2719  }
2720 
2722  if (!item) {
2724  "Can't find any matching item.");
2725  return;
2726  }
2727 
2731  "Unlocked %s.", name);
2733  } else {
2735  "Locked %s.", name);
2737  }
2738 
2739  tmp = object_merge(item, NULL);
2740  if (tmp == NULL) {
2741  /* object was not merged, if it was object_merge() handles updates for us */
2743  }
2744 }
2745 
2753 void command_use(object *op, const char *params) {
2754  char *with, copy[MAX_BUF];
2755  object *first, *second/*, *add*/;
2756  /*archetype *arch;*/
2757  /*int count;*/
2758  /*sstring data;*/
2759  recipe *transformation;
2760 
2761  if (!IS_PLAYER(op))
2762  return;
2763 
2764  strlcpy(copy, params, sizeof(copy));
2765  with = strstr(copy, " with ");
2766  if (!with) {
2767  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "Syntax is use <item> with <item>.");
2768  return;
2769  }
2770 
2771  with[0] = '\0';
2772  with = with+strlen(" with ");
2773 
2774  first = find_best_object_match(op, copy);
2775  if (!first) {
2777  return;
2778  }
2779  second = find_best_object_match(op, with);
2780  if (!second) {
2782  return;
2783  }
2784 
2785  transformation = NULL;
2786  while ((transformation = find_recipe_for_tool(first->arch->name, transformation))) {
2788  if (transformation->ingred_count != 1)
2789  continue;
2790 
2791 /* LOG(llevDebug, "use: check %s\n", transformation->title);*/
2792  if (strcmp(second->name, transformation->ingred->name) == 0) {
2794  object *generated = create_archetype(transformation->arch_name[0]);
2795  if (transformation->yield)
2796  generated->nrof = transformation->yield;
2797  object_insert_in_ob(generated, op);
2798  /*draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "Found recipe %s", transformation->title);*/
2800  return;
2801  }
2802  }
2804  return;
2805 
2806  /*
2807  snprintf(copy, sizeof(copy), "on_use_with_%s", first->arch->name);
2808  data = object_get_value(second, copy);
2809  if (!data) {
2810  snprintf(copy, sizeof(copy), "on_use_with_%d_%d", first->type, first->subtype);
2811  data = object_get_value(second, copy);
2812  if (!data) {
2813  snprintf(copy, sizeof(copy), "on_use_with_%d", first->type);
2814  data = object_get_value(second, copy);
2815  if (!data) {
2816  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "Nothing happens.");
2817  return 1;
2818  }
2819  }
2820  }
2821 
2822  while (data != NULL) {
2823  if (strncmp(data, "add ", 4) == 0) {
2824  data += 4;
2825  if (isdigit(*data)) {
2826  count = atol(data);
2827  data = strchr(data, ' ')+1;
2828  } else
2829  count = 1;
2830  with = strchr(data, ' ');
2831  if (!with) {
2832  strncpy(copy, data, sizeof(copy));
2833  data = NULL;
2834  } else {
2835  *with = '\0';
2836  strncpy(copy, data, sizeof(copy));
2837  data += strlen(copy)+1;
2838  }
2839  arch = find_archetype(copy);
2840  if (!arch) {
2841  LOG(llevError, "Use: invalid archetype %s in %s.\n", copy, second->name);
2842  return 1;
2843  }
2844  add = object_create_arch(arch);
2845  add->nrof = count;
2846  object_insert_in_ob(add, op);
2847  } else if (strncmp(data, "remove $", 8) == 0) {
2848  data += 8;
2849  if (*data == '1') {
2850  if (first)
2851  first = object_decrease_nrof_by_one(first);
2852  data += 2;
2853  } else if (*data == '2') {
2854  if (second)
2855  second = object_decrease_nrof_by_one(second);
2856  data += 2;
2857  } else {
2858  LOG(llevError, "Use: invalid use string %s in %s\n", data, second->name);
2859  return 1;
2860  }
2861  } else {
2862  LOG(llevError, "Use: invalid use string %s in %s\n", data, second->name);
2863  return 1;
2864  }
2865  }
2866 
2867  return 1;
2868  */
2869 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:70
drop
void drop(object *op, object *tmp)
Definition: c_object.cpp:1168
find_recipe_for_tool
recipe * find_recipe_for_tool(const char *tool, recipe *from)
Definition: recipe.cpp:894
give.next
def next
Definition: give.py:44
do_skill
int do_skill(object *op, object *part, object *skill, int dir, const char *string)
Definition: skill_util.cpp:431
MIMIC
@ MIMIC
Definition: object.h:254
PLAYER
@ PLAYER
Definition: object.h:112
PU_BOOTS
#define PU_BOOTS
Definition: define.h:125
global.h
castle_read.prefix
string prefix
Definition: castle_read.py:31
settings
struct Settings settings
Definition: init.cpp:139
living::maxhp
int16_t maxhp
Definition: living.h:41
matcher_pickup_type
static int matcher_pickup_type(object *who, matcher_params *params, object *item)
Definition: c_object.cpp:794
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:15
MSG_TYPE_COMMAND_SUCCESS
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:533
AP_APPLY
#define AP_APPLY
Definition: define.h:574
BOW
@ BOW
Definition: object.h:123
BRACERS
@ BRACERS
Definition: object.h:222
CLOSE_CON
@ CLOSE_CON
Definition: object.h:234
llevError
@ llevError
Definition: logger.h:11
ARMOUR_IMPROVER
@ ARMOUR_IMPROVER
Definition: object.h:237
command_search
void command_search(object *op, const char *params)
Definition: c_object.cpp:212
find_skill_by_number
object * find_skill_by_number(object *who, int skillno)
Definition: main.cpp:375
AP_NO_MERGE
#define AP_NO_MERGE
Definition: define.h:581
WAND
@ WAND
Definition: object.h:225
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
FLAG_UNDEAD
#define FLAG_UNDEAD
Definition: define.h:270
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
FLESH
@ FLESH
Definition: object.h:192
PU_NOT_CURSED
#define PU_NOT_CURSED
Definition: define.h:140
PU_ARROW
#define PU_ARROW
Definition: define.h:120
GLOVES
@ GLOVES
Definition: object.h:218
object::inv
object * inv
Definition: object.h:298
GIRDLE
@ GIRDLE
Definition: object.h:228
diamondslots.x
x
Definition: diamondslots.py:15
FLAG_STARTEQUIP
#define FLAG_STARTEQUIP
Definition: define.h:268
MSG_TYPE_SKILL
#define MSG_TYPE_SKILL
Definition: newclient.h:410
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
PU_INHIBIT
#define PU_INHIBIT
Definition: define.h:109
command_rename_item
void command_rename_item(object *op, const char *params)
Definition: c_object.cpp:2524
recipe::yield
int yield
Definition: recipe.h:21
object_merge
object * object_merge(object *op, object *top)
Definition: object.cpp:2051
examine_monster
void examine_monster(object *op, object *tmp, int level)
Definition: c_object.cpp:1614
FALSE
#define FALSE
Definition: compat.h:14
object::arch
struct archetype * arch
Definition: object.h:424
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
examine
void examine(object *op, object *tmp)
Definition: c_object.cpp:1985
SK_DET_MAGIC
@ SK_DET_MAGIC
Definition: skills.h:30
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:319
FOR_BELOW_PREPARE
#define FOR_BELOW_PREPARE(op_, it_)
Definition: define.h:704
GEM
@ GEM
Definition: object.h:172
detect_curse_on_item
int detect_curse_on_item(object *pl, object *tmp, object *skill)
Definition: skills.cpp:703
object::x
int16_t x
Definition: object.h:335
command_rskill
void command_rskill(object *pl, const char *params)
Definition: c_object.cpp:161
shop_price_buy
uint64_t shop_price_buy(const object *obj, object *who)
Definition: shop.cpp:190
ARMOUR
@ ARMOUR
Definition: object.h:125
SK_DISARM_TRAPS
@ SK_DISARM_TRAPS
Definition: skills.h:46
command_use
void command_use(object *op, const char *params)
Definition: c_object.cpp:2753
PU_FOOD
#define PU_FOOD
Definition: define.h:115
object::map
struct mapstruct * map
Definition: object.h:305
WEAPON
@ WEAPON
Definition: object.h:124
typedata::identifyskill
int identifyskill
Definition: define.h:93
esrv_send_pickup
void esrv_send_pickup(player *pl)
Definition: request.cpp:1836
PU_BOW
#define PU_BOW
Definition: define.h:118
command_uskill
void command_uskill(object *pl, const char *params)
Definition: c_object.cpp:144
PU_MAGIC_DEVICE
#define PU_MAGIC_DEVICE
Definition: define.h:138
commongive.inv
inv
Definition: commongive.py:29
AMULET
@ AMULET
Definition: object.h:144
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
matcher_name
static int matcher_name(object *who, matcher_params *params, object *item)
Definition: c_object.cpp:774
mon
object * mon
Definition: comet_perf.cpp:75
MIN
#define MIN(x, y)
Definition: compat.h:21
SKILL
@ SKILL
Definition: object.h:148
examine_wand_charge_level
void examine_wand_charge_level(object *op, object *tmp)
Definition: c_object.cpp:1812
object::count
tag_t count
Definition: object.h:307
change_skill
int change_skill(object *who, object *new_skill, int flag)
Definition: skill_util.cpp:359
MSG_TYPE_COMMAND_EXAMINE
#define MSG_TYPE_COMMAND_EXAMINE
Definition: newclient.h:535
fix_object
void fix_object(object *op)
Definition: living.cpp:1132
command_mark
void command_mark(object *op, const char *params)
Definition: c_object.cpp:1567
Ice.tmp
int tmp
Definition: Ice.py:207
command_pickup
void command_pickup(object *op, const char *params)
Definition: c_object.cpp:2361
PU_MISSILEWEAPON
#define PU_MISSILEWEAPON
Definition: define.h:130
recipe::arch_name
char ** arch_name
Definition: recipe.h:13
TRANSPORT
@ TRANSPORT
Definition: object.h:113
PU_FLESH
#define PU_FLESH
Definition: define.h:142
PU_READABLES
#define PU_READABLES
Definition: define.h:137
skills.h
PU_POTION
#define PU_POTION
Definition: define.h:133
MSG_TYPE_COMMAND_ERROR
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:532
matcher_params::item_to_pick
int item_to_pick
Definition: c_object.cpp:714
FLAG_PROBE
#define FLAG_PROBE
Definition: define.h:257
FLAG_INV_LOCKED
#define FLAG_INV_LOCKED
Definition: define.h:329
MSG_TYPE_SPELL_INFO
#define MSG_TYPE_SPELL_INFO
Definition: newclient.h:642
object_get_value
const char * object_get_value(const object *op, const char *const key)
Definition: object.cpp:4346
apply_by_living_below
void apply_by_living_below(object *pl)
Definition: apply.cpp:695
ex_autoid_result
ex_autoid_result
Definition: c_object.cpp:1693
FLAG_APPLIED
#define FLAG_APPLIED
Definition: define.h:235
NDI_BLUE
#define NDI_BLUE
Definition: newclient.h:250
object::level
int16_t level
Definition: object.h:361
events_execute_object_event
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:299
buf
StringBuffer * buf
Definition: readable.cpp:1565
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2857
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
set_pickup_mode
static void set_pickup_mode(const object *op, int i)
Definition: c_object.cpp:2426
POISONING
@ POISONING
Definition: object.h:223
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:407
command_drop
void command_drop(object *op, const char *params)
Definition: c_object.cpp:1354
body_locations_struct::nonuse_name
const char * nonuse_name
Definition: object.h:25
FLAG_NO_PICK
#define FLAG_NO_PICK
Definition: define.h:239
FOR_BELOW_FINISH
#define FOR_BELOW_FINISH()
Definition: define.h:711
command_empty
void command_empty(object *op, const char *params)
Definition: c_object.cpp:1450
object_matches_pickup_mode
int object_matches_pickup_mode(const object *item, int mode)
Definition: c_object.cpp:656
object::carrying
int32_t carrying
Definition: object.h:377
LOOK_OBJ
#define LOOK_OBJ(ob)
Definition: object.h:521
AP_NULL
#define AP_NULL
Definition: define.h:573
PU_GLOVES
#define PU_GLOVES
Definition: define.h:126
typedata
Definition: define.h:89
object::y
int16_t y
Definition: object.h:335
PU_CONTAINER
#define PU_CONTAINER
Definition: define.h:143
autojail.who
who
Definition: autojail.py:3
CLOAK
@ CLOAK
Definition: object.h:209
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
get_button_value
int get_button_value(const object *button)
Definition: button.cpp:749
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1560
put_object_in_sack
void put_object_in_sack(object *op, object *sack, object *tmp, uint32_t nrof)
Definition: c_object.cpp:937
NROF
static uint32_t NROF(const object *const ob)
Definition: object.h:625
HELMET
@ HELMET
Definition: object.h:141
use_skill
int use_skill(object *op, const char *string)
Definition: skill_util.cpp:964
matcher_all
static int matcher_all(object *who, matcher_params *params, object *item)
Definition: c_object.cpp:740
disinfect.map
map
Definition: disinfect.py:4
object_decrease_nrof_by_one
#define object_decrease_nrof_by_one(xyz)
Definition: compat.h:32
POISON
@ POISON
Definition: object.h:118
PU_RATIO
#define PU_RATIO
Definition: define.h:113
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
linked_char::name
const char * name
Definition: global.h:97
PU_KEY
#define PU_KEY
Definition: define.h:128
command_throw
void command_throw(object *op, const char *params)
Definition: c_object.cpp:239
get_typedata
const typedata * get_typedata(int itemtype)
Definition: item.cpp:323
EVENT_PICKUP
#define EVENT_PICKUP
Definition: events.h:28
matcher_params::pickup_type
int pickup_type
Definition: c_object.cpp:719
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:588
matcher_params::name
char name[MAX_BUF]
Definition: c_object.cpp:718
POTION
@ POTION
Definition: object.h:116
body_locations_struct::use_name
const char * use_name
Definition: object.h:24
FLAG_KNOWN_CURSED
#define FLAG_KNOWN_CURSED
Definition: define.h:320
examine_weight_and_material
void examine_weight_and_material(object *op, object *tmp)
Definition: c_object.cpp:1786
EVENT_DROP
#define EVENT_DROP
Definition: events.h:27
matcher_number
static int matcher_number(object *who, matcher_params *params, object *item)
Definition: c_object.cpp:754
archetype::clone
object clone
Definition: object.h:487
SK_DET_CURSE
@ SK_DET_CURSE
Definition: skills.h:33
set_object_face_main
int set_object_face_main(object *op)
Definition: apply.cpp:146
MSG_TYPE_COMMAND_INFO
#define MSG_TYPE_COMMAND_INFO
Definition: newclient.h:529
object::weight_limit
int32_t weight_limit
Definition: object.h:376
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
knowledge_add_probe_monster
void knowledge_add_probe_monster(object *op, object *mon)
Definition: knowledge.cpp:1528
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Definition: define.h:754
HEAD
#define HEAD(op)
Definition: object.h:607
player_can_find
bool player_can_find(object *op, object *ob)
Definition: item.cpp:590
pick_up_object
static void pick_up_object(object *pl, object *op, object *tmp, int nrof)
Definition: c_object.cpp:379
transport_can_hold
int transport_can_hold(const object *transport, const object *op, int nrof)
Definition: apply.cpp:54
ROD
@ ROD
Definition: object.h:114
CONTAINER
@ CONTAINER
Definition: object.h:236
object_find_by_type_and_name
object * object_find_by_type_and_name(const object *who, int type, const char *name)
Definition: object.cpp:4108
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.cpp:513
PU_STOP
#define PU_STOP
Definition: define.h:110
PU_VALUABLES
#define PU_VALUABLES
Definition: define.h:117
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
SCRIPT_FIX_ALL
#define SCRIPT_FIX_ALL
Definition: global.h:389
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
is_identified
int is_identified(const object *op)
Definition: item.cpp:1348
ob_describe
char * ob_describe(const object *op, const object *observer, int use_media_tags, char *buf, size_t size)
Definition: ob_methods.cpp:91
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:129
empty_container
static void empty_container(object *container, object *pl)
Definition: c_object.cpp:1412
MOVE_FLYING
#define MOVE_FLYING
Definition: define.h:395
SPELL_HIGHEST
#define SPELL_HIGHEST
Definition: spells.h:60
object::type
uint8_t type
Definition: object.h:348
INS_NO_MERGE
#define INS_NO_MERGE
Definition: object.h:580
SKILLSCROLL
@ SKILLSCROLL
Definition: object.h:239
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:318
CFweardisguise.tag
tag
Definition: CFweardisguise.py:25
NDI_GOLD
#define NDI_GOLD
Definition: newclient.h:257
command_dropall
void command_dropall(object *op, const char *params)
Definition: c_object.cpp:1230
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
identify_object_with_skill
int identify_object_with_skill(object *tmp, object *pl, object *skill, int print_on_success)
Definition: skills.cpp:810
INS_BELOW_ORIGINATOR
#define INS_BELOW_ORIGINATOR
Definition: object.h:584
living::food
int32_t food
Definition: living.h:48
MSG_TYPE_SKILL_MISSING
#define MSG_TYPE_SKILL_MISSING
Definition: newclient.h:590
PU_SPELLBOOK
#define PU_SPELLBOOK
Definition: define.h:135
change_exp
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Definition: living.cpp:2175
disinfect.count
int count
Definition: disinfect.py:7
matcher_params
Definition: c_object.cpp:711
knowledge_item_can_be_used_alchemy
void knowledge_item_can_be_used_alchemy(object *op, const object *item)
Definition: knowledge.cpp:1334
tag_t
uint32_t tag_t
Definition: object.h:14
body_locations
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.cpp:55
archetype
Definition: object.h:483
object_matches_string
int object_matches_string(object *pl, object *op, const char *name)
Definition: object.cpp:4574
PU_MELEEWEAPON
#define PU_MELEEWEAPON
Definition: define.h:131
sproto.h
ARROW
@ ARROW
Definition: object.h:122
make_matcher
static item_matcher make_matcher(object *who, const char *params, matcher_params *mp)
Definition: c_object.cpp:806
FLAG_NO_DROP
#define FLAG_NO_DROP
Definition: define.h:288
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.cpp:95
PU_MAGICAL
#define PU_MAGICAL
Definition: define.h:132
FOR_OB_AND_BELOW_PREPARE
#define FOR_OB_AND_BELOW_PREPARE(op_)
Definition: define.h:750
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Definition: newclient.h:414
BOOK
@ BOOK
Definition: object.h:119
SP_level_spellpoint_cost
int16_t SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Definition: spell_util.cpp:236
object::race
sstring race
Definition: object.h:326
find_best_apply_object_match
static object * find_best_apply_object_match(object *start, object *pl, const char *params, int aflag)
Definition: c_object.cpp:101
RING
@ RING
Definition: object.h:190
detect_magic_on_item
int detect_magic_on_item(object *pl, object *tmp, object *skill)
Definition: skills.cpp:752
PU_HELMET
#define PU_HELMET
Definition: define.h:121
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.cpp:2100
command_search_items
void command_search_items(object *op, const char *params)
Definition: c_object.cpp:2479
inventory
void inventory(object *op, object *inv)
Definition: c_object.cpp:2167
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
find_skill_by_name
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.cpp:211
recipe::ingred_count
int ingred_count
Definition: recipe.h:23
env
static std::shared_ptr< inja::Environment > env
Definition: mapper.cpp:2168
pick_up
void pick_up(object *op, object *alt)
Definition: c_object.cpp:519
MAX_BUF
#define MAX_BUF
Definition: define.h:35
do_skill_by_number
static void do_skill_by_number(object *op, int skill_subtype, const char *params, const char *missing_message)
Definition: c_object.cpp:188
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.cpp:222
object_insert_in_map
object * object_insert_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.cpp:2361
sack_can_hold
int sack_can_hold(const object *pl, const object *sack, const object *op, uint32_t nrof)
Definition: c_object.cpp:317
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
object_present_in_ob
object * object_present_in_ob(uint8_t type, const object *op)
Definition: object.cpp:3168
get_weight_limit
uint32_t get_weight_limit(int stat)
Definition: living.cpp:2369
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
command_disarm
void command_disarm(object *op, const char *params)
Definition: c_object.cpp:224
IS_PLAYER
static bool IS_PLAYER(object *op)
Definition: object.h:609
StringBuffer
Definition: stringbuffer.cpp:25
matcher_params::item_must_be_pickable
int item_must_be_pickable
Definition: c_object.cpp:716
probe
int probe(object *op, object *caster, object *spell_ob, int dir, int level)
Definition: spell_effect.cpp:699
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
recipe
Definition: recipe.h:10
MSG_TYPE_COMMAND_FAILURE
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:534
FLAG_KNOWN_MAGICAL
#define FLAG_KNOWN_MAGICAL
Definition: define.h:319
pickup_modes
static const uint32_t pickup_modes[]
Definition: c_object.cpp:43
find_best_object_match
static object * find_best_object_match(object *pl, const char *params)
Definition: c_object.cpp:132
get_pickup_mode_index
static int get_pickup_mode_index(const char *name)
Definition: c_object.cpp:58
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
MSG_TYPE_COMMAND_INVENTORY
#define MSG_TYPE_COMMAND_INVENTORY
Definition: newclient.h:536
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:265
object::slaying
sstring slaying
Definition: object.h:327
item_matcher
int(* item_matcher)(object *who, matcher_params *params, object *item)
Definition: c_object.cpp:731
query_weight
void query_weight(const object *op, char *buf, size_t size)
Definition: item.cpp:415
object::name
sstring name
Definition: object.h:319
PU_CLOAK
#define PU_CLOAK
Definition: define.h:127
AP_OPEN
#define AP_OPEN
Definition: define.h:576
cost_approx_str
char * cost_approx_str(const object *obj, object *who)
Definition: shop.cpp:369
object_can_pick
int object_can_pick(const object *who, const object *item)
Definition: object.cpp:3867
stringbuffer_trim_whitespace
void stringbuffer_trim_whitespace(StringBuffer *sb)
Definition: stringbuffer.cpp:222
KEY
@ KEY
Definition: object.h:132
PU_JEWELS
#define PU_JEWELS
Definition: define.h:141
item
Definition: item.py:1
cost_str
char * cost_str(uint64_t cost)
Definition: shop.cpp:365
FLAG_IS_BUILDABLE
#define FLAG_IS_BUILDABLE
Definition: define.h:367
is_identifiable_type
int is_identifiable_type(const object *op)
Definition: item.cpp:1324
mapstruct
Definition: map.h:313
object::env
object * env
Definition: object.h:301
sstring
const typedef char * sstring
Definition: sstring.h:2
command_apply
void command_apply(object *op, const char *params)
Definition: c_object.cpp:251
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
object::skill
sstring skill
Definition: object.h:329
shop.h
object_split
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
Definition: object.cpp:2637
command_examine
void command_examine(object *op, const char *params)
Definition: c_object.cpp:1489
PU_ARMOUR
#define PU_ARMOUR
Definition: define.h:123
examine_fluff
bool examine_fluff(object *op, object *tmp, bool output)
Definition: c_object.cpp:1873
apply_by_living
int apply_by_living(object *pl, object *op, int aflag, int quiet)
Definition: apply.cpp:637
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.cpp:359
Settings::max_stat
uint8_t max_stat
Definition: global.h:324
object::msg
sstring msg
Definition: object.h:330
PU_NEWMODE
#define PU_NEWMODE
Definition: define.h:111
SKILL_TOOL
@ SKILL_TOOL
Definition: object.h:194
FLAG_NO_FIX_PLAYER
#define FLAG_NO_FIX_PLAYER
Definition: define.h:277
roll-o-matic.params
params
Definition: roll-o-matic.py:193
diamondslots.y
y
Definition: diamondslots.py:16
find_marked_object
object * find_marked_object(object *op)
Definition: c_object.cpp:1520
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
npc_dialog.index
int index
Definition: npc_dialog.py:102
SK_SUBTRACT_SKILL_EXP
#define SK_SUBTRACT_SKILL_EXP
Definition: skills.h:81
apply_special
int apply_special(object *who, object *op, int aflags)
Definition: apply.cpp:1156
display_new_pickup
static void display_new_pickup(const object *op, int old)
Definition: c_object.cpp:2232
level
int level
Definition: readable.cpp:1563
typedata::identifyskill2
int identifyskill2
Definition: define.h:94
make_face_from_files.int
int
Definition: make_face_from_files.py:32
UPD_NAME
#define UPD_NAME
Definition: newclient.h:321
AT_ACID
#define AT_ACID
Definition: attack.h:82
loader.h
save_player
int save_player(object *op, int flag)
Definition: login.cpp:230
Settings::real_wiz
uint8_t real_wiz
Definition: global.h:271
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.cpp:308
stop_item
object * stop_item(object *op)
Definition: time.cpp:455
FOOD
@ FOOD
Definition: object.h:117
object_remove
void object_remove(object *op)
Definition: object.cpp:1833
recipe::ingred
linked_char * ingred
Definition: recipe.h:22
drop_object
object * drop_object(object *op, object *tmp, uint32_t nrof)
Definition: c_object.cpp:1073
EX_ID_FAILED
@ EX_ID_FAILED
Definition: c_object.cpp:1696
object::move_off
MoveType move_off
Definition: object.h:440
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
examine_rod_charge_level
void examine_rod_charge_level(object *op, object *tmp)
Definition: c_object.cpp:1841
DRINK
@ DRINK
Definition: object.h:162
sell_item
void sell_item(object *op, object *pl)
Definition: shop.cpp:966
VERY_BIG_BUF
#define VERY_BIG_BUF
Definition: define.h:36
PU_CURSED
#define PU_CURSED
Definition: define.h:144
command_lock_item
void command_lock_item(object *op, const char *params)
Definition: c_object.cpp:2710
WEAPON_IMPROVER
@ WEAPON_IMPROVER
Definition: object.h:238
archetype::name
sstring name
Definition: object.h:484
SCROLL
@ SCROLL
Definition: object.h:226
FLAG_IS_LINKED
#define FLAG_IS_LINKED
Definition: define.h:315
object::nrof
uint32_t nrof
Definition: object.h:342
say.item
dictionary item
Definition: say.py:149
matcher_params::missed
int missed
Definition: c_object.cpp:721
query_base_name
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.cpp:689
Settings::search_items
uint8_t search_items
Definition: global.h:267
object::stats
living stats
Definition: object.h:378
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.cpp:4499
AP_UNAPPLY
#define AP_UNAPPLY
Definition: define.h:575
SK_FIND_TRAPS
@ SK_FIND_TRAPS
Definition: skills.h:34
PU_DRINK
#define PU_DRINK
Definition: define.h:116
command_take
void command_take(object *op, const char *params)
Definition: c_object.cpp:845
BOOTS
@ BOOTS
Definition: object.h:217
shop_contains
bool shop_contains(object *ob)
Definition: shop.cpp:1296
pickup_names
static const char * pickup_names[]
Definition: c_object.cpp:33
FLAG_IS_CAULDRON
#define FLAG_IS_CAULDRON
Definition: define.h:338
matcher_params::item_number
int item_number
Definition: c_object.cpp:715
PU_SHIELD
#define PU_SHIELD
Definition: define.h:122
EX_ID_NO_SKILL
@ EX_ID_NO_SKILL
Definition: c_object.cpp:1695
SHIELD
@ SHIELD
Definition: object.h:140
object::attacktype
uint32_t attacktype
Definition: object.h:352
FLAG_NO_SKILL_IDENT
#define FLAG_NO_SKILL_IDENT
Definition: define.h:335
object_get_player_container
object * object_get_player_container(object *op)
Definition: object.cpp:607
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
living.h
FLAG_IS_THROWN
#define FLAG_IS_THROWN
Definition: define.h:249
SK_THROWING
@ SK_THROWING
Definition: skills.h:44
EX_ID_ABORT
@ EX_ID_ABORT
Definition: c_object.cpp:1694
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
CUSTOM_NAME_FIELD
#define CUSTOM_NAME_FIELD
Definition: object.h:98
shop_price_sell
uint64_t shop_price_sell(const object *obj, object *who)
Definition: shop.cpp:211
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
living::hp
int16_t hp
Definition: living.h:40
FORCE
@ FORCE
Definition: object.h:229
llevDebug
@ llevDebug
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:142
FLAG_IS_FLOOR
#define FLAG_IS_FLOOR
Definition: define.h:302
examine_autoidentify
ex_autoid_result examine_autoidentify(object *op, object *tmp)
Definition: c_object.cpp:1710
FORCE_NAME
#define FORCE_NAME
Definition: spells.h:169
give.name
name
Definition: give.py:27
living::Str
int8_t Str
Definition: living.h:36
PU_DEBUG
#define PU_DEBUG
Definition: define.h:108
get_archetype_by_skill_name
archetype * get_archetype_by_skill_name(const char *skill, int type)
Definition: arch.cpp:80
PU_SKILLSCROLL
#define PU_SKILLSCROLL
Definition: define.h:136
level
Definition: level.py:1