Crossfire Server, Trunk  R20590
item.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
22 #include "global.h"
23 
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "living.h"
30 #include "spells.h"
31 
55  { "body_range", "in your range slot", "in a human's range slot" },
56  { "body_arm", "on your arm", "on a human's arm" },
57  { "body_torso", "on your body", "on a human's torso" },
58  { "body_head", "on your head", "on a human's head" },
59  { "body_neck", "around your neck", "around a humans neck" },
60  { "body_skill", "in your skill slot", "in a human's skill slot" },
61  { "body_finger", "on your finger", "on a human's finger" },
62  { "body_shoulder", "around your shoulders", "around a human's shoulders" },
63  { "body_foot", "on your feet", "on a human's feet" },
64  { "body_hand", "on your hands", "on a human's hands" },
65  { "body_wrist", "around your wrists", "around a human's wrist" },
66  { "body_waist", "around your waist", "around a human's waist" },
67  { "body_leg", "around your legs", "around a human's legs" },
68  /*{"body_dragon_torso", "your body", "a dragon's body"} */
69 };
70 
72 static const char *const numbers_10[] = {
73  "zero", "ten", "twenty", "thirty", "fourty", "fifty", "sixty", "seventy",
74  "eighty", "ninety"
75 };
76 
78 static const char *const levelnumbers[] = {
79  "zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh",
80  "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth",
81  "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth",
82  "nineteenth", "twentieth"
83 };
84 
86 static const char *const levelnumbers_10[] = {
87  "zeroth", "tenth", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth",
88  "seventieth", "eightieth", "ninetieth"
89 };
90 
98 static const typedata item_types[] = {
99  { 0, "none", "none", 0, 0 },
100  { PLAYER, "player", "players", 0, 0 },
101  { ROD, "rod", "rods", SK_THAUMATURGY, 0 },
102  { TREASURE, "treasure", "treasure", 0, 0 },
103  { POTION, "potion", "potions", SK_ALCHEMY, 0 },
104  { FOOD, "food", "food", SK_WOODSMAN, 0 },
105  { POISON, "poison", "poisons", SK_ALCHEMY, 0 },
106  { BOOK, "book", "books", SK_LITERACY, 0 },
107  { CLOCK, "clock", "clocks", 0, 0 },
108  { ARROW, "arrow", "arrows", SK_BOWYER, 0 },
109  { BOW, "bow", "bows", SK_BOWYER, 0 },
110  { WEAPON, "weapon", "weapons", SK_SMITHERY, 0 },
111  { ARMOUR, "armour", "armour", SK_SMITHERY, 0 },
112  { PEDESTAL, "pedestal", "pedestals", 0, 0 },
113  { ALTAR, "altar", "altars", 0, 0 },
114  { LOCKED_DOOR, "locked door", "locked doors", 0, 0 },
115  { SPECIAL_KEY, "special key", "special keys", 0, 0 },
116  { MAP, "map", "maps", 0, 0 },
117  { DOOR, "door", "doors", 0, 0 },
118  { KEY, "key", "keys", 0, 0 },
119  { TIMED_GATE, "timed_gate", "timed_gates", 0, 0 },
120  { TRIGGER, "trigger", "triggers", 0, 0 },
121  { GRIMREAPER, "grimreaper", "grimreapers", 0, 0 },
122  { MAGIC_EAR, "magic ear", "magic ears", 0, 0 },
123  { TRIGGER_BUTTON, "trigger button", "trigger buttons", 0, 0 },
124  { TRIGGER_ALTAR, "trigger altar", "trigger altars", 0, 0 },
125  { TRIGGER_PEDESTAL, "trigger pedestal", "trigger pedestals", 0, 0 },
126  { SHIELD, "shield", "shields", SK_SMITHERY, 0 },
127  { HELMET, "helmet", "helmets", SK_SMITHERY, 0 },
128  { MONEY, "money", "money", 0, 0 },
129  { CLASS, "class", "classes", 0, 0 },
130  { AMULET, "amulet", "amulets", SK_JEWELER, 0 },
131  { PLAYERMOVER, "player mover", "player movers", 0, 0 },
132  { TELEPORTER, "teleporter", "teleporters", 0, 0 },
133  { CREATOR, "creator", "creators", 0, 0 },
134  { SKILL, "skill", "skills", 0, 0 },
135  { EARTHWALL, "earthwall", "earthwalls", 0, 0 },
136  { GOLEM, "golem", "golems", 0, 0 },
137  { THROWN_OBJ, "projectile", "projectiles", 0, 0 },
138  { BLINDNESS, "blindness", "blindness", 0, 0 },
139  { GOD, "god", "gods", 0, 0 },
140  { DETECTOR, "detector", "detectors", 0, 0 },
141  { TRIGGER_MARKER, "trigger marker", "trigger markers", 0, 0 },
142  { DEAD_OBJECT, "dead object", "dead objects", 0, 0 },
143  { DRINK, "drink", "drinks", SK_WOODSMAN, SK_ALCHEMY },
144  { MARKER, "marker", "markers", 0, 0 },
145  { HOLY_ALTAR, "holy altar", "holy altars", 0, 0 },
146  { PLAYER_CHANGER, "player changer", "player changers", 0, 0 },
147  { BATTLEGROUND, "battleground", "battlegrounds", 0, 0 },
148  { PEACEMAKER, "peacemaker", "peacemakers", 0, 0 },
149  { GEM, "gem", "gems", SK_JEWELER, 0 },
150  { FIREWALL, "firewall", "firewalls", 0, 0 },
151  { CHECK_INV, "inventory checker", "inventory checkers", 0, 0 },
152  { MOOD_FLOOR, "mood floor", "mood floors", 0, 0 },
153  { EXIT, "exit", "exits", 0, 0 },
154  { ENCOUNTER, "encounter", "encounters", 0, 0 },
155  { SHOP_FLOOR, "shop floor", "shop floors", 0, 0 },
156  { SHOP_MAT, "shop mat", "shop mats", 0, 0 },
157  { RING, "ring", "rings", SK_JEWELER, 0 },
158  { FLOOR, "floor", "floors", 0, 0 },
159  { FLESH, "flesh", "flesh", SK_WOODSMAN, 0 },
160  { INORGANIC, "inorganic", "inorganics", SK_ALCHEMY, 0 },
161  { SKILL_TOOL, "skill tool", "skill tools", 0, 0 },
162  { LIGHTER, "lighter", "lighters", 0, 0 },
163  { WALL, "wall", "walls", 0, 0 },
164  { MISC_OBJECT, "bric-a-brac", "bric-a-brac", 0, 0 },
165  { MONSTER, "monster", "monsters", 0, 0 },
166  { LAMP, "lamp", "lamps", 0, 0 },
167  { DUPLICATOR, "duplicator", "duplicators", 0, 0 },
168  { SPELLBOOK, "spellbook", "spellbooks", SK_LITERACY, 0 },
169  { CLOAK, "cloak", "cloaks", SK_SMITHERY, 0 },
170  { SPINNER, "spinner", "spinners", 0, 0 },
171  { GATE, "gate", "gates", 0, 0 },
172  { BUTTON, "button", "buttons", 0, 0 },
173  { CF_HANDLE, "cf handle", "cf handles", 0, 0 },
174  { HOLE, "hole", "holes", 0, 0 },
175  { TRAPDOOR, "trapdoor", "trapdoors", 0, 0 },
176  { SIGN, "sign", "signs", 0, 0 },
177  { BOOTS, "boots", "boots", SK_SMITHERY, 0 },
178  { GLOVES, "gloves", "gloves", SK_SMITHERY, 0 },
179  { SPELL, "spell", "spells", 0, 0 },
180  { SPELL_EFFECT, "spell effect", "spell effects", 0, 0 },
181  { CONVERTER, "converter", "converters", 0, 0 },
182  { BRACERS, "bracers", "bracers", SK_SMITHERY, 0 },
183  { POISONING, "poisoning", "poisonings", 0, 0 },
184  { SAVEBED, "savebed", "savebeds", 0, 0 },
185  { WAND, "wand", "wands", SK_THAUMATURGY, 0 },
186  { SCROLL, "scroll", "scrolls", SK_LITERACY, 0 },
187  { DIRECTOR, "director", "directors", 0, 0 },
188  { GIRDLE, "girdle", "girdles", SK_SMITHERY, 0 },
189  { FORCE, "force", "forces", 0, 0 },
190  { POTION_RESIST_EFFECT, "potion effect", "potion effects", 0, 0 },
191  { CLOSE_CON, "closed container", "closed container", 0, 0 },
192  { CONTAINER, "container", "containers", SK_ALCHEMY, 0 },
193  { ARMOUR_IMPROVER, "armour improver", "armour improvers", SK_LITERACY, 0 },
194  { WEAPON_IMPROVER, "weapon improver", "weapon improvers", SK_LITERACY, 0 },
195  { SKILLSCROLL, "skillscroll", "skillscrolls", SK_LITERACY, 0 },
196  { DEEP_SWAMP, "deep swamp", "deep swamps", 0, 0 },
197  { IDENTIFY_ALTAR, "identify altar", "identify altars", 0, 0 },
198  { SHOP_INVENTORY, "inventory list", "inventory lists", 0, 0 },
199  { RUNE, "rune", "runes", 0, 0 },
200  { TRAP, "trap", "traps", 0, 0 },
201  { POWER_CRYSTAL, "power_crystal", "power_crystals", 0, 0 },
202  { CORPSE, "corpse", "corpses", 0, 0 },
203  { DISEASE, "disease", "diseases", 0, 0 },
204  { SYMPTOM, "symptom", "symptoms", 0, 0 },
205  { BUILDER, "item builder", "item builders", 0, 0 },
206  { MATERIAL, "building material", "building materials", 0, 0 },
207  { MIMIC, "mimic", "mimics", SK_ALCHEMY, 0 },
208 };
209 
211 static const int item_types_size = sizeof(item_types)/sizeof(*item_types);
212 
222 static const int enc_to_item_power[] = {
223  0, 0, 1, 2, 3, 4, /* 5 */
224  5, 7, 9, 11, 13, /* 10 */
225  15, 18, 21, 24, 27, /* 15 */
226  30, 35, 40, 45, 50 /* 20 */
227 };
228 
229 int get_power_from_ench(int ench) {
230  if (ench < 0)
231  ench = 0;
232  if (ench > (int)(sizeof(enc_to_item_power)/sizeof(*enc_to_item_power)-1))
233  ench = sizeof(enc_to_item_power)/sizeof(*enc_to_item_power)-1;
234  return enc_to_item_power[ench];
235 }
236 
247 int calc_item_power(const object *op) {
248  int i, tmp, enc;
249 
250  enc = 0;
251  for (i = 0; i < NUM_STATS; i++)
252  enc += get_attr_value(&op->stats, i);
253 
254  /* This protection logic is pretty flawed. 20% fire resistance
255  * is much more valuable than 20% confusion, or 20% slow, or
256  * several others. Start at 1 - ignore physical - all that normal
257  * armour shouldn't be counted against
258  */
259  tmp = 0;
260  for (i = 1; i < NROFATTACKS; i++)
261  tmp += op->resist[i];
262 
263  /* Add/substract 10 so that the rounding works out right */
264  if (tmp > 0)
265  enc += (tmp+10)/20;
266  else if (tmp < 0)
267  enc += (tmp-10)/20;
268 
269  enc += op->magic;
270 
271  /* For each attacktype a weapon has, one more encantment. Start at 1 -
272  * physical doesn't count against total.
273  */
274  if (op->type == WEAPON) {
275  for (i = 1; i < NROFATTACKS; i++)
276  if (op->attacktype&(1<<i))
277  enc++;
278  if (op->slaying)
279  enc += 2; /* What it slays is probably more relevent */
280  }
281  /* Items the player can equip */
282  if ((op->type == WEAPON)
283  || (op->type == ARMOUR)
284  || (op->type == HELMET)
285  || (op->type == SHIELD)
286  || (op->type == RING)
287  || (op->type == BOOTS)
288  || (op->type == GLOVES)
289  || (op->type == AMULET)
290  || (op->type == GIRDLE)
291  || (op->type == BRACERS)
292  || (op->type == CLOAK)) {
293  enc += op->stats.food; /* sustenance */
294  enc += op->stats.hp; /* hp regen */
295  enc += op->stats.sp; /* mana regen */
296  enc += op->stats.grace; /* grace regen */
297  enc += op->stats.exp; /* speed bonus */
298  }
299  enc += op->stats.luck;
300 
301  /* Do spell paths now */
302  for (i = 1; i < NRSPELLPATHS; i++) {
303  if (op->path_attuned&(1<<i))
304  enc++;
305  else if (op->path_denied&(1<<i))
306  enc -= 2;
307  else if (op->path_repelled&(1<<i))
308  enc--;
309  }
310 
311  if (QUERY_FLAG(op, FLAG_LIFESAVE))
312  enc += 5;
313  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
314  enc += 3;
315  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
316  enc += 2;
317  if (QUERY_FLAG(op, FLAG_STEALTH))
318  enc += 1;
319  if (QUERY_FLAG(op, FLAG_XRAYS))
320  enc += 2;
321  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK))
322  enc += 1;
323  if (QUERY_FLAG(op, FLAG_MAKE_INVIS))
324  enc += 1;
325 
326  return get_power_from_ench(enc);
327 }
328 
335 const typedata *get_typedata(int itemtype) {
336  int i;
337 
338  for (i = 0; i < item_types_size; i++)
339  if (item_types[i].number == itemtype)
340  return &item_types[i];
341  return NULL;
342 }
343 
355 const typedata *get_typedata_by_name(const char *name) {
356  int i;
357 
358  for (i = 0; i < item_types_size; i++)
359  if (!strcmp(item_types[i].name, name))
360  return &item_types[i];
361  for (i = 0; i < item_types_size; i++)
362  if (!strcmp(item_types[i].name_pl, name)) {
363  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);
364  return &item_types[i];
365  }
366  return NULL;
367 }
368 
384 StringBuffer *describe_resistance(const object *op, int newline, int use_media_tags, StringBuffer *buf) {
385  int tmpvar;
386 
387  if (buf == NULL)
388  buf = stringbuffer_new();
389 
390  for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++) {
391  if (op->resist[tmpvar] && (op->type != FLESH || atnr_is_dragon_enabled(tmpvar) == 1)) {
392  if (use_media_tags) {
393  if (resist_color[tmpvar] != NULL) {
394  stringbuffer_append_printf(buf, "[color=%s]", resist_color[tmpvar]);
395  }
396  if (op->resist[tmpvar] == 100 || op->resist[tmpvar] == -100) {
397  stringbuffer_append_string(buf, "[ul]");
398  }
399  }
400  if (!newline)
401  stringbuffer_append_printf(buf, "(%s %+d)", resist_plus[tmpvar], op->resist[tmpvar]);
402  else
403  stringbuffer_append_printf(buf, "%s %d\n", resist_plus[tmpvar], op->resist[tmpvar]);
404  if (use_media_tags) {
405  if (op->resist[tmpvar] == 100 || op->resist[tmpvar] == -100) {
406  stringbuffer_append_string(buf, "[/ul]");
407  }
408  if (resist_color[tmpvar] != NULL) {
409  stringbuffer_append_string(buf, "[/color]");
410  }
411  }
412  }
413  }
414 
415  return buf;
416 }
417 
427 void query_weight(const object *op, char *buf, size_t size) {
428  int32_t i = (op->nrof ? op->nrof : 1)*op->weight+op->carrying;
429 
430  if (op->weight < 0)
431  snprintf(buf, size, " ");
432  else if (i%1000)
433  snprintf(buf, size, "%6.1f", i/1000.0);
434  else
435  snprintf(buf, size, "%4d ", i/1000);
436 }
437 
447 void get_levelnumber(int i, char *buf, size_t size) {
448  if (i > 99 || i < 0) {
449  snprintf(buf, size, "%d.", i);
450  return;
451  }
452  if (i < 21) {
453  snprintf(buf, size, "%s", levelnumbers[i]);
454  return;
455  }
456  if (!(i%10)) {
457  snprintf(buf, size, "%s", levelnumbers_10[i/10]);
458  return;
459  }
460  snprintf(buf, size, "%s%s", numbers_10[i/10], levelnumbers[i%10]);
461  return;
462 }
463 
473 static StringBuffer *ring_desc(const object *op, StringBuffer *buf) {
474  int attr, val;
475  size_t len;
476 
477  assert(op != NULL);
478  assert(op->type == RING || op->type == AMULET || op->type == SKILL);
479 
480  if (buf == NULL)
481  buf = stringbuffer_new();
482  len = stringbuffer_length(buf);
483 
484  if (!QUERY_FLAG(op, FLAG_IDENTIFIED))
485  return buf;
486 
487  for (attr = 0; attr < NUM_STATS; attr++) {
488  if ((val = get_attr_value(&(op->stats), attr)) != 0) {
489  stringbuffer_append_printf(buf, "(%s%+d)", short_stat_name[attr], val);
490  }
491  }
492  if (op->stats.exp)
493  stringbuffer_append_printf(buf, "(speed %+"FMT64")", op->stats.exp);
494  if (op->stats.wc)
495  stringbuffer_append_printf(buf, "(wc%+d)", op->stats.wc);
496  if (op->stats.dam)
497  stringbuffer_append_printf(buf, "(dam%+d)", op->stats.dam);
498  if (op->stats.ac)
499  stringbuffer_append_printf(buf, "(ac%+d)", op->stats.ac);
500 
501  describe_resistance(op, 0, 1, buf);
502 
503  if (op->stats.food != 0)
504  stringbuffer_append_printf(buf, "(sustenance%+d)", op->stats.food);
505  if (op->stats.grace)
506  stringbuffer_append_printf(buf, "(grace%+d)", op->stats.grace);
507  if (op->stats.sp && op->type != SKILL)
508  stringbuffer_append_printf(buf, "(magic%+d)", op->stats.sp);
509  if (op->stats.hp)
510  stringbuffer_append_printf(buf, "(regeneration%+d)", op->stats.hp);
511  if (op->stats.luck)
512  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
513  if (QUERY_FLAG(op, FLAG_LIFESAVE))
514  stringbuffer_append_printf(buf, "(lifesaving)");
515  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
516  stringbuffer_append_printf(buf, "(reflect spells)");
517  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
518  stringbuffer_append_printf(buf, "(reflect missiles)");
519  if (QUERY_FLAG(op, FLAG_STEALTH))
520  stringbuffer_append_printf(buf, "(stealth)");
521  if (op->glow_radius)
522  stringbuffer_append_string(buf, "(glowing)");
523 
524  describe_spellpath_attenuation("Attuned", op->path_attuned, buf);
525  describe_spellpath_attenuation("Repelled", op->path_repelled, buf);
526  describe_spellpath_attenuation("Denied", op->path_denied, buf);
527 
528  /* item_power is done by the caller */
529  /* if (op->item_power)
530  snprintf(buf+strlen(buf), size-strlen(buf), "(item_power %+d)", op->item_power);*/
531  if (stringbuffer_length(buf) == len && op->type != SKILL)
532  stringbuffer_append_string(buf, "of adornment");
533 
534  return buf;
535 }
536 
548 void query_short_name(const object *op, char *buf, size_t size) {
549  size_t len = 0;
550 
551  if (op->name == NULL) {
552  snprintf(buf, size, "(null)");
553  return;
554  }
555  if (!op->nrof && !op->weight && !op->title && !is_magical(op)) {
556  snprintf(buf, size, "%s", op->name); /* To speed things up (or make things slower?) */
557  return;
558  }
559  buf[0] = '\0';
560 
561  if (op->nrof <= 1)
562  safe_strcat(buf, op->name, &len, size);
563  else
564  safe_strcat(buf, op->name_pl, &len, size);
565 
566  if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) {
567  safe_strcat(buf, " ", &len, size);
568  safe_strcat(buf, op->title, &len, size);
569  }
570 
571  switch (op->type) {
572  case SPELLBOOK:
573  case SCROLL:
574  case WAND:
575  case ROD:
577  if (!op->title) {
578  safe_strcat(buf, " of ", &len, size);
579  if (op->inv)
580  safe_strcat(buf, op->inv->name, &len, size);
581  else
582  LOG(llevError, "Spellbook %s lacks inventory\n", op->name);
583  }
584  if (op->type != SPELLBOOK) {
585  snprintf(buf+len, size-len, " (lvl %d)", op->level);
586  len += strlen(buf+len);
587  }
588  }
589  break;
590 
591  case SKILL:
592  case AMULET:
593  case RING:
594  if (!op->title) {
595  /* If ring has a title, full description isn't so useful */
596  char* desc;
597 
598  desc = stringbuffer_finish(ring_desc(op, NULL));
599  if (desc[0]) {
600  safe_strcat(buf, " ", &len, size);
601  safe_strcat(buf, desc, &len, size);
602  }
603  free(desc);
604  }
605  break;
606 
607  default:
608  if (op->magic
610  snprintf(buf+len, size-len, " %+d", op->magic);
611  len += strlen(buf+len);
612  }
613  }
614 }
615 
626 void query_name(const object *op, char *buf, size_t size) {
627  size_t len = 0;
628 
629  buf[0] = '\0';
630  /*
631  * Since len is initialized to zero, but is not changed
632  * up to this point, I see no reason to have buf+len and size-len;
633  * buf and size should suffice, since we're just adding and
634  * subtracting zero here, anyway.
635  *
636  * SilverNexus 2014-06-04
637  */
638  query_short_name(op, buf, size);
639  len = strlen(buf);
640 
641  if (QUERY_FLAG(op, FLAG_INV_LOCKED))
642  safe_strcat(buf, " *", &len, size);
643  if (op->type == CONTAINER
644  && ((op->env && op->env->container == op) || (!op->env && QUERY_FLAG(op, FLAG_APPLIED))))
645  safe_strcat(buf, " (open)", &len, size);
646 
647  if (QUERY_FLAG(op, FLAG_KNOWN_CURSED)) {
648  if (QUERY_FLAG(op, FLAG_DAMNED))
649  safe_strcat(buf, " (damned)", &len, size);
650  else if (QUERY_FLAG(op, FLAG_CURSED))
651  safe_strcat(buf, " (cursed)", &len, size);
652  }
654  safe_strcat(buf, " (blessed)", &len, size);
655 
656  /* Basically, if the object is known magical (detect magic spell on it),
657  * and it isn't identified, print out the fact that
658  * it is magical. Assume that the detect magical spell will only set
659  * KNOWN_MAGICAL if the item actually is magical.
660  *
661  * Changed in V 0.91.4 - still print that the object is magical even
662  * if it has been applied. Equipping an item does not tell full
663  * abilities, especially for artifact items.
664  */
666  safe_strcat(buf, " (magic)", &len, size);
667 
668  if (QUERY_FLAG(op, FLAG_APPLIED)) {
669  switch (op->type) {
670  case BOW:
671  case WAND:
672  case ROD:
673  safe_strcat(buf, " (readied)", &len, size);
674  break;
675 
676  case WEAPON:
677  safe_strcat(buf, " (wielded)", &len, size);
678  break;
679 
680  case ARMOUR:
681  case HELMET:
682  case SHIELD:
683  case RING:
684  case BOOTS:
685  case GLOVES:
686  case AMULET:
687  case GIRDLE:
688  case BRACERS:
689  case CLOAK:
690  safe_strcat(buf, " (worn)", &len, size);
691  break;
692 
693  case CONTAINER:
694  safe_strcat(buf, " (active)", &len, size);
695  break;
696 
697  case SKILL:
698  default:
699  safe_strcat(buf, " (applied)", &len, size);
700  }
701  }
702  if (QUERY_FLAG(op, FLAG_UNPAID))
703  safe_strcat(buf, " (unpaid)", &len, size);
704 }
705 
723 void query_base_name(const object *op, int plural, char *buf, size_t size) {
724  size_t len;
725 
726  if ((!plural && !op->name)
727  || (plural && !op->name_pl)) {
728  strncpy(buf, "(null)", size);
729  return;
730  }
731 
732  if (!op->nrof && !op->weight && !op->title && !is_magical(op)) {
733  strncpy(buf, op->name, size); /* To speed things up (or make things slower?) */
734  return;
735  }
736 
737  buf[0] = '\0';
738 
739  snprintf(buf, size, "%s", plural ? op->name_pl : op->name);
740  len = strlen(buf);
741 
742  if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) {
743  safe_strcat(buf, " ", &len, size);
744  safe_strcat(buf, op->title, &len, size);
745  }
746 
747  switch (op->type) {
748  case SPELLBOOK:
749  case SCROLL:
750  case WAND:
751  case ROD:
753  if (!op->title) {
754  safe_strcat(buf, " of ", &len, size);
755  if (op->inv)
756  safe_strcat(buf, op->inv->name, &len, size);
757  else
758  LOG(llevError, "Spellbook %s lacks inventory\n", op->name);
759  }
760  if (op->type != SPELLBOOK) {
761  snprintf(buf+len, size-len, " (lvl %d)", op->level);
762  len += strlen(buf+len);
763  }
764  }
765  break;
766 
767  case SKILL:
768  case AMULET:
769  case RING:
770  if (!op->title) {
771  /* If ring has a title, full description isn't so useful */
772  char* s;
773 
774  s = stringbuffer_finish(ring_desc(op, NULL));
775  if (s[0]) {
776  safe_strcat(buf, " ", &len, size);
777  safe_strcat(buf, s, &len, size);
778  }
779  free(s);
780  }
781  break;
782 
783  default:
784  if (op->magic
786  snprintf(buf+strlen(buf), size-strlen(buf), " %+d", op->magic);
787  }
788  }
789 }
790 
807 StringBuffer *describe_monster(const object *op, int use_media_tags, StringBuffer *buf) {
808  assert(op != NULL);
809  assert(QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER);
810 
811  if (buf == NULL)
812  buf = stringbuffer_new();
813 
814  /* Note that the resolution this provides for players really isn't
815  * very good. Any player with a speed greater than .67 will
816  * fall into the 'lightning fast movement' category.
817  */
818  if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
819  switch ((int)((FABS(op->speed))*15)) {
820  case 0:
821  stringbuffer_append_string(buf, "(very slow movement)");
822  break;
823 
824  case 1:
825  stringbuffer_append_string(buf, "(slow movement)");
826  break;
827 
828  case 2:
829  stringbuffer_append_string(buf, "(normal movement)");
830  break;
831 
832  case 3:
833  case 4:
834  stringbuffer_append_string(buf, "(fast movement)");
835  break;
836 
837  case 5:
838  case 6:
839  stringbuffer_append_string(buf, "(very fast movement)");
840  break;
841 
842  case 7:
843  case 8:
844  case 9:
845  case 10:
846  stringbuffer_append_string(buf, "(extremely fast movement)");
847  break;
848 
849  default:
850  stringbuffer_append_string(buf, "(lightning fast movement)");
851  break;
852  }
853  }
854  if (QUERY_FLAG(op, FLAG_UNDEAD))
855  stringbuffer_append_string(buf, "(undead)");
857  stringbuffer_append_string(buf, "(see invisible)");
858  if (QUERY_FLAG(op, FLAG_USE_WEAPON))
859  stringbuffer_append_string(buf, "(wield weapon)");
860  if (QUERY_FLAG(op, FLAG_USE_BOW))
861  stringbuffer_append_string(buf, "(archer)");
862  if (QUERY_FLAG(op, FLAG_USE_ARMOUR))
863  stringbuffer_append_string(buf, "(wear armour)");
864  if (QUERY_FLAG(op, FLAG_USE_RING))
865  stringbuffer_append_string(buf, "(wear ring)");
866  if (QUERY_FLAG(op, FLAG_USE_SCROLL))
867  stringbuffer_append_string(buf, "(read scroll)");
868  if (QUERY_FLAG(op, FLAG_USE_RANGE))
869  stringbuffer_append_string(buf, "(fires wand/rod/horn)");
871  stringbuffer_append_string(buf, "(skill user)");
872  if (QUERY_FLAG(op, FLAG_CAST_SPELL))
873  stringbuffer_append_string(buf, "(spellcaster)");
874  if (QUERY_FLAG(op, FLAG_FRIENDLY))
875  stringbuffer_append_string(buf, "(friendly)");
876  if (QUERY_FLAG(op, FLAG_UNAGGRESSIVE))
877  stringbuffer_append_string(buf, "(unaggressive)");
878  if (QUERY_FLAG(op, FLAG_HITBACK))
879  stringbuffer_append_string(buf, "(hitback)");
880  if (QUERY_FLAG(op, FLAG_STEALTH))
881  stringbuffer_append_string(buf, "(stealthy)");
882  if (op->randomitems != NULL) {
883  treasure *t;
884  int first = 1;
885 
886  for (t = op->randomitems->items; t != NULL; t = t->next)
887  if (t->item && (t->item->clone.type == SPELL)) {
888  if (first) {
889  first = 0;
890  stringbuffer_append_string(buf, "(Spell abilities:)");
891  }
892  stringbuffer_append_printf(buf, "(%s)", t->item->clone.name);
893  }
894  }
895  if (op->type == PLAYER) {
896  if (op->contr->digestion) {
897  if (op->contr->digestion != 0)
898  stringbuffer_append_printf(buf, "(sustenance%+d)", op->contr->digestion);
899  }
900  if (op->contr->gen_grace) {
901  stringbuffer_append_printf(buf, "(grace%+d)", op->contr->gen_grace);
902  }
903  if (op->contr->gen_sp) {
904  stringbuffer_append_printf(buf, "(magic%+d)", op->contr->gen_sp);
905  }
906  if (op->contr->gen_hp) {
907  stringbuffer_append_printf(buf, "(regeneration%+d)", op->contr->gen_hp);
908  }
909  if (op->stats.luck) {
910  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
911  }
912  }
913 
914  /* describe attacktypes */
915  if (is_dragon_pl(op)) {
916  /* for dragon players display the attacktypes from clawing skill
917  * Break apart the for loop - move the comparison checking down -
918  * this makes it more readable.
919  */
920  object *tmp;
921 
922  tmp = object_find_by_type_and_name(op, SKILL, "clawing");
923  if (tmp && tmp->attacktype != 0) {
924  describe_attacktype("Claws", tmp->attacktype, buf);
925  } else {
926  describe_attacktype("Attacks", op->attacktype, buf);
927  }
928  } else {
929  describe_attacktype("Attacks", op->attacktype, buf);
930  }
931  describe_spellpath_attenuation("Attuned", op->path_attuned &~ op->path_denied, buf);
932  describe_spellpath_attenuation("Repelled", op->path_repelled &~ op->path_denied, buf );
933  describe_spellpath_attenuation("Denied", op->path_denied, buf);
934  describe_resistance(op, 0, use_media_tags, buf);
935 
936  return buf;
937 }
938 
981 StringBuffer *describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf) {
982  int identified, i;
983 
984  if (buf == NULL)
985  buf = stringbuffer_new();
986 
987  if (QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER) {
988  return describe_monster(op, use_media_tags, buf);
989  }
990 
991  /* figure this out once, instead of making multiple calls to need_identify.
992  * also makes the code easier to read.
993  */
994  if (!need_identify(op) || QUERY_FLAG(op, FLAG_IDENTIFIED))
995  identified = 1;
996  else {
997  stringbuffer_append_string(buf, "(unidentified)");
998  identified = 0;
999  }
1000  switch (op->type) {
1001  case BOW:
1002  case ARROW:
1003  case WAND:
1004  case ROD:
1005  case WEAPON:
1006  case ARMOUR:
1007  case HELMET:
1008  case SHIELD:
1009  case BOOTS:
1010  case GLOVES:
1011  case GIRDLE:
1012  case BRACERS:
1013  case CLOAK:
1014  case SKILL_TOOL:
1015  break; /* We have more information to do below this switch */
1016 
1017  case LAMP:
1018  break; /* just so we get the "glowing" part. */
1019 
1020  case FOOD:
1021  case FLESH:
1022  case DRINK:
1023  if (identified || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
1024  stringbuffer_append_printf(buf, "(food+%d)", op->stats.food);
1025 
1026  if (op->type == FLESH && op->last_eat > 0 && atnr_is_dragon_enabled(op->last_eat)) {
1027  stringbuffer_append_printf(buf, "(%s metabolism)", change_resist_msg[op->last_eat]);
1028  }
1029 
1030  if (!QUERY_FLAG(op, FLAG_CURSED)) {
1031  if (op->stats.hp)
1032  stringbuffer_append_string(buf, "(heals)");
1033  if (op->stats.sp)
1034  stringbuffer_append_string(buf, "(spellpoint regen)");
1035  } else {
1036  if (op->stats.hp)
1037  stringbuffer_append_string(buf, "(damages)");
1038  if (op->stats.sp)
1039  stringbuffer_append_string(buf, "(spellpoint depletion)");
1040  }
1041  }
1042  break;
1043 
1044  case SKILL:
1045  case RING:
1046  case AMULET:
1047  if (op->item_power) {
1048  stringbuffer_append_printf(buf, "(item_power %+d)", op->item_power);
1049  }
1050  if (op->title) {
1051  ring_desc(op, buf);
1052  }
1053  return buf;
1054 
1055  default:
1056  return buf;
1057  }
1058 
1059  /* Down here, we more further describe equipment type items.
1060  * only describe them if they have been identified or the like.
1061  */
1062  if (identified || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
1063  int attr, val;
1064 
1065  for (attr = 0; attr < NUM_STATS; attr++) {
1066  if ((val = get_attr_value(&(op->stats), attr)) != 0) {
1067  stringbuffer_append_printf(buf, "(%s%+d)", short_stat_name[attr], val);
1068  }
1069  }
1070  if (op->glow_radius)
1071  stringbuffer_append_string(buf, "(glowing)");
1072 
1073  switch (op->type) {
1074  case FLESH:
1075  break;
1076 
1077  default:
1078  if (op->stats.exp) {
1079  stringbuffer_append_printf(buf, "(speed %+"FMT64")", op->stats.exp);
1080  }
1081  break;
1082  }
1083  switch (op->type) {
1084  case BOW:
1085  case ARROW:
1086  case GIRDLE:
1087  case HELMET:
1088  case SHIELD:
1089  case BOOTS:
1090  case GLOVES:
1091  case WEAPON:
1092  case SKILL:
1093  case RING:
1094  case AMULET:
1095  case ARMOUR:
1096  case BRACERS:
1097  case FORCE:
1098  case CLOAK:
1099  if (op->stats.wc) {
1100  stringbuffer_append_printf(buf, "(wc%+d)", op->stats.wc);
1101  }
1102  if (op->stats.dam) {
1103  stringbuffer_append_printf(buf, "(dam%+d)", op->stats.dam);
1104  }
1105  if (op->stats.ac) {
1106  stringbuffer_append_printf(buf, "(ac%+d)", op->stats.ac);
1107  }
1108  if ((op->type == WEAPON || op->type == BOW) && op->level > 0) {
1109  stringbuffer_append_printf(buf, "(improved %d/%d)", op->last_eat, op->level);
1110  }
1111  break;
1112 
1113  default:
1114  break;
1115  }
1116  if (QUERY_FLAG(op, FLAG_XRAYS))
1117  stringbuffer_append_string(buf, "(xray-vision)");
1118  if (QUERY_FLAG(op, FLAG_SEE_IN_DARK))
1119  stringbuffer_append_string(buf, "(infravision)");
1120 
1121  /* levitate was what is was before, so we'll keep it */
1122  if (op->move_type&MOVE_FLY_LOW)
1123  stringbuffer_append_string(buf, "(levitate)");
1124 
1125  if (op->move_type&MOVE_FLY_HIGH)
1126  stringbuffer_append_string(buf, "(fly)");
1127 
1128  if (op->move_type&MOVE_SWIM)
1129  stringbuffer_append_string(buf, "(swim)");
1130 
1131  /* walking is presumed as 'normal', so doesn't need mentioning */
1132 
1133  if (op->item_power) {
1134  stringbuffer_append_printf(buf, "(item_power %+d)", op->item_power);
1135  }
1136  } /* End if identified or applied */
1137 
1138  /* This blocks only deals with fully identified object.
1139  * it is intentional that this is not an 'else' from a above -
1140  * in this way, information is added.
1141  */
1142  if (identified) {
1143  int more_info = 0;
1144 
1145  switch (op->type) {
1146  case ROD: /* These use stats.sp for spell selection and stats.food */
1147  case BOW: /* and stats.hp for spell-point regeneration... */
1148  case ARROW:
1149  case WAND:
1150  case FOOD:
1151  case FLESH:
1152  case DRINK:
1153  more_info = 0;
1154  break;
1155 
1156  /* Armor type objects */
1157  case ARMOUR:
1158  case HELMET:
1159  case SHIELD:
1160  case BOOTS:
1161  case GLOVES:
1162  case GIRDLE:
1163  case BRACERS:
1164  case CLOAK:
1165  if (ARMOUR_SPEED(op)) {
1166  stringbuffer_append_printf(buf, "(Max speed %1.2f)", ARMOUR_SPEED(op)/10.0);
1167  }
1168  if (ARMOUR_SPELLS(op)) {
1169  stringbuffer_append_printf(buf, "(Spell regen penalty %d)", ARMOUR_SPELLS(op));
1170  }
1171  more_info = 1;
1172  break;
1173 
1174  case WEAPON:
1175  /* Calculate it the same way fix_object does so the results
1176  * make sense.
1177  */
1178  i = (WEAPON_SPEED(op)*2-op->magic)/2;
1179  if (i < 0)
1180  i = 0;
1181 
1182  stringbuffer_append_printf(buf, "(weapon speed %d)", i);
1183  more_info = 1;
1184  break;
1185  }
1186  if (more_info) {
1187  if (op->stats.food) {
1188  if (op->stats.food != 0)
1189  stringbuffer_append_printf(buf, "(sustenance%+d)", op->stats.food);
1190  }
1191  if (op->stats.grace) {
1192  stringbuffer_append_printf(buf, "(grace%+d)", op->stats.grace);
1193  }
1194  if (op->stats.sp) {
1195  stringbuffer_append_printf(buf, "(magic%+d)", op->stats.sp);
1196  }
1197  if (op->stats.hp) {
1198  stringbuffer_append_printf(buf, "(regeneration%+d)", op->stats.hp);
1199  }
1200  }
1201 
1202  if (op->stats.luck) {
1203  stringbuffer_append_printf(buf, "(luck%+d)", op->stats.luck);
1204  }
1205  if (QUERY_FLAG(op, FLAG_LIFESAVE))
1206  stringbuffer_append_string(buf, "(lifesaving)");
1207  if (QUERY_FLAG(op, FLAG_REFL_SPELL))
1208  stringbuffer_append_string(buf, "(reflect spells)");
1209  if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
1210  stringbuffer_append_string(buf, "(reflect missiles)");
1211  if (QUERY_FLAG(op, FLAG_STEALTH))
1212  stringbuffer_append_string(buf, "(stealth)");
1213  if (op->slaying != NULL && op->type != FOOD) {
1214  stringbuffer_append_printf(buf, "(slay %s)", op->slaying);
1215  }
1216  describe_attacktype("Attacks", op->attacktype, buf);
1217  /* resistance on flesh is only visible for dragons. If
1218  * non flesh, everyone can see its resistances
1219  */
1220  if (op->type != FLESH || (owner && is_dragon_pl(owner))) {
1221  describe_resistance(op, 0, 1, buf);
1222  }
1223  describe_spellpath_attenuation("Attuned", op->path_attuned &~ op->path_denied, buf);
1224  describe_spellpath_attenuation("Repelled", op->path_repelled &~ op->path_denied, buf);
1225  describe_spellpath_attenuation("Denied", op->path_denied, buf);
1226  }
1227 
1228  return buf;
1229 }
1230 
1243 int is_magical(const object *op) {
1244  int i;
1245 
1246  /* living creatures are considered non magical */
1247  if (QUERY_FLAG(op, FLAG_ALIVE))
1248  return 0;
1249 
1250  /* This is a test for it being an artifact, as artifacts have titles */
1251  if (op->title != NULL)
1252  return 1;
1253 
1254  /* Handle rings and amulets specially. If they change any of these
1255  * values, it means they are magical.
1256  */
1257  if ((op->type == AMULET || op->type == RING)
1258  && (op->stats.ac || op->stats.food || op->stats.exp || op->stats.dam || op->stats.wc || op->stats.sp || op->stats.hp || op->stats.luck))
1259  return 1;
1260 
1261  /* Check for stealty, speed, flying, or just plain magic in the boots */
1262  /* Presume any boots that have a move_type are special. */
1263  if (op->type == BOOTS
1264  && ((QUERY_FLAG(op, FLAG_STEALTH) || op->move_type || op->stats.exp)))
1265  return 1;
1266 
1267  /* Take care of amulet/shield that reflects spells/missiles */
1268  if ((op->type == AMULET || op->type == SHIELD)
1270  return 1;
1271 
1272  /* Take care of helmet of xrays */
1273  if (op->type == HELMET
1274  && QUERY_FLAG(op, FLAG_XRAYS))
1275  return 1;
1276 
1277  /* Potions & rods are always magical. Wands/staves are also magical,
1278  * assuming they still have any charges left.
1279  */
1280  if (op->type == POTION || op->type == ROD || (op->type == WAND && op->stats.food))
1281  return 1;
1282 
1283  /* if something gives a protection, either positive or negative, its magical */
1284  /* This is really a pretty bad hack - as of now, ATNR_PHYSICAL is 0,
1285  * so this always works out fine.
1286  */
1287  for (i = ATNR_PHYSICAL+1; i < NROFATTACKS; i++)
1288  if (op->resist[i])
1289  return 1;
1290 
1291  /* Physical protection is expected on some item types, so they should
1292  * not be considered magical.
1293  */
1294  if (op->resist[ATNR_PHYSICAL]
1295  && op->type != HELMET
1296  && op->type != SHIELD
1297  && op->type != BOOTS
1298  && op->type != GLOVES
1299  && op->type != ARMOUR)
1300  return 1;
1301 
1302  /* power crystal, spellbooks, and scrolls are always magical. */
1303  if (op->magic
1304  || op->type == POWER_CRYSTAL
1305  || op->type == SPELLBOOK
1306  || op->type == SCROLL
1307  || op->type == GIRDLE)
1308  return 1;
1309 
1310  /* Check to see if it increases/decreases any stats */
1311  for (i = 0; i < NUM_STATS; i++)
1312  if (get_attr_value(&(op->stats), i) != 0)
1313  return 1;
1314 
1315  /* If it doesn't fall into any of the above categories, must
1316  * be non magical.
1317  */
1318  return 0;
1319 }
1320 
1332 int need_identify(const object *op) {
1333  switch (op->type) {
1334  case RING:
1335  case WAND:
1336  case ROD:
1337  case SCROLL:
1338  case SKILL:
1339  case SKILLSCROLL:
1340  case SPELLBOOK:
1341  case FOOD:
1342  case POTION:
1343  case BOW:
1344  case ARROW:
1345  case WEAPON:
1346  case ARMOUR:
1347  case SHIELD:
1348  case HELMET:
1349  case AMULET:
1350  case BOOTS:
1351  case GLOVES:
1352  case BRACERS:
1353  case GIRDLE:
1354  case CONTAINER:
1355  case DRINK:
1356  case FLESH:
1357  case INORGANIC:
1358  case CLOSE_CON:
1359  case CLOAK:
1360  case GEM:
1361  case POWER_CRYSTAL:
1362  case POISON:
1363  case BOOK:
1364  case SKILL_TOOL:
1365  case ARMOUR_IMPROVER:
1366  case WEAPON_IMPROVER:
1367  return 1;
1368  }
1369  return 0;
1370 }
1371 
1377  sstring key;
1378 
1379  key = object_get_value(op, "identified_face");
1380  if (key != NULL) {
1381  op->face = &new_faces[find_face(key, op->face->number)];
1382  /* if the face is defined, clean the animation, because else
1383  * the face can be lost ; if an animation is defined, it'll be
1384  * processed later on */
1387  op->anim_speed = 0;
1388  op->animation_id = 0;
1389  object_set_value(op, "identified_face", NULL, 0);
1390  }
1391 
1392  if (object_get_value(op, "identified_anim_random") != NULL) {
1394  object_set_value(op, "identified_anim_random", NULL, 0);
1395  }
1396 
1397  key = object_get_value(op, "identified_anim_speed");
1398  if (key != NULL) {
1399  op->anim_speed = atoi(key);
1400  op->last_anim = 1;
1401  object_set_value(op, "identified_anim_speed", NULL, 0);
1402  }
1403 
1404  key = object_get_value(op, "identified_animation");
1405  if (key != NULL) {
1406  op->animation_id = atoi(key);
1407  if (!QUERY_FLAG(op, FLAG_IS_TURNABLE))
1408  SET_FLAG(op, FLAG_ANIMATE);
1409  animate_object(op, op->facing);
1410  object_set_value(op, "identified_animation", NULL, 0);
1411  }
1412 
1413  key = object_get_value(op, "identified_name");
1414  if (key != NULL) {
1415  FREE_AND_COPY(op->name, key);
1416  object_set_value(op, "identified_name", NULL, 0);
1417  }
1418  key = object_get_value(op, "identified_name_pl");
1419  if (key != NULL) {
1420  FREE_AND_COPY(op->name_pl, key);
1421  object_set_value(op, "identified_name_pl", NULL, 0);
1422  }
1423 }
1424 
1438 object *identify(object *op) {
1439  object *pl, *op1;
1440 
1444 
1446 
1447  /*
1448  * We want autojoining of equal objects:
1449  */
1450  if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))
1452 
1453  if (QUERY_FLAG(op, FLAG_BLESSED))
1455 
1456  if (op->type == POTION) {
1457  if (op->inv && op->randomitems) {
1458  if (op->title)
1459  free_string(op->title);
1460  op->title = add_refcount(op->inv->name);
1461  } else if (op->arch) {
1462  free_string(op->name);
1463  op->name = add_refcount(op->arch->clone.name);
1464  free_string(op->name_pl);
1465  op->name_pl = add_refcount(op->arch->clone.name_pl);
1466  }
1467  }
1468 
1469  if (op->map) {
1470  /* If the object is on a map, make sure we update its face.
1471  * Also send name and such information to a player standing on it.
1472  */
1473  object *player = map_find_by_type(op->map, op->x, op->y, PLAYER);
1474 
1476  op1 = object_merge(op, GET_MAP_TOP(op->map, op->x, op->y));
1477  if (op1) op = op1;
1478 
1479  if (player)
1480  esrv_update_item(UPD_FACE | UPD_NAME | UPD_FLAGS, player, op);
1481 
1482  } else {
1483  pl = object_get_player_container(op->env);
1484  op1 = object_merge(op, op->env->inv);
1485  if (op1) op = op1;
1486 
1487  if (pl)
1488  /* A lot of the values can change from an update - might as well send
1489  * it all.
1490  */
1491  esrv_update_item(UPD_ALL, pl, op);
1492  }
1493  return op;
1494 }
See Pedestal.
Definition: object.h:121
Error, serious thing.
Definition: logger.h:11
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.c:3999
#define FLAG_KNOWN_BLESSED
Item is known to be blessed.
Definition: define.h:379
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:13
One player.
Definition: player.h:92
#define FLAG_SEE_IN_DARK
if set ob not effected by darkness
Definition: define.h:338
#define WEAPON_SPEED(xyz)
Definition: define.h:482
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:318
#define FLAG_UNPAID
Object hasn&#39;t been paid for yet.
Definition: define.h:236
int8_t ac
Armour Class, how hard to hit, the lower the better.
Definition: living.h:37
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:519
MoveType move_type
Type of movement this object uses.
Definition: object.h:424
Spell-related defines: spellpath, subtypes, ...
int16_t gen_hp
Bonuses to regeneration speed of hp.
Definition: player.h:113
See Key.
Definition: object.h:127
Information.
Definition: logger.h:12
See Ring.
Definition: object.h:185
Definition: object.h:125
Thaumaturgy.
Definition: skills.h:48
int is_magical(const object *op)
Checks whether object is magical.
Definition: item.c:1243
#define FLAG_HITBACK
Object will hit back when hit.
Definition: define.h:267
Eneq((at)csd.uu.se): Id for close_container archetype.
Definition: object.h:229
#define FLAG_USE_SCROLL
(Monster) can read scroll
Definition: define.h:292
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
Definition: item.c:1376
#define SET_FLAG(xyz, p)
Definition: define.h:223
sstring add_refcount(sstring str)
This will increase the refcount of the string str.
Definition: shstr.c:210
#define ARMOUR_SPELLS(xyz)
Definition: define.h:481
See Bracers.
Definition: object.h:217
int get_power_from_ench(int ench)
Definition: item.c:229
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
See Scroll.
Definition: object.h:221
New_Face * new_faces
Contains face information, with names, numbers, magicmap color and such.
Definition: image.c:33
uint16_t animation_id
An index into the animation array.
Definition: object.h:416
#define FLAG_USE_ARMOUR
(Monster) can wear armour/shield/helmet
Definition: define.h:296
void get_levelnumber(int i, char *buf, size_t size)
Formats a level.
Definition: item.c:447
uint8_t anim_speed
Ticks between animation-frames.
Definition: object.h:417
See Cloak.
Definition: object.h:204
See Food.
Definition: object.h:112
struct obj * container
Current container being used.
Definition: object.h:291
uint8_t last_anim
Last sequence used to draw face.
Definition: object.h:418
See Projectile.
Definition: object.h:117
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
int16_t gen_grace
Bonuses to regeneration speed of grace.
Definition: player.h:116
See Holy Altar.
Definition: object.h:161
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
See Spellbook.
Definition: object.h:203
const char * object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.c:4246
See Money.
Definition: object.h:137
struct treasureliststruct * randomitems
Items to be generated.
Definition: object.h:385
void query_base_name(const object *op, int plural, char *buf, size_t size)
Query a short name for the item.
Definition: item.c:723
static const char *const numbers_10[]
Tens.
Definition: item.c:72
object clone
An object from which to do object_copy()
Definition: object.h:470
See Rune.
Definition: object.h:240
See Creator.
Definition: object.h:142
void query_weight(const object *op, char *buf, size_t size)
Formats the item&#39;s weight.
Definition: item.c:427
See Weapon.
Definition: object.h:119
See Helmet.
Definition: object.h:136
const char * slaying
Which race to do double damage to.
Definition: object.h:319
Object for applying character class modifications to someone.
Definition: object.h:138
#define FLAG_STEALTH
Will wake monsters with less range.
Definition: define.h:313
Bowyer.
Definition: skills.h:23
See Altar Trigger.
Definition: object.h:133
See Rod.
Definition: object.h:109
#define FLAG_USE_WEAPON
(Monster) can wield weapons
Definition: define.h:297
int64_t exp
Experience.
Definition: living.h:46
#define FLAG_BLESSED
Item has a blessing, opposite of cursed/damned.
Definition: define.h:378
See Power Crystal.
Definition: object.h:242
static const char *const levelnumbers_10[]
Tens for levels.
Definition: item.c:86
See Button Trigger.
Definition: object.h:132
See Drink.
Definition: object.h:157
treasure is one element in a linked list, which together consist of a complete treasure-list.
Definition: treasure.h:63
See Girdle.
Definition: object.h:223
body_locations_struct body_locations[NUM_BODY_LOCATIONS]
The ordering of this is actually doesn&#39;t make a difference However, for ease of use, new entries should go at the end so those people that debug the code that get used to something being in the location 4 don&#39;t get confused.
Definition: item.c:54
static const typedata item_types[]
The following is a large table of item types, the fields are: item number, item name, item name (plural), and two numbers that are the skills used to identify them.
Definition: item.c:98
See Amulet.
Definition: object.h:139
int8_t get_attr_value(const living *stats, int attr)
Gets the value of a stat.
Definition: living.c:313
Definition: object.h:249
Wall.
Definition: object.h:191
Duplicator/multiplier object.
Definition: object.h:202
uint32_t path_attuned
Paths the object is attuned to.
Definition: object.h:343
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.c:1239
const typedata * get_typedata_by_name(const char *name)
Definition: item.c:355
int16_t sp
Spell points.
Definition: living.h:41
animal &#39;body parts&#39; -b.t.
Definition: object.h:187
Global type definitions and header inclusions.
Link an object type with skill needed to identify, and general name.
Definition: define.h:89
uint32_t path_repelled
Paths the object is repelled from.
Definition: object.h:344
See Boots.
Definition: object.h:212
#define FLAG_USE_RING
(Monster) can use rings, boots, gauntlets, etc
Definition: define.h:298
peterm: detector is an object which notices the presense of another object and is triggered like butt...
Definition: object.h:149
static const int enc_to_item_power[]
This curve may be too steep.
Definition: item.c:222
See Mover.
Definition: object.h:140
See Wand & Staff.
Definition: object.h:220
struct archt * item
Which item this link can be.
Definition: treasure.h:64
Smithery.
Definition: skills.h:22
int16_t hp
Hit Points.
Definition: living.h:39
#define FLAG_KNOWN_MAGICAL
The object is known to be magical.
Definition: define.h:320
Woodsman.
Definition: skills.h:40
uint16_t number
This is the image id.
Definition: face.h:15
See Magic Ear.
Definition: object.h:131
#define UPD_ALL
Definition: newclient.h:297
const typedata * get_typedata(int itemtype)
Definition: item.c:335
#define FLAG_SEE_INVISIBLE
Will see invisible player.
Definition: define.h:253
Allows the use of a skill.
Definition: object.h:189
#define FLAG_UNDEAD
Monster is undead.
Definition: define.h:270
Generic item builder, see subtypes below.
Definition: object.h:246
See Trap.
Definition: object.h:241
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
Definition: object.c:4375
const char * title
Of foo, etc.
Definition: object.h:317
int16_t y
Position in the map for this object.
Definition: object.h:326
Floor tile -> native layer 0.
Definition: object.h:186
See Shooting Weapon.
Definition: object.h:118
#define FLAG_CLIENT_ANIM_RANDOM
Client animate this, randomized.
Definition: define.h:241
static const int item_types_size
Number of items in item_types array.
Definition: item.c:211
uint32_t path_denied
Paths the object is denied access to.
Definition: object.h:345
See Sign & Magic Mouth.
Definition: object.h:211
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
#define FLAG_REFL_SPELL
Spells (some) will reflect from object.
Definition: define.h:275
See Book.
Definition: object.h:114
See Exit.
Definition: object.h:181
const char * name_pl
The plural name of the object.
Definition: object.h:315
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
Definition: stringbuffer.c:95
battleground, by Andreas Vogl
Definition: object.h:163
inserts an invisible, weightless force into a player with a specified string.
Definition: object.h:158
int16_t gen_sp
Bonuses to regeneration speed of sp.
Definition: player.h:114
#define MOVE_SWIM
Swimming object.
Definition: define.h:411
See Treasure.
Definition: object.h:110
See Special Key.
Definition: object.h:124
int32_t weight
Attributes of the object.
Definition: object.h:365
#define FLAG_CAN_USE_SKILL
The monster can use skills.
Definition: define.h:322
#define MOVE_FLY_LOW
Low flying object.
Definition: define.h:408
A real, living creature.
Definition: object.h:200
#define FLAG_UNAGGRESSIVE
Monster doesn&#39;t attack players.
Definition: define.h:272
inserts an invisible, weightless force into a player with a specified string WHEN TRIGGERED...
Definition: object.h:153
See Clock.
Definition: object.h:115
#define FLAG_USE_RANGE
(Monster) can apply and use range items
Definition: define.h:293
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
int is_dragon_pl(const object *op)
Checks if player is a dragon.
Definition: player.c:114
#define snprintf
Definition: win32.h:46
#define FLAG_CLIENT_ANIM_SYNC
Let client animate this, synchronized.
Definition: define.h:240
#define FLAG_IDENTIFIED
Player knows full info about item.
Definition: define.h:261
#define FMT64
Definition: compat.h:12
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
Definition: object.h:145
int32_t carrying
How much weight this object contains.
Definition: object.h:367
const char * name
The name of the object, obviously...
Definition: object.h:311
Alchemy.
Definition: skills.h:25
struct obj * env
Pointer to the object which is the environment.
Definition: object.h:293
#define ARMOUR_SPEED(xyz)
Definition: define.h:480
static StringBuffer * ring_desc(const object *op, StringBuffer *buf)
Describes a ring or amulet, or a skill.
Definition: item.c:473
size_t stringbuffer_length(StringBuffer *sb)
Return the current length of the buffer.
Definition: stringbuffer.c:154
#define GET_MAP_TOP(M, X, Y)
Gets the top object on a map.
Definition: map.h:174
uint32_t nrof
How many of the objects.
Definition: object.h:333
EXTERN const char *const change_resist_msg[NROFATTACKS]
Definition: attack.h:135
#define UPD_FLAGS
Definition: newclient.h:290
Number of statistics.
Definition: living.h:18
See Trapdoor.
Definition: object.h:210
See Potion.
Definition: object.h:111
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
int8_t item_power
Power rating of the object.
Definition: object.h:362
See Shop Mat.
Definition: object.h:184
#define FLAG_XRAYS
X-ray vision.
Definition: define.h:301
#define ATNR_PHYSICAL
Definition: attack.h:49
int8_t luck
Affects thaco and ac from time to time.
Definition: living.h:38
float speed
The overall speed of this object.
Definition: object.h:328
See Spell.
Definition: object.h:214
static const char *const levelnumbers[]
Levels as a full name and not a number.
Definition: item.c:78
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
See Handle Trigger.
Definition: object.h:129
#define FLAG_BEEN_APPLIED
The object has been applied.
Definition: define.h:324
See Locked Door.
Definition: object.h:123
#define NRSPELLPATHS
Number of spell paths.
Definition: spells.h:40
See Spinner.
Definition: object.h:205
See Door.
Definition: object.h:126
#define FLAG_CAST_SPELL
(Monster) can learn and cast spells
Definition: define.h:291
See Magic Wall.
Definition: object.h:168
Object owned by a player which can convert a monster into a peaceful being incapable of attack...
Definition: object.h:164
See Converter.
Definition: object.h:216
int16_t x
Definition: object.h:326
StringBuffer * describe_attacktype(const char *attack, int value, StringBuffer *buf)
Describe the specified attack type.
Definition: utils.c:561
Literacy.
Definition: skills.h:27
can add a skill to player&#39;s inventory -bt.
Definition: object.h:234
struct treasurestruct * items
Items in this list, linked.
Definition: treasure.h:90
int32_t last_eat
How long since we last ate.
Definition: object.h:356
int calc_item_power(const object *op)
This takes an object &#39;op&#39; and figures out what its item_power rating should be.
Definition: item.c:247
Lamp.
Definition: object.h:201
int8_t wc
Weapon Class, how skilled, the lower the better.
Definition: living.h:36
See Container.
Definition: object.h:231
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.c:212
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:341
#define FLAG_KNOWN_CURSED
The object is known to be cursed.
Definition: define.h:321
const char * sstring
Strings that should be manipulated through add_string() and free_string().
Definition: global.h:40
int need_identify(const object *op)
This function really should not exist - by default, any item not identified should need it...
Definition: item.c:1332
#define FLAG_CURSED
The object is cursed.
Definition: define.h:317
See Player.
Definition: object.h:107
See Poison Food.
Definition: object.h:113
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&#39;t overwrite ...
Definition: porting.c:346
See Shield.
Definition: object.h:135
See Floor (Encounter).
Definition: object.h:182
#define FLAG_ANIMATE
The object looks at archetype for faces.
Definition: define.h:242
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: item.c:405
Jeweler.
Definition: skills.h:24
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:342
StringBuffer * describe_item(const object *op, const object *owner, int use_media_tags, StringBuffer *buf)
Describes an item, in all its details.
Definition: item.c:981
Mark Wedel (mark@pyramid.com) Shop inventories.
Definition: object.h:238
See Altar.
Definition: object.h:122
#define FREE_AND_COPY(sv, nv)
Release the shared string if not NULL, and make it a reference to nv.
Definition: global.h:213
int16_t grace
Grace.
Definition: living.h:43
Definition: object.h:243
Also see SKILL_TOOL (74) below.
Definition: object.h:143
StringBuffer * describe_monster(const object *op, int use_media_tags, StringBuffer *buf)
Describes a monster.
Definition: item.c:807
living stats
Str, Con, Dex, etc.
Definition: object.h:368
struct archt * arch
Pointer to archetype.
Definition: object.h:412
See Shop Floor.
Definition: object.h:183
#define UPD_FACE
Definition: newclient.h:292
See Button.
Definition: object.h:207
See Gate.
Definition: object.h:206
misc.
Definition: object.h:193
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
Material for building.
Definition: object.h:248
See Handle.
Definition: object.h:208
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
#define NROFATTACKS
Definition: attack.h:17
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.c:1869
EXTERN const char *const resist_plus[NROFATTACKS]
Definition: attack.h:136
void query_short_name(const object *op, char *buf, size_t size)
query_short_name(object) is similar to query_name(), but doesn&#39;t contain any information about object...
Definition: item.c:548
See Timed Gate.
Definition: object.h:128
object * object_get_player_container(object *op)
Finds the player carrying an object.
Definition: object.c:353
#define FLAG_LIFESAVE
Saves a players&#39; life once, then destr.
Definition: define.h:306
signed int int32_t
Definition: win32.h:159
#define UPD_NAME
Definition: newclient.h:293
#define FLAG_MAKE_INVIS
(Item) gives invisibility when applied
Definition: define.h:329
StringBuffer * describe_resistance(const object *op, int newline, int use_media_tags, StringBuffer *buf)
Generates the visible naming for resistances.
Definition: item.c:384
object * identify(object *op)
Identifies an item.
Definition: item.c:1438
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.c:104
#define MIN_ACTIVE_SPEED
Cut off point of when an object is put on the active list or not.
Definition: define.h:674
StringBuffer * describe_spellpath_attenuation(const char *attenuation, int value, StringBuffer *buf)
Describe the specified path attenuation.
Definition: utils.c:533
int8_t glow_radius
indicates the glow radius of the object
Definition: object.h:364
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
See Monster (Grimreaper).
Definition: object.h:130
struct obj * inv
Pointer to the first object in the inventory.
Definition: object.h:290
See Gloves.
Definition: object.h:213
One body location.
Definition: object.h:20
#define MOVE_FLY_HIGH
High flying object.
Definition: define.h:409
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
A force, holding the effect of a resistance potion.
Definition: object.h:225
metals, minerals, dragon scales
Definition: object.h:188
Structure containing object statistics.
See Pit.
Definition: object.h:209
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.c:626
See Swamp.
Definition: object.h:236
const New_Face * face
Face with colors.
Definition: object.h:332
See Jewel.
Definition: object.h:167
#define FLAG_NO_SKILL_IDENT
If set, item cannot be identified w/ a skill.
Definition: define.h:336
const char *const short_stat_name[NUM_STATS]
Short name of stats.
Definition: living.c:194
See Breastplate Armor.
Definition: object.h:120
struct treasurestruct * next
Next treasure-item in a linked list.
Definition: treasure.h:66
#define FLAG_REFL_MISSILE
Arrows will reflect from object.
Definition: define.h:273
int16_t level
Level of creature or object.
Definition: object.h:351
int8_t facing
Object is oriented/facing that way.
Definition: object.h:335
#define FLAG_INV_LOCKED
Item will not be dropped from inventory.
Definition: define.h:330
unsigned find_face(const char *name, unsigned error)
This returns an the face number of face &#39;name&#39;.
Definition: image.c:303
Definition: object.h:148
See Disease.
Definition: object.h:244
int8_t magic
Any magical bonuses to this item.
Definition: object.h:348
See Director.
Definition: object.h:222
See Teleporter.
Definition: object.h:141
int16_t digestion
Any bonuses/penalties to digestion.
Definition: player.h:112
#define FLAG_USE_BOW
(Monster) can apply and fire bows
Definition: define.h:294
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
EXTERN const char *const resist_color[NROFATTACKS]
Definition: attack.h:137
b.t.
Definition: object.h:170
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.c:2974
See Savebed.
Definition: object.h:219
int atnr_is_dragon_enabled(int attacknr)
Determine if the attacktype represented by the specified attack-number is enabled for dragon players...
Definition: player.c:95
int32_t food
How much food in stomach.
Definition: living.h:47
b.t.
Definition: object.h:169
Definition: object.h:224
#define FLAG_IS_TURNABLE
Object can change face with direction.
Definition: define.h:256