Crossfire Server, Trunk  R21670
item.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
22 #include "global.h"
23 
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "living.h"
30 #include "spells.h"
31 
55  { "body_range", "in your range slot", "in a human's range slot" },
56  { "body_arm", "on your arm", "on a human's arm" },
57  { "body_torso", "on your body", "on a human's torso" },
58  { "body_head", "on your head", "on a human's head" },
59  { "body_neck", "around your neck", "around a humans neck" },
60  { "body_skill", "in your skill slot", "in a human's skill slot" },
61  { "body_finger", "on your finger", "on a human's finger" },
62  { "body_shoulder", "around your shoulders", "around a human's shoulders" },
63  { "body_foot", "on your feet", "on a human's feet" },
64  { "body_hand", "on your hands", "on a human's hands" },
65  { "body_wrist", "around your wrists", "around a human's wrist" },
66  { "body_waist", "around your waist", "around a human's waist" },
67  { "body_leg", "around your legs", "around a human's legs" },
68  /*{"body_dragon_torso", "your body", "a dragon's body"} */
69 };
70 
78 static const typedata item_types[] = {
79  { 0, "none", "none", 0, 0 },
80  { PLAYER, "player", "players", 0, 0 },
81  { ROD, "rod", "rods", SK_THAUMATURGY, 0 },
82  { TREASURE, "treasure", "treasure", 0, 0 },
83  { POTION, "potion", "potions", SK_ALCHEMY, 0 },
84  { FOOD, "food", "food", SK_WOODSMAN, 0 },
85  { POISON, "poison", "poisons", SK_ALCHEMY, 0 },
86  { BOOK, "book", "books", SK_LITERACY, 0 },
87  { CLOCK, "clock", "clocks", 0, 0 },
88  { ARROW, "arrow", "arrows", SK_BOWYER, 0 },
89  { BOW, "bow", "bows", SK_BOWYER, 0 },
90  { WEAPON, "weapon", "weapons", SK_SMITHERY, 0 },
91  { ARMOUR, "armour", "armour", SK_SMITHERY, 0 },
92  { PEDESTAL, "pedestal", "pedestals", 0, 0 },
93  { ALTAR, "altar", "altars", 0, 0 },
94  { LOCKED_DOOR, "locked door", "locked doors", 0, 0 },
95  { SPECIAL_KEY, "special key", "special keys", 0, 0 },
96  { MAP, "map", "maps", 0, 0 },
97  { DOOR, "door", "doors", 0, 0 },
98  { KEY, "key", "keys", 0, 0 },
99  { TIMED_GATE, "timed_gate", "timed_gates", 0, 0 },
100  { TRIGGER, "trigger", "triggers", 0, 0 },
101  { GRIMREAPER, "grimreaper", "grimreapers", 0, 0 },
102  { MAGIC_EAR, "magic ear", "magic ears", 0, 0 },
103  { TRIGGER_BUTTON, "trigger button", "trigger buttons", 0, 0 },
104  { TRIGGER_ALTAR, "trigger altar", "trigger altars", 0, 0 },
105  { TRIGGER_PEDESTAL, "trigger pedestal", "trigger pedestals", 0, 0 },
106  { SHIELD, "shield", "shields", SK_SMITHERY, 0 },
107  { HELMET, "helmet", "helmets", SK_SMITHERY, 0 },
108  { MONEY, "money", "money", 0, 0 },
109  { CLASS, "class", "classes", 0, 0 },
110  { AMULET, "amulet", "amulets", SK_JEWELER, 0 },
111  { PLAYERMOVER, "player mover", "player movers", 0, 0 },
112  { TELEPORTER, "teleporter", "teleporters", 0, 0 },
113  { CREATOR, "creator", "creators", 0, 0 },
114  { SKILL, "skill", "skills", 0, 0 },
115  { EARTHWALL, "earthwall", "earthwalls", 0, 0 },
116  { GOLEM, "golem", "golems", 0, 0 },
117  { THROWN_OBJ, "projectile", "projectiles", 0, 0 },
118  { BLINDNESS, "blindness", "blindness", 0, 0 },
119  { GOD, "god", "gods", 0, 0 },
120  { DETECTOR, "detector", "detectors", 0, 0 },
121  { TRIGGER_MARKER, "trigger marker", "trigger markers", 0, 0 },
122  { DEAD_OBJECT, "dead object", "dead objects", 0, 0 },
123  { DRINK, "drink", "drinks", SK_WOODSMAN, SK_ALCHEMY },
124  { MARKER, "marker", "markers", 0, 0 },
125  { HOLY_ALTAR, "holy altar", "holy altars", 0, 0 },
126  { PLAYER_CHANGER, "player changer", "player changers", 0, 0 },
127  { BATTLEGROUND, "battleground", "battlegrounds", 0, 0 },
128  { PEACEMAKER, "peacemaker", "peacemakers", 0, 0 },
129  { GEM, "gem", "gems", SK_JEWELER, 0 },
130  { FIREWALL, "firewall", "firewalls", 0, 0 },
131  { CHECK_INV, "inventory checker", "inventory checkers", 0, 0 },
132  { MOOD_FLOOR, "mood floor", "mood floors", 0, 0 },
133  { EXIT, "exit", "exits", 0, 0 },
134  { ENCOUNTER, "encounter", "encounters", 0, 0 },
135  { SHOP_FLOOR, "shop floor", "shop floors", 0, 0 },
136  { SHOP_MAT, "shop mat", "shop mats", 0, 0 },
137  { RING, "ring", "rings", SK_JEWELER, 0 },
138  { FLOOR, "floor", "floors", 0, 0 },
139  { FLESH, "flesh", "flesh", SK_WOODSMAN, 0 },
140  { INORGANIC, "inorganic", "inorganics", SK_ALCHEMY, 0 },
141  { SKILL_TOOL, "skill tool", "skill tools", 0, 0 },
142  { LIGHTER, "lighter", "lighters", 0, 0 },
143  { WALL, "wall", "walls", 0, 0 },
144  { MISC_OBJECT, "bric-a-brac", "bric-a-brac", 0, 0 },
145  { MONSTER, "monster", "monsters", 0, 0 },
146  { LAMP, "lamp", "lamps", 0, 0 },
147  { DUPLICATOR, "duplicator", "duplicators", 0, 0 },
148  { SPELLBOOK, "spellbook", "spellbooks", SK_LITERACY, 0 },
149  { CLOAK, "cloak", "cloaks", SK_SMITHERY, 0 },
150  { SPINNER, "spinner", "spinners", 0, 0 },
151  { GATE, "gate", "gates", 0, 0 },
152  { BUTTON, "button", "buttons", 0, 0 },
153  { CF_HANDLE, "cf handle", "cf handles", 0, 0 },
154  { HOLE, "hole", "holes", 0, 0 },
155  { TRAPDOOR, "trapdoor", "trapdoors", 0, 0 },
156  { SIGN, "sign", "signs", 0, 0 },
157  { BOOTS, "boots", "boots", SK_SMITHERY, 0 },
158  { GLOVES, "gloves", "gloves", SK_SMITHERY, 0 },
159  { SPELL, "spell", "spells", 0, 0 },
160  { SPELL_EFFECT, "spell effect", "spell effects", 0, 0 },
161  { CONVERTER, "converter", "converters", 0, 0 },
162  { BRACERS, "bracers", "bracers", SK_SMITHERY, 0 },
163  { POISONING, "poisoning", "poisonings", 0, 0 },
164  { SAVEBED, "savebed", "savebeds", 0, 0 },
165  { WAND, "wand", "wands", SK_THAUMATURGY, 0 },
166  { SCROLL, "scroll", "scrolls", SK_LITERACY, 0 },
167  { DIRECTOR, "director", "directors", 0, 0 },
168  { GIRDLE, "girdle", "girdles", SK_SMITHERY, 0 },
169  { FORCE, "force", "forces", 0, 0 },
170  { POTION_RESIST_EFFECT, "potion effect", "potion effects", 0, 0 },
171  { CLOSE_CON, "closed container", "closed container", SK_ALCHEMY, 0 },
172  { CONTAINER, "container", "containers", SK_ALCHEMY, 0 },
173  { ARMOUR_IMPROVER, "armour improver", "armour improvers", SK_LITERACY, 0 },
174  { WEAPON_IMPROVER, "weapon improver", "weapon improvers", SK_LITERACY, 0 },
175  { SKILLSCROLL, "skillscroll", "skillscrolls", SK_LITERACY, 0 },
176  { DEEP_SWAMP, "deep swamp", "deep swamps", 0, 0 },
177  { IDENTIFY_ALTAR, "identify altar", "identify altars", 0, 0 },
178  { SHOP_INVENTORY, "inventory list", "inventory lists", 0, 0 },
179  { RUNE, "rune", "runes", 0, 0 },
180  { TRAP, "trap", "traps", 0, 0 },
181  { POWER_CRYSTAL, "power_crystal", "power_crystals", SK_THAUMATURGY, 0 },
182  { CORPSE, "corpse", "corpses", 0, 0 },
183  { DISEASE, "disease", "diseases", 0, 0 },
184  { SYMPTOM, "symptom", "symptoms", 0, 0 },
185  { BUILDER, "item builder", "item builders", 0, 0 },
186  { MATERIAL, "building material", "building materials", 0, 0 },
187  { MIMIC, "mimic", "mimics", SK_ALCHEMY, 0 },
188 };
189 
191 static const int item_types_size = sizeof(item_types)/sizeof(*item_types);
192 
202 static const int enc_to_item_power[] = {
203  0, 0, 1, 2, 3, 4, /* 5 */
204  5, 7, 9, 11, 13, /* 10 */
205  15, 18, 21, 24, 27, /* 15 */
206  30, 35, 40, 45, 50 /* 20 */
207 };
208 
209 int get_power_from_ench(int ench) {
210  if (ench < 0)
211  ench = 0;
212  if (ench > (int)(sizeof(enc_to_item_power)/sizeof(*enc_to_item_power)-1))
213  ench = sizeof(enc_to_item_power)/sizeof(*enc_to_item_power)-1;
214  return enc_to_item_power[ench];
215 }
216 
217 static int bits_set(uint32_t x, int start, int end) {
218  int enc = 0;
219  for (int i = start; i < end; i++) {
220  if (x&(1<<i)) {
221  enc++;
222  }
223  }
224  return enc;
225 }
226 
237 int calc_item_power(const object *op) {
238  int i, tmp, enc;
239 
240  enc = 0;
241  for (i = 0; i < NUM_STATS; i++)
242  enc += get_attr_value(&op->stats, i);
243 
244  /* This protection logic is pretty flawed. 20% fire resistance
245  * is much more valuable than 20% confusion, or 20% slow, or
246  * several others. Start at 1 - ignore physical - all that normal
247  * armour shouldn't be counted against
248  */
249  tmp = 0;
250  for (i = 1; i < NROFATTACKS; i++)
251  tmp += op->resist[i];
252 
253  /* Add/substract 10 so that the rounding works out right */
254  if (tmp > 0)
255  enc += (tmp+10)/20;
256  else if (tmp < 0)
257  enc += (tmp-10)/20;
258 
259  enc += op->magic;
260 
261  /* For each attacktype a weapon has, one more encantment. Start at 1 -
262  * physical doesn't count against total.
263  */
264  if (op->type == WEAPON) {
265  enc += bits_set(op->attacktype, 1, NROFATTACKS);
266  if (op->slaying)
267  enc += 2; /* What it slays is probably more relevent */
268  }
269  /* Items the player can equip */
270  if ((op->type == WEAPON)
271  || (op->type == ARMOUR)
272  || (op->type == HELMET)
273  || (op->type == SHIELD)
274  || (op->type == RING)
275  || (op->type == BOOTS)
276  || (op->type == GLOVES)
277  || (op->type == AMULET)
278  || (op->type == GIRDLE)
279  || (op->type == BRACERS)
280  || (op->type == CLOAK)) {
281  enc += op->stats.food; /* sustenance */
282  enc += op->stats.hp; /* hp regen */
283  enc += op->stats.sp; /* mana regen */
284  enc += op->stats.grace; /* grace regen */
285  enc += op->stats.exp; /* speed bonus */
286  }
287  enc += op->stats.luck;
288 
289  /* Do spell paths now */
290  enc += bits_set(op->path_attuned, 1, NRSPELLPATHS);
291  enc -= bits_set(op->path_repelled, 1, NRSPELLPATHS);
292  enc -= 2*bits_set(op->path_denied, 1, NRSPELLPATHS);
293 
294  if (QUERY_FLAG(op, FLAG_LIFESAVE))
295  enc += 5;
296  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
297  enc += 3;
298  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
299  enc += 2;
300  if (QUERY_FLAG(op, FLAG_STEALTH))
301  enc += 1;
302  if (QUERY_FLAG(op, FLAG_XRAYS))
303  enc += 2;
304  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK))
305  enc += 1;
306  if (QUERY_FLAG(op, FLAG_MAKE_INVIS))
307  enc += 1;
308 
309  return get_power_from_ench(enc);
310 }
311 
318 const typedata *get_typedata(int itemtype) {
319  int i;
320 
321  for (i = 0; i < item_types_size; i++)
322  if (item_types[i].number == itemtype)
323  return &item_types[i];
324  return NULL;
325 }
326 
338 const typedata *get_typedata_by_name(const char *name) {
339  int i;
340 
341  for (i = 0; i < item_types_size; i++)
342  if (!strcmp(item_types[i].name, name))
343  return &item_types[i];
344  for (i = 0; i < item_types_size; i++)
345  if (!strcmp(item_types[i].name_pl, name)) {
346  LOG(llevInfo, "get_typedata_by_name: I have been sent the plural %s, the singular form %s is preffered\n", name, item_types[i].name);
347  return &item_types[i];
348  }
349  return NULL;
350 }
351 
367 StringBuffer *describe_resistance(const object *op, int newline, int use_media_tags, StringBuffer *buf) {
368  int tmpvar;
369 
370  if (buf == NULL)
371  buf = stringbuffer_new();
372 
373  for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++) {
374  if (op->resist[tmpvar] && (op->type != FLESH || atnr_is_dragon_enabled(tmpvar) == 1)) {
375  if (use_media_tags) {
376  if (resist_color[tmpvar] != NULL) {
377  stringbuffer_append_printf(buf, "[color=%s]", resist_color[tmpvar]);
378  }
379  if (op->resist[tmpvar] == 100 || op->resist[tmpvar] == -100) {
380  stringbuffer_append_string(buf, "[ul]");
381  }
382  }
383  if (!newline)
384  stringbuffer_append_printf(buf, "(%s %+d)", resist_plus[tmpvar], op->resist[tmpvar]);
385  else
386  stringbuffer_append_printf(buf, "%s %d\n", resist_plus[tmpvar], op->resist[tmpvar]);
387  if (use_media_tags) {
388  if (op->resist[tmpvar] == 100 || op->resist[tmpvar] == -100) {
389  stringbuffer_append_string(buf, "[/ul]");
390  }
391  if (resist_color[tmpvar] != NULL) {
392  stringbuffer_append_string(buf, "[/color]");
393  }
394  }
395  }
396  }
397 
398  return buf;
399 }
400 
410 void query_weight(const object *op, char *buf, size_t size) {
411  int32_t i = NROF(op)*op->weight+op->carrying;
412 
413  if (op->weight < 0)
414  snprintf(buf, size, " ");
415  else if (i%1000)
416  snprintf(buf, size, "%6.1f", i/1000.0);
417  else
418  snprintf(buf, size, "%4d ", i/1000);
419 }
420 
433 static StringBuffer *ring_desc(const object *op, int use_media_tags, StringBuffer *buf) {
434  int attr, val;
435  size_t len;
436 
437  assert(op != NULL);
438  assert(op->type == RING || op->type == AMULET || op->type == SKILL);
439 
440  if (buf == NULL)
441  buf = stringbuffer_new();
442  len = stringbuffer_length(buf);
443 
444  if (!QUERY_FLAG(op, FLAG_IDENTIFIED))
445  return buf;
446 
447  for (attr = 0; attr < NUM_STATS; attr++) {
448  if ((val = get_attr_value(&(op->stats), attr)) != 0) {
449  stringbuffer_append_printf(buf, "(%s%+d)", short_stat_name[attr], val);
450  }
451  }
452  if (op->stats.exp)
453  stringbuffer_append_printf(buf, "(speed %+"FMT64")", op->stats.exp);
454  if (op->stats.wc)
455  stringbuffer_append_printf(buf, "(wc%+d)", op->stats.wc);
456  if (op->stats.dam)
457  stringbuffer_append_printf(buf, "(dam%+d)", op->stats.dam);
458  if (op->stats.ac)
459  stringbuffer_append_printf(buf, "(ac%+d)", op->stats.ac);
460 
461  describe_resistance(op, 0, use_media_tags, buf);
462 
463  if (op->stats.food != 0)
464  stringbuffer_append_printf(buf, "(sustenance%+d)", op->stats.food);
465  if (op->stats.grace)
466  stringbuffer_append_printf(buf, "(grace%+d)", op->stats.grace);
467  if (op->stats.sp && op->type != SKILL)
468  stringbuffer_append_printf(buf, "(magic%+d)", op->stats.sp);
469  if (op->stats.hp)
470  stringbuffer_append_printf(buf, "(regeneration%+d)", op->stats.hp);
471  if (op->stats.luck)
472  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
473  if (QUERY_FLAG(op, FLAG_LIFESAVE))
474  stringbuffer_append_printf(buf, "(lifesaving)");
475  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
476  stringbuffer_append_printf(buf, "(reflect spells)");
477  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
478  stringbuffer_append_printf(buf, "(reflect missiles)");
479  if (QUERY_FLAG(op, FLAG_STEALTH))
480  stringbuffer_append_printf(buf, "(stealth)");
481  if (op->glow_radius)
482  stringbuffer_append_string(buf, "(glowing)");
483 
484  describe_spellpath_attenuation("Attuned", op->path_attuned, buf);
485  describe_spellpath_attenuation("Repelled", op->path_repelled, buf);
486  describe_spellpath_attenuation("Denied", op->path_denied, buf);
487 
488  /* item_power is done by the caller */
489  /* if (op->item_power)
490  snprintf(buf+strlen(buf), size-strlen(buf), "(item_power %+d)", op->item_power);*/
491  if (stringbuffer_length(buf) == len && op->type != SKILL)
492  stringbuffer_append_string(buf, "of adornment");
493 
494  return buf;
495 }
496 
508 void query_short_name(const object *op, char *buf, size_t size) {
509  size_t len = 0;
510 
511  if (op->name == NULL) {
512  snprintf(buf, size, "(null)");
513  return;
514  }
515  if (!op->nrof && !op->weight && !op->title && !is_magical(op)) {
516  strlcpy(buf, op->name, size); /* To speed things up (or make things slower?) */
517  return;
518  }
519  buf[0] = '\0';
520 
521  if (op->nrof <= 1)
522  safe_strcat(buf, op->name, &len, size);
523  else
524  safe_strcat(buf, op->name_pl, &len, size);
525 
526  if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) {
527  safe_strcat(buf, " ", &len, size);
528  safe_strcat(buf, op->title, &len, size);
529  }
530 
531  switch (op->type) {
532  case SPELLBOOK:
533  case SCROLL:
534  case WAND:
535  case ROD:
537  if (!op->title && (op->inv)) {
538  safe_strcat(buf, " of ", &len, size);
539  safe_strcat(buf, op->inv->name, &len, size);
540  }
541  if (op->type != SPELLBOOK) {
542  snprintf(buf+len, size-len, " (lvl %d)", op->level);
543  len += strlen(buf+len);
544  }
545  }
546  break;
547 
548  case SKILL:
549  case AMULET:
550  case RING:
551  if (!op->title) {
552  /* If ring has a title, full description isn't so useful */
553  char* desc;
554 
555  desc = stringbuffer_finish(ring_desc(op, 0, NULL));
556  if (desc[0]) {
557  safe_strcat(buf, " ", &len, size);
558  safe_strcat(buf, desc, &len, size);
559  }
560  free(desc);
561  }
562  break;
563 
564  default:
565  if (op->magic
566  && (QUERY_FLAG(op, FLAG_BEEN_APPLIED) || is_identified(op))) {
567  snprintf(buf+len, size-len, " %+d", op->magic);
568  len += strlen(buf+len);
569  }
570  }
571 }
572 
583 void query_name(const object *op, char *buf, size_t size) {
584  size_t len = 0;
585 
586  buf[0] = '\0';
587  /*
588  * Since len is initialized to zero, but is not changed
589  * up to this point, I see no reason to have buf+len and size-len;
590  * buf and size should suffice, since we're just adding and
591  * subtracting zero here, anyway.
592  *
593  * SilverNexus 2014-06-04
594  */
595  query_short_name(op, buf, size);
596  len = strlen(buf);
597 
598  if (QUERY_FLAG(op, FLAG_INV_LOCKED))
599  safe_strcat(buf, " *", &len, size);
600  if (op->type == CONTAINER
601  && ((op->env && op->env->container == op) || (!op->env && QUERY_FLAG(op, FLAG_APPLIED))))
602  safe_strcat(buf, " (open)", &len, size);
603 
604  if (QUERY_FLAG(op, FLAG_KNOWN_CURSED)) {
605  if (QUERY_FLAG(op, FLAG_DAMNED))
606  safe_strcat(buf, " (damned)", &len, size);
607  else if (QUERY_FLAG(op, FLAG_CURSED))
608  safe_strcat(buf, " (cursed)", &len, size);
609  }
611  safe_strcat(buf, " (blessed)", &len, size);
612 
613  /* Basically, if the object is known magical (detect magic spell on it),
614  * and it isn't identified, print out the fact that
615  * it is magical. Assume that the detect magical spell will only set
616  * KNOWN_MAGICAL if the item actually is magical.
617  *
618  * Changed in V 0.91.4 - still print that the object is magical even
619  * if it has been applied. Equipping an item does not tell full
620  * abilities, especially for artifact items.
621  */
623  safe_strcat(buf, " (magic)", &len, size);
624 
625  if (QUERY_FLAG(op, FLAG_APPLIED)) {
626  switch (op->type) {
627  case BOW:
628  case WAND:
629  case ROD:
630  safe_strcat(buf, " (readied)", &len, size);
631  break;
632 
633  case WEAPON:
634  safe_strcat(buf, " (wielded)", &len, size);
635  break;
636 
637  case ARMOUR:
638  case HELMET:
639  case SHIELD:
640  case RING:
641  case BOOTS:
642  case GLOVES:
643  case AMULET:
644  case GIRDLE:
645  case BRACERS:
646  case CLOAK:
647  safe_strcat(buf, " (worn)", &len, size);
648  break;
649 
650  case CONTAINER:
651  safe_strcat(buf, " (active)", &len, size);
652  break;
653 
654  case SKILL:
655  default:
656  safe_strcat(buf, " (applied)", &len, size);
657  }
658  }
659  if (QUERY_FLAG(op, FLAG_UNPAID))
660  safe_strcat(buf, " (unpaid)", &len, size);
661 }
662 
680 void query_base_name(const object *op, int plural, char *buf, size_t size) {
681  size_t len;
682 
683  if ((!plural && !op->name)
684  || (plural && !op->name_pl)) {
685  strncpy(buf, "(null)", size);
686  return;
687  }
688 
689  if (!op->nrof && !op->weight && !op->title && !is_magical(op)) {
690  strncpy(buf, op->name, size); /* To speed things up (or make things slower?) */
691  return;
692  }
693 
694  buf[0] = '\0';
695 
696  strlcpy(buf, plural ? op->name_pl : op->name, size);
697  len = strlen(buf);
698 
699  if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) {
700  safe_strcat(buf, " ", &len, size);
701  safe_strcat(buf, op->title, &len, size);
702  }
703 
704  switch (op->type) {
705  case SPELLBOOK:
706  case SCROLL:
707  case WAND:
708  case ROD:
710  if (!op->title && (op->inv)) {
711  safe_strcat(buf, " of ", &len, size);
712  safe_strcat(buf, op->inv->name, &len, size);
713  }
714  if (op->type != SPELLBOOK) {
715  snprintf(buf+len, size-len, " (lvl %d)", op->level);
716  len += strlen(buf+len);
717  }
718  }
719  break;
720 
721  case SKILL:
722  case AMULET:
723  case RING:
724  if (!op->title) {
725  /* If ring has a title, full description isn't so useful */
726  char* s;
727 
728  s = stringbuffer_finish(ring_desc(op, 0, NULL));
729  if (s[0]) {
730  safe_strcat(buf, " ", &len, size);
731  safe_strcat(buf, s, &len, size);
732  }
733  free(s);
734  }
735  break;
736 
737  default:
738  if (op->magic
739  && (QUERY_FLAG(op, FLAG_BEEN_APPLIED) || is_identified(op))) {
740  snprintf(buf+strlen(buf), size-strlen(buf), " %+d", op->magic);
741  }
742  }
743 }
744 
761 StringBuffer *describe_monster(const object *op, int use_media_tags, StringBuffer *buf) {
762  assert(op != NULL);
763  assert(QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER);
764 
765  if (buf == NULL)
766  buf = stringbuffer_new();
767 
768  /* Note that the resolution this provides for players really isn't
769  * very good. Any player with a speed greater than .67 will
770  * fall into the 'lightning fast movement' category.
771  */
772  if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
773  switch ((int)((FABS(op->speed))*15)) {
774  case 0:
775  stringbuffer_append_string(buf, "(very slow movement)");
776  break;
777 
778  case 1:
779  stringbuffer_append_string(buf, "(slow movement)");
780  break;
781 
782  case 2:
783  stringbuffer_append_string(buf, "(normal movement)");
784  break;
785 
786  case 3:
787  case 4:
788  stringbuffer_append_string(buf, "(fast movement)");
789  break;
790 
791  case 5:
792  case 6:
793  stringbuffer_append_string(buf, "(very fast movement)");
794  break;
795 
796  case 7:
797  case 8:
798  case 9:
799  case 10:
800  stringbuffer_append_string(buf, "(extremely fast movement)");
801  break;
802 
803  default:
804  stringbuffer_append_string(buf, "(lightning fast movement)");
805  break;
806  }
807  }
808  if (QUERY_FLAG(op, FLAG_UNDEAD))
809  stringbuffer_append_string(buf, "(undead)");
811  stringbuffer_append_string(buf, "(see invisible)");
812  if (QUERY_FLAG(op, FLAG_USE_WEAPON))
813  stringbuffer_append_string(buf, "(wield weapon)");
814  if (QUERY_FLAG(op, FLAG_USE_BOW))
815  stringbuffer_append_string(buf, "(archer)");
816  if (QUERY_FLAG(op, FLAG_USE_ARMOUR))
817  stringbuffer_append_string(buf, "(wear armour)");
818  if (QUERY_FLAG(op, FLAG_USE_RING))
819  stringbuffer_append_string(buf, "(wear ring)");
820  if (QUERY_FLAG(op, FLAG_USE_SCROLL))
821  stringbuffer_append_string(buf, "(read scroll)");
822  if (QUERY_FLAG(op, FLAG_USE_RANGE))
823  stringbuffer_append_string(buf, "(fires wand/rod/horn)");
825  stringbuffer_append_string(buf, "(skill user)");
826  if (QUERY_FLAG(op, FLAG_CAST_SPELL))
827  stringbuffer_append_string(buf, "(spellcaster)");
828  if (QUERY_FLAG(op, FLAG_FRIENDLY))
829  stringbuffer_append_string(buf, "(friendly)");
830  if (QUERY_FLAG(op, FLAG_UNAGGRESSIVE))
831  stringbuffer_append_string(buf, "(unaggressive)");
832  if (QUERY_FLAG(op, FLAG_HITBACK))
833  stringbuffer_append_string(buf, "(hitback)");
834  if (QUERY_FLAG(op, FLAG_STEALTH))
835  stringbuffer_append_string(buf, "(stealthy)");
836  if (op->randomitems != NULL) {
837  treasure *t;
838  int first = 1;
839 
840  for (t = op->randomitems->items; t != NULL; t = t->next)
841  if (t->item && (t->item->clone.type == SPELL)) {
842  if (first) {
843  first = 0;
844  stringbuffer_append_string(buf, "(Spell abilities:)");
845  }
846  stringbuffer_append_printf(buf, "(%s)", t->item->clone.name);
847  }
848  }
849  if (op->type == PLAYER) {
850  if (op->contr->digestion) {
851  if (op->contr->digestion != 0)
852  stringbuffer_append_printf(buf, "(sustenance%+d)", op->contr->digestion);
853  }
854  if (op->contr->gen_grace) {
855  stringbuffer_append_printf(buf, "(grace%+d)", op->contr->gen_grace);
856  }
857  if (op->contr->gen_sp) {
858  stringbuffer_append_printf(buf, "(magic%+d)", op->contr->gen_sp);
859  }
860  if (op->contr->gen_hp) {
861  stringbuffer_append_printf(buf, "(regeneration%+d)", op->contr->gen_hp);
862  }
863  if (op->stats.luck) {
864  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
865  }
866  }
867 
868  /* describe attacktypes */
869  if (is_dragon_pl(op)) {
870  /* for dragon players display the attacktypes from clawing skill
871  * Break apart the for loop - move the comparison checking down -
872  * this makes it more readable.
873  */
874  object *tmp;
875 
876  tmp = object_find_by_type_and_name(op, SKILL, "clawing");
877  if (tmp && tmp->attacktype != 0) {
878  describe_attacktype("Claws", tmp->attacktype, buf);
879  } else {
880  describe_attacktype("Attacks", op->attacktype, buf);
881  }
882  } else {
883  describe_attacktype("Attacks", op->attacktype, buf);
884  }
885  describe_spellpath_attenuation("Attuned", op->path_attuned &~ op->path_denied, buf);
886  describe_spellpath_attenuation("Repelled", op->path_repelled &~ op->path_denied, buf );
887  describe_spellpath_attenuation("Denied", op->path_denied, buf);
888  describe_resistance(op, 0, use_media_tags, buf);
889 
890  return buf;
891 }
892 
935 StringBuffer *describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf) {
936  int identified, i;
937 
938  if (buf == NULL)
939  buf = stringbuffer_new();
940 
941  if (QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER) {
942  return describe_monster(op, use_media_tags, buf);
943  }
944 
945  /* figure this out once, instead of making multiple calls to is_identified.
946  * also makes the code easier to read.
947  */
948  if (is_identified(op)) {
949  identified = 1;
950  } else {
951  stringbuffer_append_string(buf, "(unidentified)");
952  identified = 0;
953  }
954  switch (op->type) {
955  case BOW:
956  case ARROW:
957  case WAND:
958  case ROD:
959  case WEAPON:
960  case ARMOUR:
961  case HELMET:
962  case SHIELD:
963  case BOOTS:
964  case GLOVES:
965  case GIRDLE:
966  case BRACERS:
967  case CLOAK:
968  case SKILL_TOOL:
969  break; /* We have more information to do below this switch */
970 
971  case LAMP:
972  break; /* just so we get the "glowing" part. */
973 
974  case FOOD:
975  case FLESH:
976  case DRINK:
977  if (identified || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
978  stringbuffer_append_printf(buf, "(food+%d)", op->stats.food);
979 
980  if (op->type == FLESH && op->last_eat > 0 && atnr_is_dragon_enabled(op->last_eat)) {
981  stringbuffer_append_printf(buf, "(%s metabolism)", change_resist_msg[op->last_eat]);
982  }
983 
984  if (!QUERY_FLAG(op, FLAG_CURSED)) {
985  if (op->stats.hp)
986  stringbuffer_append_string(buf, "(heals)");
987  if (op->stats.sp)
988  stringbuffer_append_string(buf, "(spellpoint regen)");
989  } else {
990  if (op->stats.hp)
991  stringbuffer_append_string(buf, "(damages)");
992  if (op->stats.sp)
993  stringbuffer_append_string(buf, "(spellpoint depletion)");
994  }
995  }
996  break;
997 
998  case SKILL:
999  case RING:
1000  case AMULET:
1001  if (op->item_power) {
1002  stringbuffer_append_printf(buf, "(item_power %+d)", op->item_power);
1003  }
1004  ring_desc(op, use_media_tags, buf);
1005  return buf;
1006 
1007  default:
1008  return buf;
1009  }
1010 
1011  /* Down here, we more further describe equipment type items.
1012  * only describe them if they have been identified or the like.
1013  */
1014  if (identified || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
1015  int attr, val;
1016 
1017  for (attr = 0; attr < NUM_STATS; attr++) {
1018  if ((val = get_attr_value(&(op->stats), attr)) != 0) {
1019  stringbuffer_append_printf(buf, "(%s%+d)", short_stat_name[attr], val);
1020  }
1021  }
1022  if (op->glow_radius)
1023  stringbuffer_append_string(buf, "(glowing)");
1024 
1025  switch (op->type) {
1026  case FLESH:
1027  break;
1028 
1029  default:
1030  if (op->stats.exp) {
1031  stringbuffer_append_printf(buf, "(speed %+"FMT64")", op->stats.exp);
1032  }
1033  break;
1034  }
1035  switch (op->type) {
1036  case BOW:
1037  case ARROW:
1038  case GIRDLE:
1039  case HELMET:
1040  case SHIELD:
1041  case BOOTS:
1042  case GLOVES:
1043  case WEAPON:
1044  case SKILL:
1045  case RING:
1046  case AMULET:
1047  case ARMOUR:
1048  case BRACERS:
1049  case FORCE:
1050  case CLOAK:
1051  if (op->stats.wc) {
1052  stringbuffer_append_printf(buf, "(wc%+d)", op->stats.wc);
1053  }
1054  if (op->stats.dam) {
1055  stringbuffer_append_printf(buf, "(dam%+d)", op->stats.dam);
1056  }
1057  if (op->stats.ac) {
1058  stringbuffer_append_printf(buf, "(ac%+d)", op->stats.ac);
1059  }
1060  if ((op->type == WEAPON || op->type == BOW) && op->level > 0) {
1061  stringbuffer_append_printf(buf, "(improved %d/%d)", op->last_eat, op->level);
1062  }
1063  break;
1064 
1065  default:
1066  break;
1067  }
1068  if (QUERY_FLAG(op, FLAG_XRAYS))
1069  stringbuffer_append_string(buf, "(xray-vision)");
1070  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK))
1071  stringbuffer_append_string(buf, "(infravision)");
1072 
1073  /* levitate was what is was before, so we'll keep it */
1074  if (op->move_type&MOVE_FLY_LOW)
1075  stringbuffer_append_string(buf, "(levitate)");
1076 
1077  if (op->move_type&MOVE_FLY_HIGH)
1078  stringbuffer_append_string(buf, "(fly)");
1079 
1080  if (op->move_type&MOVE_SWIM)
1081  stringbuffer_append_string(buf, "(swim)");
1082 
1083  /* walking is presumed as 'normal', so doesn't need mentioning */
1084 
1085  if (op->item_power) {
1086  stringbuffer_append_printf(buf, "(item_power %+d)", op->item_power);
1087  }
1088  } /* End if identified or applied */
1089 
1090  /* This blocks only deals with fully identified object.
1091  * it is intentional that this is not an 'else' from a above -
1092  * in this way, information is added.
1093  */
1094  if (identified) {
1095  int more_info = 0;
1096 
1097  switch (op->type) {
1098  case ROD: /* These use stats.sp for spell selection and stats.food */
1099  case BOW: /* and stats.hp for spell-point regeneration... */
1100  case ARROW:
1101  case WAND:
1102  case FOOD:
1103  case FLESH:
1104  case DRINK:
1105  more_info = 0;
1106  break;
1107 
1108  /* Armor type objects */
1109  case ARMOUR:
1110  case HELMET:
1111  case SHIELD:
1112  case BOOTS:
1113  case GLOVES:
1114  case GIRDLE:
1115  case BRACERS:
1116  case CLOAK:
1117  if (ARMOUR_SPEED(op)) {
1118  stringbuffer_append_printf(buf, "(Max speed %1.2f)", ARMOUR_SPEED(op)/10.0);
1119  }
1120  if (ARMOUR_SPELLS(op)) {
1121  stringbuffer_append_printf(buf, "(Spell regen penalty %d)", ARMOUR_SPELLS(op));
1122  }
1123  more_info = 1;
1124  break;
1125 
1126  case WEAPON:
1127  /* Calculate it the same way fix_object does so the results
1128  * make sense.
1129  */
1130  i = (WEAPON_SPEED(op)*2-op->magic)/2;
1131  if (i < 0)
1132  i = 0;
1133 
1134  stringbuffer_append_printf(buf, "(weapon speed %d)", i);
1135  more_info = 1;
1136  break;
1137  }
1138  if (more_info) {
1139  if (op->stats.food) {
1140  if (op->stats.food != 0)
1141  stringbuffer_append_printf(buf, "(sustenance%+d)", op->stats.food);
1142  }
1143  if (op->stats.grace) {
1144  stringbuffer_append_printf(buf, "(grace%+d)", op->stats.grace);
1145  }
1146  if (op->stats.sp) {
1147  stringbuffer_append_printf(buf, "(magic%+d)", op->stats.sp);
1148  }
1149  if (op->stats.hp) {
1150  stringbuffer_append_printf(buf, "(regeneration%+d)", op->stats.hp);
1151  }
1152  }
1153 
1154  if (op->stats.luck) {
1155  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
1156  }
1157  if (QUERY_FLAG(op, FLAG_LIFESAVE))
1158  stringbuffer_append_string(buf, "(lifesaving)");
1159  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
1160  stringbuffer_append_string(buf, "(reflect spells)");
1161  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
1162  stringbuffer_append_string(buf, "(reflect missiles)");
1163  if (QUERY_FLAG(op, FLAG_STEALTH))
1164  stringbuffer_append_string(buf, "(stealth)");
1165  if (op->slaying != NULL && op->type != FOOD) {
1166  stringbuffer_append_printf(buf, "(slay %s)", op->slaying);
1167  }
1168  describe_attacktype("Attacks", op->attacktype, buf);
1169  /* resistance on flesh is only visible for dragons. If
1170  * non flesh, everyone can see its resistances
1171  */
1172  if (op->type != FLESH || (owner && is_dragon_pl(owner))) {
1173  describe_resistance(op, 0, 1, buf);
1174  }
1175  describe_spellpath_attenuation("Attuned", op->path_attuned &~ op->path_denied, buf);
1176  describe_spellpath_attenuation("Repelled", op->path_repelled &~ op->path_denied, buf);
1177  describe_spellpath_attenuation("Denied", op->path_denied, buf);
1178  }
1179 
1180  return buf;
1181 }
1182 
1195 int is_magical(const object *op) {
1196  int i;
1197 
1198  /* living creatures are considered non magical */
1199  if (QUERY_FLAG(op, FLAG_ALIVE))
1200  return 0;
1201 
1202  /* This is a test for it being an artifact, as artifacts have titles */
1203  if (op->title != NULL)
1204  return 1;
1205 
1206  /* Handle rings and amulets specially. If they change any of these
1207  * values, it means they are magical.
1208  */
1209  if ((op->type == AMULET || op->type == RING)
1210  && (op->stats.ac || op->stats.food || op->stats.exp || op->stats.dam || op->stats.wc || op->stats.sp || op->stats.hp || op->stats.luck))
1211  return 1;
1212 
1213  /* Check for stealty, speed, flying, or just plain magic in the boots */
1214  /* Presume any boots that have a move_type are special. */
1215  if (op->type == BOOTS
1216  && ((QUERY_FLAG(op, FLAG_STEALTH) || op->move_type || op->stats.exp)))
1217  return 1;
1218 
1219  /* Take care of amulet/shield that reflects spells/missiles */
1220  if ((op->type == AMULET || op->type == SHIELD)
1222  return 1;
1223 
1224  /* Take care of helmet of xrays */
1225  if (op->type == HELMET
1226  && QUERY_FLAG(op, FLAG_XRAYS))
1227  return 1;
1228 
1229  /* Potions & rods are always magical. Wands/staves are also magical,
1230  * assuming they still have any charges left.
1231  */
1232  if (op->type == POTION || op->type == ROD || (op->type == WAND && op->stats.food))
1233  return 1;
1234 
1235  /* if something gives a protection, either positive or negative, its magical */
1236  /* This is really a pretty bad hack - as of now, ATNR_PHYSICAL is 0,
1237  * so this always works out fine.
1238  */
1239  for (i = ATNR_PHYSICAL+1; i < NROFATTACKS; i++)
1240  if (op->resist[i])
1241  return 1;
1242 
1243  /* Physical protection is expected on some item types, so they should
1244  * not be considered magical.
1245  */
1246  if (op->resist[ATNR_PHYSICAL]
1247  && op->type != HELMET
1248  && op->type != SHIELD
1249  && op->type != BOOTS
1250  && op->type != GLOVES
1251  && op->type != ARMOUR)
1252  return 1;
1253 
1254  /* power crystal, spellbooks, and scrolls are always magical. */
1255  if (op->magic
1256  || op->type == POWER_CRYSTAL
1257  || op->type == SPELLBOOK
1258  || op->type == SCROLL
1259  || op->type == GIRDLE)
1260  return 1;
1261 
1262  /* Check to see if it increases/decreases any stats */
1263  for (i = 0; i < NUM_STATS; i++)
1264  if (get_attr_value(&(op->stats), i) != 0)
1265  return 1;
1266 
1267  /* If it doesn't fall into any of the above categories, must
1268  * be non magical.
1269  */
1270  return 0;
1271 }
1272 
1292 int is_identifiable_type(const object *op) {
1293  /* Special case -- skill tools don't have an associated identification
1294  * skill but still need IDing. TODO: we should probably have per-tool ID
1295  * skills, e.g. thievery for lockpicks and thaumaturgy for talismans, but
1296  * currently there's no good way to do this because the identifyskill is
1297  * tied to the itemtype rather than to the arch. */
1298  if (op->type == SKILL_TOOL) return true;
1299 
1300  /* Sometimes an itemtype has no associated typedata?! */
1301  const typedata *td = get_typedata(op->type);
1302  return td && td->identifyskill;
1303 }
1304 
1316 int is_identified(const object *op) {
1317  return !is_identifiable_type(op) || QUERY_FLAG(op, FLAG_IDENTIFIED);
1318 }
1319 
1325  sstring key;
1326 
1327  key = object_get_value(op, "identified_face");
1328  if (key != NULL) {
1329  op->face = find_face(key, op->face);
1330  /* if the face is defined, clean the animation, because else
1331  * the face can be lost ; if an animation is defined, it'll be
1332  * processed later on */
1335  op->anim_speed = 0;
1336  op->animation = 0;
1337  object_set_value(op, "identified_face", NULL, 0);
1338  }
1339 
1340  if (object_get_value(op, "identified_anim_random") != NULL) {
1342  object_set_value(op, "identified_anim_random", NULL, 0);
1343  }
1344 
1345  key = object_get_value(op, "identified_anim_speed");
1346  if (key != NULL) {
1347  op->anim_speed = atoi(key);
1348  op->last_anim = 1;
1349  object_set_value(op, "identified_anim_speed", NULL, 0);
1350  }
1351 
1352  key = object_get_value(op, "identified_animation");
1353  if (key != NULL) {
1354  op->animation = find_animation(key);
1355  if (!QUERY_FLAG(op, FLAG_IS_TURNABLE))
1356  SET_FLAG(op, FLAG_ANIMATE);
1357  animate_object(op, op->facing);
1358  object_set_value(op, "identified_animation", NULL, 0);
1359  }
1360 
1361  key = object_get_value(op, "identified_name");
1362  if (key != NULL) {
1363  FREE_AND_COPY(op->name, key);
1364  object_set_value(op, "identified_name", NULL, 0);
1365  }
1366  key = object_get_value(op, "identified_name_pl");
1367  if (key != NULL) {
1368  FREE_AND_COPY(op->name_pl, key);
1369  object_set_value(op, "identified_name_pl", NULL, 0);
1370  }
1371 }
1372 
1386 object *identify(object *op) {
1387  object *pl, *op1;
1388 
1392 
1394 
1395  /*
1396  * We want autojoining of equal objects:
1397  */
1398  if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))
1400 
1401  if (QUERY_FLAG(op, FLAG_BLESSED))
1403 
1404  if (op->type == POTION) {
1405  if (op->inv && op->randomitems) {
1406  if (op->title)
1407  free_string(op->title);
1408  op->title = add_refcount(op->inv->name);
1409  } else if (op->arch) {
1410  free_string(op->name);
1411  op->name = add_refcount(op->arch->clone.name);
1412  free_string(op->name_pl);
1413  op->name_pl = add_refcount(op->arch->clone.name_pl);
1414  }
1415  }
1416 
1417  if (op->map) {
1418  /* If the object is on a map, make sure we update its face.
1419  * Also send name and such information to a player standing on it.
1420  */
1421  object *player = map_find_by_type(op->map, op->x, op->y, PLAYER);
1422 
1424  op1 = object_merge(op, GET_MAP_TOP(op->map, op->x, op->y));
1425  if (op1) op = op1;
1426 
1427  if (player)
1428  esrv_update_item(UPD_FACE | UPD_NAME | UPD_FLAGS, player, op);
1429 
1430  } else {
1431  pl = object_get_player_container(op->env);
1432  op1 = object_merge(op, op->env->inv);
1433  if (op1) op = op1;
1434 
1435  if (pl)
1436  /* A lot of the values can change from an update - might as well send
1437  * it all.
1438  */
1439  esrv_update_item(UPD_ALL, pl, op);
1440  }
1441  return op;
1442 }
object * object_find_by_type_and_name(const object *who, int type, const char *name)
Definition: object.c:3887
#define FLAG_KNOWN_BLESSED
Definition: define.h:379
#define NUM_BODY_LOCATIONS
Definition: object.h:13
Definition: player.h:92
#define FLAG_SEE_IN_DARK
Definition: define.h:338
#define WEAPON_SPEED(xyz)
Definition: define.h:483
#define FLAG_DAMNED
Definition: define.h:318
#define FLAG_UNPAID
Definition: define.h:236
int8_t ac
Definition: living.h:38
#define UP_OBJ_FACE
Definition: object.h:519
MoveType move_type
Definition: object.h:427
int16_t gen_hp
Definition: player.h:113
Definition: object.h:127
Definition: object.h:185
Definition: object.h:125
int is_magical(const object *op)
Definition: item.c:1195
#define FLAG_HITBACK
Definition: define.h:267
#define FLAG_USE_SCROLL
Definition: define.h:292
void object_give_identified_properties(object *op)
Definition: item.c:1324
#define SET_FLAG(xyz, p)
Definition: define.h:223
sstring add_refcount(sstring str)
Definition: shstr.c:210
#define ARMOUR_SPELLS(xyz)
Definition: define.h:482
int get_power_from_ench(int ench)
Definition: item.c:209
#define FABS(x)
Definition: define.h:22
Definition: object.h:221
int identifyskill
Definition: define.h:93
static int bits_set(uint32_t x, int start, int end)
Definition: item.c:217
#define FLAG_USE_ARMOUR
Definition: define.h:296
uint8_t anim_speed
Definition: object.h:420
Definition: object.h:204
Definition: object.h:112
struct obj * container
Definition: object.h:291
uint8_t last_anim
Definition: object.h:421
Definition: object.h:117
#define FLAG_FRIENDLY
Definition: define.h:246
int16_t gen_grace
Definition: player.h:116
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
void free_string(sstring str)
Definition: shstr.c:280
const char * object_get_value(const object *op, const char *const key)
Definition: object.c:4125
Definition: object.h:137
struct treasureliststruct * randomitems
Definition: object.h:388
static uint32_t NROF(const object *const ob)
Definition: object.h:612
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.c:680
object clone
Definition: object.h:472
Definition: object.h:240
void query_weight(const object *op, char *buf, size_t size)
Definition: item.c:410
Definition: object.h:119
Definition: object.h:136
const char * slaying
Definition: object.h:319
Definition: object.h:138
#define FLAG_STEALTH
Definition: define.h:313
Definition: object.h:109
#define FLAG_USE_WEAPON
Definition: define.h:297
int64_t exp
Definition: living.h:47
#define FLAG_BLESSED
Definition: define.h:378
Definition: object.h:157
Definition: object.h:223
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
Definition: item.c:54
static const typedata item_types[]
Definition: item.c:78
Definition: object.h:139
int8_t get_attr_value(const living *stats, int attr)
Definition: living.c:314
Definition: object.h:249
Definition: object.h:191
uint32_t path_attuned
Definition: object.h:345
void object_update(object *op, int action)
Definition: object.c:1190
const typedata * get_typedata_by_name(const char *name)
Definition: item.c:338
int16_t sp
Definition: living.h:42
Definition: object.h:187
uint32_t path_repelled
Definition: object.h:346
Definition: object.h:212
#define FLAG_USE_RING
Definition: define.h:298
static const int enc_to_item_power[]
Definition: item.c:202
Definition: object.h:220
struct archt * item
Definition: treasure.h:64
int16_t hp
Definition: living.h:40
#define FLAG_KNOWN_MAGICAL
Definition: define.h:320
#define UPD_ALL
Definition: newclient.h:297
const typedata * get_typedata(int itemtype)
Definition: item.c:318
#define FLAG_SEE_INVISIBLE
Definition: define.h:253
#define FLAG_UNDEAD
Definition: define.h:270
Definition: object.h:241
int object_set_value(object *op, const char *key, const char *value, int add_key)
Definition: object.c:4248
const char * title
Definition: object.h:317
int16_t y
Definition: object.h:327
Definition: object.h:186
Definition: object.h:118
#define FLAG_CLIENT_ANIM_RANDOM
Definition: define.h:241
static const int item_types_size
Definition: item.c:191
uint32_t path_denied
Definition: object.h:347
Definition: object.h:211
#define FLAG_ALIVE
Definition: define.h:230
#define FLAG_REFL_SPELL
Definition: define.h:275
Definition: object.h:114
int is_identified(const object *op)
Definition: item.c:1316
Definition: object.h:181
const char * name_pl
Definition: object.h:315
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:95
Definition: object.h:158
int16_t gen_sp
Definition: player.h:114
#define MOVE_SWIM
Definition: define.h:411
int32_t weight
Definition: object.h:367
#define FLAG_CAN_USE_SKILL
Definition: define.h:322
#define MOVE_FLY_LOW
Definition: define.h:408
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
Definition: object.h:115
#define FLAG_USE_RANGE
Definition: define.h:293
struct mapdef * map
Definition: object.h:297
int is_dragon_pl(const object *op)
Definition: player.c:114
#define snprintf
Definition: win32.h:46
#define FLAG_CLIENT_ANIM_SYNC
Definition: define.h:240
#define FLAG_IDENTIFIED
Definition: define.h:261
#define FMT64
Definition: compat.h:12
int16_t dam
Definition: living.h:46
Definition: object.h:145
int32_t carrying
Definition: object.h:369
const char * name
Definition: object.h:311
struct obj * env
Definition: object.h:293
#define ARMOUR_SPEED(xyz)
Definition: define.h:481
size_t stringbuffer_length(StringBuffer *sb)
Definition: stringbuffer.c:162
#define GET_MAP_TOP(M, X, Y)
Definition: map.h:174
uint32_t nrof
Definition: object.h:334
EXTERN const char *const change_resist_msg[NROFATTACKS]
Definition: attack.h:135
#define UPD_FLAGS
Definition: newclient.h:290
Definition: object.h:111
struct pl * contr
Definition: object.h:276
int8_t item_power
Definition: object.h:364
#define FLAG_XRAYS
Definition: define.h:301
#define ATNR_PHYSICAL
Definition: attack.h:49
int8_t luck
Definition: living.h:39
float speed
Definition: object.h:329
Definition: object.h:214
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define FLAG_BEEN_APPLIED
Definition: define.h:324
#define NRSPELLPATHS
Definition: spells.h:40
const Animations * animation
Definition: object.h:419
Definition: object.h:126
#define FLAG_CAST_SPELL
Definition: define.h:291
int16_t x
Definition: object.h:327
StringBuffer * describe_attacktype(const char *attack, int value, StringBuffer *buf)
Definition: utils.c:562
struct treasurestruct * items
Definition: treasure.h:90
int32_t last_eat
Definition: object.h:358
int calc_item_power(const object *op)
Definition: item.c:237
Definition: object.h:201
int8_t wc
Definition: living.h:37
void animate_object(object *op, int dir)
Definition: anim.c:212
int16_t resist[NROFATTACKS]
Definition: object.h:343
#define FLAG_KNOWN_CURSED
Definition: define.h:321
const char * sstring
Definition: global.h:40
#define FLAG_CURSED
Definition: define.h:317
unsigned int uint32_t
Definition: win32.h:162
Definition: object.h:107
const Animations * find_animation(const char *name)
Definition: anim.c:173
Definition: object.h:113
void safe_strcat(char *dest, const char *orig, size_t *curlen, size_t maxlen)
Definition: porting.c:346
Definition: object.h:135
#define FLAG_ANIMATE
Definition: define.h:242
void esrv_update_item(int flags, object *pl, object *op)
Definition: item.c:405
uint32_t attacktype
Definition: object.h:344
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Definition: item.c:935
Definition: object.h:122
#define FREE_AND_COPY(sv, nv)
Definition: global.h:210
int16_t grace
Definition: living.h:44
Definition: object.h:243
Definition: object.h:143
StringBuffer * describe_monster(const object *op, int use_media_tags, StringBuffer *buf)
Definition: item.c:761
living stats
Definition: object.h:370
struct archt * arch
Definition: object.h:415
#define UPD_FACE
Definition: newclient.h:292
Definition: object.h:207
Definition: object.h:206
uint8_t type
Definition: object.h:340
#define FLAG_APPLIED
Definition: define.h:235
#define NROFATTACKS
Definition: attack.h:17
object * object_merge(object *op, object *top)
Definition: object.c:1789
EXTERN const char *const resist_plus[NROFATTACKS]
Definition: attack.h:136
void query_short_name(const object *op, char *buf, size_t size)
Definition: item.c:508
object * object_get_player_container(object *op)
Definition: object.c:377
#define FLAG_LIFESAVE
Definition: define.h:306
signed int int32_t
Definition: win32.h:159
#define UPD_NAME
Definition: newclient.h:293
#define FLAG_MAKE_INVIS
Definition: define.h:329
StringBuffer * describe_resistance(const object *op, int newline, int use_media_tags, StringBuffer *buf)
Definition: item.c:367
object * identify(object *op)
Definition: item.c:1386
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:104
#define MIN_ACTIVE_SPEED
Definition: define.h:676
StringBuffer * describe_spellpath_attenuation(const char *attenuation, int value, StringBuffer *buf)
Definition: utils.c:534
int8_t glow_radius
Definition: object.h:366
#define FLAG_MONSTER
Definition: define.h:245
struct obj * inv
Definition: object.h:290
Definition: object.h:213
#define MOVE_FLY_HIGH
Definition: define.h:409
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
Definition: object.h:209
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:583
const Face * find_face(const char *name, const Face *error)
Definition: image.c:316
int is_identifiable_type(const object *op)
Definition: item.c:1292
const Face * face
Definition: object.h:333
Definition: object.h:167
static StringBuffer * ring_desc(const object *op, int use_media_tags, StringBuffer *buf)
Definition: item.c:433
#define FLAG_NO_SKILL_IDENT
Definition: define.h:336
const char *const short_stat_name[NUM_STATS]
Definition: living.c:195
Definition: object.h:120
struct treasurestruct * next
Definition: treasure.h:66
#define FLAG_REFL_MISSILE
Definition: define.h:273
int16_t level
Definition: object.h:353
int8_t facing
Definition: object.h:337
#define FLAG_INV_LOCKED
Definition: define.h:330
Definition: object.h:148
int8_t magic
Definition: object.h:350
int16_t digestion
Definition: player.h:112
#define FLAG_USE_BOW
Definition: define.h:294
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:366
EXTERN const char *const resist_color[NROFATTACKS]
Definition: attack.h:137
object * map_find_by_type(mapstruct *m, int x, int y, uint8_t type)
Definition: object.c:2866
int atnr_is_dragon_enabled(int attacknr)
Definition: player.c:95
int32_t food
Definition: living.h:48
Definition: object.h:224
#define FLAG_IS_TURNABLE
Definition: define.h:256