ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/alchemy.C
(Generate patch)

Comparing deliantra/server/server/alchemy.C (file contents):
Revision 1.18 by pippijn, Mon Jan 15 21:06:19 2007 UTC vs.
Revision 1.30 by root, Sat Jul 12 22:46:58 2008 UTC

1/* 1/*
2 * CrossFire, A Multiplayer game for X-windows 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team 4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * 20 *
22 * The authors can be reached via e-mail at <crossfire@schmorp.de> 21 * The authors can be reached via e-mail to <support@deliantra.net>
23 */ 22 */
24 23
25/* March 96 - Laid down original code. -b.t. thomas@astro.psu.edu */ 24/* March 96 - Laid down original code. -b.t. thomas@astro.psu.edu */
26 25
27#include <global.h> 26#include <global.h>
232 int tval = 0, formula = 0; 231 int tval = 0, formula = 0;
233 232
234 while (tmp) 233 while (tmp)
235 { 234 {
236 tval = 0; 235 tval = 0;
237 strcpy (name, tmp->name); 236 assign (name, tmp->name);
238 if (tmp->title) 237 if (tmp->title)
239 sprintf (name, "%s %s", &tmp->name, &tmp->title); 238 sprintf (name, "%s %s", &tmp->name, &tmp->title);
240 tval = (strtoint (name) * (tmp->nrof ? tmp->nrof : 1)); 239 tval = (strtoint (name) * (tmp->nrof ? tmp->nrof : 1));
241#ifdef ALCHEMY_DEBUG 240#ifdef ALCHEMY_DEBUG
242 LOG (llevDebug, "Got ingredient %d %s(%d)\n", tmp->nrof ? tmp->nrof : 1, name, tval); 241 LOG (llevDebug, "Got ingredient %d %s(%d)\n", tmp->nrof ? tmp->nrof : 1, name, tval);
292 /* this should be passed to this fctn, not effiecent cpu use this way */ 291 /* this should be passed to this fctn, not effiecent cpu use this way */
293 int batches = abs (nbatches); 292 int batches = abs (nbatches);
294 293
295 294
296 /* is the cauldron the right type? */ 295 /* is the cauldron the right type? */
297 if (strcmp (rp->cauldron, cauldron->arch->name) != 0) 296 if (rp->cauldron != cauldron->arch->archname)
298 { 297 {
299 new_draw_info (NDI_UNIQUE, 0, caster, "You are not using the proper" " facilities for this formula."); 298 new_draw_info (NDI_UNIQUE, 0, caster, "You are not using the proper" " facilities for this formula.");
300 return 0; 299 return 0;
301 } 300 }
302 301
310 { 309 {
311 object *tmp; 310 object *tmp;
312 311
313 for (tmp = caster->inv; tmp; tmp = tmp->below) 312 for (tmp = caster->inv; tmp; tmp = tmp->below)
314 { 313 {
315 if (tmp->type == FORCE && tmp->slaying && !strcmp (rp->keycode, tmp->slaying)) 314 if (tmp->type == FORCE && tmp->slaying && rp->keycode == tmp->slaying)
316 break; 315 break;
317 } 316 }
318 317
319 if (!tmp) 318 if (!tmp)
320 { /* failure--no code found */ 319 { /* failure--no code found */
321 new_draw_info (NDI_UNIQUE, 0, caster, "You know the ingredients," " but not the technique. Go learn how to do this recipe."); 320 new_draw_info (NDI_UNIQUE, 0, caster, "You know the ingredients, but not the technique. Go learn how to do this recipe.");
322 return 0; 321 return 0;
323 } 322 }
324 } 323 }
325 324
326#ifdef EXTREME_ALCHEMY_DEBUG 325#ifdef EXTREME_ALCHEMY_DEBUG
330 329
331 if ((item = make_item_from_recipe (cauldron, rp)) != NULL) 330 if ((item = make_item_from_recipe (cauldron, rp)) != NULL)
332 { 331 {
333 remove_contents (cauldron->inv, item); 332 remove_contents (cauldron->inv, item);
334 /* Recalc carrying of the cauldron, in case recipe did not conserve mass */ 333 /* Recalc carrying of the cauldron, in case recipe did not conserve mass */
335 sum_weight (cauldron); 334 cauldron->update_weight ();
336 /* adj lvl, nrof on caster level */ 335 /* adj lvl, nrof on caster level */
337 adjust_product (item, ability, rp->yield ? (rp->yield * batches) : batches); 336 adjust_product (item, ability, rp->yield ? (rp->yield * batches) : batches);
338 if (!item->env && (item = insert_ob_in_ob (item, cauldron)) == NULL) 337 if (!item->env && (item = insert_ob_in_ob (item, cauldron)) == NULL)
339 { 338 {
340 new_draw_info (NDI_UNIQUE, 0, caster, "Nothing happened."); 339 new_draw_info (NDI_UNIQUE, 0, caster, "Nothing happened.");
448 { 447 {
449 size_t i; 448 size_t i;
450 449
451 for (i = 0; i < rp->arch_names; i++) 450 for (i = 0; i < rp->arch_names; i++)
452 { 451 {
453 if (strcmp (item->arch->name, rp->arch_name[i]) == 0) 452 if (item->arch->archname == rp->arch_name[i])
454 { 453 {
455 *rp_arch_index = i; 454 *rp_arch_index = i;
456 break; 455 break;
457 } 456 }
458 } 457 }
458
459 if (i < rp->arch_names) 459 if (i < rp->arch_names)
460 break; 460 break;
461 } 461 }
462 462
463 /* failed, create a fresh object. Note no nrof>1 because that would 463 /* failed, create a fresh object. Note no nrof>1 because that would
510 510
511 if (rndm (0, 2)) 511 if (rndm (0, 2))
512 { /* slag created */ 512 { /* slag created */
513 object *tmp = cauldron->inv; 513 object *tmp = cauldron->inv;
514 int weight = 0; 514 int weight = 0;
515 uint16 material = M_STONE;
516 515
517 while (tmp)
518 { /* slag has coadded ingredient properties */
519 weight += tmp->weight;
520 if (!(material & tmp->material))
521 material |= tmp->material;
522 tmp = tmp->below;
523 }
524 tmp = get_archetype ("rock"); 516 tmp = get_archetype ("rock");
525 tmp->weight = weight; 517 tmp->weight = weight;
526 tmp->value = 0; 518 tmp->value = 0;
527 tmp->material = material;
528 tmp->materialname = "stone"; 519 tmp->materialname = "stone";
529 tmp->name = "slag"; 520 tmp->name = "slag";
530 tmp->name_pl = "slags"; 521 tmp->name_pl = "slags";
531 item = insert_ob_in_ob (tmp, cauldron); 522 item = insert_ob_in_ob (tmp, cauldron);
532 CLEAR_FLAG (tmp, FLAG_CAN_ROLL); 523 CLEAR_FLAG (tmp, FLAG_CAN_ROLL);
533 CLEAR_FLAG (tmp, FLAG_NO_PICK); 524 CLEAR_FLAG (tmp, FLAG_NO_PICK);
534 tmp->move_block = 0; 525 tmp->move_block = 0;
535 } 526 }
527
536 remove_contents (cauldron->inv, item); 528 remove_contents (cauldron->inv, item);
537 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ()); 529 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ());
538 return; 530 return;
539 } 531 }
540 else if (level < 40) 532 else if (level < 40)
566 } 558 }
567 while (rndm (0, 2)); 559 while (rndm (0, 2));
568 } 560 }
569 return; 561 return;
570 } 562 }
563
571 if (level == 40) 564 if (level == 40)
572 { /* MAKE RANDOM RECIPE */ 565 { /* MAKE RANDOM RECIPE */
573 recipelist *fl; 566 recipelist *fl;
574 int numb = numb_ob_inside (cauldron); 567 int numb = numb_ob_inside (cauldron);
575 568
577 if (fl && (rp = get_random_recipe (fl))) 570 if (fl && (rp = get_random_recipe (fl)))
578 /* even though random, don't grant user any EXP for it */ 571 /* even though random, don't grant user any EXP for it */
579 (void) attempt_recipe (op, cauldron, 1, rp, -1); 572 (void) attempt_recipe (op, cauldron, 1, rp, -1);
580 else 573 else
581 alchemy_failure_effect (op, cauldron, rp, level - 1); 574 alchemy_failure_effect (op, cauldron, rp, level - 1);
582 return;
583
584 } 575 }
585 else if (level < 45) 576 else if (level < 45)
586 { /* INFURIATE NPC's */ 577 { /* INFURIATE NPC's */
587 /* this is kind of kludgy I know... */ 578 /* this is kind of kludgy I know... */
588 cauldron->enemy = op; 579 cauldron->enemy = op;
589 npc_call_help (cauldron); 580 npc_call_help (cauldron);
590 cauldron->enemy = NULL; 581 cauldron->enemy = NULL;
591 582
592 alchemy_failure_effect (op, cauldron, rp, level - 5); 583 alchemy_failure_effect (op, cauldron, rp, level - 5);
593 return;
594 } 584 }
595 else if (level < 50) 585 else if (level < 50)
596 { /* MINOR EXPLOSION/FIREBALL */ 586 { /* MINOR EXPLOSION/FIREBALL */
597 object *tmp; 587 object *tmp;
598 588
612 tmp->stats.hp = random_roll (1, level, op, PREFER_LOW) / 10 + 2; 602 tmp->stats.hp = random_roll (1, level, op, PREFER_LOW) / 10 + 2;
613 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s erupts in flame!", &cauldron->name); 603 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s erupts in flame!", &cauldron->name);
614 break; 604 break;
615 } 605 }
616 606
617 op->insert_at (cauldron); 607 tmp->insert_at (cauldron);
618 return;
619
620 } 608 }
621 else if (level < 60) 609 else if (level < 60)
622 { /* CREATE MONSTER */ 610 { /* CREATE MONSTER */
623 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ()); 611 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ());
624 remove_contents (cauldron->inv, NULL); 612 remove_contents (cauldron->inv, NULL);
625 return;
626 } 613 }
627 else if (level < 80) 614 else if (level < 80)
628 { /* MAJOR FIRE */ 615 { /* MAJOR FIRE */
629 object *fb = get_archetype (SP_MED_FIREBALL); 616 object *fb = get_archetype (SP_MED_FIREBALL);
630 617
631 remove_contents (cauldron->inv, NULL); 618 remove_contents (cauldron->inv, NULL);
632 fire_arch_from_position (cauldron, cauldron, cauldron->x, cauldron->y, 0, fb); 619 fire_arch_from_position (cauldron, cauldron, cauldron->x, cauldron->y, 0, fb);
633 fb->destroy (); 620 fb->destroy ();
634 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s erupts in flame!", &cauldron->name); 621 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s erupts in flame!", &cauldron->name);
635 return;
636
637 } 622 }
638 else if (level < 100) 623 else if (level < 100)
639 { /* WHAMMY the CAULDRON */ 624 { /* WHAMMY the CAULDRON */
640 if (!QUERY_FLAG (cauldron, FLAG_CURSED)) 625 if (!QUERY_FLAG (cauldron, FLAG_CURSED))
641 SET_FLAG (cauldron, FLAG_CURSED); 626 SET_FLAG (cauldron, FLAG_CURSED);
642 else 627 else
643 cauldron->magic--; 628 cauldron->magic--;
629
644 cauldron->magic -= random_roll (0, 4, op, PREFER_LOW); 630 cauldron->magic -= random_roll (0, 4, op, PREFER_LOW);
631
645 if (rndm (0, 1)) 632 if (rndm (0, 1))
646 { 633 {
647 remove_contents (cauldron->inv, NULL); 634 remove_contents (cauldron->inv, NULL);
648 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s turns darker then makes a gulping sound!", &cauldron->name); 635 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s turns darker then makes a gulping sound!", &cauldron->name);
649 } 636 }
650 else 637 else
651 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s becomes darker.", &cauldron->name); 638 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s becomes darker.", &cauldron->name);
652 return;
653
654 } 639 }
655 else if (level < 110) 640 else if (level < 110)
656 { /* SUMMON EVIL MONSTERS */ 641 { /* SUMMON EVIL MONSTERS */
657 object *tmp = get_random_mon (level / 5); 642 object *tmp = get_random_mon (level / 5);
658 643
659 remove_contents (cauldron->inv, NULL); 644 remove_contents (cauldron->inv, NULL);
645
660 if (!tmp) 646 if (!tmp)
661 alchemy_failure_effect (op, cauldron, rp, level); 647 alchemy_failure_effect (op, cauldron, rp, level);
662 else if (summon_hostile_monsters (cauldron, random_roll (1, 10, op, PREFER_LOW), tmp->arch->name)) 648 else if (summon_hostile_monsters (cauldron, random_roll (1, 10, op, PREFER_LOW), tmp->arch->archname))
663 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s and then pours forth monsters!", &cauldron->name, cauldron_sound ()); 649 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s and then pours forth monsters!", &cauldron->name, cauldron_sound ());
664 return;
665
666 } 650 }
667 else if (level < 150) 651 else if (level < 150)
668 { /* COMBO EFFECT */ 652 { /* COMBO EFFECT */
669 int roll = rndm (1, 3); 653 int roll = rndm (1, 3);
670 654
671 while (roll) 655 while (roll)
672 { 656 {
673 alchemy_failure_effect (op, cauldron, rp, level - 39); 657 alchemy_failure_effect (op, cauldron, rp, level - 39);
674 roll--; 658 roll--;
675 } 659 }
676 return;
677 } 660 }
678 else if (level == 151) 661 else if (level == 151)
679 { /* CREATE RANDOM ARTIFACT */ 662 { /* CREATE RANDOM ARTIFACT */
680 object *tmp; 663 object *tmp;
681 664
692 { 675 {
693 remove_contents (cauldron->inv, tmp); 676 remove_contents (cauldron->inv, tmp);
694 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ()); 677 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s %s.", &cauldron->name, cauldron_sound ());
695 } 678 }
696 } 679 }
697 return;
698 } 680 }
699 else 681 else
700 { /* MANA STORM - watch out!! */ 682 { /* MANA STORM - watch out!! */
701 object *tmp = get_archetype (LOOSE_MANA); 683 object *tmp = get_archetype (LOOSE_MANA);
702 684
703 new_draw_info (NDI_UNIQUE, 0, op, "You unwisely release potent forces!"); 685 new_draw_info (NDI_UNIQUE, 0, op, "You unwisely release potent forces!");
704 remove_contents (cauldron->inv, NULL); 686 remove_contents (cauldron->inv, NULL);
705 cast_magic_storm (op, tmp, level); 687 cast_magic_storm (op, tmp, level);
706 return;
707 } 688 }
708} 689}
709 690
710 691
711/* 692/*
737 tmp->destroy (); 718 tmp->destroy ();
738 tmp = next; 719 tmp = next;
739 } 720 }
740} 721}
741 722
742/** 723/**
743 *"Danger" level, will determine how bad the backfire 724 *"Danger" level, will determine how bad the backfire
744 * could be if the user fails to concoct a recipe properly. Factors include 725 * could be if the user fails to concoct a recipe properly. Factors include
745 * the number of ingredients, the length of the name of each ingredient, 726 * the number of ingredients, the length of the name of each ingredient,
746 * the user's effective level, the user's Int and the enchantment on the 727 * the user's effective level, the user's Int and the enchantment on the
747 * mixing device (aka "cauldron"). Higher values of 'danger' indicate more 728 * mixing device (aka "cauldron"). Higher values of 'danger' indicate more
748 * danger. Note that we assume that we have had the caster ready the alchemy 729 * danger. Note that we assume that we have had the caster ready the alchemy
749 * skill *before* this routine is called. (no longer auto-readies that skill) 730 * skill *before* this routine is called. (no longer auto-readies that skill)
750 * -b.t. 731 * -b.t.
751 */ 732 */
752
753int 733int
754calc_alch_danger (object *caster, object *cauldron, recipe *rp) 734calc_alch_danger (object *caster, object *cauldron, recipe *rp)
755{ 735{
756 object *item; 736 object *item;
757 char name[MAX_BUF]; 737 char name[MAX_BUF];
758 int danger = 0, nrofi = 0; 738 int danger = 0, nrofi = 0;
759 739
760 /* Knowing alchemy skill reduces yer risk */ 740 /* Knowing alchemy skill reduces yer risk */
761 danger -= caster->chosen_skill ? caster->chosen_skill->level : caster->level; 741 danger -= caster->chosen_skill ? caster->chosen_skill->level : caster->level;
742
743 if (!caster->chosen_skill)
744 LOG (llevError | logBacktrace, "calc_alch_danger called without a chosen skill, caster %s, cauldron %s\n",
745 caster->debug_desc (), cauldron->debug_desc ());
762 746
763 /* better cauldrons reduce risk */ 747 /* better cauldrons reduce risk */
764 danger -= cauldron->magic; 748 danger -= cauldron->magic;
765 749
766 /* Higher Int, lower the risk */ 750 /* Higher Int, lower the risk */
770 * Thus the backfire is worse. Also, more ingredients 754 * Thus the backfire is worse. Also, more ingredients
771 * means we are attempting a more powerfull potion, 755 * means we are attempting a more powerfull potion,
772 * and thus the backfire will be worse. */ 756 * and thus the backfire will be worse. */
773 for (item = cauldron->inv; item; item = item->below) 757 for (item = cauldron->inv; item; item = item->below)
774 { 758 {
775 strcpy (name, item->name); 759 assign (name, item->name);
776 if (item->title) 760 if (item->title)
777 sprintf (name, "%s %s", &item->name, &item->title); 761 sprintf (name, "%s %s", &item->name, &item->title);
778 danger += (strtoint (name) / 1000) + 3; 762 danger += (strtoint (name) / 1000) + 3;
779 nrofi++; 763 nrofi++;
780 } 764 }
765
781 if (rp == NULL) 766 if (rp == NULL)
782 danger += 110; 767 danger += 110;
783 else 768 else
784 danger += rp->diff * 3; 769 danger += rp->diff * 3;
785 770
794#endif 779#endif
795 780
796 return danger; 781 return danger;
797} 782}
798 783
799/** 784/**
800 * Determines if ingredients in a container match the 785 * Determines if ingredients in a container match the
801 * proper ingredients for a recipe. 786 * proper ingredients for a recipe.
802 * 787 *
803 * rp is the recipe to check 788 * rp is the recipe to check
804 * cauldron is the container that holds the ingredients 789 * cauldron is the container that holds the ingredients
908 LOG (llevDebug, "looking for formula %d:\n", formula); 893 LOG (llevDebug, "looking for formula %d:\n", formula);
909#endif 894#endif
910 result = NULL; 895 result = NULL;
911 recipes_matching = 0; 896 recipes_matching = 0;
912 transmute_found = 0; 897 transmute_found = 0;
898
913 for (rp = fl->items; rp != NULL; rp = rp->next) 899 for (rp = fl->items; rp; rp = rp->next)
914 { 900 {
915 /* check if recipe matches at all */ 901 /* check if recipe matches at all */
916 if (formula % rp->index != 0) 902 if (formula % rp->index != 0)
917 { 903 {
918#ifdef EXTREME_ALCHEMY_DEBUG 904#ifdef EXTREME_ALCHEMY_DEBUG

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines