ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.24
Committed: Wed Mar 14 04:12:27 2007 UTC (17 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.23: +1 -1 lines
Log Message:
- rewrote more face handling code
- automatically send smooth faces, as the client will need them anyways
  and it makes little sense to wait for the client to axk for it. of course,
  gcfclient suffers from weird ordering problems again.
- UP_OBJ_FACE was often abused in situations where other things changed,
  updated lots of spaces, probably more to be done.
- update_smooth became so small that inlining it actually clarified
  the code. similar for update_space, which is not inlined for other reasons.
- faces were not initialised properly
- add versioncheck for face data
- rewrite invisibility handling a bit: god finger etc. now makes you blink,
  blinking routine has changed to be less annoying and more useful while
  still indicating invisibleness.

File Contents

# Content
1 /*
2 * CrossFire, A Multiplayer game for X-windows
3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (C) 1992 Frank Tore Johansen
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * The authors can be reached via e-mail at <crossfire@schmorp.de>
23 */
24
25 #include <global.h>
26 #include <funcpoint.h>
27 #include <living.h>
28 #include <spells.h>
29
30 /* the ordering of this is actually doesn't make a difference
31 * However, for ease of use, new entries should go at the end
32 * so those people that debug the code that get used to something
33 * being in the location 4 don't get confused.
34 *
35 * The ordering in save_name, use_name, nonuse_name.
36 * save_name is the name used to load/save it from files. It should
37 * match that of the doc/Developers/objects. The only
38 * real limitation is that it shouldn't have spaces or other characters
39 * that may mess up the match code. It must also start with body_
40 * use_name is how we describe the location if we can use it.
41 * nonuse_name is how we describe it if we can't use it. I think
42 * the values below will make it pretty clear how those work out
43 * They are basically there to make life a little easier - if a character
44 * examines an item and it says it goes on 'your arm', its pretty clear
45 * they can use it. See the last sample (commented out) for a dragon
46 * Note that using the term 'human' may not be very accurate, humanoid
47 * may be better.
48 * Basically, for the use/nonuse, the code does something like:
49 * "This item goes %s\n", with the use/nonuse values filling in the %s
50 */
51 Body_Locations body_locations[NUM_BODY_LOCATIONS] = {
52 {"body_range", "in your range slot", "in a human's range slot"},
53 {"body_arm", "on your arm", "on a human's arm"},
54 {"body_torso", "on your body", "on a human's torso"},
55 {"body_head", "on your head", "on a human's head"},
56 {"body_neck", "around your neck", "around a humans neck"},
57 {"body_skill", "in your skill slot", "in a human's skill slot"},
58 {"body_finger", "on your finger", "on a human's finger"} ,
59 {"body_shoulder", "around your shoulders", "around a human's shoulders"},
60 {"body_foot", "on your feet", "on a human's feet"},
61 {"body_hand", "on your hands", "on a human's hands"},
62 {"body_wrist", "around your wrists", "around a human's wrist"},
63 {"body_waist", "around your waist", "around a human's waist"},
64 /*{"body_dragon_torso", "your body", "a dragon's body"} */
65 };
66
67 static char numbers[21][20] = {
68 "no", "", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
69 "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
70 "eighteen", "nineteen", "twenty"
71 };
72
73 static char numbers_10[10][20] = {
74 "zero", "ten", "twenty", "thirty", "fourty", "fifty", "sixty", "seventy",
75 "eighty", "ninety"
76 };
77
78 static char levelnumbers[21][20] = {
79 "zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh",
80 "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth",
81 "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteen",
82 "nineteen", "twentieth"
83 };
84
85 static char levelnumbers_10[11][20] = {
86 "zeroth", "tenth", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth",
87 "seventieth", "eightieth", "ninetieth"
88 };
89
90 /* The following is a large table of item types, the fields are:
91 * item number, item name, item name (plural), and two numbers that are the skills
92 * used to identify them. Anytime a new item type is added or removed, this list
93 * should be altered to reflect that. The defines for the numerical values are in
94 * define.h
95 */
96 static const typedata item_types[] = {
97 {PLAYER, "player", "players", 0, 0},
98 {ROD, "rod", "rods", SK_THAUMATURGY, 0},
99 {TREASURE, "treasure", "treasure", 0, 0},
100 {POTION, "potion", "potions", SK_ALCHEMY, 0},
101 {FOOD, "food", "food", SK_WOODSMAN, 0},
102 {POISON, "poison", "poisons", SK_ALCHEMY, 0},
103 {BOOK, "book", "books", SK_LITERACY, 0},
104 {CLOCK, "clock", "clocks", 0, 0},
105 {ARROW, "arrow", "arrows", SK_BOWYER, 0},
106 {BOW, "bow", "bows", SK_BOWYER, 0},
107 {WEAPON, "weapon", "weapons", SK_SMITHERY, 0},
108 {ARMOUR, "armour", "armour", SK_SMITHERY, 0},
109 {PEDESTAL, "pedestal", "pedestals", 0, 0},
110 {ALTAR, "altar", "altars", 0, 0},
111 {LOCKED_DOOR, "locked door", "locked doors", 0, 0},
112 {SPECIAL_KEY, "special key", "special keys", 0, 0},
113 {MAP, "map", "maps", 0, 0},
114 {DOOR, "door", "doors", 0, 0},
115 {KEY, "key", "keys", 0, 0},
116 {TIMED_GATE, "timed_gate", "timed_gates", 0, 0},
117 {TRIGGER, "trigger", "triggers", 0, 0},
118 {GRIMREAPER, "grimreaper", "grimreapers", 0, 0},
119 {MAGIC_EAR, "magic ear", "magic ears", 0, 0},
120 {TRIGGER_BUTTON, "trigger button", "trigger buttons", 0, 0},
121 {TRIGGER_ALTAR, "trigger altar", "trigger altars", 0, 0},
122 {TRIGGER_PEDESTAL, "trigger pedestal", "trigger pedestals", 0, 0},
123 {SHIELD, "shield", "shields", SK_SMITHERY, 0},
124 {HELMET, "helmet", "helmets", SK_SMITHERY, 0},
125 {HORN, "horn", "horns", SK_THAUMATURGY, 0},
126 {MONEY, "money", "money", 0, 0},
127 {CLASS, "class", "classes", 0, 0},
128 {GRAVESTONE, "gravestone", "gravestones", 0, 0},
129 {AMULET, "amulet", "amulets", SK_JEWELER, 0},
130 {PLAYERMOVER, "player mover", "player movers", 0, 0},
131 {TELEPORTER, "teleporter", "teleporters", 0, 0},
132 {CREATOR, "creator", "creators", 0, 0},
133 {SKILL, "skill", "skills", 0, 0},
134 {EARTHWALL, "earthwall", "earthwalls", 0, 0},
135 {GOLEM, "golem", "golems", 0, 0},
136 {THROWN_OBJ, "projectile", "projectiles", 0, 0},
137 {BLINDNESS, "blindness", "blindness", 0, 0},
138 {GOD, "god", "gods", 0, 0},
139 {DETECTOR, "detector", "detectors", 0, 0},
140 {TRIGGER_MARKER, "trigger marker", "trigger markers", 0, 0},
141 {DEAD_OBJECT, "dead object", "dead objects", 0, 0},
142 {DRINK, "drink", "drinks", SK_WOODSMAN, SK_ALCHEMY},
143 {MARKER, "marker", "markers", 0, 0},
144 {HOLY_ALTAR, "holy altar", "holy altars", 0, 0},
145 {PLAYER_CHANGER, "player changer", "player changers", 0, 0},
146 {BATTLEGROUND, "battleground", "battlegrounds", 0, 0},
147 {PEACEMAKER, "peacemaker", "peacemakers", 0, 0},
148 {GEM, "gem", "gems", SK_JEWELER, 0},
149 {FIREWALL, "firewall", "firewalls", 0, 0},
150 {ANVIL, "anvil", "anvils", 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 {BUILDABLE_WALL, "buildable wall", "buildable walls", 0, 0},
164 {MISC_OBJECT, "bric-a-brac", "bric-a-brac", 0, 0},
165 {LAMP, "lamp", "lamps", 0, 0},
166 {DUPLICATOR, "duplicator", "duplicators", 0, 0},
167 {SPELLBOOK, "spellbook", "spellbooks", SK_LITERACY, 0},
168 {CLOAK, "cloak", "cloaks", SK_SMITHERY, 0},
169 {SPINNER, "spinner", "spinners", 0, 0},
170 {GATE, "gate", "gates", 0, 0},
171 {BUTTON, "button", "buttons", 0, 0},
172 {CF_HANDLE, "cf handle", "cf handles", 0, 0},
173 {HOLE, "hole", "holes", 0, 0},
174 {TRAPDOOR, "trapdoor", "trapdoors", 0, 0},
175 {SIGN, "sign", "signs", 0, 0},
176 {BOOTS, "boots", "boots", SK_SMITHERY, 0},
177 {GLOVES, "gloves", "gloves", SK_SMITHERY, 0},
178 {SPELL, "spell", "spells", 0, 0},
179 {SPELL_EFFECT, "spell effect", "spell effects", 0, 0},
180 {CONVERTER, "converter", "converters", 0, 0},
181 {BRACERS, "bracers", "bracers", SK_SMITHERY, 0},
182 {POISONING, "poisoning", "poisonings", 0, 0},
183 {SAVEBED, "savebed", "savebeds", 0, 0},
184 {WAND, "wand", "wands", SK_THAUMATURGY, 0},
185 {SCROLL, "scroll", "scrolls", SK_LITERACY, 0},
186 {DIRECTOR, "director", "directors", 0, 0},
187 {GIRDLE, "girdle", "girdles", SK_SMITHERY, 0},
188 {FORCE, "force", "forces", 0, 0},
189 {POTION_EFFECT, "potion effect", "potion effects", 0, 0},
190 {CLOSE_CON, "closed container", "closed container", 0, 0},
191 {CONTAINER, "container", "containers", SK_ALCHEMY, 0},
192 {ARMOUR_IMPROVER, "armour improver", "armour improvers", 0, 0},
193 {WEAPON_IMPROVER, "weapon improver", "weapon improvers", 0, 0},
194 {SKILLSCROLL, "skillscroll", "skillscrolls", 0, 0},
195 {DEEP_SWAMP, "deep swamp", "deep swamps", 0, 0},
196 {IDENTIFY_ALTAR, "identify altar", "identify altars", 0, 0},
197 {MENU, "inventory list", "inventory lists", 0, 0},
198 {RUNE, "rune", "runes", 0, 0},
199 {TRAP, "trap", "traps", 0, 0},
200 {POWER_CRYSTAL, "power_crystal", "power_crystals", 0, 0},
201 {CORPSE, "corpse", "corpses", 0, 0},
202 {DISEASE, "disease", "diseases", 0, 0},
203 {SYMPTOM, "symptom", "symptoms", 0, 0},
204 {BUILDER, "item builder", "item builders", 0, 0},
205 {MATERIAL, "building material", "building materials", 0, 0},
206 {ITEM_TRANSFORMER, "item_transformer", "item_transformers", 0, 0},
207 };
208
209 const int item_types_size = sizeof (item_types) / sizeof (*item_types);
210
211 materialtype_t *materialt;
212
213 /*
214 materialtype material[NROFMATERIALS] = {
215 * P M F E C C A D W G P S P T F C D D C C G H B I *
216 * H A I L O O C R E H O L A U E A E E H O O O L N *
217 * Y G R E L N I A A O I O R R A N P A A U D L I T *
218 * S I E C D F D I P S S W A N R C L T O N Y N R *
219 * I C T U N O T O L E E H S T P D N *
220 {"paper", {15,10,17, 9, 5, 7,13, 0,20,15, 0,0,0,0,0,10,0,0,0,0,0,0,0,0}},
221 {"metal", { 2,12, 3,12, 2,10, 7, 0,20,15, 0,0,0,0,0,10,0,0,0,0,0,0,0,0}},
222 {"glass", {14,11, 8, 3,10, 5, 1, 0,20,15, 0,0,0,0,0, 0,0,0,0,0,0,0,0,0}},
223 {"leather", { 5,10,10, 3, 3,10,10, 0,20,15, 0,0,0,0,0,12,0,0,0,0,0,0,0,0}},
224 {"wood", {10,11,13, 2, 2,10, 9, 0,20,15, 0,0,0,0,0,12,0,0,0,0,0,0,0,0}},
225 {"organics", { 3,12, 9,11, 3,10, 9, 0,20,15, 0,0,0,0,0, 0,0,0,0,0,0,0,0,0}},
226 {"stone", { 2, 5, 2, 2, 2, 2, 1, 0,20,15, 0,0,0,0,0, 5,0,0,0,0,0,0,0,0}},
227 {"cloth", {14,11,13, 4, 4, 5,10, 0,20,15, 0,0,0,0,0, 5,0,0,0,0,0,0,0,0}},
228 {"adamant", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0, 0,0,0,0,0,0,0,0,0}},
229 {"liquid", { 0, 8, 9, 6,17, 0,15, 0,20,15,12,0,0,0,0,11,0,0,0,0,0,0,0,0}},
230 {"soft metal",{ 6,12, 6,14, 2,10, 1, 0,20,15, 0,0,0,0,0,10,0,0,0,0,0,0,0,0}},
231 {"bone", {10, 9, 4, 5, 3,10,10, 0,20,15, 0,0,0,0,0, 2,0,0,0,0,0,0,0,0}},
232 {"ice", {14,11,16, 5, 0, 5, 6, 0,20,15, 0,0,0,0,0, 7,0,0,0,0,0,0,0,0}}
233 };
234 */
235
236 /* This curve may be too steep. But the point is that there should
237 * be tough choices - there is no real point to this if everyone can
238 * wear whatever they want with no worries. Perhaps having the steep
239 * curve is good (maybe even steeper), but allowing players to
240 * have 2 * level instead. Ideally, top level characters should only be
241 * able to use 2-3 of the most powerful items.
242 * note that this table is only really used for program generated items -
243 * custom objects can use whatever they want.
244 */
245 static int enc_to_item_power[21] = {
246 0, 0, 1, 2, 3, 4, /* 5 */
247 5, 7, 9, 11, 13, /* 10 */
248 15, 18, 21, 24, 27, /* 15 */
249 30, 35, 40, 45, 50 /* 20 */
250 };
251
252 int
253 get_power_from_ench (int ench)
254 {
255 if (ench < 0)
256 ench = 0;
257 if (ench > 20)
258 ench = 20;
259 return enc_to_item_power[ench];
260 }
261
262 /* This takes an object 'op' and figures out what its item_power
263 * rating should be. This should only really be used by the treasure
264 * generation code, and when loading legacy objects. It returns
265 * the item_power it calculates.
266 * If flag is 1, we return the number of enchantment, and not the
267 * the power. This is used in the treasure code.
268 */
269 int
270 calc_item_power (const object *op, int flag)
271 {
272 int i, tmp, enc;
273
274 enc = 0;
275 for (i = 0; i < NUM_STATS; i++)
276 enc += get_attr_value (&op->stats, i);
277
278 /* This protection logic is pretty flawed. 20% fire resistance
279 * is much more valuable than 20% confusion, or 20% slow, or
280 * several others. Start at 1 - ignore physical - all that normal
281 * armour shouldn't be counted against
282 */
283 tmp = 0;
284 for (i = 1; i < NROFATTACKS; i++)
285 tmp += op->resist[i];
286
287 /* Add/substract 10 so that the rounding works out right */
288 if (tmp > 0)
289 enc += (tmp + 10) / 20;
290 else if (tmp < 0)
291 enc += (tmp - 10) / 20;
292
293 enc += op->magic;
294
295 /* For each attacktype a weapon has, one more encantment. Start at 1 -
296 * physical doesn't count against total.
297 */
298 if (op->type == WEAPON)
299 {
300 for (i = 1; i < NROFATTACKS; i++)
301 if (op->attacktype & (1 << i))
302 enc++;
303 if (op->slaying)
304 enc += 2; /* What it slays is probably more relevent */
305 }
306 /* Items the player can equip */
307 if ((op->type == WEAPON) || (op->type == ARMOUR) || (op->type == HELMET) ||
308 (op->type == SHIELD) || (op->type == RING) ||
309 (op->type == BOOTS) || (op->type == GLOVES) ||
310 (op->type == AMULET) || (op->type == GIRDLE) || (op->type == BRACERS) || (op->type == CLOAK))
311 {
312 enc += op->stats.food; /* sustenance */
313 enc += op->stats.hp; /* hp regen */
314 enc += op->stats.sp; /* mana regen */
315 enc += op->stats.grace; /* grace regen */
316 enc += op->stats.exp; /* speed bonus */
317 }
318 enc += op->stats.luck;
319
320 /* Do spell paths now */
321 for (i = 1; i < NRSPELLPATHS; i++)
322 {
323 if (op->path_attuned & (1 << i))
324 enc++;
325 else if (op->path_denied & (1 << i))
326 enc -= 2;
327 else if (op->path_repelled & (1 << i))
328 enc--;
329 }
330
331 if (QUERY_FLAG (op, FLAG_LIFESAVE))
332 enc += 5;
333 if (QUERY_FLAG (op, FLAG_REFL_SPELL))
334 enc += 3;
335 if (QUERY_FLAG (op, FLAG_REFL_MISSILE))
336 enc += 2;
337 if (QUERY_FLAG (op, FLAG_STEALTH))
338 enc += 1;
339 if (QUERY_FLAG (op, FLAG_XRAYS))
340 enc += 2;
341 if (QUERY_FLAG (op, FLAG_SEE_IN_DARK))
342 enc += 1;
343 if (QUERY_FLAG (op, FLAG_MAKE_INVIS))
344 enc += 1;
345
346 return get_power_from_ench (enc);
347
348 }
349
350 /* returns the typedata that has a number equal to itemtype, if there
351 * isn't one, returns NULL */
352
353 const typedata *
354 get_typedata (int itemtype)
355 {
356 int i;
357
358 for (i = 0; i < item_types_size; i++)
359 if (item_types[i].number == itemtype)
360 return &item_types[i];
361 return NULL;
362 }
363
364 /* returns the typedata that has a name equal to itemtype, if there
365 * isn't one, return the plural name that matches, if there still isn't
366 * one return NULL */
367
368 const typedata *
369 get_typedata_by_name (const char *name)
370 {
371 int i;
372
373 for (i = 0; i < item_types_size; i++)
374 if (!strcmp (item_types[i].name, name))
375 return &item_types[i];
376 for (i = 0; i < item_types_size; i++)
377 if (!strcmp (item_types[i].name_pl, name))
378 {
379 LOG (llevInfo,
380 "get_typedata_by_name: I have been sent the plural %s, the singular form %s is preffered\n", name, item_types[i].name);
381 return &item_types[i];
382 }
383 return NULL;
384 }
385
386 /* describe_resistance generates the visible naming for resistances.
387 * returns a static array of the description. This can return
388 * a big buffer.
389 * if newline is true, we don't put parens around the description
390 * but do put a newline at the end. Useful when dumping to files
391 */
392 char *
393 describe_resistance (const object *op, int newline)
394 {
395 static char buf[VERY_BIG_BUF];
396 char buf1[VERY_BIG_BUF];
397 int tmpvar;
398
399 buf[0] = 0;
400 for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++)
401 {
402 if (op->resist[tmpvar] && (op->type != FLESH || atnr_is_dragon_enabled (tmpvar) == 1))
403 {
404 if (!newline)
405 sprintf (buf1, "(%s %+d)", resist_plus[tmpvar], op->resist[tmpvar]);
406 else
407 sprintf (buf1, "%s %d\n", resist_plus[tmpvar], op->resist[tmpvar]);
408
409 strcat (buf, buf1);
410 }
411 }
412 return buf;
413 }
414
415
416 /*
417 * query_weight(object) returns a character pointer to a static buffer
418 * containing the text-representation of the weight of the given object.
419 * The buffer will be overwritten by the next call to query_weight().
420 */
421
422 char *
423 query_weight (const object *op)
424 {
425 static char buf[10];
426 sint32 i = (op->nrof ? op->nrof : 1) * op->weight + op->carrying;
427
428 if (op->weight < 0)
429 return " ";
430 if (i % 1000)
431 sprintf (buf, "%6.1f", i / 1000.0);
432 else
433 sprintf (buf, "%4d ", i / 1000);
434 return buf;
435 }
436
437 /*
438 * Returns the pointer to a static buffer containing
439 * the number requested (of the form first, second, third...)
440 */
441
442 char *
443 get_levelnumber (int i)
444 {
445 static char buf[MAX_BUF];
446
447 if (i > 99)
448 {
449 sprintf (buf, "%d.", i);
450 return buf;
451 }
452 if (i < 21)
453 return levelnumbers[i];
454 if (!(i % 10))
455 return levelnumbers_10[i / 10];
456 strcpy (buf, numbers_10[i / 10]);
457 strcat (buf, levelnumbers[i % 10]);
458 return buf;
459 }
460
461 /*
462 * get_number(integer) returns the text-representation of the given number
463 * in a static buffer. The buffer might be overwritten at the next
464 * call to get_number().
465 * It is currently only used by the query_name() function.
466 */
467 char *
468 get_number (int i)
469 {
470 if (i <= 20)
471 return numbers[i];
472 else
473 {
474 static char buf[MAX_BUF];
475
476 sprintf (buf, "%d", i);
477 return buf;
478 }
479 }
480
481 /*
482 * Returns pointer to static buffer containing ring's or amulet's
483 * abilities
484 * These are taken from old query_name(), but it would work better
485 * if describle_item() would be called to get this information and
486 * caller would handle FULL_RING_DESCRIPTION definition.
487 * Or make FULL_RING_DESCRIPTION standard part of a game and let
488 * client handle names.
489 */
490
491 /* Aug 95 modified this slightly so that Skill tools don't have magic bonus
492 * from stats.sp - b.t.
493 */
494 char *
495 ring_desc (const object *op)
496 {
497 static char buf[VERY_BIG_BUF];
498 int attr, val, len;
499
500 buf[0] = 0;
501
502 if (!QUERY_FLAG (op, FLAG_IDENTIFIED))
503 return buf;
504
505 for (attr = 0; attr < NUM_STATS; attr++)
506 {
507 if ((val = get_attr_value (&(op->stats), attr)) != 0)
508 {
509 sprintf (buf + strlen (buf), "(%s%+d)", short_stat_name[attr], val);
510 }
511 }
512 if (op->stats.exp)
513 sprintf (buf + strlen (buf), "(speed %+lld)", (long long) op->stats.exp);
514 if (op->stats.wc)
515 sprintf (buf + strlen (buf), "(wc%+d)", op->stats.wc);
516 if (op->stats.dam)
517 sprintf (buf + strlen (buf), "(dam%+d)", op->stats.dam);
518 if (op->stats.ac)
519 sprintf (buf + strlen (buf), "(ac%+d)", op->stats.ac);
520
521 strcat (buf, describe_resistance (op, 0));
522
523 if (op->stats.food != 0)
524 sprintf (buf + strlen (buf), "(sustenance%+d)", op->stats.food);
525 /* else if (op->stats.food < 0)
526 sprintf(buf+strlen(buf), "(hunger%+d)", op->stats.food); */
527 if (op->stats.grace)
528 sprintf (buf + strlen (buf), "(grace%+d)", op->stats.grace);
529 if (op->stats.sp && op->type != SKILL)
530 sprintf (buf + strlen (buf), "(magic%+d)", op->stats.sp);
531 if (op->stats.hp)
532 sprintf (buf + strlen (buf), "(regeneration%+d)", op->stats.hp);
533 if (op->stats.luck)
534 sprintf (buf + strlen (buf), "(luck%+d)", op->stats.luck);
535 if (QUERY_FLAG (op, FLAG_LIFESAVE))
536 strcat (buf, "(lifesaving)");
537 if (QUERY_FLAG (op, FLAG_REFL_SPELL))
538 strcat (buf, "(reflect spells)");
539 if (QUERY_FLAG (op, FLAG_REFL_MISSILE))
540 strcat (buf, "(reflect missiles)");
541 if (QUERY_FLAG (op, FLAG_STEALTH))
542 strcat (buf, "(stealth)");
543 /* Shorten some of the names, so they appear better in the windows */
544 len = strlen (buf);
545 DESCRIBE_PATH_SAFE (buf, op->path_attuned, "Attuned", &len, VERY_BIG_BUF);
546 DESCRIBE_PATH_SAFE (buf, op->path_repelled, "Repelled", &len, VERY_BIG_BUF);
547 DESCRIBE_PATH_SAFE (buf, op->path_denied, "Denied", &len, VERY_BIG_BUF);
548
549 /* if(op->item_power)
550 sprintf(buf+strlen(buf), "(item_power %+d)",op->item_power);
551 */
552 if (buf[0] == 0 && op->type != SKILL)
553 strcpy (buf, "of adornment");
554
555
556 return buf;
557 }
558
559 /*
560 * query_short_name(object) is similar to query_name, but doesn't
561 * contain any information about object status (worn/cursed/etc.)
562 */
563 const char *
564 query_short_name (const object *op)
565 {
566 static char buf[HUGE_BUF];
567 char buf2[HUGE_BUF];
568 int len = 0;
569
570 if (op->name == NULL)
571 return "(null)";
572
573 if (!op->nrof && !op->weight && !op->title && !is_magical (op))
574 return op->name; /* To speed things up (or make things slower?) */
575
576 if (op->nrof <= 1)
577 safe_strcat (buf, op->name, &len, HUGE_BUF);
578 else
579 safe_strcat (buf, op->name_pl, &len, HUGE_BUF);
580
581 if (op->title && QUERY_FLAG (op, FLAG_IDENTIFIED))
582 {
583 safe_strcat (buf, " ", &len, HUGE_BUF);
584 safe_strcat (buf, op->title, &len, HUGE_BUF);
585 }
586
587 switch (op->type)
588 {
589 case SPELLBOOK:
590 case SCROLL:
591 case WAND:
592 case ROD:
593 if (QUERY_FLAG (op, FLAG_IDENTIFIED) || QUERY_FLAG (op, FLAG_BEEN_APPLIED))
594 {
595 if (!op->title)
596 {
597 safe_strcat (buf, " of ", &len, HUGE_BUF);
598 if (op->inv)
599 safe_strcat (buf, op->inv->name, &len, HUGE_BUF);
600 else
601 LOG (llevError, "Spellbook %s lacks inventory\n", &op->name);
602 }
603 if (op->type != SPELLBOOK)
604 {
605 sprintf (buf2, " (lvl %d)", op->level);
606 safe_strcat (buf, buf2, &len, HUGE_BUF);
607 }
608 }
609 break;
610
611 case SKILL:
612 case AMULET:
613 case RING:
614 if (!op->title)
615 {
616 /* If ring has a title, full description isn't so useful */
617 char *s = ring_desc (op);
618
619 if (s[0])
620 {
621 safe_strcat (buf, " ", &len, HUGE_BUF);
622 safe_strcat (buf, s, &len, HUGE_BUF);
623 }
624 }
625 break;
626 default:
627 if (op->magic && ((QUERY_FLAG (op, FLAG_BEEN_APPLIED) && need_identify (op)) || QUERY_FLAG (op, FLAG_IDENTIFIED)))
628 {
629 sprintf (buf2, " %+d", op->magic);
630 safe_strcat (buf, buf2, &len, HUGE_BUF);
631 }
632 }
633 return buf;
634 }
635
636 /*
637 * query_name(object) returns a character pointer pointing to a static
638 * buffer which contains a verbose textual representation of the name
639 * of the given object.
640 * cf 0.92.6: Put in 5 buffers that it will cycle through. In this way,
641 * you can make several calls to query_name before the bufs start getting
642 * overwritten. This may be a bad thing (it may be easier to assume the value
643 * returned is good forever.) However, it makes printing statements that
644 * use several names much easier (don't need to store them to temp variables.)
645 *
646 */
647 char *
648 query_name (const object *op)
649 {
650 static char buf[5][HUGE_BUF]; // OMFG
651 static int use_buf = 0;
652 int len = 0;
653
654 #ifdef NEW_MATERIAL_CODE
655 materialtype_t *mt;
656 #endif
657
658 use_buf++;
659 use_buf %= 5;
660
661 #ifdef NEW_MATERIAL_CODE
662 if ((op->is_armor () || op->is_weapon ()) && op->materialname)
663 {
664 mt = name_to_material (op->materialname);
665 if (mt)
666 {
667 safe_strcat (buf[use_buf], mt->description, &len, HUGE_BUF);
668 safe_strcat (buf[use_buf], " ", &len, HUGE_BUF);
669 }
670 }
671 #endif
672
673 safe_strcat (buf[use_buf], query_short_name (op), &len, HUGE_BUF);
674
675 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
676 safe_strcat (buf[use_buf], " *", &len, HUGE_BUF);
677 if (op->type == CONTAINER && ((op->env && op->env->container == op) || (!op->env && QUERY_FLAG (op, FLAG_APPLIED))))
678 safe_strcat (buf[use_buf], " (open)", &len, HUGE_BUF);
679
680 if (QUERY_FLAG (op, FLAG_KNOWN_CURSED))
681 {
682 if (QUERY_FLAG (op, FLAG_DAMNED))
683 safe_strcat (buf[use_buf], " (damned)", &len, HUGE_BUF);
684 else if (QUERY_FLAG (op, FLAG_CURSED))
685 safe_strcat (buf[use_buf], " (cursed)", &len, HUGE_BUF);
686 }
687
688 /* Basically, if the object is known magical (detect magic spell on it),
689 * and it isn't identified, print out the fact that
690 * it is magical. Assume that the detect magical spell will only set
691 * KNOWN_MAGICAL if the item actually is magical.
692 *
693 * Changed in V 0.91.4 - still print that the object is magical even
694 * if it has been applied. Equipping an item does not tell full
695 * abilities, especially for artifact items.
696 */
697 if (QUERY_FLAG (op, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (op, FLAG_IDENTIFIED))
698 safe_strcat (buf[use_buf], " (magic)", &len, HUGE_BUF);
699
700 #if 0
701 /* item_power will be returned in desribe_item - it shouldn't really
702 * be returned in the name.
703 */
704 if (op->item_power)
705 sprintf (buf[use_buf] + strlen (buf[use_buf]), "(item_power %+d)", op->item_power);
706
707 #endif
708
709 if (QUERY_FLAG (op, FLAG_APPLIED))
710 {
711 switch (op->type)
712 {
713 case BOW:
714 case WAND:
715 case ROD:
716 case HORN:
717 safe_strcat (buf[use_buf], " (readied)", &len, HUGE_BUF);
718 break;
719 case WEAPON:
720 safe_strcat (buf[use_buf], " (wielded)", &len, HUGE_BUF);
721 break;
722 case ARMOUR:
723 case HELMET:
724 case SHIELD:
725 case RING:
726 case BOOTS:
727 case GLOVES:
728 case AMULET:
729 case GIRDLE:
730 case BRACERS:
731 case CLOAK:
732 safe_strcat (buf[use_buf], " (worn)", &len, HUGE_BUF);
733 break;
734 case CONTAINER:
735 safe_strcat (buf[use_buf], " (active)", &len, HUGE_BUF);
736 break;
737 case SKILL:
738 default:
739 safe_strcat (buf[use_buf], " (applied)", &len, HUGE_BUF);
740 }
741 }
742
743 if (QUERY_FLAG (op, FLAG_UNPAID))
744 safe_strcat (buf[use_buf], " (unpaid)", &len, HUGE_BUF);
745
746 return buf [use_buf];
747 }
748
749 /*
750 * query_base_name(object) returns a character pointer pointing to a static
751 * buffer which contains a verbose textual representation of the name
752 * of the given object. The buffer will be overwritten at the next
753 * call to query_base_name(). This is a lot like query_name, but we
754 * don't include the item count or item status. Used for inventory sorting
755 * and sending to client.
756 * If plural is set, we generate the plural name of this.
757 */
758 const char *
759 query_base_name (const object *op, int plural)
760 {
761 static char buf[MAX_BUF], buf2[MAX_BUF];
762 int len;
763 materialtype_t *mt;
764
765 if ((!plural && !op->name) || (plural && !op->name_pl))
766 return "(null)";
767
768 if (!op->nrof && !op->weight && !op->title && !is_magical (op))
769 return op->name; /* To speed things up (or make things slower?) */
770
771 if ((op->is_armor () || op->is_weapon ()) && op->materialname)
772 mt = name_to_material (op->materialname);
773
774 #ifdef NEW_MATERIAL_CODE
775 if ((op->is_armor () || op->is_weapon ()) && op->materialname && mt &&
776 op->arch->clone.materialname != mt->name && !(op->material & M_SPECIAL))
777 {
778 strcpy (buf, mt->description);
779 len = strlen (buf);
780 safe_strcat (buf, " ", &len, MAX_BUF);
781 if (!plural)
782 safe_strcat (buf, op->name, &len, MAX_BUF);
783 else
784 safe_strcat (buf, op->name_pl, &len, MAX_BUF);
785 }
786 else
787 {
788 #endif
789 if (!plural)
790 assign (buf, op->name);
791 else
792 assign (buf, op->name_pl);
793
794 len = strlen (buf);
795 #ifdef NEW_MATERIAL_CODE
796 }
797 #endif
798
799 if (op->title && QUERY_FLAG (op, FLAG_IDENTIFIED))
800 {
801 safe_strcat (buf, " ", &len, MAX_BUF);
802 safe_strcat (buf, op->title, &len, MAX_BUF);
803 }
804
805 switch (op->type)
806 {
807 case SPELLBOOK:
808 case SCROLL:
809 case WAND:
810 case ROD:
811 if (QUERY_FLAG (op, FLAG_IDENTIFIED) || QUERY_FLAG (op, FLAG_BEEN_APPLIED))
812 {
813 if (!op->title)
814 {
815 safe_strcat (buf, " of ", &len, MAX_BUF);
816 if (op->inv)
817 safe_strcat (buf, op->inv->name, &len, MAX_BUF);
818 else
819 LOG (llevError, "Spellbook %s lacks inventory\n", &op->name);
820 }
821 if (op->type != SPELLBOOK)
822 {
823 sprintf (buf2, " (lvl %d)", op->level);
824 safe_strcat (buf, buf2, &len, MAX_BUF);
825 }
826 }
827 break;
828
829
830 case SKILL:
831 case AMULET:
832 case RING:
833 if (!op->title)
834 {
835 /* If ring has a title, full description isn't so useful */
836 char *s = ring_desc (op);
837
838 if (s[0])
839 {
840 safe_strcat (buf, " ", &len, MAX_BUF);
841 safe_strcat (buf, s, &len, MAX_BUF);
842 }
843 }
844 break;
845 default:
846 if (op->magic && ((QUERY_FLAG (op, FLAG_BEEN_APPLIED) && need_identify (op)) || QUERY_FLAG (op, FLAG_IDENTIFIED)))
847 {
848 sprintf (buf + strlen (buf), " %+d", op->magic);
849 }
850 }
851
852 return buf;
853 }
854
855 /* Break this off from describe_item - that function was way
856 * too long, making it difficult to read. This function deals
857 * with describing the monsters & players abilities. It should only
858 * be called with monster & player objects. Returns a description
859 * in a static buffer.
860 */
861 static char *
862 describe_monster (const object *op)
863 {
864 char buf[MAX_BUF];
865 static char retbuf[VERY_BIG_BUF];
866 int i;
867
868 retbuf[0] = '\0';
869
870 /* Note that the resolution this provides for players really isn't
871 * very good. Any player with a speed greater than .67 will
872 * fall into the 'lightning fast movement' category.
873 */
874 if (op->has_active_speed ())
875 {
876 switch ((int) ((FABS (op->speed)) * 15))
877 {
878 case 0:
879 strcat (retbuf, "(very slow movement)");
880 break;
881 case 1:
882 strcat (retbuf, "(slow movement)");
883 break;
884 case 2:
885 strcat (retbuf, "(normal movement)");
886 break;
887 case 3:
888 case 4:
889 strcat (retbuf, "(fast movement)");
890 break;
891 case 5:
892 case 6:
893 strcat (retbuf, "(very fast movement)");
894 break;
895 case 7:
896 case 8:
897 case 9:
898 case 10:
899 strcat (retbuf, "(extremely fast movement)");
900 break;
901 default:
902 strcat (retbuf, "(lightning fast movement)");
903 break;
904 }
905 }
906 if (QUERY_FLAG (op, FLAG_UNDEAD))
907 strcat (retbuf, "(undead)");
908 if (QUERY_FLAG (op, FLAG_SEE_INVISIBLE))
909 strcat (retbuf, "(see invisible)");
910 if (QUERY_FLAG (op, FLAG_USE_WEAPON))
911 strcat (retbuf, "(wield weapon)");
912 if (QUERY_FLAG (op, FLAG_USE_BOW))
913 strcat (retbuf, "(archer)");
914 if (QUERY_FLAG (op, FLAG_USE_ARMOUR))
915 strcat (retbuf, "(wear armour)");
916 if (QUERY_FLAG (op, FLAG_USE_RING))
917 strcat (retbuf, "(wear ring)");
918 if (QUERY_FLAG (op, FLAG_USE_SCROLL))
919 strcat (retbuf, "(read scroll)");
920 if (QUERY_FLAG (op, FLAG_USE_RANGE))
921 strcat (retbuf, "(fires wand/rod/horn)");
922 if (QUERY_FLAG (op, FLAG_CAN_USE_SKILL))
923 strcat (retbuf, "(skill user)");
924 if (QUERY_FLAG (op, FLAG_CAST_SPELL))
925 strcat (retbuf, "(spellcaster)");
926 if (QUERY_FLAG (op, FLAG_FRIENDLY))
927 strcat (retbuf, "(friendly)");
928 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE))
929 strcat (retbuf, "(unaggressive)");
930 if (QUERY_FLAG (op, FLAG_HITBACK))
931 strcat (retbuf, "(hitback)");
932 if (QUERY_FLAG (op, FLAG_STEALTH))
933 strcat (retbuf, "(stealthy)");
934 if (op->randomitems != NULL)
935 {
936 treasure *t;
937 int first = 1;
938
939 for (t = op->randomitems->items; t != NULL; t = t->next)
940 if (t->item && t->item->clone.type == SPELL)
941 {
942 if (first)
943 {
944 first = 0;
945 strcat (retbuf, "(Spell abilities:)");
946 }
947 strcat (retbuf, "(");
948 strcat (retbuf, t->item->clone.name);
949 strcat (retbuf, ")");
950 }
951 }
952 if (op->type == PLAYER)
953 {
954 if (op->contr->digestion)
955 {
956 if (op->contr->digestion != 0)
957 sprintf (buf, "(sustenance%+d)", op->contr->digestion);
958 strcat (retbuf, buf);
959 }
960 if (op->contr->gen_grace)
961 {
962 sprintf (buf, "(grace%+d)", op->contr->gen_grace);
963 strcat (retbuf, buf);
964 }
965 if (op->contr->gen_sp)
966 {
967 sprintf (buf, "(magic%+d)", op->contr->gen_sp);
968 strcat (retbuf, buf);
969 }
970 if (op->contr->gen_hp)
971 {
972 sprintf (buf, "(regeneration%+d)", op->contr->gen_hp);
973 strcat (retbuf, buf);
974 }
975 if (op->stats.luck)
976 {
977 sprintf (buf, "(luck%+d)", op->stats.luck);
978 strcat (retbuf, buf);
979 }
980 }
981
982 /* describe attacktypes */
983 if (is_dragon_pl (op))
984 {
985 /* for dragon players display the attacktypes from clawing skill
986 * Break apart the for loop - move the comparison checking down -
987 * this makes it more readable.
988 */
989 object *tmp;
990
991 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
992 if (tmp->type == SKILL && !strcmp (tmp->name, "clawing"))
993 break;
994
995 if (tmp && tmp->attacktype != 0)
996 { DESCRIBE_ABILITY (retbuf, tmp->attacktype, "Claws") }
997 else
998 { DESCRIBE_ABILITY (retbuf, op->attacktype, "Attacks") }
999 }
1000 else
1001 { DESCRIBE_ABILITY (retbuf, op->attacktype, "Attacks") }
1002
1003 DESCRIBE_PATH (retbuf, op->path_attuned, "Attuned");
1004 DESCRIBE_PATH (retbuf, op->path_repelled, "Repelled");
1005 DESCRIBE_PATH (retbuf, op->path_denied, "Denied");
1006
1007 for (i = 0; i < NROFATTACKS; i++)
1008 if (op->resist[i])
1009 {
1010 sprintf (buf, "(%s %+d)", resist_plus[i], op->resist[i]);
1011 strcat (retbuf, buf);
1012 }
1013
1014 return retbuf;
1015 }
1016
1017
1018 /*
1019 * Returns a pointer to a static buffer which contains a
1020 * description of the given object.
1021 * If it is a monster, lots of information about its abilities
1022 * will be returned.
1023 * If it is an item, lots of information about which abilities
1024 * will be gained about its user will be returned.
1025 * If it is a player, it writes out the current abilities
1026 * of the player, which is usually gained by the items applied.
1027 * It would be really handy to actually pass another object
1028 * pointer on who is examining this object. Then, you could reveal
1029 * certain information depending on what the examiner knows, eg,
1030 * wouldn't need to use the SEE_INVISIBLE flag to know it is
1031 * a dragon player examining food. Could have things like
1032 * a dwarven axe, in which the full abilities are only known to
1033 * dwarves, etc.
1034 *
1035 * This function is really much more complicated than it should
1036 * be, because different objects have different meanings
1037 * for the same field (eg, wands use 'food' for charges). This
1038 * means these special cases need to be worked out.
1039 *
1040 * Add 'owner' who is the person examining this object.
1041 * owner can be null if no one is being associated with this
1042 * item (eg, debug dump or the like)
1043 */
1044
1045 char *
1046 describe_item (const object *op, object *owner)
1047 {
1048 char buf[MAX_BUF];
1049 static char retbuf[VERY_BIG_BUF];
1050 int identified, i;
1051
1052 retbuf[0] = '\0';
1053 if (QUERY_FLAG (op, FLAG_MONSTER) || op->type == PLAYER)
1054 {
1055 return describe_monster (op);
1056 }
1057 /* figure this out once, instead of making multiple calls to need_identify.
1058 * also makes the code easier to read.
1059 */
1060 if (!need_identify (op) || QUERY_FLAG (op, FLAG_IDENTIFIED))
1061 identified = 1;
1062 else
1063 {
1064 strcpy (retbuf, "(unidentified)");
1065 identified = 0;
1066 }
1067 switch (op->type)
1068 {
1069 case BOW:
1070 case ARROW:
1071 case WAND:
1072 case ROD:
1073 case HORN:
1074 case WEAPON:
1075 case ARMOUR:
1076 case HELMET:
1077 case SHIELD:
1078 case BOOTS:
1079 case GLOVES:
1080 case GIRDLE:
1081 case BRACERS:
1082 case CLOAK:
1083 case SKILL_TOOL:
1084 break; /* We have more information to do below this switch */
1085
1086 case POWER_CRYSTAL:
1087 if (op->stats.maxsp > 1000)
1088 { /*higher capacity crystals */
1089 i = (op->stats.maxsp % 100) / 10;
1090 if (i)
1091 snprintf (buf, MAX_BUF, "(capacity %d.%dk). It is ", op->stats.maxsp / 100, i);
1092 else
1093 snprintf (buf, MAX_BUF, "(capacity %dk). It is ", op->stats.maxsp / 100);
1094 }
1095 else
1096 snprintf (buf, MAX_BUF, "(capacity %d). It is ", op->stats.maxsp);
1097 strcat (retbuf, buf);
1098 i = (op->stats.sp * 10) / op->stats.maxsp;
1099 if (op->stats.sp == 0)
1100 strcat (retbuf, "empty.");
1101 else if (i == 0)
1102 strcat (retbuf, "almost empty.");
1103 else if (i < 3)
1104 strcat (retbuf, "partially filled.");
1105 else if (i < 6)
1106 strcat (retbuf, "half full.");
1107 else if (i < 9)
1108 strcat (retbuf, "well charged.");
1109 else if (op->stats.sp == op->stats.maxsp)
1110 strcat (retbuf, "fully charged.");
1111 else
1112 strcat (retbuf, "almost full.");
1113 break;
1114 case FOOD:
1115 case FLESH:
1116 case DRINK:
1117 if (identified || QUERY_FLAG (op, FLAG_BEEN_APPLIED))
1118 {
1119 sprintf (buf, "(food+%d)", op->stats.food);
1120 strcat (retbuf, buf);
1121
1122 if (op->type == FLESH && op->last_eat > 0 && atnr_is_dragon_enabled (op->last_eat))
1123 {
1124 sprintf (buf, "(%s metabolism)", change_resist_msg[op->last_eat]);
1125 strcat (retbuf, buf);
1126 }
1127
1128 if (!QUERY_FLAG (op, FLAG_CURSED))
1129 {
1130 if (op->stats.hp)
1131 strcat (retbuf, "(heals)");
1132 if (op->stats.sp)
1133 strcat (retbuf, "(spellpoint regen)");
1134 }
1135 else
1136 {
1137 if (op->stats.hp)
1138 strcat (retbuf, "(damages)");
1139 if (op->stats.sp)
1140 strcat (retbuf, "(spellpoint depletion)");
1141 }
1142 }
1143 break;
1144
1145
1146 case SKILL:
1147 case RING:
1148 case AMULET:
1149 if (op->item_power)
1150 {
1151 sprintf (buf, "(item_power %+d)", op->item_power);
1152 strcat (retbuf, buf);
1153 }
1154 if (op->title)
1155 strcat (retbuf, ring_desc (op));
1156 return retbuf;
1157
1158 default:
1159 return retbuf;
1160 }
1161
1162 /* Down here, we more further describe equipment type items.
1163 * only describe them if they have been identified or the like.
1164 */
1165 if (identified || QUERY_FLAG (op, FLAG_BEEN_APPLIED))
1166 {
1167 int attr, val;
1168
1169 for (attr = 0; attr < NUM_STATS; attr++)
1170 {
1171 if ((val = get_attr_value (&(op->stats), attr)) != 0)
1172 {
1173 sprintf (buf, "(%s%+d)", short_stat_name[attr], val);
1174 strcat (retbuf, buf);
1175 }
1176 }
1177
1178 if (op->stats.exp)
1179 {
1180 sprintf (buf, "(speed %+lld)", (long long) op->stats.exp);
1181 strcat (retbuf, buf);
1182 }
1183
1184
1185 switch (op->type)
1186 {
1187 case BOW:
1188 case ARROW:
1189 case GIRDLE:
1190 case HELMET:
1191 case SHIELD:
1192 case BOOTS:
1193 case GLOVES:
1194 case WEAPON:
1195 case SKILL:
1196 case RING:
1197 case AMULET:
1198 case ARMOUR:
1199 case BRACERS:
1200 case FORCE:
1201 case CLOAK:
1202 if (op->stats.wc)
1203 {
1204 sprintf (buf, "(wc%+d)", op->stats.wc);
1205 strcat (retbuf, buf);
1206 }
1207 if (op->stats.dam)
1208 {
1209 sprintf (buf, "(dam%+d)", op->stats.dam);
1210 strcat (retbuf, buf);
1211 }
1212 if (op->stats.ac)
1213 {
1214 sprintf (buf, "(ac%+d)", op->stats.ac);
1215 strcat (retbuf, buf);
1216 }
1217 if ((op->type == WEAPON || op->type == BOW) && op->level > 0)
1218 {
1219 sprintf (buf, "(improved %d/%d)", op->last_eat, op->level);
1220 strcat (retbuf, buf);
1221 }
1222 break;
1223
1224 default:
1225 break;
1226 }
1227 if (QUERY_FLAG (op, FLAG_XRAYS))
1228 strcat (retbuf, "(xray-vision)");
1229 if (QUERY_FLAG (op, FLAG_SEE_IN_DARK))
1230 strcat (retbuf, "(infravision)");
1231
1232 /* levitate was what is was before, so we'll keep it */
1233 if (op->move_type & MOVE_FLY_LOW)
1234 strcat (retbuf, "(levitate)");
1235
1236 if (op->move_type & MOVE_FLY_HIGH)
1237 strcat (retbuf, "(fly)");
1238
1239 if (op->move_type & MOVE_SWIM)
1240 strcat (retbuf, "(swim)");
1241
1242 /* walking is presumed as 'normal', so doesn't need mentioning */
1243
1244 if (op->item_power)
1245 {
1246 sprintf (buf, "(item_power %+d)", op->item_power);
1247 strcat (retbuf, buf);
1248 }
1249 } /* End if identified or applied */
1250
1251 /* This blocks only deals with fully identified object.
1252 * it is intentional that this is not an 'else' from a above -
1253 * in this way, information is added.
1254 */
1255 if (identified)
1256 {
1257 int more_info = 0;
1258
1259 switch (op->type)
1260 {
1261 case ROD: /* These use stats.sp for spell selection and stats.food */
1262 case HORN: /* and stats.hp for spell-point regeneration... */
1263 case BOW:
1264 case ARROW:
1265 case WAND:
1266 case FOOD:
1267 case FLESH:
1268 case DRINK:
1269 more_info = 0;
1270 break;
1271
1272 /* Armor type objects */
1273 case ARMOUR:
1274 case HELMET:
1275 case SHIELD:
1276 case BOOTS:
1277 case GLOVES:
1278 case GIRDLE:
1279 case BRACERS:
1280 case CLOAK:
1281 if (ARMOUR_SPEED (op))
1282 {
1283 sprintf (buf, "(Max speed %1.2f)", ARMOUR_SPEED (op) / 10.0);
1284 strcat (retbuf, buf);
1285 }
1286 if (ARMOUR_SPELLS (op))
1287 {
1288 sprintf (buf, "(Spell regen penalty %d)", ARMOUR_SPELLS (op));
1289 strcat (retbuf, buf);
1290 }
1291 more_info = 1;
1292 break;
1293
1294 case WEAPON:
1295 /* Calculate it the same way fix_player does so the results
1296 * make sense.
1297 */
1298 i = (WEAPON_SPEED (op) * 2 - op->magic) / 2;
1299 if (i < 0)
1300 i = 0;
1301
1302 sprintf (buf, "(weapon speed %d)", i);
1303 strcat (retbuf, buf);
1304 more_info = 1;
1305 break;
1306
1307 }
1308 if (more_info)
1309 {
1310 if (op->stats.food)
1311 {
1312 if (op->stats.food != 0)
1313 sprintf (buf, "(sustenance%+d)", op->stats.food);
1314 strcat (retbuf, buf);
1315 }
1316 if (op->stats.grace)
1317 {
1318 sprintf (buf, "(grace%+d)", op->stats.grace);
1319 strcat (retbuf, buf);
1320 }
1321 if (op->stats.sp)
1322 {
1323 sprintf (buf, "(magic%+d)", op->stats.sp);
1324 strcat (retbuf, buf);
1325 }
1326 if (op->stats.hp)
1327 {
1328 sprintf (buf, "(regeneration%+d)", op->stats.hp);
1329 strcat (retbuf, buf);
1330 }
1331 }
1332
1333 if (op->stats.luck)
1334 {
1335 sprintf (buf, "(luck%+d)", op->stats.luck);
1336 strcat (retbuf, buf);
1337 }
1338 if (QUERY_FLAG (op, FLAG_LIFESAVE))
1339 strcat (retbuf, "(lifesaving)");
1340 if (QUERY_FLAG (op, FLAG_REFL_SPELL))
1341 strcat (retbuf, "(reflect spells)");
1342 if (QUERY_FLAG (op, FLAG_REFL_MISSILE))
1343 strcat (retbuf, "(reflect missiles)");
1344 if (QUERY_FLAG (op, FLAG_STEALTH))
1345 strcat (retbuf, "(stealth)");
1346 if (op->slaying != NULL && op->type != FOOD)
1347 {
1348 sprintf (buf, "(slay %s)", &op->slaying);
1349 strcat (retbuf, buf);
1350 }
1351 DESCRIBE_ABILITY (retbuf, op->attacktype, "Attacks");
1352 /* resistance on flesh is only visible for quetzals. If
1353 * non flesh, everyone can see its resistances
1354 */
1355 if (op->type != FLESH || (owner && is_dragon_pl (owner)))
1356 strcat (retbuf, describe_resistance (op, 0));
1357 DESCRIBE_PATH (retbuf, op->path_attuned, "Attuned");
1358 DESCRIBE_PATH (retbuf, op->path_repelled, "Repelled");
1359 DESCRIBE_PATH (retbuf, op->path_denied, "Denied");
1360 }
1361
1362 return retbuf;
1363 }
1364
1365 /* Return true if the item is magical. A magical item is one that
1366 * increases/decreases any abilities, provides a resistance,
1367 * has a generic magical bonus, or is an artifact.
1368 * This function is used by detect_magic to determine if an item
1369 * should be marked as magical.
1370 */
1371
1372 int
1373 is_magical (const object *op)
1374 {
1375 int i;
1376
1377 /* living creatures are considered non magical */
1378 if (QUERY_FLAG (op, FLAG_ALIVE))
1379 return 0;
1380
1381 /* This is a test for it being an artifact, as artifacts have titles */
1382 if (op->title != NULL)
1383 return 1;
1384
1385 /* Handle rings and amulets specially. If they change any of these
1386 * values, it means they are magical.
1387 */
1388 if ((op->type == AMULET || op->type == RING) &&
1389 (op->stats.ac || op->stats.food || op->stats.exp || op->stats.dam || op->stats.wc || op->stats.sp || op->stats.hp || op->stats.luck))
1390 return 1;
1391
1392 /* Check for stealty, speed, flying, or just plain magic in the boots */
1393 /* Presume any boots that hvae a move_type are special. */
1394 if (op->type == BOOTS && ((QUERY_FLAG (op, FLAG_STEALTH) || op->move_type || op->stats.exp)))
1395 return 1;
1396
1397 /* Take care of amulet/shield that reflects spells/missiles */
1398 if ((op->type == AMULET || op->type == SHIELD) && (QUERY_FLAG (op, FLAG_REFL_SPELL) || QUERY_FLAG (op, FLAG_REFL_MISSILE)))
1399 return 1;
1400
1401 /* Take care of helmet of xrays */
1402 if (op->type == HELMET && QUERY_FLAG (op, FLAG_XRAYS))
1403 return 1;
1404
1405 /* Potions & rods are always magical. Wands/staves are also magical,
1406 * assuming they still have any charges left.
1407 */
1408 if (op->type == POTION || op->type == ROD || (op->type == WAND && op->stats.food))
1409 return 1;
1410
1411 /* if something gives a protection, either positive or negative, its magical */
1412 /* This is really a pretty bad hack - as of now, ATNR_PHYSICAL is 0,
1413 * so this always works out fine.
1414 */
1415 for (i = ATNR_PHYSICAL + 1; i < NROFATTACKS; i++)
1416 if (op->resist[i])
1417 return 1;
1418
1419 /* Physical protection is expected on some item types, so they should
1420 * not be considered magical.
1421 */
1422 if (op->resist[ATNR_PHYSICAL] && op->type != HELMET && op->type != SHIELD &&
1423 op->type != BOOTS && op->type != GLOVES && op->type != ARMOUR)
1424 return 1;
1425
1426 /* power crystal, spellbooks, and scrolls are always magical. */
1427 if (op->magic || op->type == POWER_CRYSTAL || op->type == SPELLBOOK || op->type == SCROLL || op->type == GIRDLE)
1428 return 1;
1429
1430 /* Check to see if it increases/decreases any stats */
1431 for (i = 0; i < NUM_STATS; i++)
1432 if (get_attr_value (&(op->stats), i) != 0)
1433 return 1;
1434
1435 /* If it doesn't fall into any of the above categories, must
1436 * be non magical.
1437 */
1438 return 0;
1439 }
1440
1441 /* need_identify returns true if the item should be identified. This
1442 * function really should not exist - by default, any item not identified
1443 * should need it.
1444 */
1445
1446 int
1447 need_identify (const object *op)
1448 {
1449 switch (op->type)
1450 {
1451 case RING:
1452 case WAND:
1453 case ROD:
1454 case HORN:
1455 case SCROLL:
1456 case SKILL:
1457 case SKILLSCROLL:
1458 case SPELLBOOK:
1459 case FOOD:
1460 case POTION:
1461 case BOW:
1462 case ARROW:
1463 case WEAPON:
1464 case ARMOUR:
1465 case SHIELD:
1466 case HELMET:
1467 case AMULET:
1468 case BOOTS:
1469 case GLOVES:
1470 case BRACERS:
1471 case GIRDLE:
1472 case CONTAINER:
1473 case DRINK:
1474 case FLESH:
1475 case INORGANIC:
1476 case CLOSE_CON:
1477 case CLOAK:
1478 case GEM:
1479 case POWER_CRYSTAL:
1480 case POISON:
1481 case BOOK:
1482 case SKILL_TOOL:
1483 return 1;
1484 }
1485 /* Try to track down some stuff that may show up here. Thus, the
1486 * archetype file can be updated, and this function removed.
1487 */
1488 #if 0
1489 LOG (llevDebug, "need_identify: %s does not need to be id'd\n", op->name);
1490 #endif
1491 return 0;
1492 }
1493
1494 /*
1495 * Supposed to fix face-values as well here, but later.
1496 */
1497 void
1498 identify (object *op)
1499 {
1500 object *pl;
1501
1502 SET_FLAG (op, FLAG_IDENTIFIED);
1503 CLEAR_FLAG (op, FLAG_KNOWN_MAGICAL);
1504 CLEAR_FLAG (op, FLAG_NO_SKILL_IDENT);
1505
1506 /*
1507 * We want autojoining of equal objects:
1508 */
1509 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
1510 SET_FLAG (op, FLAG_KNOWN_CURSED);
1511
1512 if (op->type == POTION)
1513 {
1514 if (op->inv && op->randomitems)
1515 op->title = op->inv->name;
1516 else if (op->arch)
1517 {
1518 op->name = op->arch->clone.name;
1519 op->name_pl = op->arch->clone.name_pl;
1520 }
1521 }
1522
1523 /* If the object is on a map, make sure we update its face */
1524 if (op->map)
1525 update_object (op, UP_OBJ_CHANGE);
1526 else
1527 {
1528 pl = op->in_player ();
1529 if (pl)
1530 /* A lot of the values can change from an update - might as well send
1531 * it all.
1532 */
1533 esrv_send_item (pl, op);
1534 }
1535 }
1536