|
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 #define ALCHEMY_DEBUG 00034 00036 #define EXTREME_ALCHEMY_DEBUG 00037 00039 static char *cauldron_effect[] = 00040 { 00041 "vibrates briefly", 00042 "produces a cloud of steam", 00043 "emits bright flames", 00044 "pours forth heavy black smoke", 00045 "emits sparks", 00046 "shoots out small flames", 00047 "whines painfully", 00048 "hiccups loudly", 00049 "wheezes", 00050 "burps", 00051 "shakes", 00052 "rattles", 00053 "makes chugging sounds", 00054 "smokes heavily for a while" 00055 }; 00056 00057 static const char *cauldron_sound(); 00058 static int content_recipe_value(object *op); 00059 static int numb_ob_inside(object *op); 00060 static void adjust_product(object *item, int lvl, int yield); 00061 static object *make_item_from_recipe(object *cauldron, recipe *rp); 00062 static void alchemy_failure_effect(object *op, object *cauldron, recipe *rp, int danger); 00063 static void remove_contents(object *first_ob, object *save_item); 00064 static int calc_alch_danger(object *caster, object *cauldron); 00065 static object *find_transmution_ob(object *first_ingred, recipe *rp); 00066 static object *attempt_recipe(object *caster, object *cauldron, int ability, recipe *rp, int nbatches); 00067 00070 static const char *cauldron_sound() 00071 { 00072 int size = sizeof(cauldron_effect) / sizeof(char *); 00073 00074 return cauldron_effect[rndm(1, size) - 1]; 00075 } 00076 00102 static void attempt_do_alchemy(object *caster, object *cauldron) 00103 { 00104 recipelist *fl; 00105 recipe *rp = NULL; 00106 float success_chance; 00107 int numb, ability = 1; 00108 int formula = 0; 00109 00110 /* Only players for now */ 00111 if (caster->type != PLAYER) 00112 { 00113 return; 00114 } 00115 00116 /* If no ingredients, no formula! Let's forget it */ 00117 if (!(formula = content_recipe_value(cauldron))) 00118 { 00119 return; 00120 } 00121 00122 numb = numb_ob_inside(cauldron); 00123 00124 if ((fl = get_formulalist(numb))) 00125 { 00126 /* The caster only gets an increase in ability if they know 00127 * alchemy skill */ 00128 if (find_skill(caster, SK_ALCHEMY) != NULL) 00129 { 00130 change_skill(caster, SK_ALCHEMY); 00131 ability += (int) (SK_level(caster) * (float) ((float) (4 + cauldron->magic) / 4.0f)); 00132 } 00133 00134 #ifdef ALCHEMY_DEBUG 00135 LOG(llevDebug, "Got alchemy ability lvl = %d\n", ability); 00136 #endif 00137 00138 if (QUERY_FLAG(caster, FLAG_WIZ)) 00139 { 00140 rp = fl->items; 00141 00142 while (rp && (formula % rp->index) != 0) 00143 { 00144 #ifdef EXTREME_ALCHEMY_DEBUG 00145 LOG(llevDebug, "found list %d formula: %s of %s (%d)\n", numb, rp->arch_name, rp->title, rp->index); 00146 #endif 00147 rp = rp->next; 00148 } 00149 00150 if (rp) 00151 { 00152 #ifdef ALCHEMY_DEBUG 00153 if (rp->title != shstr_cons.NONE) 00154 { 00155 LOG(llevDebug, "WIZ got formula: %s of %s\n", rp->arch_name, rp->title); 00156 } 00157 else 00158 { 00159 LOG(llevDebug, "WIZ got formula: %s (nbatches:%d)\n", rp->arch_name, formula / rp->index); 00160 } 00161 #endif 00162 attempt_recipe(caster, cauldron, ability, rp, formula / rp->index); 00163 } 00164 else 00165 { 00166 LOG(llevDebug, "WIZ couldn't find formula for ingredients.\n"); 00167 } 00168 00169 return; 00170 } 00171 00172 /* Find the recipe */ 00173 for (rp = fl->items; rp != NULL && (formula % rp->index) != 0; rp = rp->next) 00174 { 00175 } 00176 00177 /* If we found a recipe */ 00178 if (rp) 00179 { 00180 float ave_chance = fl->total_chance / (float) fl->number; 00181 object *item; 00182 00183 /* Create the object **FIRST**, then decide whether to keep it. */ 00184 if ((item = attempt_recipe(caster, cauldron, ability, rp, formula / rp->index)) != NULL) 00185 { 00186 /* Compute base chance of recipe success */ 00187 success_chance = ((float) (15 * ability) / (float) (15 * ability + numb * item->level * (numb + item->level + formula / rp->index))); 00188 00189 if (ave_chance == 0) 00190 { 00191 ave_chance = 1; 00192 } 00193 00194 /* Adjust the success chance by the chance from the recipe list */ 00195 if (ave_chance > rp->chance) 00196 { 00197 success_chance *= ((float) rp->chance + ave_chance) / (2.0f * ave_chance); 00198 } 00199 else 00200 { 00201 success_chance = 1.0f - ((1.0f - success_chance) * ((float) rp->chance + ave_chance) / (2.0f * (float) rp->chance)); 00202 } 00203 00204 #ifdef ALCHEMY_DEBUG 00205 LOG(llevDebug, "percent success chance = %f\n", success_chance); 00206 #endif 00207 00208 /* Roll the dice */ 00209 if (rndm(0, 99) <= 100.0 * success_chance) 00210 { 00211 /* We learn from our experience IF we know something of the alchemical arts */ 00212 if (caster->chosen_skill && caster->chosen_skill->stats.sp == SK_ALCHEMY) 00213 { 00214 /* More exp is given for higher ingred number recipes */ 00215 sint64 amount = numb * numb * calc_skill_exp(caster, item, -1); 00216 add_exp(caster, amount, SK_ALCHEMY, 0); 00217 /* So when skill id this item, less xp is awarded */ 00218 item->stats.exp = 0; 00219 #ifdef EXTREME_ALCHEMY_DEBUG 00220 LOG(llevDebug, "%s gains %"FMT64" experience points.\n", caster->name, amount); 00221 #endif 00222 } 00223 00224 return; 00225 } 00226 } 00227 } 00228 } 00229 00230 /* If we get here, we failed! */ 00231 alchemy_failure_effect(caster, cauldron, rp, calc_alch_danger(caster, cauldron)); 00232 } 00233 00242 static int content_recipe_value(object *op) 00243 { 00244 char name[MAX_BUF]; 00245 object *tmp = op->inv; 00246 int tval = 0, formula = 0; 00247 00248 while (tmp) 00249 { 00250 tval = 0; 00251 strcpy(name, tmp->name); 00252 00253 if (tmp->title) 00254 { 00255 snprintf(name, sizeof(name), "%s %s", tmp->name, tmp->title); 00256 } 00257 00258 tval = (strtoint(name) * (tmp->nrof ? tmp->nrof : 1)); 00259 00260 #ifdef ALCHEMY_DEBUG 00261 LOG(llevDebug, "Got ingredient %d %s(%d)\n", tmp->nrof ? tmp->nrof : 1, name, tval); 00262 #endif 00263 00264 formula += tval; 00265 tmp = tmp->below; 00266 } 00267 00268 #ifdef ALCHEMY_DEBUG 00269 LOG(llevDebug, "Formula value=%d\n", formula); 00270 #endif 00271 00272 return formula; 00273 } 00274 00280 static int numb_ob_inside(object *op) 00281 { 00282 object *tmp = op->inv; 00283 int o_number = 0; 00284 00285 while (tmp) 00286 { 00287 o_number++; 00288 tmp = tmp->below; 00289 } 00290 00291 #ifdef ALCHEMY_DEBUG 00292 LOG(llevDebug, "numb_ob_inside(%s): found %d ingredients\n", op->name, o_number); 00293 #endif 00294 00295 return o_number; 00296 } 00297 00310 static object *attempt_recipe(object *caster, object *cauldron, int ability, recipe *rp, int nbatches) 00311 { 00312 object *item = NULL; 00313 /* This should be passed to this function, not too efficient CPU use this way */ 00314 int batches = abs(nbatches); 00315 00316 /* Code required for this recipe, search the caster */ 00317 if (rp->keycode) 00318 { 00319 object *tmp; 00320 00321 for (tmp = caster->inv; tmp != NULL; tmp = tmp->below) 00322 { 00323 if (tmp->type == FORCE && tmp->slaying && !strcmp(rp->keycode, tmp->slaying)) 00324 { 00325 break; 00326 } 00327 } 00328 00329 /* Failure - no code found */ 00330 if (tmp == NULL) 00331 { 00332 new_draw_info(0, COLOR_WHITE, caster, "You know the ingredients, but not the technique. Go learn how to do this recipe."); 00333 return NULL; 00334 } 00335 } 00336 00337 #ifdef EXTREME_ALCHEMY_DEBUG 00338 LOG(llevDebug, "attempt_recipe(): got %d nbatches\n", nbatches); 00339 LOG(llevDebug, "attempt_recipe(): using recipe %s\n", rp->title ? rp->title : "unknown"); 00340 #endif 00341 00342 if ((item = make_item_from_recipe(cauldron, rp)) != NULL) 00343 { 00344 remove_contents(cauldron->inv, item); 00345 /* adj lvl, nrof on caster level */ 00346 adjust_product(item, ability, rp->yield ? (rp->yield * batches) : batches); 00347 00348 if (!item->env && (item = insert_ob_in_ob(item, cauldron)) == NULL) 00349 { 00350 new_draw_info(0, COLOR_WHITE, caster, "Nothing happened."); 00351 } 00352 else 00353 { 00354 new_draw_info_format(0, COLOR_WHITE, caster, "The %s %s.", cauldron->name, cauldron_sound()); 00355 } 00356 } 00357 00358 return item; 00359 } 00360 00367 static void adjust_product(object *item, int lvl, int yield) 00368 { 00369 int nrof = 1; 00370 00371 if (!yield) 00372 { 00373 yield = 1; 00374 } 00375 00376 /* Avoid division by zero */ 00377 if (lvl <= 0) 00378 { 00379 lvl = 1; 00380 } 00381 00382 if (item->nrof) 00383 { 00384 nrof = (int) ((1.0f - 1.0f / ((float) lvl / 10.0f + 1.0f)) * (float) (rndm(0, yield - 1) + rndm(0, yield - 1) + rndm(0, yield - 1)) + 1.0f); 00385 00386 if (nrof > yield) 00387 { 00388 nrof = yield; 00389 } 00390 00391 item->nrof = nrof; 00392 } 00393 00394 /* Item exp. This will be used later for experience calculation */ 00395 item->stats.exp += lvl * lvl * nrof; 00396 00397 #if 0 00398 /* avg between default and caster levels */ 00399 item->level = (lvl + item->level) / 2; 00400 #endif 00401 } 00402 00409 static object *make_item_from_recipe(object *cauldron, recipe *rp) 00410 { 00411 artifact *art = NULL; 00412 object *item = NULL; 00413 00414 if (rp == NULL) 00415 { 00416 return NULL; 00417 } 00418 00419 /* Find the appropriate object to transform...*/ 00420 if ((item = find_transmution_ob(cauldron->inv, rp)) == NULL) 00421 { 00422 LOG(llevDebug, "make_alchemy_item(): Failed to create alchemical object.\n"); 00423 return NULL; 00424 } 00425 00426 /* Find the appropriate artifact template...*/ 00427 if (rp->title != shstr_cons.NONE) 00428 { 00429 if ((art = locate_recipe_artifact(rp)) == NULL) 00430 { 00431 LOG(llevBug, "make_alchemy_item(): failed to locate recipe artifact.\n"); 00432 LOG(llevBug, "--requested recipe: %s of %s.\n", rp->arch_name, rp->title); 00433 return NULL; 00434 } 00435 00436 give_artifact_abilities(item, art); 00437 } 00438 00439 if (QUERY_FLAG(cauldron, FLAG_CURSED)) 00440 { 00441 SET_FLAG(item, FLAG_CURSED); 00442 } 00443 00444 if (QUERY_FLAG(cauldron, FLAG_DAMNED)) 00445 { 00446 SET_FLAG(item, FLAG_DAMNED); 00447 } 00448 00449 return item; 00450 } 00451 00459 static object *find_transmution_ob(object *first_ingred, recipe *rp) 00460 { 00461 object *item = NULL; 00462 00463 /* Look for matching ingredient/prod archs */ 00464 if (rp->transmute) 00465 { 00466 for (item = first_ingred; item; item = item->below) 00467 { 00468 if (!strcmp(item->arch->name, rp->arch_name)) 00469 { 00470 break; 00471 } 00472 } 00473 } 00474 00475 /* Failed, create a fresh object. Note no nrof > 1 because that would 00476 * allow players to create massive amounts of artifacts easily. */ 00477 if (!item || item->nrof > 1) 00478 { 00479 item = get_archetype(rp->arch_name); 00480 } 00481 00482 #ifdef ALCHEMY_DEBUG 00483 LOG(llevDebug, "recipe calls for%stransmution.\n", rp->transmute ? " " : " no "); 00484 00485 if (strcmp(item->arch->name, rp->arch_name)) 00486 { 00487 LOG(llevDebug, "recipe calls for arch: %s\n", rp->arch_name); 00488 } 00489 00490 LOG(llevDebug, "find_transmutable_ob(): returns arch %s(sp:%d)\n", item->arch->name, item->stats.sp); 00491 #endif 00492 00493 return item; 00494 } 00495 00506 static void alchemy_failure_effect(object *op, object *cauldron, recipe *rp, int danger) 00507 { 00508 int level = 0; 00509 00510 if (!op || !cauldron) 00511 { 00512 return; 00513 } 00514 00515 if (danger > 1) 00516 { 00517 level = rndm(1, danger); 00518 } 00519 00520 #ifdef ALCHEMY_DEBUG 00521 LOG(llevDebug, "Alchemy_failure_effect(): using level=%d\n", level); 00522 #endif 00523 00524 /* possible outcomes based on level */ 00525 00526 /* Ingredients destroyed, and possibly create slag. */ 00527 if (level < 25) 00528 { 00529 object *item = NULL; 00530 00531 /* Slag created */ 00532 if (rndm(0, 2)) 00533 { 00534 object *tmp = cauldron->inv; 00535 int weight = 0; 00536 uint16 material = M_STONE; 00537 00538 /* Slag has coadded ingredient properties */ 00539 while (tmp) 00540 { 00541 weight += tmp->weight; 00542 00543 if (!(material & tmp->material)) 00544 { 00545 material = material | tmp->material; 00546 } 00547 00548 tmp = tmp->below; 00549 } 00550 00551 tmp = get_archetype("rock"); 00552 tmp->weight = weight; 00553 tmp->value = 0; 00554 tmp->material = material; 00555 FREE_AND_COPY_HASH(tmp->name, "slag"); 00556 item = insert_ob_in_ob(tmp, cauldron); 00557 CLEAR_FLAG(tmp, FLAG_CAN_ROLL); 00558 CLEAR_FLAG(tmp, FLAG_NO_PICK); 00559 CLEAR_FLAG(tmp, FLAG_NO_PASS); 00560 } 00561 00562 remove_contents(cauldron->inv, item); 00563 new_draw_info_format(0, COLOR_WHITE, op, "The %s %s.", cauldron->name, cauldron_sound()); 00564 return; 00565 } 00566 /* Make tained item. */ 00567 else if (level < 40) 00568 { 00569 object *tmp = NULL; 00570 00571 if (!rp) 00572 { 00573 if ((rp = get_random_recipe(NULL)) == NULL) 00574 { 00575 return; 00576 } 00577 } 00578 00579 if ((tmp = attempt_recipe(op, cauldron, 1, rp, -1))) 00580 { 00581 /* Curse it */ 00582 if (!QUERY_FLAG(tmp, FLAG_CURSED)) 00583 { 00584 SET_FLAG(tmp, FLAG_CURSED); 00585 } 00586 00587 /* Special stuff for consumables */ 00588 if (tmp->type == FOOD) 00589 { 00590 tmp->stats.sp = 0; 00591 00592 /* Poisonous */ 00593 if (rndm(0, 1)) 00594 { 00595 tmp->type = FOOD; 00596 tmp->stats.hp = rndm(0, 149); 00597 } 00598 } 00599 00600 /* Unsaleable item */ 00601 tmp->value = 0; 00602 00603 /* Change stats downward */ 00604 do 00605 { 00606 change_attr_value(&tmp->stats, rndm(0, 6), (signed char) (-1 * (rndm(1, 3)))); 00607 } 00608 while (rndm(0, 2)); 00609 } 00610 00611 return; 00612 } 00613 00614 /* Make random recipe. */ 00615 if (level == 40) 00616 { 00617 recipelist *fl; 00618 int numb = numb_ob_inside(cauldron); 00619 00620 /* Take a lower recipe list */ 00621 fl = get_formulalist(numb - 1); 00622 00623 if (fl && (rp = get_random_recipe(fl))) 00624 { 00625 /* Even though random, don't grant user any EXP for it */ 00626 (void) attempt_recipe(op, cauldron, 1, rp, -1); 00627 } 00628 else 00629 { 00630 alchemy_failure_effect(op, cauldron, rp, level - 1); 00631 } 00632 00633 return; 00634 } 00635 /* Infuriate NPCs */ 00636 else if (level < 45) 00637 { 00638 alchemy_failure_effect(op, cauldron, rp, level - 5); 00639 return; 00640 } 00641 /* Minor explosion/fireball */ 00642 else if (level < 50) 00643 { 00644 object *tmp; 00645 00646 remove_contents(cauldron->inv, NULL); 00647 00648 switch (rndm(0, 2)) 00649 { 00650 case 0: 00651 tmp = get_archetype("bomb"); 00652 tmp->stats.dam = rndm(1, level); 00653 tmp->stats.hp = rndm(1, level); 00654 new_draw_info_format(0, COLOR_WHITE, op, "The %s creates a bomb!", cauldron->name); 00655 break; 00656 00657 default: 00658 tmp = get_archetype("fireball"); 00659 tmp->stats.dam = rndm(1, level) / 5 + 1; 00660 tmp->stats.hp = rndm(1, level) / 10 + 2; 00661 new_draw_info_format(0, COLOR_WHITE, op, "The %s erupts in flame!", cauldron->name); 00662 break; 00663 } 00664 00665 tmp->x = cauldron->x, tmp->y = cauldron->y; 00666 insert_ob_in_map(tmp, op->map, NULL, 0); 00667 return; 00668 } 00669 /* Create monster */ 00670 else if (level < 60) 00671 { 00672 new_draw_info_format(0, COLOR_WHITE, op, "The %s %s.", cauldron->name, cauldron_sound()); 00673 remove_contents(cauldron->inv, NULL); 00674 return; 00675 } 00676 /* Major fire */ 00677 else if (level < 80) 00678 { 00679 remove_contents(cauldron->inv, NULL); 00680 #if 0 00681 fire_arch_from_position(cauldron, cauldron, cauldron->x, cauldron->y, 0, spellarch[SP_L_FIREBALL], SP_L_FIREBALL, NULL); 00682 #endif 00683 new_draw_info_format(0, COLOR_WHITE, op, "The %s erupts in flame!", cauldron->name); 00684 return; 00685 } 00686 /* Whammy the cauldron */ 00687 else if (level < 100) 00688 { 00689 if (!QUERY_FLAG(cauldron, FLAG_CURSED)) 00690 { 00691 SET_FLAG(cauldron, FLAG_CURSED); 00692 } 00693 else 00694 { 00695 cauldron->magic--; 00696 } 00697 00698 cauldron->magic -= rndm(0, 4); 00699 00700 if (rndm(0, 1)) 00701 { 00702 remove_contents(cauldron->inv, NULL); 00703 new_draw_info_format(0, COLOR_WHITE, op, "Your %s turns darker then makes a gulping sound!", cauldron->name); 00704 } 00705 else 00706 { 00707 new_draw_info_format(0, COLOR_WHITE, op, "Your %s becomes darker.", cauldron->name); 00708 } 00709 00710 return; 00711 } 00712 /* Summon evil monsters */ 00713 else if (level < 110) 00714 { 00715 object *tmp = get_random_mon(); 00716 00717 remove_contents(cauldron->inv, NULL); 00718 00719 if (!tmp) 00720 { 00721 alchemy_failure_effect(op, cauldron, rp, level); 00722 } 00723 00724 return; 00725 } 00726 /* Combo effect */ 00727 else if (level < 150) 00728 { 00729 int roll = rndm(1, 3); 00730 00731 while (roll) 00732 { 00733 alchemy_failure_effect(op, cauldron, rp, level - 39); 00734 roll--; 00735 } 00736 00737 return; 00738 } 00739 /* Create random artifact */ 00740 else if (level == 151) 00741 { 00742 object *tmp; 00743 00744 /* this is meant to be better than prior possibility, 00745 * in this one, we allow *any* valid alchemy artifact 00746 * to be made (rather than only those on the given 00747 * formulalist) */ 00748 if (!rp) 00749 { 00750 rp = get_random_recipe((recipelist *) NULL); 00751 } 00752 00753 if (rp && (tmp = get_archetype(rp->arch_name))) 00754 { 00755 generate_artifact(tmp, rndm(1, op->level / 2 + 1) + 1, 0, 99); 00756 00757 if ((tmp = insert_ob_in_ob(tmp, cauldron))) 00758 { 00759 remove_contents(cauldron->inv, tmp); 00760 new_draw_info_format(0, COLOR_WHITE, op, "The %s %s.", cauldron->name, cauldron_sound()); 00761 } 00762 } 00763 00764 return; 00765 } 00766 /* Mana storm -- watch out! */ 00767 else if (level < 200) 00768 { 00769 new_draw_info(0, COLOR_WHITE, op, "You unwisely release potent forces!"); 00770 remove_contents(cauldron->inv, NULL); 00771 cast_magic_storm(op, get_archetype("loose_magic"), level); 00772 return; 00773 } 00774 } 00775 00782 static void remove_contents(object *first_ob, object *save_item) 00783 { 00784 object *next, *tmp = first_ob; 00785 00786 while (tmp) 00787 { 00788 next = tmp->below; 00789 00790 if (tmp == save_item) 00791 { 00792 if (!(tmp = next)) 00793 { 00794 break; 00795 } 00796 else 00797 { 00798 next = next->below; 00799 } 00800 } 00801 00802 if (tmp->inv) 00803 { 00804 remove_contents(tmp->inv, NULL); 00805 } 00806 00807 remove_ob(tmp); 00808 tmp = next; 00809 } 00810 } 00811 00824 static int calc_alch_danger(object *caster, object *cauldron) 00825 { 00826 object *item; 00827 char name[MAX_BUF]; 00828 int danger = 0, nrofi = 0; 00829 00830 /* Knowing alchemy skill reduces yer risk */ 00831 if (caster->chosen_skill && caster->chosen_skill->stats.sp == SK_ALCHEMY) 00832 { 00833 danger -= SK_level(caster); 00834 } 00835 00836 /* Better cauldrons reduce risk */ 00837 danger -= cauldron->magic; 00838 00839 /* Higher Int, lower the risk */ 00840 danger -= 3 * (caster->stats.Int - 15); 00841 00842 /* Ingredients. Longer names usually mean rarer stuff. Thus the 00843 * backfire is worse. Also, more ingredients means we are attempting 00844 * a more powerful potion, and thus the backfire will be worse. */ 00845 for (item = cauldron->inv; item; item = item->below) 00846 { 00847 strcpy(name, item->name); 00848 00849 if (item->title) 00850 { 00851 snprintf(name, sizeof(name), "%s %s", item->name, item->title); 00852 } 00853 00854 danger += (strtoint(name) / 1000) + 3; 00855 nrofi++; 00856 } 00857 00858 if (nrofi > 1) 00859 { 00860 danger *= nrofi; 00861 } 00862 00863 /* Using a bad device is *very* stupid */ 00864 if (QUERY_FLAG(cauldron, FLAG_CURSED)) 00865 { 00866 danger += 80; 00867 } 00868 00869 if (QUERY_FLAG(cauldron, FLAG_DAMNED)) 00870 { 00871 danger += 200; 00872 } 00873 00874 #ifdef ALCHEMY_DEBUG 00875 LOG(llevDebug, "calc_alch_danger() returned danger=%d\n", danger); 00876 #endif 00877 00878 return danger; 00879 } 00880 00887 int use_alchemy(object *op) 00888 { 00889 object *tmp, *item, *next; 00890 object *unpaid_cauldron = NULL; 00891 object *unpaid_item = NULL; 00892 int did_alchemy = 0; 00893 00894 for (tmp = GET_MAP_OB(op->map, op->x, op->y); tmp != NULL; tmp = next) 00895 { 00896 next = tmp->above; 00897 00898 if (QUERY_FLAG(tmp, FLAG_IS_CAULDRON)) 00899 { 00900 if (QUERY_FLAG(tmp, FLAG_UNPAID)) 00901 { 00902 unpaid_cauldron = tmp; 00903 continue; 00904 } 00905 00906 unpaid_item = NULL; 00907 00908 for (item = tmp->inv; item; item = item->below) 00909 { 00910 if (QUERY_FLAG(item, FLAG_UNPAID)) 00911 { 00912 unpaid_item = item; 00913 break; 00914 } 00915 } 00916 00917 if (unpaid_item != NULL) 00918 { 00919 continue; 00920 } 00921 00922 attempt_do_alchemy(op, tmp); 00923 00924 if (QUERY_FLAG(tmp, FLAG_APPLIED)) 00925 { 00926 esrv_send_inventory(op, tmp); 00927 } 00928 00929 did_alchemy = 1; 00930 } 00931 } 00932 00933 if (unpaid_cauldron) 00934 { 00935 new_draw_info_format(0, COLOR_WHITE, op, "You must pay for your %s first!", query_base_name(unpaid_cauldron, NULL)); 00936 } 00937 else if (unpaid_item) 00938 { 00939 new_draw_info_format(0, COLOR_WHITE, op, "You must pay for your %s first!", query_base_name(unpaid_item, NULL)); 00940 } 00941 00942 return did_alchemy; 00943 }
1.7.4