1 | /* |
1 | /* |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
3 | * |
3 | * |
4 | * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
4 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2002 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2002 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992 Frank Tore Johansen |
6 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * |
7 | * |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
9 | * the terms of the Affero GNU General Public License as published by the |
9 | * the terms of the Affero GNU General Public License as published by the |
… | |
… | |
63 | |
63 | |
64 | /** Returns a random selection from cauldron_effect[] */ |
64 | /** Returns a random selection from cauldron_effect[] */ |
65 | static const char * |
65 | static const char * |
66 | cauldron_sound () |
66 | cauldron_sound () |
67 | { |
67 | { |
68 | int size = sizeof (cauldron_effect) / sizeof (char *); |
68 | return cauldron_effect [rndm (array_length (cauldron_effect))]; |
69 | |
|
|
70 | return cauldron_effect[rndm (0, size - 1)]; |
|
|
71 | } |
69 | } |
72 | |
70 | |
73 | /** |
71 | /** |
74 | * Recipe value of the entire contents of a container. |
72 | * Recipe value of the entire contents of a container. |
75 | * This appears to just generate a hash value, which I guess for now works |
73 | * This appears to just generate a hash value, which I guess for now works |
76 | * ok, but the possibility of duplicate hashes is certainly possible - msw |
74 | * ok, but the possibility of duplicate hashes is certainly possible - msw |
77 | */ |
75 | */ |
78 | static int |
76 | static int |
79 | content_recipe_value (object *op) |
77 | content_recipe_value (object *op) |
80 | { |
78 | { |
81 | char name[MAX_BUF]; |
|
|
82 | object *tmp = op->inv; |
79 | object *tmp = op->inv; |
83 | int tval = 0, formula = 0; |
80 | int formula = 0; |
84 | |
81 | |
85 | while (tmp) |
82 | while (tmp) |
86 | { |
83 | { |
87 | tval = 0; |
84 | const char *name = tmp->title |
88 | assign (name, tmp->name); |
|
|
89 | if (tmp->title) |
|
|
90 | sprintf (name, "%s %s", &tmp->name, &tmp->title); |
85 | ? (const char *)format ("%s %s", &tmp->name, &tmp->title) |
|
|
86 | : tmp->name; |
|
|
87 | |
91 | tval = (strtoint (name) * (tmp->nrof ? tmp->nrof : 1)); |
88 | int tval = strtoint (name) * tmp->number_of (); |
92 | #ifdef ALCHEMY_DEBUG |
89 | #ifdef ALCHEMY_DEBUG |
93 | LOG (llevDebug, "Got ingredient %d %s(%d)\n", tmp->nrof ? tmp->nrof : 1, name, tval); |
90 | LOG (llevDebug, "Got ingredient %d %s(%d)\n", tmp->nrof ? tmp->nrof : 1, name, tval); |
94 | #endif |
91 | #endif |
95 | formula += tval; |
92 | formula += tval; |
96 | tmp = tmp->below; |
93 | tmp = tmp->below; |
97 | } |
94 | } |
98 | #ifdef ALCHEMY_DEBUG |
95 | #ifdef ALCHEMY_DEBUG |
99 | LOG (llevDebug, " Formula value=%d\n", formula); |
96 | LOG (llevDebug, " Formula value=%d\n", formula); |
100 | #endif |
97 | #endif |
|
|
98 | |
101 | return formula; |
99 | return formula; |
102 | } |
100 | } |
103 | |
101 | |
104 | /** |
102 | /** |
105 | * Returns total number of items in op |
103 | * Returns total number of items in op |
… | |
… | |
342 | { |
340 | { |
343 | remove_contents (cauldron->inv, item); |
341 | remove_contents (cauldron->inv, item); |
344 | /* Recalc carrying of the cauldron, in case recipe did not conserve mass */ |
342 | /* Recalc carrying of the cauldron, in case recipe did not conserve mass */ |
345 | cauldron->update_weight (); |
343 | cauldron->update_weight (); |
346 | /* adj lvl, nrof on caster level */ |
344 | /* adj lvl, nrof on caster level */ |
347 | adjust_product (item, ability, rp->yield ? (rp->yield * batches) : batches); |
345 | adjust_product (item, ability, rp->yield ? rp->yield * batches : batches); |
|
|
346 | |
348 | if (!item->env && (item = insert_ob_in_ob (item, cauldron)) == NULL) |
347 | if (!item->env && (item = insert_ob_in_ob (item, cauldron)) == NULL) |
349 | { |
348 | { |
350 | new_draw_info (NDI_UNIQUE, 0, caster, "Nothing happened."); |
349 | new_draw_info (NDI_UNIQUE, 0, caster, "Nothing happened."); |
351 | /* new_draw_info_format(NDI_UNIQUE, 0,caster, |
350 | /* new_draw_info_format(NDI_UNIQUE, 0,caster, |
352 | "Your spell causes the %s to explode!",&cauldron->name); */ |
351 | "Your spell causes the %s to explode!",&cauldron->name); */ |
… | |
… | |
576 | * danger. Note that we assume that we have had the caster ready the alchemy |
575 | * danger. Note that we assume that we have had the caster ready the alchemy |
577 | * skill *before* this routine is called. (no longer auto-readies that skill) |
576 | * skill *before* this routine is called. (no longer auto-readies that skill) |
578 | * -b.t. |
577 | * -b.t. |
579 | */ |
578 | */ |
580 | static int |
579 | static int |
581 | calc_alch_danger (object *caster, object *cauldron, recipe *rp) |
580 | calc_alch_danger (object *caster, object *cauldron, object *skill, recipe *rp) |
582 | { |
581 | { |
583 | object *item; |
|
|
584 | char name[MAX_BUF]; |
|
|
585 | int danger = 0, nrofi = 0; |
582 | int danger = 0; |
586 | |
583 | |
587 | /* Knowing alchemy skill reduces yer risk */ |
584 | /* Knowing alchemy skill reduces yer risk */ |
588 | danger -= caster->chosen_skill ? caster->chosen_skill->level : caster->level; |
585 | danger -= skill->level; |
589 | |
|
|
590 | if (!caster->chosen_skill) |
|
|
591 | LOG (llevError | logBacktrace, "calc_alch_danger called without a chosen skill, caster %s, cauldron %s\n", |
|
|
592 | caster->debug_desc (), cauldron->debug_desc ()); |
|
|
593 | |
586 | |
594 | /* better cauldrons reduce risk */ |
587 | /* better cauldrons reduce risk */ |
595 | danger -= cauldron->magic; |
588 | danger -= cauldron->magic; |
596 | |
589 | |
597 | /* Higher Int, lower the risk */ |
590 | /* Higher Int, lower the risk */ |
… | |
… | |
599 | |
592 | |
600 | /* Ingredients. Longer names usually mean rarer stuff. |
593 | /* Ingredients. Longer names usually mean rarer stuff. |
601 | * Thus the backfire is worse. Also, more ingredients |
594 | * Thus the backfire is worse. Also, more ingredients |
602 | * means we are attempting a more powerfull potion, |
595 | * means we are attempting a more powerfull potion, |
603 | * and thus the backfire will be worse. */ |
596 | * and thus the backfire will be worse. */ |
604 | for (item = cauldron->inv; item; item = item->below) |
597 | for (object *item = cauldron->inv; item; item = item->below) |
605 | { |
598 | { |
606 | assign (name, item->name); |
599 | const char *name = item->title |
607 | if (item->title) |
|
|
608 | sprintf (name, "%s %s", &item->name, &item->title); |
600 | ? format ("%s %s", &item->name, &item->title) |
|
|
601 | : &item->name; |
|
|
602 | |
609 | danger += (strtoint (name) / 1000) + 3; |
603 | danger += strtoint (name) / 1000 + 3; |
610 | nrofi++; |
|
|
611 | } |
604 | } |
612 | |
605 | |
613 | if (rp == NULL) |
606 | if (!rp) |
614 | danger += 110; |
607 | danger += 110; |
615 | else |
608 | else |
616 | danger += rp->diff * 3; |
609 | danger += rp->diff * 3; |
617 | |
610 | |
618 | /* Using a bad device is *majorly* stupid */ |
611 | /* Using a bad device is *majorly* stupid */ |
619 | if (cauldron->flag [FLAG_CURSED]) |
612 | if (cauldron->flag [FLAG_CURSED]) danger += 80; |
620 | danger += 80; |
|
|
621 | if (cauldron->flag [FLAG_DAMNED]) |
613 | if (cauldron->flag [FLAG_DAMNED]) danger += 200; |
622 | danger += 200; |
|
|
623 | |
614 | |
624 | #ifdef ALCHEMY_DEBUG |
615 | #ifdef ALCHEMY_DEBUG |
625 | LOG (llevDebug, "calc_alch_danger() returned danger=%d\n", danger); |
616 | LOG (llevDebug, "calc_alch_danger() returned danger=%d\n", danger); |
626 | #endif |
617 | #endif |
627 | |
618 | |
… | |
… | |
898 | |
889 | |
899 | /* create the object **FIRST**, then decide whether to keep it. */ |
890 | /* create the object **FIRST**, then decide whether to keep it. */ |
900 | if ((item = attempt_recipe (caster, cauldron, ability, rp, formula / rp->index)) != NULL) |
891 | if ((item = attempt_recipe (caster, cauldron, ability, rp, formula / rp->index)) != NULL) |
901 | { |
892 | { |
902 | /* compute base chance of recipe success */ |
893 | /* compute base chance of recipe success */ |
903 | success_chance = ((float) ability / (float) (rp->diff * (item->level + 2))); |
894 | success_chance = ((float)ability / (float)(rp->diff * (item->level + 2))); |
904 | if (ave_chance == 0) |
895 | if (ave_chance == 0) |
905 | ave_chance = 1; |
896 | ave_chance = 1; |
906 | |
897 | |
907 | #ifdef ALCHEMY_DEBUG |
898 | #ifdef ALCHEMY_DEBUG |
908 | LOG (llevDebug, "percent success chance = %f ab%d / diff%d*lev%d\n", success_chance, ability, rp->diff, item->level); |
899 | LOG (llevDebug, "percent success chance = %f ab%d / diff%d*lev%d\n", success_chance, ability, rp->diff, item->level); |
… | |
… | |
930 | } |
921 | } |
931 | } |
922 | } |
932 | } |
923 | } |
933 | |
924 | |
934 | /* if we get here, we failed!! */ |
925 | /* if we get here, we failed!! */ |
935 | alchemy_failure_effect (caster, cauldron, rp, calc_alch_danger (caster, cauldron, rp)); |
926 | alchemy_failure_effect (caster, cauldron, rp, calc_alch_danger (caster, cauldron, skill, rp)); |
936 | } |
927 | } |
937 | |
928 | |