Crossfire Server, Trunk  1.75.0
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 #include <cmath>
30 
31 #include "living.h"
32 #include "spells.h"
33 
57  { "body_range", "in your range slot", "in a human's range slot" },
58  { "body_arm", "on your arm", "on a human's arm" },
59  { "body_torso", "on your body", "on a human's torso" },
60  { "body_head", "on your head", "on a human's head" },
61  { "body_neck", "around your neck", "around a human's neck" },
62  { "body_skill", "in your skill slot", "in a human's skill slot" },
63  { "body_finger", "on your finger", "on a human's finger" },
64  { "body_shoulder", "around your shoulders", "around a human's shoulders" },
65  { "body_foot", "on your feet", "on a human's feet" },
66  { "body_hand", "on your hands", "on a human's hands" },
67  { "body_wrist", "around your wrists", "around a human's wrist" },
68  { "body_waist", "around your waist", "around a human's waist" },
69  { "body_leg", "around your legs", "around a human's legs" },
70  /*{"body_dragon_torso", "your body", "a dragon's body"} */
71 };
72 
80 static const typedata item_types[] = {
81  { 0, "none", "none", 0, 0 },
82  { PLAYER, "player", "players", 0, 0 },
83  { TRANSPORT, "transport", "transports", 0, 0 },
84  { ROD, "rod", "rods", SK_THAUMATURGY, 0 },
85  { TREASURE, "treasure", "treasure", 0, 0 },
86  { POTION, "potion", "potions", SK_ALCHEMY, 0 },
87  { FOOD, "food", "food", SK_WOODSMAN, 0 },
88  { POISON, "poison", "poisons", SK_ALCHEMY, 0 },
89  { BOOK, "book", "books", SK_LITERACY, 0 },
90  { CLOCK, "clock", "clocks", 0, 0 },
91  { ARROW, "arrow", "arrows", SK_BOWYER, 0 },
92  { BOW, "bow", "bows", SK_BOWYER, 0 },
93  { WEAPON, "weapon", "weapons", SK_SMITHERY, 0 },
94  { ARMOUR, "armour", "armour", SK_SMITHERY, 0 },
95  { PEDESTAL, "pedestal", "pedestals", 0, 0 },
96  { ALTAR, "altar", "altars", 0, 0 },
97  { LOCKED_DOOR, "locked door", "locked doors", 0, 0 },
98  { SPECIAL_KEY, "special key", "special keys", 0, 0 },
99  { MAP, "map", "maps", 0, 0 },
100  { DOOR, "door", "doors", 0, 0 },
101  { KEY, "key", "keys", 0, 0 },
102  { TIMED_GATE, "timed_gate", "timed_gates", 0, 0 },
103  { TRIGGER, "trigger", "triggers", 0, 0 },
104  { GRIMREAPER, "grimreaper", "grimreapers", 0, 0 },
105  { MAGIC_EAR, "magic ear", "magic ears", 0, 0 },
106  { TRIGGER_BUTTON, "trigger button", "trigger buttons", 0, 0 },
107  { TRIGGER_ALTAR, "trigger altar", "trigger altars", 0, 0 },
108  { TRIGGER_PEDESTAL, "trigger pedestal", "trigger pedestals", 0, 0 },
109  { SHIELD, "shield", "shields", SK_SMITHERY, 0 },
110  { HELMET, "helmet", "helmets", SK_SMITHERY, 0 },
111  { MONEY, "money", "money", 0, 0 },
112  { CLASS, "class", "classes", 0, 0 },
113  { AMULET, "amulet", "amulets", SK_JEWELER, 0 },
114  { PLAYERMOVER, "player mover", "player movers", 0, 0 },
115  { TELEPORTER, "teleporter", "teleporters", 0, 0 },
116  { CREATOR, "creator", "creators", 0, 0 },
117  { SKILL, "skill", "skills", 0, 0 },
118  { EARTHWALL, "earthwall", "earthwalls", 0, 0 },
119  { GOLEM, "golem", "golems", 0, 0 },
120  { THROWN_OBJ, "projectile", "projectiles", 0, 0 },
121  { BLINDNESS, "blindness", "blindness", 0, 0 },
122  { GOD, "god", "gods", 0, 0 },
123  { DETECTOR, "detector", "detectors", 0, 0 },
124  { TRIGGER_MARKER, "trigger marker", "trigger markers", 0, 0 },
125  { DEAD_OBJECT, "dead object", "dead objects", 0, 0 },
126  { DRINK, "drink", "drinks", SK_WOODSMAN, SK_ALCHEMY },
127  { MARKER, "marker", "markers", 0, 0 },
128  { HOLY_ALTAR, "holy altar", "holy altars", 0, 0 },
129  { PLAYER_CHANGER, "player changer", "player changers", 0, 0 },
130  { BATTLEGROUND, "battleground", "battlegrounds", 0, 0 },
131  { PEACEMAKER, "peacemaker", "peacemakers", 0, 0 },
132  { GEM, "gem", "gems", SK_JEWELER, 0 },
133  { FIREWALL, "firewall", "firewalls", 0, 0 },
134  { CHECK_INV, "inventory checker", "inventory checkers", 0, 0 },
135  { MOOD_FLOOR, "mood floor", "mood floors", 0, 0 },
136  { EXIT, "exit", "exits", 0, 0 },
137  { ENCOUNTER, "encounter", "encounters", 0, 0 },
138  { SHOP_FLOOR, "shop floor", "shop floors", 0, 0 },
139  { SHOP_MAT, "shop mat", "shop mats", 0, 0 },
140  { RING, "ring", "rings", SK_JEWELER, 0 },
141  { FLOOR, "floor", "floors", 0, 0 },
142  { FLESH, "flesh", "flesh", SK_WOODSMAN, 0 },
143  { INORGANIC, "inorganic", "inorganics", SK_ALCHEMY, 0 },
144  { SKILL_TOOL, "skill tool", "skill tools", 0, 0 },
145  { LIGHTER, "lighter", "lighters", 0, 0 },
146  { WALL, "wall", "walls", 0, 0 },
147  { MISC_OBJECT, "bric-a-brac", "bric-a-brac", 0, 0 },
148  { MONSTER, "monster", "monsters", 0, 0 },
149  { LAMP, "lamp", "lamps", 0, 0 },
150  { DUPLICATOR, "duplicator", "duplicators", 0, 0 },
151  { SPELLBOOK, "spellbook", "spellbooks", SK_LITERACY, 0 },
152  { CLOAK, "cloak", "cloaks", SK_SMITHERY, 0 },
153  { SPINNER, "spinner", "spinners", 0, 0 },
154  { GATE, "gate", "gates", 0, 0 },
155  { BUTTON, "button", "buttons", 0, 0 },
156  { CF_HANDLE, "cf handle", "cf handles", 0, 0 },
157  { HOLE, "hole", "holes", 0, 0 },
158  { TRAPDOOR, "trapdoor", "trapdoors", 0, 0 },
159  { SIGN, "sign", "signs", 0, 0 },
160  { BOOTS, "boots", "boots", SK_SMITHERY, 0 },
161  { GLOVES, "gloves", "gloves", SK_SMITHERY, 0 },
162  { SPELL, "spell", "spells", 0, 0 },
163  { SPELL_EFFECT, "spell effect", "spell effects", 0, 0 },
164  { CONVERTER, "converter", "converters", 0, 0 },
165  { BRACERS, "bracers", "bracers", SK_SMITHERY, 0 },
166  { POISONING, "poisoning", "poisonings", 0, 0 },
167  { SAVEBED, "savebed", "savebeds", 0, 0 },
168  { WAND, "wand", "wands", SK_THAUMATURGY, 0 },
169  { SCROLL, "scroll", "scrolls", SK_LITERACY, 0 },
170  { DIRECTOR, "director", "directors", 0, 0 },
171  { GIRDLE, "girdle", "girdles", SK_SMITHERY, 0 },
172  { FORCE, "force", "forces", 0, 0 },
173  { POTION_RESIST_EFFECT, "potion effect", "potion effects", 0, 0 },
174  { CLOSE_CON, "closed container", "closed container", SK_ALCHEMY, 0 },
175  { CONTAINER, "container", "containers", SK_ALCHEMY, 0 },
176  { ARMOUR_IMPROVER, "armour improver", "armour improvers", SK_LITERACY, 0 },
177  { WEAPON_IMPROVER, "weapon improver", "weapon improvers", SK_LITERACY, 0 },
178  { SKILLSCROLL, "skillscroll", "skillscrolls", SK_LITERACY, 0 },
179  { DEEP_SWAMP, "deep swamp", "deep swamps", 0, 0 },
180  { IDENTIFY_ALTAR, "identify altar", "identify altars", 0, 0 },
181  { SHOP_INVENTORY, "inventory list", "inventory lists", 0, 0 },
182  { RUNE, "rune", "runes", 0, 0 },
183  { TRAP, "trap", "traps", 0, 0 },
184  { POWER_CRYSTAL, "power_crystal", "power_crystals", SK_THAUMATURGY, 0 },
185  { CORPSE, "corpse", "corpses", 0, 0 },
186  { DISEASE, "disease", "diseases", 0, 0 },
187  { SYMPTOM, "symptom", "symptoms", 0, 0 },
188  { BUILDER, "item builder", "item builders", 0, 0 },
189  { MATERIAL, "building material", "building materials", 0, 0 },
190  { MIMIC, "mimic", "mimics", SK_ALCHEMY, 0 },
191  { LIGHTABLE, "lightable", "lightables", 0, 0 },
192 };
193 
195 static const int item_types_size = sizeof(item_types)/sizeof(*item_types);
196 
206 static const int enc_to_item_power[] = {
207  0, 0, 1, 2, 3, 4, /* 5 */
208  5, 7, 9, 11, 13, /* 10 */
209  15, 18, 21, 24, 27, /* 15 */
210  30, 35, 40, 45, 50 /* 20 */
211 };
212 
213 int get_power_from_ench(int ench) {
214  if (ench < 0)
215  ench = 0;
216  if (ench > (int)(sizeof(enc_to_item_power)/sizeof(*enc_to_item_power)-1))
217  ench = sizeof(enc_to_item_power)/sizeof(*enc_to_item_power)-1;
218  return enc_to_item_power[ench];
219 }
220 
221 static int bits_set(uint32_t x) {
222  std::bitset<32> xs = x;
223  return xs.count();
224 }
225 
226 int calc_item_enhancement(const object *op) {
227  int i, tmp, enc;
228 
229  // If we get, for example, a pile of gypsum here,
230  // don't give it an item power. Nothing in the inorganic
231  // type can be applied; their resistances are just to avoid
232  // or encourage destruction by specific attacktypes.
233  if (op->type == INORGANIC)
234  return 0;
235 
236  enc = 0;
237  for (i = 0; i < NUM_STATS; i++)
238  enc += get_attr_value(&op->stats, i);
239 
240  /* This protection logic is pretty flawed. 20% fire resistance
241  * is much more valuable than 20% confusion, or 20% slow, or
242  * several others. Start at 1 - ignore physical - all that normal
243  * armour shouldn't be counted against
244  */
245  tmp = 0;
246  for (i = 1; i < NROFATTACKS; i++)
247  tmp += op->resist[i];
248 
249  /* Add/substract 10 so that the rounding works out right */
250  if (tmp > 0)
251  enc += (tmp+10)/20;
252  else if (tmp < 0)
253  enc += (tmp-10)/20;
254 
255  enc += op->magic;
256 
257  /* For each attacktype a weapon has, one more encantment. Start at 1 -
258  * physical doesn't count against total.
259  */
260  if (op->type == WEAPON) {
261  enc += bits_set(op->attacktype);
262  if (op->slaying)
263  enc += 2; /* What it slays is probably more relevent */
264  }
265  /* Items the player can equip */
266  if ((op->type == WEAPON)
267  || (op->type == ARMOUR)
268  || (op->type == HELMET)
269  || (op->type == SHIELD)
270  || (op->type == RING)
271  || (op->type == BOOTS)
272  || (op->type == GLOVES)
273  || (op->type == AMULET)
274  || (op->type == GIRDLE)
275  || (op->type == BRACERS)
276  || (op->type == CLOAK)) {
277  enc += op->stats.food; /* sustenance */
278  enc += op->stats.hp; /* hp regen */
279  enc += op->stats.sp; /* mana regen */
280  enc += op->stats.grace; /* grace regen */
281  enc += op->stats.exp; /* speed bonus */
282  }
283  enc += op->stats.luck;
284 
285  /* Do spell paths now */
286  enc += bits_set(op->path_attuned);
287  enc -= bits_set(op->path_repelled);
288  enc -= 2*bits_set(op->path_denied);
289 
290  if (QUERY_FLAG(op, FLAG_LIFESAVE))
291  enc += 5;
292  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
293  enc += 3;
294  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
295  enc += 2;
296  if (QUERY_FLAG(op, FLAG_STEALTH))
297  enc += 1;
298  if (QUERY_FLAG(op, FLAG_XRAYS))
299  enc += 2;
300  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK))
301  enc += 1;
302  if (QUERY_FLAG(op, FLAG_MAKE_INVIS))
303  enc += 1;
304 
305  return enc;
306 }
307 
318 int calc_item_power(const object *op) {
320 }
321 
328 const typedata *get_typedata(int itemtype) {
329  int i;
330 
331  for (i = 0; i < item_types_size; i++)
332  if (item_types[i].number == itemtype)
333  return &item_types[i];
334  return NULL;
335 }
336 
348 const typedata *get_typedata_by_name(const char *name) {
349  int i;
350 
351  for (i = 0; i < item_types_size; i++)
352  if (!strcmp(item_types[i].name, name))
353  return &item_types[i];
354  for (i = 0; i < item_types_size; i++)
355  if (!strcmp(item_types[i].name_pl, name)) {
356  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);
357  return &item_types[i];
358  }
359  return NULL;
360 }
361 
377 StringBuffer *describe_resistance(const object *op, int newline, int use_media_tags, StringBuffer *buf) {
378  int tmpvar;
379 
380  if (buf == NULL)
381  buf = stringbuffer_new();
382 
383  for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++) {
384  if (op->resist[tmpvar] && (op->type != FLESH || atnr_is_dragon_enabled(tmpvar) == 1)) {
385  if (use_media_tags) {
386  if (resist_color[tmpvar] != NULL) {
387  stringbuffer_append_printf(buf, "[color=%s]", resist_color[tmpvar]);
388  }
389  if (op->resist[tmpvar] == 100 || op->resist[tmpvar] == -100) {
391  }
392  }
393  if (!newline)
394  stringbuffer_append_printf(buf, "(%s %+d)", resist_plus[tmpvar], op->resist[tmpvar]);
395  else
396  stringbuffer_append_printf(buf, "%s %d\n", resist_plus[tmpvar], op->resist[tmpvar]);
397  if (use_media_tags) {
398  if (op->resist[tmpvar] == 100 || op->resist[tmpvar] == -100) {
400  }
401  if (resist_color[tmpvar] != NULL) {
402  stringbuffer_append_string(buf, "[/color]");
403  }
404  }
405  }
406  }
407 
408  return buf;
409 }
410 
420 void query_weight(const object *op, char *buf, size_t size) {
421  int32_t i = NROF(op)*op->weight+op->carrying;
422 
423  if (op->weight < 0)
424  snprintf(buf, size, " ");
425  else if (i%1000)
426  snprintf(buf, size, "%6.1f", i/1000.0);
427  else
428  snprintf(buf, size, "%4d ", i/1000);
429 }
430 
443 static StringBuffer *ring_desc(const object *op, int use_media_tags, StringBuffer *buf) {
444  int attr, val;
445  size_t len;
446 
447  assert(op != NULL);
448  assert(op->type == RING || op->type == AMULET || op->type == SKILL);
449 
450  if (buf == NULL)
451  buf = stringbuffer_new();
452  len = stringbuffer_length(buf);
453 
454  if (!QUERY_FLAG(op, FLAG_IDENTIFIED))
455  return buf;
456 
457  for (attr = 0; attr < NUM_STATS; attr++) {
458  if ((val = get_attr_value(&(op->stats), attr)) != 0) {
459  stringbuffer_append_printf(buf, "(%s%+d)", short_stat_name[attr], val);
460  }
461  }
462  if (op->stats.exp)
463  stringbuffer_append_printf(buf, "(speed %+" FMT64 ")", op->stats.exp);
464  if (op->stats.wc)
465  stringbuffer_append_printf(buf, "(wc%+d)", op->stats.wc);
466  if (op->stats.dam)
467  stringbuffer_append_printf(buf, "(dam%+d)", op->stats.dam);
468  if (op->stats.ac)
469  stringbuffer_append_printf(buf, "(ac%+d)", op->stats.ac);
470 
471  describe_resistance(op, 0, use_media_tags, buf);
472 
473  if (op->stats.food != 0)
474  stringbuffer_append_printf(buf, "(sustenance%+d)", op->stats.food);
475  if (op->stats.grace)
476  stringbuffer_append_printf(buf, "(grace%+d)", op->stats.grace);
477  if (op->stats.sp && op->type != SKILL)
478  stringbuffer_append_printf(buf, "(magic%+d)", op->stats.sp);
479  if (op->stats.hp)
480  stringbuffer_append_printf(buf, "(regeneration%+d)", op->stats.hp);
481  if (op->stats.luck)
482  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
483  if (QUERY_FLAG(op, FLAG_LIFESAVE))
484  stringbuffer_append_printf(buf, "(lifesaving)");
485  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
486  stringbuffer_append_printf(buf, "(reflect spells)");
487  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
488  stringbuffer_append_printf(buf, "(reflect missiles)");
489  if (QUERY_FLAG(op, FLAG_STEALTH))
490  stringbuffer_append_printf(buf, "(stealth)");
491  if (op->glow_radius)
492  stringbuffer_append_string(buf, "(glowing)");
493 
497 
498  /* item_power is done by the caller */
499  /* if (op->item_power)
500  snprintf(buf+strlen(buf), size-strlen(buf), "(item_power %+d)", op->item_power);*/
501  if (stringbuffer_length(buf) == len && op->type != SKILL)
502  stringbuffer_append_string(buf, "of adornment");
503 
504  return buf;
505 }
506 
518 void query_short_name(const object *op, char *buf, size_t size) {
519  size_t len = 0;
520 
521  if (op->name == NULL) {
522  snprintf(buf, size, "(null)");
523  return;
524  }
525  if (!op->nrof && !op->weight && !op->title && !is_magical(op)) {
526  strlcpy(buf, op->name, size); /* To speed things up (or make things slower?) */
527  return;
528  }
529  buf[0] = '\0';
530 
531  if (op->nrof <= 1)
532  safe_strcat(buf, op->name, &len, size);
533  else
534  safe_strcat(buf, op->name_pl, &len, size);
535 
536  if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) {
537  safe_strcat(buf, " ", &len, size);
538  safe_strcat(buf, op->title, &len, size);
539  }
540 
541  switch (op->type) {
542  case SPELLBOOK:
543  case SCROLL:
544  case WAND:
545  case ROD:
546  case POTION:
548  if (!op->title && (op->inv)) {
549  safe_strcat(buf, " of ", &len, size);
550  safe_strcat(buf, op->inv->name, &len, size);
551  }
552  if (op->type != SPELLBOOK) {
553  snprintf(buf+len, size-len, " (lvl %d)", op->level);
554  len += strlen(buf+len);
555  }
556  }
557  break;
558 
559  case SKILL:
560  case AMULET:
561  case RING:
562  if (!op->title) {
563  /* If ring has a title, full description isn't so useful */
564  char* desc;
565 
566  desc = stringbuffer_finish(ring_desc(op, 0, NULL));
567  if (desc[0]) {
568  safe_strcat(buf, " ", &len, size);
569  safe_strcat(buf, desc, &len, size);
570  }
571  free(desc);
572  }
573  break;
574 
575  default:
576  if (op->magic
577  && (QUERY_FLAG(op, FLAG_BEEN_APPLIED) || is_identified(op))) {
578  snprintf(buf+len, size-len, " %+d", op->magic);
579  len += strlen(buf+len);
580  }
581  }
582 }
583 
594 void query_name(const object *op, char *buf, size_t size) {
595  size_t len = 0;
596 
597  buf[0] = '\0';
598  /*
599  * Since len is initialized to zero, but is not changed
600  * up to this point, I see no reason to have buf+len and size-len;
601  * buf and size should suffice, since we're just adding and
602  * subtracting zero here, anyway.
603  *
604  * SilverNexus 2014-06-04
605  */
606  query_short_name(op, buf, size);
607  len = strlen(buf);
608 
609  if (QUERY_FLAG(op, FLAG_INV_LOCKED))
610  safe_strcat(buf, " *", &len, size);
611  if (op->type == CONTAINER
612  && ((op->env && op->env->container == op) || (!op->env && QUERY_FLAG(op, FLAG_APPLIED))))
613  safe_strcat(buf, " (open)", &len, size);
614 
615  if (QUERY_FLAG(op, FLAG_KNOWN_CURSED)) {
616  if (QUERY_FLAG(op, FLAG_DAMNED))
617  safe_strcat(buf, " (damned)", &len, size);
618  else if (QUERY_FLAG(op, FLAG_CURSED))
619  safe_strcat(buf, " (cursed)", &len, size);
620  }
622  safe_strcat(buf, " (blessed)", &len, size);
623 
624  /* Basically, if the object is known magical (detect magic spell on it),
625  * and it isn't identified, print out the fact that
626  * it is magical. Assume that the detect magical spell will only set
627  * KNOWN_MAGICAL if the item actually is magical.
628  *
629  * Changed in V 0.91.4 - still print that the object is magical even
630  * if it has been applied. Equipping an item does not tell full
631  * abilities, especially for artifact items.
632  */
634  safe_strcat(buf, " (magic)", &len, size);
635 
636  if (QUERY_FLAG(op, FLAG_APPLIED)) {
637  switch (op->type) {
638  case BOW:
639  case WAND:
640  case ROD:
641  safe_strcat(buf, " (readied)", &len, size);
642  break;
643 
644  case WEAPON:
645  safe_strcat(buf, " (wielded)", &len, size);
646  break;
647 
648  case ARMOUR:
649  case HELMET:
650  case SHIELD:
651  case RING:
652  case BOOTS:
653  case GLOVES:
654  case AMULET:
655  case GIRDLE:
656  case BRACERS:
657  case CLOAK:
658  safe_strcat(buf, " (worn)", &len, size);
659  break;
660 
661  case CONTAINER:
662  safe_strcat(buf, " (active)", &len, size);
663  break;
664 
665  case SKILL:
666  default:
667  safe_strcat(buf, " (applied)", &len, size);
668  }
669  }
670  // NO_SKILL_IDENT is set when identification fails or when the book is read. So the book is read only when it is
671  // both identified and NO_SKILL_IDENT.
673  safe_strcat(buf, " (read)", &len, size);
674  if (QUERY_FLAG(op, FLAG_UNPAID))
675  safe_strcat(buf, " (unpaid)", &len, size);
676 }
677 
695 void query_base_name(const object *op, int plural, char *buf, size_t size) {
696  size_t len;
697 
698  if ((!plural && !op->name)
699  || (plural && !op->name_pl)) {
700  strncpy(buf, "(null)", size);
701  return;
702  }
703 
704  if (!op->nrof && !op->weight && !op->title && !is_magical(op)) {
705  strncpy(buf, op->name, size); /* To speed things up (or make things slower?) */
706  return;
707  }
708 
709  buf[0] = '\0';
710 
711  strlcpy(buf, plural ? op->name_pl : op->name, size);
712  len = strlen(buf);
713 
714  if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) {
715  safe_strcat(buf, " ", &len, size);
716  safe_strcat(buf, op->title, &len, size);
717  }
718 
719  switch (op->type) {
720  case SPELLBOOK:
721  case SCROLL:
722  case WAND:
723  case ROD:
724  case POTION:
726  if (!op->title && (op->inv)) {
727  safe_strcat(buf, " of ", &len, size);
728  // If, for some reason, a spell on a scroll were to stop existing as an arch,
729  // we would get here. The scroll will hold an inventory object with no name.
730  // So, to prevent a segfault, only print the spell name if it exists.
731  if (op->inv->name)
732  safe_strcat(buf, op->inv->name, &len, size);
733  // scroll of nothing seems like a good replacement for when the name does not exist.
734  else
735  safe_strcat(buf, "nothing", &len, size);
736  }
737  if (op->type != SPELLBOOK) {
738  snprintf(buf+len, size-len, " (lvl %d)", op->level);
739  len += strlen(buf+len);
740  }
741  }
742  break;
743 
744  case SKILL:
745  case AMULET:
746  case RING:
747  if (!op->title) {
748  /* If ring has a title, full description isn't so useful */
749  char* s;
750 
751  s = stringbuffer_finish(ring_desc(op, 0, NULL));
752  if (s[0]) {
753  safe_strcat(buf, " ", &len, size);
754  safe_strcat(buf, s, &len, size);
755  }
756  free(s);
757  }
758  break;
759 
760  default:
761  if (op->magic
762  && (QUERY_FLAG(op, FLAG_BEEN_APPLIED) || is_identified(op))) {
763  snprintf(buf+strlen(buf), size-strlen(buf), " %+d", op->magic);
764  }
765  }
766 }
767 
784 StringBuffer *describe_monster(const object *op, int use_media_tags, StringBuffer *buf) {
785  assert(op != NULL);
786  assert(QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER);
787 
788  if (buf == NULL)
789  buf = stringbuffer_new();
790 
791  /* Note that the resolution this provides for players really isn't
792  * very good. Any player with a speed greater than .67 will
793  * fall into the 'lightning fast movement' category.
794  */
795  if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
796  switch ((int)((FABS(op->speed))*15)) {
797  case 0:
798  stringbuffer_append_string(buf, "(very slow movement)");
799  break;
800 
801  case 1:
802  stringbuffer_append_string(buf, "(slow movement)");
803  break;
804 
805  case 2:
806  stringbuffer_append_string(buf, "(normal movement)");
807  break;
808 
809  case 3:
810  case 4:
811  stringbuffer_append_string(buf, "(fast movement)");
812  break;
813 
814  case 5:
815  case 6:
816  stringbuffer_append_string(buf, "(very fast movement)");
817  break;
818 
819  case 7:
820  case 8:
821  case 9:
822  case 10:
823  stringbuffer_append_string(buf, "(extremely fast movement)");
824  break;
825 
826  default:
827  stringbuffer_append_string(buf, "(lightning fast movement)");
828  break;
829  }
830  }
831  if (QUERY_FLAG(op, FLAG_UNDEAD))
832  stringbuffer_append_string(buf, "(undead)");
834  stringbuffer_append_string(buf, "(see invisible)");
835  if (QUERY_FLAG(op, FLAG_USE_WEAPON))
836  stringbuffer_append_string(buf, "(wield weapon)");
837  if (QUERY_FLAG(op, FLAG_USE_BOW))
838  stringbuffer_append_string(buf, "(archer)");
839  if (QUERY_FLAG(op, FLAG_USE_ARMOUR))
840  stringbuffer_append_string(buf, "(wear armour)");
841  if (QUERY_FLAG(op, FLAG_USE_RING))
842  stringbuffer_append_string(buf, "(wear ring)");
843  if (QUERY_FLAG(op, FLAG_USE_SCROLL))
844  stringbuffer_append_string(buf, "(read scroll)");
845  if (QUERY_FLAG(op, FLAG_USE_RANGE))
846  stringbuffer_append_string(buf, "(fires wand/rod/horn)");
848  stringbuffer_append_string(buf, "(skill user)");
849  if (QUERY_FLAG(op, FLAG_CAST_SPELL))
850  stringbuffer_append_string(buf, "(spellcaster)");
851  if (QUERY_FLAG(op, FLAG_FRIENDLY))
852  stringbuffer_append_string(buf, "(friendly)");
853  if (QUERY_FLAG(op, FLAG_UNAGGRESSIVE))
854  stringbuffer_append_string(buf, "(unaggressive)");
855  if (QUERY_FLAG(op, FLAG_HITBACK))
856  stringbuffer_append_string(buf, "(hitback)");
857  if (QUERY_FLAG(op, FLAG_STEALTH))
858  stringbuffer_append_string(buf, "(stealthy)");
859  if (op->randomitems != NULL) {
860  treasure *t;
861  int first = 1;
862 
863  for (t = op->randomitems->items; t != NULL; t = t->next)
864  if (t->item && (t->item->clone.type == SPELL)) {
865  if (first) {
866  first = 0;
867  stringbuffer_append_string(buf, "(Spell abilities:)");
868  }
869  stringbuffer_append_printf(buf, "(%s)", t->item->clone.name);
870  }
871  }
872  if (op->type == PLAYER) {
873  if (op->contr->digestion) {
874  if (op->contr->digestion != 0)
875  stringbuffer_append_printf(buf, "(sustenance%+d)", op->contr->digestion);
876  }
877  if (op->contr->gen_grace) {
878  stringbuffer_append_printf(buf, "(grace%+d)", op->contr->gen_grace);
879  }
880  if (op->contr->gen_sp) {
881  stringbuffer_append_printf(buf, "(magic%+d)", op->contr->gen_sp);
882  }
883  if (op->contr->gen_hp) {
884  stringbuffer_append_printf(buf, "(regeneration%+d)", op->contr->gen_hp);
885  }
886  if (op->stats.luck) {
887  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
888  }
889  }
890 
891  /* describe attacktypes */
892  if (is_dragon_pl(op)) {
893  /* for dragon players display the attacktypes from clawing skill
894  * Break apart the for loop - move the comparison checking down -
895  * this makes it more readable.
896  */
897  object *tmp;
898 
899  tmp = object_find_by_type_and_name(op, SKILL, "clawing");
900  if (tmp && tmp->attacktype != 0) {
901  describe_attacktype("Claws", tmp->attacktype, buf);
902  } else {
903  describe_attacktype("Attacks", op->attacktype, buf);
904  }
905  } else {
906  describe_attacktype("Attacks", op->attacktype, buf);
907  }
911  describe_resistance(op, 0, use_media_tags, buf);
912 
913  return buf;
914 }
915 
958 StringBuffer *describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf) {
959  int identified, i;
960 
961  if (buf == NULL)
962  buf = stringbuffer_new();
963 
964  if (QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER) {
965  return describe_monster(op, use_media_tags, buf);
966  }
967 
968  /* figure this out once, instead of making multiple calls to is_identified.
969  * also makes the code easier to read.
970  */
971  if (is_identified(op)) {
972  identified = 1;
973  } else {
974  stringbuffer_append_string(buf, "(unidentified)");
975  identified = 0;
976  }
977  switch (op->type) {
978  case BOW:
979  case ARROW:
980  case WAND:
981  case ROD:
982  case WEAPON:
983  case ARMOUR:
984  case HELMET:
985  case SHIELD:
986  case BOOTS:
987  case GLOVES:
988  case GIRDLE:
989  case BRACERS:
990  case CLOAK:
991  case SKILL_TOOL:
992  break; /* We have more information to do below this switch */
993 
994  case LAMP:
995  break; /* just so we get the "glowing" part. */
996 
997  case FOOD:
998  case FLESH:
999  case DRINK:
1000  if (identified || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
1001  stringbuffer_append_printf(buf, "(food+%d)", op->stats.food);
1002 
1003  if (op->type == FLESH && op->last_eat > 0 && atnr_is_dragon_enabled(op->last_eat)) {
1004  stringbuffer_append_printf(buf, "(%s metabolism)", change_resist_msg[op->last_eat]);
1005  }
1006 
1007  if (!QUERY_FLAG(op, FLAG_CURSED)) {
1008  if (op->stats.hp > 0)
1009  stringbuffer_append_string(buf, "(heals)");
1010  else if (op->stats.hp < 0)
1011  stringbuffer_append_string(buf, "(damages)");
1012 
1013  if (op->stats.sp > 0)
1014  stringbuffer_append_string(buf, "(spellpoint regen)");
1015  else if (op->stats.sp < 0)
1016  stringbuffer_append_string(buf, "(spellpoint depletion)");
1017  } else {
1018  if (op->stats.hp)
1019  stringbuffer_append_string(buf, "(damages)");
1020  if (op->stats.sp)
1021  stringbuffer_append_string(buf, "(spellpoint depletion)");
1022  }
1023  }
1024  break;
1025 
1026  case SKILL:
1027  case RING:
1028  case AMULET:
1029  if (op->item_power) {
1030  stringbuffer_append_printf(buf, "(item_power %+d)", op->item_power);
1031  }
1032  if (op->title) {
1033  ring_desc(op, use_media_tags, buf);
1034  }
1035  return buf;
1036 
1037  default:
1038  return buf;
1039  }
1040 
1041  /* Down here, we more further describe equipment type items.
1042  * only describe them if they have been identified or the like.
1043  */
1044  if (identified || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
1045  int attr, val;
1046 
1047  for (attr = 0; attr < NUM_STATS; attr++) {
1048  if ((val = get_attr_value(&(op->stats), attr)) != 0) {
1049  stringbuffer_append_printf(buf, "(%s%+d)", short_stat_name[attr], val);
1050  }
1051  }
1052  if (op->glow_radius)
1053  stringbuffer_append_string(buf, "(glowing)");
1054 
1055  switch (op->type) {
1056  case FLESH:
1057  break;
1058 
1059  default:
1060  if (op->stats.exp) {
1061  stringbuffer_append_printf(buf, "(speed %+" FMT64 ")", op->stats.exp);
1062  }
1063  break;
1064  }
1065  switch (op->type) {
1066  case BOW:
1067  case ARROW:
1068  case GIRDLE:
1069  case HELMET:
1070  case SHIELD:
1071  case BOOTS:
1072  case GLOVES:
1073  case WEAPON:
1074  case SKILL:
1075  case RING:
1076  case AMULET:
1077  case ARMOUR:
1078  case BRACERS:
1079  case FORCE:
1080  case CLOAK:
1081  if (op->stats.wc) {
1082  stringbuffer_append_printf(buf, "(wc%+d)", op->stats.wc);
1083  }
1084  if (op->stats.dam) {
1085  stringbuffer_append_printf(buf, "(dam%+d)", op->stats.dam);
1086  }
1087  if (op->stats.ac) {
1088  stringbuffer_append_printf(buf, "(ac%+d)", op->stats.ac);
1089  }
1090  if ((op->type == WEAPON || op->type == BOW) && op->level > 0) {
1091  stringbuffer_append_printf(buf, "(improved %d/%d)", op->last_eat, op->level);
1092  }
1093  break;
1094 
1095  default:
1096  break;
1097  }
1098  if (QUERY_FLAG(op, FLAG_XRAYS))
1099  stringbuffer_append_string(buf, "(xray-vision)");
1100  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK))
1101  stringbuffer_append_string(buf, "(infravision)");
1102 
1103  /* levitate was what is was before, so we'll keep it */
1104  if (op->move_type&MOVE_FLY_LOW)
1105  stringbuffer_append_string(buf, "(levitate)");
1106 
1107  if (op->move_type&MOVE_FLY_HIGH)
1108  stringbuffer_append_string(buf, "(fly)");
1109 
1110  if (op->move_type&MOVE_SWIM)
1111  stringbuffer_append_string(buf, "(swim)");
1112 
1113  /* walking is presumed as 'normal', so doesn't need mentioning */
1114 
1115  if (op->item_power) {
1116  stringbuffer_append_printf(buf, "(item_power %+d)", op->item_power);
1117  }
1118  } /* End if identified or applied */
1119 
1120  /* This blocks only deals with fully identified object.
1121  * it is intentional that this is not an 'else' from a above -
1122  * in this way, information is added.
1123  */
1124  if (identified) {
1125  int more_info = 0;
1126 
1127  switch (op->type) {
1128  case ROD: /* These use stats.sp for spell selection and stats.food */
1129  /* and stats.hp for spell-point regeneration... */
1130  case ARROW:
1131  case WAND:
1132  case FOOD:
1133  case FLESH:
1134  case DRINK:
1135  more_info = 0;
1136  break;
1137 
1138  /* Bows use sp for firing rate. Per fire_bow(), the bow can be fired every 100/firing rate
1139  * character movements. It also makes sure it calculates the speed at no less than 1, to avoid floating point errors
1140  */
1141  case BOW:
1142  if (op->stats.sp) {
1143  stringbuffer_append_printf(buf, "(Firing delay %.2f)", 100./op->stats.sp);
1144  }
1145  more_info = 0;
1146  break;
1147 
1148  /* Armor type objects */
1149  case ARMOUR:
1150  case HELMET:
1151  case SHIELD:
1152  case BOOTS:
1153  case GLOVES:
1154  case GIRDLE:
1155  case BRACERS:
1156  case CLOAK:
1157  if (ARMOUR_SPEED(op)) {
1158  stringbuffer_append_printf(buf, "(Max speed %1.2f)", ARMOUR_SPEED(op)/10.0);
1159  }
1160  if (ARMOUR_SPELLS(op)) {
1161  stringbuffer_append_printf(buf, "(Spell regen penalty %d)", ARMOUR_SPELLS(op));
1162  }
1163  more_info = 1;
1164  break;
1165 
1166  case WEAPON:
1167  /* Calculate it the same way fix_object does so the results
1168  * make sense.
1169  */
1170  i = (WEAPON_SPEED(op)*2-op->magic)/2;
1171  if (i < 0)
1172  i = 0;
1173 
1174  stringbuffer_append_printf(buf, "(weapon speed %d)", i);
1175  /* If the reflecting flag is set, the weapon will bounce off walls when thrown. */
1176  if (QUERY_FLAG(op, FLAG_REFLECTING)) {
1177  stringbuffer_append_string(buf, "(ricochet)");
1178  }
1179  more_info = 1;
1180  break;
1181  }
1182  if (more_info) {
1183  if (op->stats.food) {
1184  if (op->stats.food != 0)
1185  stringbuffer_append_printf(buf, "(sustenance%+d)", op->stats.food);
1186  }
1187  if (op->stats.grace) {
1188  stringbuffer_append_printf(buf, "(grace%+d)", op->stats.grace);
1189  }
1190  if (op->stats.sp) {
1191  stringbuffer_append_printf(buf, "(magic%+d)", op->stats.sp);
1192  }
1193  if (op->stats.hp) {
1194  stringbuffer_append_printf(buf, "(regeneration%+d)", op->stats.hp);
1195  }
1196  }
1197 
1198  if (op->stats.luck) {
1199  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
1200  }
1201  if (QUERY_FLAG(op, FLAG_LIFESAVE))
1202  stringbuffer_append_string(buf, "(lifesaving)");
1203  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
1204  stringbuffer_append_string(buf, "(reflect spells)");
1205  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
1206  stringbuffer_append_string(buf, "(reflect missiles)");
1207  if (QUERY_FLAG(op, FLAG_STEALTH))
1208  stringbuffer_append_string(buf, "(stealth)");
1209  if (op->slaying != NULL && op->type != FOOD) {
1210  stringbuffer_append_printf(buf, "(slay %s)", op->slaying);
1211  }
1212  describe_attacktype("Attacks", op->attacktype, buf);
1213  /* resistance on flesh is only visible for dragons. If
1214  * non flesh, everyone can see its resistances
1215  */
1216  if (op->type != FLESH || (owner && is_dragon_pl(owner))) {
1217  describe_resistance(op, 0, 1, buf);
1218  }
1222  }
1223 
1224  return buf;
1225 }
1226 
1239 int is_magical(const object *op) {
1240  int i;
1241 
1242  /* living creatures are considered non magical */
1243  if (QUERY_FLAG(op, FLAG_ALIVE))
1244  return 0;
1245 
1246  /* This is a test for it being an artifact, as artifacts have titles */
1247  if (op->title != NULL)
1248  return 1;
1249 
1250  /* Handle rings and amulets specially. If they change any of these
1251  * values, it means they are magical.
1252  */
1253  if ((op->type == AMULET || op->type == RING)
1254  && (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))
1255  return 1;
1256 
1257  /* Check for stealty, speed, flying, or just plain magic in the boots */
1258  /* Presume any boots that have a move_type are special. */
1259  if (op->type == BOOTS
1260  && ((QUERY_FLAG(op, FLAG_STEALTH) || op->move_type || op->stats.exp)))
1261  return 1;
1262 
1263  /* Take care of amulet/shield that reflects spells/missiles */
1264  if ((op->type == AMULET || op->type == SHIELD)
1266  return 1;
1267 
1268  /* Take care of helmet of xrays */
1269  if (op->type == HELMET
1270  && QUERY_FLAG(op, FLAG_XRAYS))
1271  return 1;
1272 
1273  /* Potions & rods are always magical. Wands/staves are also magical,
1274  * assuming they still have any charges left.
1275  */
1276  if (op->type == POTION || op->type == ROD || (op->type == WAND && op->stats.food))
1277  return 1;
1278 
1279  /* if something gives a protection, either positive or negative, its magical */
1280  /* This is really a pretty bad hack - as of now, ATNR_PHYSICAL is 0,
1281  * so this always works out fine.
1282  */
1283  for (i = ATNR_PHYSICAL+1; i < NROFATTACKS; i++)
1284  if (op->resist[i])
1285  return 1;
1286 
1287  /* Physical protection is expected on some item types, so they should
1288  * not be considered magical.
1289  */
1290  if (op->resist[ATNR_PHYSICAL]
1291  && op->type != HELMET
1292  && op->type != SHIELD
1293  && op->type != BOOTS
1294  && op->type != GLOVES
1295  && op->type != ARMOUR)
1296  return 1;
1297 
1298  /* power crystal, spellbooks, and scrolls are always magical. */
1299  if (op->magic
1300  || op->type == POWER_CRYSTAL
1301  || op->type == SPELLBOOK
1302  || op->type == SCROLL
1303  || op->type == GIRDLE)
1304  return 1;
1305 
1306  /* Check to see if it increases/decreases any stats */
1307  for (i = 0; i < NUM_STATS; i++)
1308  if (get_attr_value(&(op->stats), i) != 0)
1309  return 1;
1310 
1311  /* If it doesn't fall into any of the above categories, must
1312  * be non magical.
1313  */
1314  return 0;
1315 }
1316 
1336 int is_identifiable_type(const object *op) {
1337  /* Special case -- skill tools don't have an associated identification
1338  * skill but still need IDing. TODO: we should probably have per-tool ID
1339  * skills, e.g. thievery for lockpicks and thaumaturgy for talismans, but
1340  * currently there's no good way to do this because the identifyskill is
1341  * tied to the itemtype rather than to the arch. */
1342  if (op->type == SKILL_TOOL) return true;
1343 
1344  /* Sometimes an itemtype has no associated typedata?! */
1345  const typedata *td = get_typedata(op->type);
1346  return td && td->identifyskill;
1347 }
1348 
1360 int is_identified(const object *op) {
1361  return !is_identifiable_type(op) || QUERY_FLAG(op, FLAG_IDENTIFIED);
1362 }
1363 
1369  // Make sure identified objects stack correctly
1373 
1374  // The rest only apply to identifiable items. We don't want, e.g. shop
1375  // floors to show up as 'damned'.
1376  if (!is_identifiable_type(op))
1377  return;
1378 
1379  if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))
1381 
1382  if (QUERY_FLAG(op, FLAG_BLESSED))
1384 
1385  sstring key;
1386 
1387  key = object_get_value(op, "identified_face");
1388  if (key != NULL) {
1389  op->face = try_find_face(key, op->face);
1390  /* if the face is defined, clean the animation, because else
1391  * the face can be lost ; if an animation is defined, it'll be
1392  * processed later on */
1395  op->anim_speed = 0;
1396  op->animation = 0;
1397  object_set_value(op, "identified_face", NULL, 0);
1398  }
1399 
1400  if (object_get_value(op, "identified_anim_random") != NULL) {
1402  object_set_value(op, "identified_anim_random", NULL, 0);
1403  }
1404 
1405  key = object_get_value(op, "identified_anim_speed");
1406  if (key != NULL) {
1407  op->anim_speed = atoi(key);
1408  op->last_anim = 1;
1409  object_set_value(op, "identified_anim_speed", NULL, 0);
1410  }
1411 
1412  key = object_get_value(op, "identified_animation");
1413  if (key != NULL) {
1414  Animations *anim = try_find_animation(key);
1415  if (anim) {
1416  op->animation = anim;
1417  if (!QUERY_FLAG(op, FLAG_IS_TURNABLE))
1418  SET_FLAG(op, FLAG_ANIMATE);
1419  animate_object(op, op->facing);
1420  }
1421  object_set_value(op, "identified_animation", NULL, 0);
1422  }
1423 
1424  key = object_get_value(op, "identified_name");
1425  if (key != NULL) {
1426  FREE_AND_COPY(op->name, key);
1427  object_set_value(op, "identified_name", NULL, 0);
1428  }
1429  key = object_get_value(op, "identified_name_pl");
1430  if (key != NULL) {
1431  FREE_AND_COPY(op->name_pl, key);
1432  object_set_value(op, "identified_name_pl", NULL, 0);
1433  }
1434 }
1435 
1449 object *identify(object *op) {
1450  object *pl, *op1;
1451 
1454 
1455  if (op->type == POTION) {
1456  if (op->inv && op->randomitems) {
1457  if (op->title)
1458  free_string(op->title);
1459  op->title = add_refcount(op->inv->name);
1460  } else if (op->arch) {
1461  free_string(op->name);
1462  op->name = add_refcount(op->arch->clone.name);
1463  free_string(op->name_pl);
1464  op->name_pl = add_refcount(op->arch->clone.name_pl);
1465  }
1466  }
1467 
1468  if (op->map) {
1469  /* If the object is on a map, make sure we update its face.
1470  * Also send name and such information to a player standing on it.
1471  */
1472  object *player = map_find_by_type(op->map, op->x, op->y, PLAYER);
1473 
1475  op1 = object_merge(op, GET_MAP_TOP(op->map, op->x, op->y));
1476  if (op1) op = op1;
1477 
1478  if (player)
1480 
1481  } else if (op->env) {
1482  /* If the object is in an inventory, merge it.
1483  */
1484  pl = object_get_player_container(op->env);
1485  op1 = object_merge(op, op->env->inv);
1486  if (op1) op = op1;
1487 
1488  if (pl)
1489  /* Item is directly in the player's inventory
1490  * A lot of the values can change from an update - might as well send
1491  * it all.
1492  */
1493  esrv_update_item(UPD_ALL, pl, op);
1494  else if (op->env->map &&
1495  (pl = map_find_by_type(op->env->map, op->env->x, op->env->y, PLAYER))
1496  && (pl->container == op->env)) {
1497  /* The item is in a container (on the ground) opened by a player, update */
1499  }
1500  }
1501  /* There is a third option where we do nothing extra:
1502  * identifying a created item as it is created. */
1503  return op;
1504 }
1505 
1510 uint64_t price_base(const object *obj) {
1511  // When there are zero objects, there is really one.
1512  const int number = NROF(obj);
1513  const bool identified = is_identified(obj);
1514  uint64_t val = (uint64_t)obj->value * number;
1515 
1516  // Objects with price adjustments skip the rest of the calculations.
1517  const char *key = object_get_value(obj, "price_adjustment");
1518  if (key != NULL) {
1519  float ratio = atof(key);
1520  return val * ratio;
1521  }
1522 
1523  // Money and gems have fixed prices at shops.
1524  if (obj->type == MONEY || obj->type == GEM) {
1525  return val;
1526  }
1527 
1528  // Assume that good items, e.g. artifacts have that priced into their
1529  // value. Bad items may not.
1530  if (calc_item_enhancement(obj) < 0) {
1531  return 0;
1532  }
1533 
1534  // If unidentified, price item based on its archetype.
1535  if (!identified && obj->arch) {
1536  val = obj->arch->clone.value * number;
1537  }
1538 
1544  if (QUERY_FLAG(obj, FLAG_BLESSED)){
1545  val *= 1.15;
1546  } else if (QUERY_FLAG(obj, FLAG_CURSED)) {
1547  val *= 0.8;
1548  } else if (QUERY_FLAG(obj, FLAG_DAMNED)) {
1549  val *= 0.6;
1550  }
1551 
1552  // If an item is identified to have an enchantment above its archetype
1553  // enchantment, increase price exponentially.
1554  if (obj->arch != NULL && identified) {
1555  int diff = obj->magic - obj->arch->clone.magic;
1556  val *= pow(1.15, diff);
1557  }
1558 
1559  // FIXME: Is the 'baseline' 50 charges per wand?
1560  if (obj->type == WAND) {
1561  val *= obj->stats.food / 50.0;
1562  }
1563 
1564  /* we need to multiply these by 4.0 to keep buy costs roughly the same
1565  * (otherwise, you could buy a potion of charisma for around 400 pp.
1566  * Arguable, the costs in the archetypes should be updated to better
1567  * reflect values (potion charisma list for 1250 gold)
1568  */
1569  val *= 4; // FIXME
1570 
1571  return val;
1572 }
player::gen_sp
int16_t gen_sp
Bonuses to regeneration speed of sp.
Definition: player.h:127
CLASS
@ CLASS
Object for applying character class modifications to someone.
Definition: object.h:143
object::name_pl
sstring name_pl
The plural name of the object.
Definition: object.h:323
FLAG_USE_BOW
#define FLAG_USE_BOW
(Monster) can apply and fire bows
Definition: define.h:293
living::exp
int64_t exp
Experience.
Definition: living.h:47
UP_OBJ_FACE
#define UP_OBJ_FACE
Only thing that changed was the 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:321
CF_HANDLE
@ CF_HANDLE
Definition: object.h:213
stringbuffer_length
size_t stringbuffer_length(StringBuffer *sb)
Return the current length of the buffer.
Definition: stringbuffer.cpp:218
MAP
@ MAP
Definition: object.h:130
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:15
MONSTER
@ MONSTER
A real, living creature.
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)
Gets the top object on a map.
Definition: map.h:172
CLOSE_CON
@ CLOSE_CON
Eneq((at)csd.uu.se): Id for close_container archetype.
Definition: object.h:234
FABS
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
FLAG_CLIENT_ANIM_RANDOM
#define FLAG_CLIENT_ANIM_RANDOM
Client animate this, randomized.
Definition: define.h:241
ARMOUR_IMPROVER
@ ARMOUR_IMPROVER
Definition: object.h:237
SYMPTOM
@ SYMPTOM
Definition: object.h:250
object::path_attuned
uint32_t path_attuned
Paths the object is attuned to.
Definition: object.h:353
WAND
@ WAND
Definition: object.h:225
FLAG_USE_RING
#define FLAG_USE_RING
(Monster) can use rings, boots, gauntlets, etc
Definition: define.h:297
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
FLAG_UNDEAD
#define FLAG_UNDEAD
Monster is undead.
Definition: define.h:270
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
FLESH
@ FLESH
animal 'body parts' -b.t.
Definition: object.h:192
player::digestion
int16_t digestion
Any bonuses/penalties to digestion.
Definition: player.h:125
ENCOUNTER
@ ENCOUNTER
Definition: object.h:187
SK_ALCHEMY
@ SK_ALCHEMY
Alchemy.
Definition: skills.h:25
player
One player.
Definition: player.h:105
GLOVES
@ GLOVES
Definition: object.h:218
object::inv
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
GIRDLE
@ GIRDLE
Definition: object.h:228
player::gen_grace
int16_t gen_grace
Bonuses to regeneration speed of grace.
Definition: player.h:129
safe_strcat
void safe_strcat(char *dest, const char *orig, size_t *curlen, size_t maxlen)
Simple function we use below to keep adding to the same string but also make sure we don't overwrite ...
Definition: porting.cpp:202
BUTTON
@ BUTTON
Definition: object.h:212
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
FLAG_REFL_MISSILE
#define FLAG_REFL_MISSILE
Arrows will reflect from object.
Definition: define.h:273
treasurelist::items
treasure * items
Items in this list, linked.
Definition: treasure.h:92
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
KEY
@ KEY
Definition: object.h:132
FLAG_IS_TURNABLE
#define FLAG_IS_TURNABLE
Object can change face with direction.
Definition: define.h:256
object_merge
object * object_merge(object *op, object *top)
This function goes through all objects below and including top, and merges op to the first matching o...
Definition: object.cpp:2036
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.cpp:138
FLAG_SEE_IN_DARK
#define FLAG_SEE_IN_DARK
if set ob not effected by darkness
Definition: define.h:337
object::item_power
int8_t item_power
Power rating of the object.
Definition: object.h:372
object::arch
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.cpp:57
bits_set
static int bits_set(uint32_t x)
Definition: item.cpp:221
SHOP_FLOOR
@ SHOP_FLOOR
Definition: object.h:188
object::speed
float speed
Frequency of object 'moves' relative to server tick rate.
Definition: object.h:337
if
if(!(yy_init))
Definition: loader.cpp:36435
GEM
@ GEM
Definition: object.h:172
TRAP
@ TRAP
Definition: object.h:246
object::x
int16_t x
Definition: object.h:335
ARMOUR
@ ARMOUR
Definition: object.h:125
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
WEAPON
@ WEAPON
Definition: object.h:124
TIMED_GATE
@ TIMED_GATE
Definition: object.h:133
typedata::identifyskill
int identifyskill
Skill used to identify this object class.
Definition: define.h:93
FLAG_SEE_INVISIBLE
#define FLAG_SEE_INVISIBLE
Will see invisible player.
Definition: define.h:253
AMULET
@ AMULET
Definition: object.h:144
CHECK_INV
@ CHECK_INV
b.t.
Definition: object.h:174
TREASURE
@ TREASURE
Definition: object.h:115
SKILL
@ SKILL
Also see SKILL_TOOL (74) below.
Definition: object.h:148
get_power_from_ench
int get_power_from_ench(int ench)
Definition: item.cpp:213
ARMOUR_SPELLS
#define ARMOUR_SPELLS(xyz)
Definition: define.h:461
RUNE
@ RUNE
Definition: object.h:245
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: item.cpp:414
CREATOR
@ CREATOR
Definition: object.h:147
FLAG_BLESSED
#define FLAG_BLESSED
Item has a blessing, opposite of cursed/damned.
Definition: define.h:369
TRANSPORT
@ TRANSPORT
see doc/Developers/objects
Definition: object.h:113
ATNR_PHYSICAL
#define ATNR_PHYSICAL
Definition: attack.h:49
POTION_RESIST_EFFECT
@ POTION_RESIST_EFFECT
A force, holding the effect of a resistance potion.
Definition: object.h:230
FLOOR
@ FLOOR
Floor tile -> native layer 0.
Definition: object.h:191
ARMOUR_SPEED
#define ARMOUR_SPEED(xyz)
Definition: define.h:460
SIGN
@ SIGN
Definition: object.h:216
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:137
object::title
sstring title
Of foo, etc.
Definition: object.h:325
FLAG_INV_LOCKED
#define FLAG_INV_LOCKED
Item will not be dropped from inventory.
Definition: define.h:329
FLAG_APPLIED
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
object::level
int16_t level
Level of creature or object.
Definition: object.h:361
FLAG_STEALTH
#define FLAG_STEALTH
Will wake monsters with less range.
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
object::resist
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:351
item_types
static const typedata item_types[]
The following is a large table of item types, the fields are: item number, item name,...
Definition: item.cpp:80
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
FLAG_ALIVE
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
object::path_denied
uint32_t path_denied
Paths the object is denied access to.
Definition: object.h:355
short_stat_name
const char *const short_stat_name[NUM_STATS]
Short name of stats.
Definition: living.cpp:194
object::carrying
int32_t carrying
How much weight this object contains.
Definition: object.h:377
TRIGGER_MARKER
@ TRIGGER_MARKER
inserts an invisible, weightless force into a player with a specified string WHEN TRIGGERED.
Definition: object.h:158
typedata
Link an object type with skill needed to identify, and general name.
Definition: define.h:89
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
object::path_repelled
uint32_t path_repelled
Paths the object is repelled from.
Definition: object.h:354
CLOAK
@ CLOAK
Definition: object.h:209
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
object_update
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.cpp:1419
object::contr
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
FMT64
#define FMT64
Definition: compat.h:16
NROF
static uint32_t NROF(const object *const ob)
Returns ob->nrof, unless it is 0, in which case return 1.
Definition: object.h:625
HELMET
@ HELMET
Definition: object.h:141
POISON
@ POISON
Definition: object.h:118
add_refcount
sstring add_refcount(sstring str)
This will increase the refcount of the string 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)
Generates the visible naming for resistances.
Definition: item.cpp:377
object::anim_speed
uint8_t anim_speed
Ticks between animation-frames.
Definition: object.h:429
SK_JEWELER
@ SK_JEWELER
Jeweler.
Definition: skills.h:24
MARKER
@ MARKER
inserts an invisible, weightless force into a player with a specified string.
Definition: object.h:163
get_typedata
const typedata * get_typedata(int itemtype)
Definition: item.cpp:328
query_name
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:594
SAVEBED
@ SAVEBED
Definition: object.h:224
FLAG_USE_RANGE
#define FLAG_USE_RANGE
(Monster) can apply and use range items
Definition: define.h:292
FLAG_KNOWN_BLESSED
#define FLAG_KNOWN_BLESSED
Item is known to be blessed.
Definition: define.h:370
map_find_by_type
object * map_find_by_type(mapstruct *m, int x, int y, uint8_t type)
Searches for any objects with a matching type variable at the given map and coordinates.
Definition: object.cpp:3130
LIGHTABLE
@ LIGHTABLE
Definition: object.h:255
POTION
@ POTION
Definition: object.h:116
FLAG_KNOWN_CURSED
#define FLAG_KNOWN_CURSED
The object is known to be cursed.
Definition: define.h:320
BUILDER
@ BUILDER
Generic item builder, see subtypes below.
Definition: object.h:251
SK_LITERACY
@ SK_LITERACY
Literacy.
Definition: skills.h:27
archetype::clone
object clone
An object from which to do object_copy()
Definition: object.h:487
describe_spellpath_attenuation
StringBuffer * describe_spellpath_attenuation(const char *attenuation, int value, StringBuffer *buf)
Describe the specified path attenuation.
Definition: utils.cpp:507
price_base
uint64_t price_base(const object *obj)
Price an item based on its value or archetype value, type, identification/BUC status,...
Definition: item.cpp:1510
SK_BOWYER
@ SK_BOWYER
Bowyer.
Definition: skills.h:23
ROD
@ ROD
Definition: object.h:114
CONTAINER
@ CONTAINER
Definition: object.h:236
INORGANIC
@ INORGANIC
metals, minerals, dragon scales
Definition: object.h:193
object::move_type
MoveType move_type
Type of movement this object uses.
Definition: object.h:436
object_find_by_type_and_name
object * object_find_by_type_and_name(const object *who, int type, const char *name)
Find object in inventory by type and name.
Definition: object.cpp:4093
query_short_name
void query_short_name(const object *op, char *buf, size_t size)
query_short_name(object) is similar to query_name(), but doesn't contain any information about object...
Definition: item.cpp:518
LOCKED_DOOR
@ LOCKED_DOOR
Definition: object.h:128
ring_desc
static StringBuffer * ring_desc(const object *op, int use_media_tags, StringBuffer *buf)
Describes a ring or amulet, or a skill.
Definition: item.cpp:443
PLAYERMOVER
@ PLAYERMOVER
Definition: object.h:145
object::face
const Face * face
Face with colors.
Definition: object.h:341
describe_attacktype
StringBuffer * describe_attacktype(const char *attack, int value, StringBuffer *buf)
Describe the specified attack type.
Definition: utils.cpp:538
FLAG_MAKE_INVIS
#define FLAG_MAKE_INVIS
(Item) gives invisibility when applied
Definition: define.h:328
change_resist_msg
const char *const change_resist_msg[NROFATTACKS]
These are the descriptions of the resistances displayed when a player puts on/takes off an item.
Definition: init.cpp:70
object::last_eat
int32_t last_eat
How long since we last ate.
Definition: object.h:366
object::value
int32_t value
How much money it is worth (or contains)
Definition: object.h:360
is_identified
int is_identified(const object *op)
Return true if the item is identified, either because it is of a type that doesn't ever need identifi...
Definition: item.cpp:1360
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:129
HOLE
@ HOLE
Definition: object.h:214
object::last_anim
uint8_t last_anim
Last sequence used to draw face.
Definition: object.h:430
PEACEMAKER
@ PEACEMAKER
Object owned by a player which can convert a monster into a peaceful being incapable of attack.
Definition: object.h:169
FREE_AND_COPY
#define FREE_AND_COPY(sv, nv)
Release the shared string if not NULL, and make it a reference to nv.
Definition: global.h:206
CONVERTER
@ CONVERTER
Definition: object.h:221
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
SKILLSCROLL
@ SKILLSCROLL
can add a skill to player's inventory -bt.
Definition: object.h:239
FLAG_DAMNED
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:317
living::dam
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
t
in that case they will be relative to whatever the PWD of the crossfire server process is You probably shouldn t
Definition: server-directories.txt:28
object::magic
int8_t magic
Any magical bonuses to this item.
Definition: object.h:358
UPD_FLAGS
#define UPD_FLAGS
Definition: newclient.h:319
LAMP
@ LAMP
Lamp.
Definition: object.h:206
calc_item_enhancement
int calc_item_enhancement(const object *op)
Definition: item.cpp:226
living::food
int32_t food
How much food in stomach.
Definition: living.h:48
GOLEM
@ GOLEM
Definition: object.h:150
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Monster doesn't attack players.
Definition: define.h:272
body_locations
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
The ordering of this is actually doesn't make a difference However, for ease of use,...
Definition: item.cpp:56
MOOD_FLOOR
@ MOOD_FLOOR
b.t.
Definition: object.h:175
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:296
ARROW
@ ARROW
Definition: object.h:122
living::sp
int16_t sp
Spell points.
Definition: living.h:42
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
Definition: stringbuffer.cpp:95
FLAG_CAN_USE_SKILL
#define FLAG_CAN_USE_SKILL
The monster can use skills.
Definition: define.h:321
BOOK
@ BOOK
Definition: object.h:119
object::facing
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
object::animation
const Animations * animation
Animation of this item, NULL if not animated.
Definition: object.h:428
RING
@ RING
Definition: object.h:190
BLINDNESS
@ BLINDNESS
Definition: object.h:152
FLAG_MONSTER
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
get_typedata_by_name
const typedata * get_typedata_by_name(const char *name)
Definition: item.cpp:348
CLOCK
@ CLOCK
Definition: object.h:120
FLAG_HITBACK
#define FLAG_HITBACK
Object will hit back when hit.
Definition: define.h:267
resist_plus
const char *const resist_plus[NROFATTACKS]
Attack types to show to the player.
Definition: init.cpp:49
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Portable implementation of strlcpy(3).
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)
Describes an item, in all its details.
Definition: item.cpp:958
object::weight
int32_t weight
Attributes of the object.
Definition: object.h:375
free_string
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:280
item_types_size
static const int item_types_size
Number of items in item_types array.
Definition: item.cpp:195
living::wc
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
try_find_animation
Animations * try_find_animation(const char *name)
Definition: assets.cpp:278
StringBuffer
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.cpp:25
MOVE_FLY_LOW
#define MOVE_FLY_LOW
Low flying object.
Definition: define.h:393
FLAG_CLIENT_ANIM_SYNC
#define FLAG_CLIENT_ANIM_SYNC
Let client animate this, synchronized.
Definition: define.h:240
EXIT
@ EXIT
Definition: object.h:186
FLAG_KNOWN_MAGICAL
#define FLAG_KNOWN_MAGICAL
The object is known to be magical.
Definition: define.h:319
MAGIC_EAR
@ MAGIC_EAR
Definition: object.h:136
player::gen_hp
int16_t gen_hp
Bonuses to regeneration speed of hp.
Definition: player.h:126
FLAG_REFL_SPELL
#define FLAG_REFL_SPELL
Spells (some) will reflect from object.
Definition: define.h:275
llevInfo
@ llevInfo
Information.
Definition: logger.h:12
SK_WOODSMAN
@ SK_WOODSMAN
Woodsman.
Definition: skills.h:40
object::slaying
sstring slaying
Which race to do double damage to.
Definition: object.h:327
object::glow_radius
int8_t glow_radius
indicates the glow radius of the object
Definition: object.h:374
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
spells.h
query_weight
void query_weight(const object *op, char *buf, size_t size)
Formats the item's weight.
Definition: item.cpp:420
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
BATTLEGROUND
@ BATTLEGROUND
battleground, by Andreas Vogl
Definition: object.h:168
WEAPON_SPEED
#define WEAPON_SPEED(xyz)
Definition: define.h:462
is_dragon_pl
int is_dragon_pl(const object *op)
Checks if player is a dragon.
Definition: player.cpp:122
GRIMREAPER
@ GRIMREAPER
Definition: object.h:135
FLAG_USE_ARMOUR
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:295
FLAG_CAST_SPELL
#define FLAG_CAST_SPELL
(Monster) can learn and cast spells
Definition: define.h:290
EARTHWALL
@ EARTHWALL
Definition: object.h:149
DUPLICATOR
@ DUPLICATOR
Duplicator/multiplier object.
Definition: object.h:207
is_magical
int is_magical(const object *op)
Checks whether object is magical.
Definition: item.cpp:1239
DISEASE
@ DISEASE
Definition: object.h:249
FIREWALL
@ FIREWALL
Definition: object.h:173
is_identifiable_type
int is_identifiable_type(const object *op)
Return true if this item's type is one that cares about whether or not it's been identified – e....
Definition: item.cpp:1336
TRIGGER_ALTAR
@ TRIGGER_ALTAR
Definition: object.h:138
PLAYER_CHANGER
@ PLAYER_CHANGER
Definition: object.h:167
object::env
object * env
Pointer to the object which is the environment.
Definition: object.h:301
sstring
const typedef char * sstring
Definition: sstring.h:2
LIGHTER
@ LIGHTER
Definition: object.h:195
Animations
This represents one animation.
Definition: face.h:25
animate_object
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.cpp:44
MATERIAL
@ MATERIAL
Material for building.
Definition: object.h:253
FLAG_REFLECTING
#define FLAG_REFLECTING
Object reflects from walls (lightning)
Definition: define.h:262
SPINNER
@ SPINNER
Definition: object.h:210
SPELL_EFFECT
@ SPELL_EFFECT
Definition: object.h:220
SKILL_TOOL
@ SKILL_TOOL
Allows the use of a skill.
Definition: object.h:194
object_get_value
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.cpp:4331
SHOP_INVENTORY
@ SHOP_INVENTORY
Mark Wedel (mark@pyramid.com) Shop inventories.
Definition: object.h:243
PEDESTAL
@ PEDESTAL
Definition: object.h:126
FLAG_BEEN_APPLIED
#define FLAG_BEEN_APPLIED
Object was ever applied, for identification purposes.
Definition: define.h:323
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
living::ac
int8_t ac
Armor Class, lower AC increases probability of not getting hit.
Definition: living.h:38
atnr_is_dragon_enabled
int atnr_is_dragon_enabled(int attacknr)
Determine if the attacktype represented by the specified attack-number is enabled for dragon players.
Definition: player.cpp:103
enc_to_item_power
static const int enc_to_item_power[]
This curve may be too steep.
Definition: item.cpp:206
resist_color
const char *const resist_color[NROFATTACKS]
Colors to add to the resistances for media tags.
Definition: init.cpp:61
object_give_identified_properties
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
Definition: item.cpp:1368
DEAD_OBJECT
@ DEAD_OBJECT
Definition: object.h:161
DIRECTOR
@ DIRECTOR
Definition: object.h:227
CORPSE
@ CORPSE
Definition: object.h:248
MIN_ACTIVE_SPEED
#define MIN_ACTIVE_SPEED
Cut off point of when an object is put on the active list or not.
Definition: define.h:633
FLAG_ANIMATE
#define FLAG_ANIMATE
The object looks at archetype for faces.
Definition: define.h:242
UPD_NAME
#define UPD_NAME
Definition: newclient.h:322
object::randomitems
struct treasurelist * randomitems
Items to be generated.
Definition: object.h:395
SK_SMITHERY
@ SK_SMITHERY
Smithery.
Definition: skills.h:22
FOOD
@ FOOD
Definition: object.h:117
object::container
object * container
Current container being used.
Definition: object.h:299
MOVE_FLY_HIGH
#define MOVE_FLY_HIGH
High flying object.
Definition: define.h:394
ALTAR
@ ALTAR
Definition: object.h:127
DOOR
@ DOOR
Definition: object.h:131
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
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
Thaumaturgy.
Definition: skills.h:48
DRINK
@ DRINK
Definition: object.h:162
UPD_ALL
#define UPD_ALL
Definition: newclient.h:326
WALL
@ WALL
Wall.
Definition: object.h:196
WEAPON_IMPROVER
@ WEAPON_IMPROVER
Definition: object.h:238
SCROLL
@ SCROLL
Definition: object.h:226
object::nrof
uint32_t nrof
Number of objects.
Definition: object.h:342
FLAG_XRAYS
#define FLAG_XRAYS
X-ray vision.
Definition: define.h:300
describe_monster
StringBuffer * describe_monster(const object *op, int use_media_tags, StringBuffer *buf)
Describes a monster.
Definition: item.cpp:784
body_locations_struct
One body location.
Definition: object.h:22
living::grace
int16_t grace
Grace.
Definition: living.h:44
query_base_name
void query_base_name(const object *op, int plural, char *buf, size_t size)
Query a short name for the item.
Definition: item.cpp:695
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
treasure
treasure is one element in a linked list, which together consist of a complete treasure-list.
Definition: treasure.h:63
MOVE_SWIM
#define MOVE_SWIM
Swimming object.
Definition: define.h:396
object_set_value
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
Definition: object.cpp:4484
get_attr_value
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.cpp:313
calc_item_power
int calc_item_power(const object *op)
This takes an object 'op' and figures out what its item_power rating should be.
Definition: item.cpp:318
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
object::attacktype
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:352
FLAG_NO_SKILL_IDENT
#define FLAG_NO_SKILL_IDENT
If set, item cannot be identified w/ a skill.
Definition: define.h:335
FLAG_USE_SCROLL
#define FLAG_USE_SCROLL
(Monster) can read scroll
Definition: define.h:291
FLAG_CURSED
#define FLAG_CURSED
The object is cursed.
Definition: define.h:316
TELEPORTER
@ TELEPORTER
Definition: object.h:146
object_get_player_container
object * object_get_player_container(object *op)
Finds the player carrying an object.
Definition: object.cpp:592
living.h
THROWN_OBJ
@ THROWN_OBJ
Definition: object.h:151
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
NUM_STATS
@ NUM_STATS
Number of statistics.
Definition: living.h:18
living::hp
int16_t hp
Hit Points.
Definition: living.h:40
living::luck
int8_t luck
Affects thaco and ac from time to time.
Definition: living.h:39
FORCE
@ FORCE
Definition: object.h:229
HOLY_ALTAR
@ HOLY_ALTAR
Definition: object.h:166
TRAPDOOR
@ TRAPDOOR
Definition: object.h:215
DETECTOR
@ DETECTOR
peterm: detector is an object which notices the presense of another object and is triggered like butt...
Definition: object.h:154
GOD
@ GOD
Definition: object.h:153
FLAG_LIFESAVE
#define FLAG_LIFESAVE
Saves a players' life once, then destr.
Definition: define.h:305
MISC_OBJECT
@ MISC_OBJECT
misc.
Definition: object.h:198
MONEY
@ MONEY
Definition: object.h:142
GATE
@ GATE
Definition: object.h:211
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Item is identifiable (e.g.
Definition: define.h:261
identify
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1449