ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.38
Committed: Sun Jul 1 05:00:17 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.37: +11 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

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