|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00033 static float weapon_speed_table[19] = 00034 { 00035 20.0f, 18.0f, 10.0f, 8.0f, 5.5f, 4.25f, 3.50f, 3.05f, 2.70f, 2.35f, 00036 2.15f, 1.95f, 1.80f, 1.60f, 1.52f, 1.44f, 1.32f, 1.25f, 1.20f 00037 }; 00038 00040 static char numbers[21][20] = 00041 { 00042 "no", 00043 "", 00044 "two", 00045 "three", 00046 "four", 00047 "five", 00048 "six", 00049 "seven", 00050 "eight", 00051 "nine", 00052 "ten", 00053 "eleven", 00054 "twelve", 00055 "thirteen", 00056 "fourteen", 00057 "fifteen", 00058 "sixteen", 00059 "seventeen", 00060 "eighteen", 00061 "nineteen", 00062 "twenty" 00063 }; 00064 00066 static char numbers_10[10][20] = 00067 { 00068 "zero", 00069 "ten", 00070 "twenty", 00071 "thirty", 00072 "forty", 00073 "fifty", 00074 "sixty", 00075 "seventy", 00076 "eighty", 00077 "ninety" 00078 }; 00079 00081 static char levelnumbers[21][20] = 00082 { 00083 "zeroth", 00084 "first", 00085 "second", 00086 "third", 00087 "fourth", 00088 "fifth", 00089 "sixth", 00090 "seventh", 00091 "eighth", 00092 "ninth", 00093 "tenth", 00094 "eleventh", 00095 "twelfth", 00096 "thirteenth", 00097 "fourteenth", 00098 "fifteenth", 00099 "sixteenth", 00100 "seventeenth", 00101 "eighteen", 00102 "nineteen", 00103 "twentieth" 00104 }; 00105 00107 static char levelnumbers_10[11][20] = 00108 { 00109 "zeroth", 00110 "tenth", 00111 "twentieth", 00112 "thirtieth", 00113 "fortieth", 00114 "fiftieth", 00115 "sixtieth", 00116 "seventieth", 00117 "eightieth", 00118 "ninetieth" 00119 }; 00120 00121 static char *describe_attack(object *op, int newline); 00122 static char *get_number(int i); 00123 00132 static char *describe_attack(object *op, int newline) 00133 { 00134 static char buf[VERY_BIG_BUF]; 00135 char buf1[VERY_BIG_BUF]; 00136 int tmpvar, flag = 1; 00137 00138 buf[0] = '\0'; 00139 00140 for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++) 00141 { 00142 if (op->attack[tmpvar]) 00143 { 00144 if (flag && !newline) 00145 { 00146 strncat(buf, "(Attacks: ", sizeof(buf) - strlen(buf) - 1); 00147 } 00148 00149 if (!newline) 00150 { 00151 if (!flag) 00152 { 00153 strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1); 00154 } 00155 00156 snprintf(buf1, sizeof(buf1), "%s %+d%%", attack_name[tmpvar], op->attack[tmpvar]); 00157 } 00158 else 00159 { 00160 snprintf(buf1, sizeof(buf1), "%s %+d%%\n", attack_name[tmpvar], op->attack[tmpvar]); 00161 } 00162 00163 flag = 0; 00164 strncat(buf, buf1, sizeof(buf) - strlen(buf) - 1); 00165 } 00166 } 00167 00168 if (!newline && !flag) 00169 { 00170 strncat(buf, ") ", sizeof(buf) - strlen(buf) - 1); 00171 } 00172 00173 return buf; 00174 } 00175 00184 char *describe_protections(object *op, int newline) 00185 { 00186 static char buf[VERY_BIG_BUF]; 00187 char buf1[VERY_BIG_BUF]; 00188 int tmpvar, flag = 1; 00189 00190 buf[0] = '\0'; 00191 00192 for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++) 00193 { 00194 if (op->protection[tmpvar]) 00195 { 00196 if (flag && !newline) 00197 { 00198 strncat(buf, "(Protections: ", sizeof(buf) - strlen(buf) - 1); 00199 } 00200 00201 if (!newline) 00202 { 00203 if (!flag) 00204 { 00205 strncat(buf, ", ", sizeof(buf) - strlen(buf) - 1); 00206 } 00207 00208 snprintf(buf1, sizeof(buf1), "%s %+d%%", attack_name[tmpvar], op->protection[tmpvar]); 00209 } 00210 else 00211 { 00212 snprintf(buf1, sizeof(buf1), "%s %d%%\n", attack_name[tmpvar], op->protection[tmpvar]); 00213 } 00214 00215 flag = 0; 00216 strncat(buf, buf1, sizeof(buf) - strlen(buf) - 1); 00217 } 00218 } 00219 00220 if (!newline && !flag) 00221 { 00222 strncat(buf, ") ", sizeof(buf) - strlen(buf) - 1); 00223 } 00224 00225 return buf; 00226 } 00227 00232 char *query_weight(object *op) 00233 { 00234 static char buf[10]; 00235 int i = op->nrof ? (int) op->nrof * op->weight : op->weight + op->carrying; 00236 00237 if (op->weight < 0) 00238 { 00239 return " "; 00240 } 00241 00242 if (i % 1000) 00243 { 00244 snprintf(buf, sizeof(buf), "%6.1f", (float) i / 1000.0f); 00245 } 00246 else 00247 { 00248 snprintf(buf, sizeof(buf), "%4d ", i / 1000); 00249 } 00250 00251 return buf; 00252 } 00253 00258 char *get_levelnumber(int i) 00259 { 00260 static char buf[MAX_BUF]; 00261 00262 if (i > 99) 00263 { 00264 snprintf(buf, sizeof(buf), "%d.", i); 00265 return buf; 00266 } 00267 00268 if (i < 21) 00269 { 00270 return levelnumbers[i]; 00271 } 00272 00273 if (!(i % 10)) 00274 { 00275 return levelnumbers_10[i / 10]; 00276 } 00277 00278 strcpy(buf, numbers_10[i / 10]); 00279 strcat(buf, levelnumbers[i % 10]); 00280 00281 return buf; 00282 } 00283 00292 static char *get_number(int i) 00293 { 00294 if (i <= 20) 00295 { 00296 return numbers[i]; 00297 } 00298 else 00299 { 00300 static char buf[MAX_BUF]; 00301 snprintf(buf, sizeof(buf), "%d", i); 00302 return buf; 00303 } 00304 } 00305 00312 char *query_short_name(object *op, object *caller) 00313 { 00314 static char buf[HUGE_BUF]; 00315 char buf2[HUGE_BUF]; 00316 size_t len = 0; 00317 00318 buf[0] = '\0'; 00319 00320 if (!op || !op->name) 00321 { 00322 return buf; 00323 } 00324 00325 if (op->nrof) 00326 { 00327 safe_strcat(buf, get_number(op->nrof), &len, sizeof(buf)); 00328 00329 if (op->nrof != 1) 00330 { 00331 safe_strcat(buf, " ", &len, sizeof(buf)); 00332 } 00333 00334 if (!QUERY_FLAG(op, FLAG_IS_NAMED)) 00335 { 00336 /* Add the item race name */ 00337 if (!IS_LIVE(op) && op->type != BASE_INFO) 00338 { 00339 safe_strcat(buf, item_races[op->item_race], &len, sizeof(buf)); 00340 } 00341 00342 if (op->material_real && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00343 { 00344 safe_strcat(buf, material_real[op->material_real].name, &len, sizeof(buf)); 00345 } 00346 } 00347 00348 safe_strcat(buf, op->name, &len, sizeof(buf)); 00349 00350 if (op->nrof != 1) 00351 { 00352 char *buf3 = strstr(buf, " of "); 00353 00354 if (buf3) 00355 { 00356 strcpy(buf2, buf3); 00357 /* Also changes value in buf */ 00358 *buf3 = '\0'; 00359 } 00360 00361 len = strlen(buf); 00362 00363 /* If buf3 is set, then this was a string that contained 00364 * something of something (potion of dexterity.) The part before 00365 * the of gets made plural, so now we need to copy the rest 00366 * (after and including the " of "), to the buffer string. */ 00367 if (buf3) 00368 { 00369 safe_strcat(buf, buf2, &len, sizeof(buf)); 00370 } 00371 } 00372 } 00373 /* If nrof is 0, the object is not mergable, and thus, op->name 00374 * should contain the name to be used. */ 00375 else 00376 { 00377 if (!QUERY_FLAG(op, FLAG_IS_NAMED)) 00378 { 00379 if (!IS_LIVE(op) && op->type != BASE_INFO) 00380 { 00381 safe_strcat(buf, item_races[op->item_race], &len, sizeof(buf)); 00382 } 00383 00384 if (op->material_real && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00385 { 00386 safe_strcat(buf, material_real[op->material_real].name, &len, sizeof(buf)); 00387 } 00388 } 00389 00390 safe_strcat(buf, op->name, &len, sizeof(buf)); 00391 } 00392 00393 switch (op->type) 00394 { 00395 case CONTAINER: 00396 if (QUERY_FLAG(op, FLAG_IDENTIFIED)) 00397 { 00398 if (op->title) 00399 { 00400 safe_strcat(buf, " ", &len, sizeof(buf)); 00401 safe_strcat(buf, op->title, &len, sizeof(buf)); 00402 } 00403 } 00404 00405 if (op->sub_type >= ST1_CONTAINER_NORMAL_party) 00406 { 00407 if (op->sub_type == ST1_CONTAINER_CORPSE_party) 00408 { 00409 if (op->slaying) 00410 { 00411 if (!caller || caller->type != PLAYER) 00412 { 00413 safe_strcat(buf, " (bounty of a party)", &len, sizeof(buf)); 00414 } 00415 else if (CONTR(caller)->party && CONTR(caller)->party->name == op->slaying) 00416 { 00417 safe_strcat(buf, " (bounty of your party", &len, sizeof(buf)); 00418 00419 /* A searched bounty */ 00420 if (QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00421 { 00422 safe_strcat(buf, ", searched", &len, sizeof(buf)); 00423 } 00424 00425 safe_strcat(buf, ")", &len, sizeof(buf)); 00426 } 00427 /* It's a different party */ 00428 else 00429 { 00430 safe_strcat(buf, " (bounty of another party)", &len, sizeof(buf)); 00431 } 00432 } 00433 else if (QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00434 { 00435 safe_strcat(buf, " (searched)", &len, sizeof(buf)); 00436 } 00437 } 00438 } 00439 else if (op->sub_type >= ST1_CONTAINER_NORMAL_player) 00440 { 00441 if (op->sub_type == ST1_CONTAINER_CORPSE_player) 00442 { 00443 if (op->slaying) 00444 { 00445 safe_strcat(buf, " (bounty of ", &len, sizeof(buf)); 00446 safe_strcat(buf, op->slaying, &len, sizeof(buf)); 00447 00448 /* A searched bounty */ 00449 if ((caller && caller->name == op->slaying) && QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00450 { 00451 safe_strcat(buf, ", searched", &len, sizeof(buf)); 00452 } 00453 00454 safe_strcat(buf,")", &len, sizeof(buf)); 00455 } 00456 else if (QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00457 { 00458 safe_strcat(buf, " (searched)", &len, sizeof(buf)); 00459 } 00460 } 00461 } 00462 00463 break; 00464 00465 case SPELLBOOK: 00466 if (QUERY_FLAG(op, FLAG_IDENTIFIED) || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00467 { 00468 if (!op->title) 00469 { 00470 safe_strcat(buf, " of ", &len, sizeof(buf)); 00471 00472 if (op->slaying) 00473 { 00474 safe_strcat(buf, op->slaying, &len, sizeof(buf)); 00475 } 00476 else 00477 { 00478 if (op->stats.sp == SP_NO_SPELL) 00479 { 00480 safe_strcat(buf, "nothing", &len, sizeof(buf)); 00481 } 00482 else 00483 { 00484 safe_strcat(buf, spells[op->stats.sp].name, &len, sizeof(buf)); 00485 } 00486 } 00487 } 00488 else 00489 { 00490 safe_strcat(buf, " ", &len, sizeof(buf)); 00491 safe_strcat(buf, op->title, &len, sizeof(buf)); 00492 } 00493 } 00494 00495 break; 00496 00497 case SCROLL: 00498 case WAND: 00499 case ROD: 00500 case HORN: 00501 case POTION: 00502 if (QUERY_FLAG(op, FLAG_IDENTIFIED) || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00503 { 00504 if (!op->title) 00505 { 00506 if (op->stats.sp != SP_NO_SPELL) 00507 { 00508 safe_strcat(buf, " of ", &len, sizeof(buf)); 00509 safe_strcat(buf, spells[op->stats.sp].name, &len, sizeof(buf)); 00510 } 00511 else 00512 { 00513 safe_strcat(buf, " of nothing", &len, sizeof(buf)); 00514 } 00515 } 00516 else 00517 { 00518 safe_strcat(buf, " ", &len, sizeof(buf)); 00519 safe_strcat(buf, op->title, &len, sizeof(buf)); 00520 } 00521 00522 sprintf(buf2, " (lvl %d)", op->level); 00523 safe_strcat(buf, buf2, &len, sizeof(buf)); 00524 } 00525 00526 break; 00527 00528 case SKILL: 00529 case AMULET: 00530 case RING: 00531 if (QUERY_FLAG(op, FLAG_IDENTIFIED)) 00532 { 00533 if (!op->title) 00534 { 00535 /* If ring has a title, full description isn't so useful */ 00536 char *s = describe_item(op); 00537 00538 if (s[0]) 00539 { 00540 safe_strcat(buf, " ", &len, sizeof(buf)); 00541 safe_strcat(buf, s, &len, sizeof(buf)); 00542 } 00543 } 00544 else 00545 { 00546 safe_strcat(buf, " ", &len, sizeof(buf)); 00547 safe_strcat(buf, op->title, &len, sizeof(buf)); 00548 } 00549 } 00550 00551 break; 00552 00553 default: 00554 if (op->magic && (!need_identify(op) || QUERY_FLAG(op, FLAG_BEEN_APPLIED) || QUERY_FLAG(op, FLAG_IDENTIFIED))) 00555 { 00556 if (!IS_LIVE(op) && op->type != BASE_INFO) 00557 { 00558 sprintf(buf2, " %+d", op->magic); 00559 safe_strcat(buf, buf2, &len, sizeof(buf)); 00560 } 00561 } 00562 00563 if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00564 { 00565 safe_strcat(buf, " ", &len, sizeof(buf)); 00566 safe_strcat(buf, op->title, &len, sizeof(buf)); 00567 } 00568 00569 if ((op->type == ARROW || op->type == WEAPON) && op->slaying && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00570 { 00571 safe_strcat(buf, " ", &len, sizeof(buf)); 00572 safe_strcat(buf, op->slaying, &len, sizeof(buf)); 00573 } 00574 } 00575 00576 return buf; 00577 } 00578 00592 char *query_name(object *op, object *caller) 00593 { 00594 static char buf[5][HUGE_BUF]; 00595 static int use_buf = 0; 00596 size_t len = 0; 00597 00598 use_buf++; 00599 use_buf %= 5; 00600 00601 if (!op || !op->name) 00602 { 00603 buf[use_buf][0] = 0; 00604 return buf[use_buf]; 00605 } 00606 00607 safe_strcat(buf[use_buf], query_short_name(op, caller), &len, HUGE_BUF); 00608 00609 if (QUERY_FLAG(op, FLAG_ONE_DROP)) 00610 { 00611 safe_strcat(buf[use_buf], " (one-drop)", &len, HUGE_BUF); 00612 } 00613 else if (QUERY_FLAG(op, FLAG_QUEST_ITEM)) 00614 { 00615 safe_strcat(buf[use_buf], " (quest)", &len, HUGE_BUF); 00616 } 00617 00618 if (QUERY_FLAG(op, FLAG_INV_LOCKED)) 00619 { 00620 safe_strcat(buf[use_buf], " *", &len, HUGE_BUF); 00621 } 00622 00623 if (op->type == CONTAINER && QUERY_FLAG(op, FLAG_APPLIED)) 00624 { 00625 if (op->attacked_by && op->attacked_by->type == PLAYER) 00626 { 00627 safe_strcat(buf[use_buf], " (open)", &len, HUGE_BUF); 00628 } 00629 else 00630 { 00631 safe_strcat(buf[use_buf], " (ready)", &len, HUGE_BUF); 00632 } 00633 } 00634 00635 if (QUERY_FLAG(op, FLAG_IDENTIFIED) || QUERY_FLAG(op, FLAG_APPLIED)) 00636 { 00637 if (QUERY_FLAG(op, FLAG_PERM_DAMNED)) 00638 { 00639 safe_strcat(buf[use_buf], " (perm. damned)", &len, HUGE_BUF); 00640 } 00641 else if (QUERY_FLAG(op, FLAG_DAMNED)) 00642 { 00643 safe_strcat(buf[use_buf], " (damned)", &len, HUGE_BUF); 00644 } 00645 else if (QUERY_FLAG(op, FLAG_PERM_CURSED)) 00646 { 00647 safe_strcat(buf[use_buf], " (perm. cursed)", &len, HUGE_BUF); 00648 } 00649 else if (QUERY_FLAG(op, FLAG_CURSED)) 00650 { 00651 safe_strcat(buf[use_buf], " (cursed)", &len, HUGE_BUF); 00652 } 00653 } 00654 00655 if (QUERY_FLAG(op, FLAG_IS_MAGICAL) && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00656 { 00657 safe_strcat(buf[use_buf], " (magical)", &len, HUGE_BUF); 00658 } 00659 00660 if (QUERY_FLAG(op, FLAG_APPLIED)) 00661 { 00662 switch (op->type) 00663 { 00664 case BOW: 00665 case WAND: 00666 case ROD: 00667 case HORN: 00668 safe_strcat(buf[use_buf], " (readied)", &len, HUGE_BUF); 00669 break; 00670 00671 case WEAPON: 00672 safe_strcat(buf[use_buf], " (wielded)", &len, HUGE_BUF); 00673 break; 00674 00675 case ARMOUR: 00676 case HELMET: 00677 case SHIELD: 00678 case RING: 00679 case BOOTS: 00680 case GLOVES: 00681 case AMULET: 00682 case GIRDLE: 00683 case BRACERS: 00684 case CLOAK: 00685 safe_strcat(buf[use_buf], " (worn)", &len, HUGE_BUF); 00686 break; 00687 00688 case CONTAINER: 00689 safe_strcat(buf[use_buf], " (active)", &len, HUGE_BUF); 00690 break; 00691 00692 case SKILL: 00693 case SKILL_ITEM: 00694 default: 00695 safe_strcat(buf[use_buf], " (applied)", &len, HUGE_BUF); 00696 } 00697 } 00698 00699 if (QUERY_FLAG(op, FLAG_UNPAID)) 00700 { 00701 safe_strcat(buf[use_buf], " (unpaid)", &len, HUGE_BUF); 00702 } 00703 00704 return buf[use_buf]; 00705 } 00706 00712 char *query_material_name(object *op) 00713 { 00714 static char buf[MAX_BUF]; 00715 size_t len; 00716 00717 buf[0] = '\0'; 00718 len = 0; 00719 00720 if (!op->name) 00721 { 00722 return "(null)"; 00723 } 00724 00725 if (!QUERY_FLAG(op, FLAG_IS_NAMED)) 00726 { 00727 /* Add the item race name */ 00728 if (!IS_LIVE(op) && op->type != BASE_INFO) 00729 { 00730 safe_strcat(buf, item_races[op->item_race], &len, sizeof(buf)); 00731 } 00732 00733 if (op->material_real && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00734 { 00735 safe_strcat(buf, material_real[op->material_real].name, &len, sizeof(buf)); 00736 } 00737 } 00738 00739 safe_strcat(buf, op->name, &len, sizeof(buf)); 00740 00741 if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00742 { 00743 safe_strcat(buf, " ", &len, sizeof(buf)); 00744 safe_strcat(buf, op->title, &len, sizeof(buf)); 00745 } 00746 00747 return buf; 00748 } 00749 00762 char *query_base_name(object *op, object *caller) 00763 { 00764 static char buf[MAX_BUF]; 00765 char buf2[32]; 00766 size_t len; 00767 00768 buf[0] = '\0'; 00769 00770 if (op->name == NULL) 00771 { 00772 return "(null)"; 00773 } 00774 00775 if (!QUERY_FLAG(op, FLAG_IS_NAMED)) 00776 { 00777 /* Add the item race name */ 00778 if (!IS_LIVE(op) && op->type != BASE_INFO) 00779 { 00780 strcpy(buf, item_races[op->item_race]); 00781 } 00782 00783 if (op->material_real && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00784 { 00785 strcat(buf, material_real[op->material_real].name); 00786 } 00787 } 00788 00789 strcat(buf, op->name); 00790 00791 /* To speed things up */ 00792 if (!op->weight && !op->title && !is_magical(op)) 00793 { 00794 return buf; 00795 } 00796 00797 len = strlen(buf); 00798 00799 switch (op->type) 00800 { 00801 case CONTAINER: 00802 if (QUERY_FLAG(op, FLAG_IDENTIFIED)) 00803 { 00804 if (op->title) 00805 { 00806 safe_strcat(buf, " ", &len, sizeof(buf)); 00807 safe_strcat(buf, op->title, &len, sizeof(buf)); 00808 } 00809 } 00810 00811 if (op->sub_type >= ST1_CONTAINER_NORMAL_party) 00812 { 00813 if (op->sub_type == ST1_CONTAINER_CORPSE_party) 00814 { 00815 if (op->slaying) 00816 { 00817 if (!caller || caller->type != PLAYER) 00818 { 00819 safe_strcat(buf, " (bounty of a party)", &len, sizeof(buf)); 00820 } 00821 else if (CONTR(caller)->party && CONTR(caller)->party->name == op->slaying) 00822 { 00823 safe_strcat(buf, " (bounty of your party", &len, sizeof(buf)); 00824 00825 /* A searched bounty */ 00826 if (QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00827 { 00828 safe_strcat(buf, ", searched", &len, sizeof(buf)); 00829 } 00830 00831 safe_strcat(buf, ")", &len, sizeof(buf)); 00832 } 00833 /* It's a different party */ 00834 else 00835 { 00836 safe_strcat(buf, " (bounty of another party)", &len, sizeof(buf)); 00837 } 00838 } 00839 else if (QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00840 { 00841 safe_strcat(buf, " (searched)", &len, sizeof(buf)); 00842 } 00843 } 00844 } 00845 else if (op->sub_type >= ST1_CONTAINER_NORMAL_player) 00846 { 00847 if (op->sub_type == ST1_CONTAINER_CORPSE_player) 00848 { 00849 if (op->slaying) 00850 { 00851 safe_strcat(buf, " (bounty of ", &len, sizeof(buf)); 00852 safe_strcat(buf, op->slaying, &len, sizeof(buf)); 00853 00854 /* A searched bounty */ 00855 if ((caller && caller->name == op->slaying) && QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00856 { 00857 safe_strcat(buf, ", searched", &len, sizeof(buf)); 00858 } 00859 00860 safe_strcat(buf, ")", &len, sizeof(buf)); 00861 } 00862 else if (QUERY_FLAG(op, FLAG_BEEN_APPLIED)) 00863 { 00864 safe_strcat(buf, " (searched)", &len, sizeof(buf)); 00865 } 00866 } 00867 } 00868 00869 break; 00870 00871 case SPELLBOOK: 00872 if (QUERY_FLAG(op, FLAG_IDENTIFIED)) 00873 { 00874 if (!op->title) 00875 { 00876 safe_strcat(buf, " of ", &len, sizeof(buf)); 00877 00878 if (op->slaying) 00879 { 00880 safe_strcat(buf, op->slaying, &len, sizeof(buf)); 00881 } 00882 else 00883 { 00884 if (op->stats.sp == SP_NO_SPELL) 00885 { 00886 safe_strcat(buf, "nothing", &len, sizeof(buf)); 00887 } 00888 else 00889 { 00890 safe_strcat(buf, spells[op->stats.sp].name, &len, sizeof(buf)); 00891 } 00892 } 00893 } 00894 else 00895 { 00896 safe_strcat(buf, " ", &len, sizeof(buf)); 00897 safe_strcat(buf, op->title, &len, sizeof(buf)); 00898 } 00899 } 00900 00901 break; 00902 00903 case SCROLL: 00904 case WAND: 00905 case ROD: 00906 case HORN: 00907 case POTION: 00908 if (QUERY_FLAG(op, FLAG_IDENTIFIED)) 00909 { 00910 if (!op->title) 00911 { 00912 if (op->stats.sp != SP_NO_SPELL) 00913 { 00914 safe_strcat(buf, " of ", &len, sizeof(buf)); 00915 safe_strcat(buf, spells[op->stats.sp].name, &len, sizeof(buf)); 00916 } 00917 else 00918 { 00919 safe_strcat(buf, " of nothing", &len, sizeof(buf)); 00920 } 00921 } 00922 else 00923 { 00924 safe_strcat(buf, " ", &len, sizeof(buf)); 00925 safe_strcat(buf, op->title, &len, sizeof(buf)); 00926 } 00927 00928 sprintf(buf2, " (lvl %d)", op->level); 00929 safe_strcat(buf, buf2, &len, sizeof(buf)); 00930 } 00931 00932 break; 00933 00934 case SKILL: 00935 case AMULET: 00936 case RING: 00937 if (QUERY_FLAG(op, FLAG_IDENTIFIED)) 00938 { 00939 if (!op->title) 00940 { 00941 /* If ring has a title, full description isn't so useful */ 00942 char *s = describe_item(op); 00943 00944 if (s[0]) 00945 { 00946 safe_strcat (buf, " ", &len, sizeof(buf)); 00947 safe_strcat (buf, s, &len, sizeof(buf)); 00948 } 00949 } 00950 else 00951 { 00952 safe_strcat(buf, " ", &len, sizeof(buf)); 00953 safe_strcat(buf, op->title, &len, sizeof(buf)); 00954 } 00955 } 00956 00957 break; 00958 00959 default: 00960 if (op->magic && (!need_identify(op) || QUERY_FLAG(op, FLAG_BEEN_APPLIED) || QUERY_FLAG(op, FLAG_IDENTIFIED))) 00961 { 00962 if (!IS_LIVE(op) && op->type != BASE_INFO) 00963 { 00964 sprintf(buf2, " %+d", op->magic); 00965 safe_strcat(buf, buf2, &len, sizeof(buf)); 00966 } 00967 } 00968 00969 if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00970 { 00971 safe_strcat(buf, " ", &len, sizeof(buf)); 00972 safe_strcat(buf, op->title, &len, sizeof(buf)); 00973 } 00974 00975 if ((op->type == ARROW || op->type == WEAPON) && op->slaying && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00976 { 00977 safe_strcat(buf, " ", &len, sizeof(buf)); 00978 safe_strcat(buf, op->slaying, &len, sizeof(buf)); 00979 } 00980 } 00981 00982 return buf; 00983 } 00984 00989 static void describe_terrain(object *op, char *retbuf) 00990 { 00991 if (op->terrain_flag & TERRAIN_AIRBREATH) 00992 { 00993 strcat(retbuf, "(air breathing)"); 00994 } 00995 00996 if (op->terrain_flag & TERRAIN_WATERWALK) 00997 { 00998 strcat(retbuf, "(water walking)"); 00999 } 01000 01001 if (op->terrain_flag & TERRAIN_FIREWALK) 01002 { 01003 strcat(retbuf, "(fire walking)"); 01004 } 01005 01006 if (op->terrain_flag & TERRAIN_CLOUDWALK) 01007 { 01008 strcat(retbuf, "(cloud walking)"); 01009 } 01010 01011 if (op->terrain_flag & TERRAIN_WATERBREATH) 01012 { 01013 strcat(retbuf, "(water breathing)"); 01014 } 01015 01016 if (op->terrain_flag & TERRAIN_FIREBREATH) 01017 { 01018 strcat(retbuf, "(fire breathing)"); 01019 } 01020 } 01021 01039 char *describe_item(object *op) 01040 { 01041 int attr,val, more_info = 0, id_true = 0; 01042 char buf[MAX_BUF]; 01043 static char retbuf[VERY_BIG_BUF * 3]; 01044 01045 retbuf[0] = '\0'; 01046 01047 /* We start with players */ 01048 if (op->type == PLAYER) 01049 { 01050 describe_terrain(op, retbuf); 01051 01052 if (CONTR(op)->digestion) 01053 { 01054 if (CONTR(op)->digestion > 0) 01055 { 01056 sprintf(buf, "(sustenance%+d)", CONTR(op)->digestion); 01057 } 01058 else if (CONTR(op)->digestion < 0) 01059 { 01060 sprintf(buf, "(hunger%+d)", -CONTR(op)->digestion); 01061 } 01062 01063 strcat(retbuf, buf); 01064 } 01065 01066 if (CONTR(op)->gen_client_grace) 01067 { 01068 sprintf(buf, "(grace reg. %3.1f)", (float) CONTR(op)->gen_client_grace / 10); 01069 strcat(retbuf, buf); 01070 } 01071 01072 if (CONTR(op)->gen_client_sp) 01073 { 01074 sprintf(buf, "(mana reg. %3.1f)", (float) CONTR(op)->gen_client_sp / 10); 01075 strcat(retbuf, buf); 01076 } 01077 01078 if (CONTR(op)->gen_client_hp) 01079 { 01080 sprintf(buf, "(hp reg. %3.1f)", (float) CONTR(op)->gen_client_hp / 10); 01081 strcat(retbuf, buf); 01082 } 01083 } 01084 /* And then monsters */ 01085 else if (QUERY_FLAG(op, FLAG_MONSTER)) 01086 { 01087 describe_terrain(op, retbuf); 01088 01089 if (QUERY_FLAG(op, FLAG_UNDEAD)) 01090 { 01091 strcat(retbuf, "(undead)"); 01092 } 01093 01094 if (QUERY_FLAG(op, FLAG_CAN_PASS_THRU)) 01095 { 01096 strcat(retbuf, "(pass through doors)"); 01097 } 01098 01099 if (QUERY_FLAG(op, FLAG_SEE_INVISIBLE)) 01100 { 01101 strcat(retbuf, "(see invisible)"); 01102 } 01103 01104 if (QUERY_FLAG(op, FLAG_USE_WEAPON)) 01105 { 01106 strcat(retbuf, "(wield weapon)"); 01107 } 01108 01109 if (QUERY_FLAG(op, FLAG_USE_BOW)) 01110 { 01111 strcat(retbuf, "(archer)"); 01112 } 01113 01114 if (QUERY_FLAG(op, FLAG_USE_ARMOUR)) 01115 { 01116 strcat(retbuf, "(wear armour)"); 01117 } 01118 01119 if (QUERY_FLAG(op, FLAG_CAST_SPELL)) 01120 { 01121 strcat(retbuf, "(spellcaster)"); 01122 } 01123 01124 if (QUERY_FLAG(op, FLAG_FRIENDLY)) 01125 { 01126 strcat(retbuf, "(friendly)"); 01127 } 01128 01129 if (QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) 01130 { 01131 strcat(retbuf, "(unaggressive)"); 01132 } 01133 01134 if (QUERY_FLAG(op, FLAG_HITBACK)) 01135 { 01136 strcat(retbuf, "(hitback)"); 01137 } 01138 01139 if (FABS(op->speed) > MIN_ACTIVE_SPEED) 01140 { 01141 switch ((int) ((FABS(op->speed)) * 15)) 01142 { 01143 case 0: 01144 strcat(retbuf, "(very slow movement)"); 01145 break; 01146 01147 case 1: 01148 strcat(retbuf, "(slow movement)"); 01149 break; 01150 01151 case 2: 01152 strcat(retbuf, "(normal movement)"); 01153 break; 01154 01155 case 3: 01156 case 4: 01157 strcat(retbuf, "(fast movement)"); 01158 break; 01159 01160 case 5: 01161 case 6: 01162 strcat(retbuf, "(very fast movement)"); 01163 break; 01164 01165 case 7: 01166 case 8: 01167 case 9: 01168 case 10: 01169 strcat(retbuf, "(extremely fast movement)"); 01170 break; 01171 01172 default: 01173 strcat(retbuf, "(lightning fast movement)"); 01174 break; 01175 } 01176 } 01177 } 01178 /* Here we handle items */ 01179 else 01180 { 01181 /* We only need calculate this once */ 01182 if (QUERY_FLAG(op, FLAG_IDENTIFIED) || QUERY_FLAG(op, FLAG_BEEN_APPLIED) || !need_identify(op)) 01183 { 01184 id_true = 1; 01185 } 01186 01187 /* We only need to show the full details of an item if it is identified */ 01188 if (id_true) 01189 { 01190 /* Terrain flags have no double use... If valid, show them */ 01191 if (op->terrain_type) 01192 { 01193 describe_terrain(op, retbuf); 01194 } 01195 01196 /* Deal with special cases */ 01197 switch (op->type) 01198 { 01199 case WAND: 01200 case ROD: 01201 case HORN: 01202 sprintf(buf, "(delay%+2.1fs)", ((float) op->last_grace / (1000000 / MAX_TIME))); 01203 strcat(retbuf, buf); 01204 01205 break; 01206 01207 /* Armour type objects */ 01208 case ARMOUR: 01209 case HELMET: 01210 case SHIELD: 01211 case BOOTS: 01212 case GLOVES: 01213 case GIRDLE: 01214 case BRACERS: 01215 case CLOAK: 01216 if (ARMOUR_SPEED(op)) 01217 { 01218 sprintf(buf, "(speed cap %1.2f)", ARMOUR_SPEED(op) / 10.0); 01219 strcat(retbuf, buf); 01220 } 01221 01222 /* Do this in all cases - otherwise it gets confusing - does that 01223 * item have no penalty, or is it not fully identified for example. */ 01224 if (ARMOUR_SPELLS(op)) 01225 { 01226 sprintf(buf, "(armour mana reg %d)", -1 * ARMOUR_SPELLS(op)); 01227 strcat(retbuf, buf); 01228 } 01229 01230 case WEAPON: 01231 case RING: 01232 case AMULET: 01233 case FORCE: 01234 more_info = 1; 01235 01236 case BOW: 01237 case ARROW: 01238 if (op->type == BOW) 01239 { 01240 sprintf(buf, "(delay%+2.1fs)", ((float) op->stats.sp / (1000000 / MAX_TIME))); 01241 strcat(retbuf, buf); 01242 } 01243 else if (op->type == ARROW) 01244 { 01245 sprintf(buf, "(delay%+2.1fs)", ((float) op->last_grace / (1000000 / MAX_TIME))); 01246 strcat(retbuf, buf); 01247 } 01248 01249 if (op->last_sp && !IS_ARMOR(op)) 01250 { 01251 sprintf(buf, "(range%+d)", op->last_sp); 01252 strcat(retbuf, buf); 01253 } 01254 01255 if (op->stats.wc) 01256 { 01257 sprintf(buf, "(wc%+d)", op->stats.wc); 01258 strcat(retbuf, buf); 01259 } 01260 01261 if (op->stats.dam) 01262 { 01263 sprintf(buf, "(dam%+d)", op->stats.dam); 01264 strcat(retbuf, buf); 01265 } 01266 01267 if (op->stats.ac) 01268 { 01269 sprintf(buf, "(ac%+d)", op->stats.ac); 01270 strcat(retbuf, buf); 01271 } 01272 01273 if (op->type == WEAPON) 01274 { 01275 /* This is ugly to calculate because it's a curve that increases heavily 01276 * with lower weapon_speed... So, we use a table */ 01277 int ws_temp = (int) (op->weapon_speed / 0.0025f); 01278 01279 if (ws_temp < 0) 01280 { 01281 ws_temp = 0; 01282 } 01283 else if (ws_temp > 18) 01284 { 01285 ws_temp = 18; 01286 } 01287 01288 sprintf(buf, "(%3.2f sec)", weapon_speed_table[ws_temp]); 01289 strcat(retbuf, buf); 01290 01291 if (op->level > 0) 01292 { 01293 sprintf(buf, "(improved %d/%d)", op->last_eat, op->level); 01294 strcat(retbuf, buf); 01295 } 01296 } 01297 01298 break; 01299 01300 case FOOD: 01301 case FLESH: 01302 case DRINK: 01303 { 01304 int curse_multiplier = 1; 01305 01306 sprintf(buf, "(food%s%d)", op->stats.food >= 0 ? "+" : "", op->stats.food); 01307 strcat(retbuf, buf); 01308 01309 if (QUERY_FLAG(op, FLAG_CURSED)) 01310 { 01311 curse_multiplier = 2; 01312 } 01313 01314 if (QUERY_FLAG(op, FLAG_DAMNED)) 01315 { 01316 curse_multiplier = 3; 01317 } 01318 01319 if (op->stats.hp) 01320 { 01321 snprintf(buf, sizeof(buf), "(hp%s%d)", curse_multiplier == 1 ? "+" : "", op->stats.hp * curse_multiplier); 01322 strcat(retbuf, buf); 01323 } 01324 01325 if (op->stats.sp) 01326 { 01327 snprintf(buf, sizeof(buf), "(mana%s%d)", curse_multiplier == 1 ? "+" : "", op->stats.sp * curse_multiplier); 01328 strcat(retbuf, buf); 01329 } 01330 01331 if (op->stats.grace) 01332 { 01333 snprintf(buf, sizeof(buf), "(grace%s%d)", curse_multiplier == 1 ? "+" : "", op->stats.grace * curse_multiplier); 01334 strcat(retbuf, buf); 01335 } 01336 01337 break; 01338 } 01339 01340 case POTION: 01341 if (op->last_sp) 01342 { 01343 sprintf(buf, "(range%+d)", op->last_sp); 01344 strcat(retbuf, buf); 01345 } 01346 01347 break; 01348 01349 case BOOK: 01350 if (op->level) 01351 { 01352 sprintf(buf, "(lvl %d)", op->level); 01353 strcat(retbuf, buf); 01354 } 01355 01356 if (op->msg) 01357 { 01358 if (QUERY_FLAG(op, FLAG_NO_SKILL_IDENT)) 01359 { 01360 strcat(retbuf, "(read)"); 01361 } 01362 else 01363 { 01364 strcat(retbuf, "(unread)"); 01365 } 01366 } 01367 01368 default: 01369 return retbuf; 01370 } 01371 01372 /* These count for every "normal" item player deals with - mostly equipment */ 01373 for (attr = 0; attr < NUM_STATS; attr++) 01374 { 01375 if ((val = get_attr_value(&(op->stats), attr)) != 0) 01376 { 01377 sprintf(buf, "(%s%+d)", short_stat_name[attr], val); 01378 strcat(retbuf, buf); 01379 } 01380 } 01381 } 01382 } 01383 01384 /* Some special info for some identified items */ 01385 if (id_true && more_info) 01386 { 01387 if (op->stats.sp) 01388 { 01389 sprintf(buf, "(mana reg.%+3.1f)", 0.4f * op->stats.sp); 01390 strcat(retbuf, buf); 01391 } 01392 01393 if (op->stats.grace) 01394 { 01395 sprintf(buf, "(grace reg.%+3.1f)", 0.4f * op->stats.grace); 01396 strcat(retbuf, buf); 01397 } 01398 01399 if (op->stats.hp) 01400 { 01401 sprintf(buf, "(hp reg.%+3.1f)", 0.4f * op->stats.hp); 01402 strcat(retbuf, buf); 01403 } 01404 01405 if (op->stats.food) 01406 { 01407 if (op->stats.food > 0) 01408 { 01409 sprintf(buf, "(sustenance%+d)", op->stats.food); 01410 } 01411 else if (op->stats.food < 0) 01412 { 01413 sprintf(buf, "(hunger%+d)", -op->stats.food); 01414 } 01415 01416 strcat(retbuf, buf); 01417 } 01418 01419 if (op->stats.exp) 01420 { 01421 sprintf(buf, "(speed %+"FMT64")", op->stats.exp); 01422 strcat(retbuf, buf); 01423 } 01424 } 01425 01426 /* Here we deal with all the special flags */ 01427 if (id_true || QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER) 01428 { 01429 if (QUERY_FLAG(op, FLAG_SEE_INVISIBLE)) 01430 { 01431 strcat(retbuf, "(see invisible)"); 01432 } 01433 01434 if (QUERY_FLAG(op, FLAG_MAKE_ETHEREAL)) 01435 { 01436 strcat(retbuf, "(makes ethereal)"); 01437 } 01438 01439 if (QUERY_FLAG(op, FLAG_IS_ETHEREAL)) 01440 { 01441 strcat(retbuf, "(ethereal)"); 01442 } 01443 01444 if (QUERY_FLAG(op, FLAG_MAKE_INVISIBLE)) 01445 { 01446 strcat(retbuf, "(makes invisible)"); 01447 } 01448 01449 if (QUERY_FLAG(op, FLAG_IS_INVISIBLE)) 01450 { 01451 strcat(retbuf, "(invisible)"); 01452 } 01453 01454 if (QUERY_FLAG(op, FLAG_XRAYS)) 01455 { 01456 strcat(retbuf, "(xray-vision)"); 01457 } 01458 01459 if (QUERY_FLAG(op, FLAG_SEE_IN_DARK)) 01460 { 01461 strcat(retbuf, "(infravision)"); 01462 } 01463 01464 if (QUERY_FLAG(op, FLAG_LIFESAVE)) 01465 { 01466 strcat(retbuf, "(lifesaving)"); 01467 } 01468 01469 if (QUERY_FLAG(op, FLAG_REFL_SPELL)) 01470 { 01471 strcat(retbuf, "(reflect spells)"); 01472 } 01473 01474 if (QUERY_FLAG(op, FLAG_REFL_MISSILE)) 01475 { 01476 strcat(retbuf, "(reflect missiles)"); 01477 } 01478 01479 if (QUERY_FLAG(op, FLAG_STEALTH)) 01480 { 01481 strcat(retbuf, "(stealth)"); 01482 } 01483 01484 if (QUERY_FLAG(op, FLAG_FLYING)) 01485 { 01486 strcat(retbuf, "(levitate)"); 01487 } 01488 } 01489 01490 if (id_true) 01491 { 01492 if (op->slaying != NULL) 01493 { 01494 strcat(retbuf, "(slay "); 01495 strcat(retbuf, op->slaying); 01496 strcat(retbuf, ")"); 01497 } 01498 01499 strcat(retbuf, describe_attack(op, 0)); 01500 strcat(retbuf, describe_protections(op, 0)); 01501 01502 DESCRIBE_PATH(retbuf, op->path_attuned, "Attuned"); 01503 DESCRIBE_PATH(retbuf, op->path_repelled, "Repelled"); 01504 DESCRIBE_PATH(retbuf, op->path_denied, "Denied"); 01505 01506 if (op->stats.maxhp && (op->type != HORN && op->type != ROD && op->type != WAND)) 01507 { 01508 sprintf(buf, "(hp%+d)", op->stats.maxhp); 01509 strcat(retbuf, buf); 01510 } 01511 01512 if (op->stats.maxsp) 01513 { 01514 sprintf(buf, "(mana%+d)", op->stats.maxsp); 01515 strcat(retbuf, buf); 01516 } 01517 01518 if (op->stats.maxgrace) 01519 { 01520 sprintf(buf, "(grace%+d)", op->stats.maxgrace); 01521 strcat(retbuf, buf); 01522 } 01523 01524 if (op->item_power) 01525 { 01526 sprintf(buf, "(item power%+d)", op->item_power); 01527 strcat(retbuf, buf); 01528 } 01529 } 01530 01531 return retbuf; 01532 } 01533 01538 int need_identify(object *op) 01539 { 01540 switch (op->type) 01541 { 01542 case RING: 01543 case WAND: 01544 case ROD: 01545 case HORN: 01546 case SCROLL: 01547 case SKILL: 01548 case SKILLSCROLL: 01549 case SPELLBOOK: 01550 case FOOD: 01551 case POTION: 01552 case BOW: 01553 case ARROW: 01554 case WEAPON: 01555 case ARMOUR: 01556 case SHIELD: 01557 case HELMET: 01558 case AMULET: 01559 case BOOTS: 01560 case GLOVES: 01561 case BRACERS: 01562 case GIRDLE: 01563 case CONTAINER: 01564 case DRINK: 01565 case FLESH: 01566 case INORGANIC: 01567 case CLOSE_CON: 01568 case CLOAK: 01569 case GEM: 01570 case JEWEL: 01571 case NUGGET: 01572 case PEARL: 01573 case POWER_CRYSTAL: 01574 case POISON: 01575 case BOOK: 01576 case LIGHT_APPLY: 01577 case LIGHT_REFILL: 01578 return 1; 01579 } 01580 01581 return 0; 01582 } 01583 01588 void identify(object *op) 01589 { 01590 object *pl; 01591 01592 if (!op) 01593 { 01594 return; 01595 } 01596 01597 SET_FLAG(op, FLAG_IDENTIFIED); 01598 01599 if (op->type == POTION && op->arch != (archetype *) NULL) 01600 { 01601 FREE_AND_ADD_REF_HASH(op->name, op->arch->clone.name); 01602 } 01603 else if (op->type == SPELLBOOK && op->slaying != NULL) 01604 { 01605 if ((op->stats.sp = look_up_spell_name(op->slaying)) < 0) 01606 { 01607 char buf[256]; 01608 01609 op->stats.sp = -1; 01610 snprintf(buf, sizeof(buf), "Spell formula for %s", op->slaying); 01611 FREE_AND_COPY_HASH(op->name, buf); 01612 } 01613 else 01614 { 01615 /* Clear op->slaying since we no longer need it */ 01616 FREE_AND_CLEAR_HASH(op->slaying); 01617 } 01618 } 01619 01620 /* The shop identifies items before they hit the ground */ 01621 if (op->map) 01622 { 01623 update_object(op, UP_OBJ_FACE); 01624 } 01625 else 01626 { 01627 pl = is_player_inv(op->env); 01628 01629 /* A lot of the values can change from an update - might as well send 01630 * it all. */ 01631 if (pl) 01632 { 01633 esrv_send_item(pl, op); 01634 } 01635 } 01636 } 01637 01642 void set_trapped_flag(object *op) 01643 { 01644 object *tmp; 01645 int flag; 01646 01647 if (!op) 01648 { 01649 return; 01650 } 01651 01652 /* Player and monsters are not marked */ 01653 if (op->type == PLAYER || op->type == MONSTER) 01654 { 01655 return; 01656 } 01657 01658 flag = QUERY_FLAG(op, FLAG_IS_TRAPPED); 01659 01660 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 01661 { 01662 /* Must be a rune AND visible */ 01663 if (tmp->type == RUNE && tmp->stats.Cha <= 1) 01664 { 01665 SET_FLAG(op, FLAG_IS_TRAPPED); 01666 01667 if (!flag) 01668 { 01669 goto set_trapped_view; 01670 } 01671 01672 return; 01673 } 01674 } 01675 01676 /* Clean */ 01677 CLEAR_FLAG(op, FLAG_IS_TRAPPED); 01678 01679 if (!flag) 01680 { 01681 return; 01682 } 01683 01684 set_trapped_view: 01685 /* Env object is on map */ 01686 if (!op->env) 01687 { 01688 update_object(op, UP_OBJ_FACE); 01689 } 01690 /* Somewhere else - if visible, update */ 01691 else 01692 { 01693 if (op->env->type == PLAYER || op->env->type == CONTAINER) 01694 { 01695 esrv_update_item(UPD_FLAGS, op->env, op); 01696 } 01697 } 01698 }
1.7.4