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