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.20 by root, Mon Feb 5 02:07:40 2007 UTC vs.
Revision 1.31 by root, Mon Sep 29 10:20:48 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>
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 (rp->cauldron != cauldron->arch->name) 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
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 (item->arch->name == rp->arch_name[i]) 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 }
511 510
512 if (rndm (0, 2)) 511 if (rndm (0, 2))
513 { /* slag created */ 512 { /* slag created */
514 object *tmp = cauldron->inv; 513 object *tmp = cauldron->inv;
515 int weight = 0; 514 int weight = 0;
516 uint16 material = M_STONE;
517 515
518 while (tmp)
519 { /* slag has coadded ingredient properties */
520 weight += tmp->weight;
521 if (!(material & tmp->material))
522 material |= tmp->material;
523 tmp = tmp->below;
524 }
525 tmp = get_archetype ("rock"); 516 tmp = get_archetype ("rock");
526 tmp->weight = weight; 517 tmp->weight = weight;
527 tmp->value = 0; 518 tmp->value = 0;
528 tmp->material = material;
529 tmp->materialname = "stone"; 519 tmp->materialname = "stone";
530 tmp->name = "slag"; 520 tmp->name = "slag";
531 tmp->name_pl = "slags"; 521 tmp->name_pl = "slags";
532 item = insert_ob_in_ob (tmp, cauldron); 522 item = insert_ob_in_ob (tmp, cauldron);
533 CLEAR_FLAG (tmp, FLAG_CAN_ROLL); 523 CLEAR_FLAG (tmp, FLAG_CAN_ROLL);
534 CLEAR_FLAG (tmp, FLAG_NO_PICK); 524 CLEAR_FLAG (tmp, FLAG_NO_PICK);
535 tmp->move_block = 0; 525 tmp->move_block = 0;
536 } 526 }
527
537 remove_contents (cauldron->inv, item); 528 remove_contents (cauldron->inv, item);
538 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 ());
539 return; 530 return;
540 } 531 }
541 else if (level < 40) 532 else if (level < 40)
567 } 558 }
568 while (rndm (0, 2)); 559 while (rndm (0, 2));
569 } 560 }
570 return; 561 return;
571 } 562 }
563
572 if (level == 40) 564 if (level == 40)
573 { /* MAKE RANDOM RECIPE */ 565 { /* MAKE RANDOM RECIPE */
574 recipelist *fl; 566 recipelist *fl;
575 int numb = numb_ob_inside (cauldron); 567 int numb = numb_ob_inside (cauldron);
576 568
578 if (fl && (rp = get_random_recipe (fl))) 570 if (fl && (rp = get_random_recipe (fl)))
579 /* even though random, don't grant user any EXP for it */ 571 /* even though random, don't grant user any EXP for it */
580 (void) attempt_recipe (op, cauldron, 1, rp, -1); 572 (void) attempt_recipe (op, cauldron, 1, rp, -1);
581 else 573 else
582 alchemy_failure_effect (op, cauldron, rp, level - 1); 574 alchemy_failure_effect (op, cauldron, rp, level - 1);
583 return;
584
585 } 575 }
586 else if (level < 45) 576 else if (level < 45)
587 { /* INFURIATE NPC's */ 577 { /* INFURIATE NPC's */
588 /* this is kind of kludgy I know... */ 578 /* this is kind of kludgy I know... */
589 cauldron->enemy = op; 579 cauldron->enemy = op;
590 npc_call_help (cauldron); 580 npc_call_help (cauldron);
591 cauldron->enemy = NULL; 581 cauldron->enemy = NULL;
592 582
593 alchemy_failure_effect (op, cauldron, rp, level - 5); 583 alchemy_failure_effect (op, cauldron, rp, level - 5);
594 return;
595 } 584 }
596 else if (level < 50) 585 else if (level < 50)
597 { /* MINOR EXPLOSION/FIREBALL */ 586 { /* MINOR EXPLOSION/FIREBALL */
598 object *tmp; 587 object *tmp;
599 588
613 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;
614 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);
615 break; 604 break;
616 } 605 }
617 606
618 op->insert_at (cauldron); 607 tmp->insert_at (cauldron);
619 return;
620
621 } 608 }
622 else if (level < 60) 609 else if (level < 60)
623 { /* CREATE MONSTER */ 610 { /* CREATE MONSTER */
624 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 ());
625 remove_contents (cauldron->inv, NULL); 612 remove_contents (cauldron->inv, NULL);
626 return;
627 } 613 }
628 else if (level < 80) 614 else if (level < 80)
629 { /* MAJOR FIRE */ 615 { /* MAJOR FIRE */
630 object *fb = get_archetype (SP_MED_FIREBALL); 616 object *fb = get_archetype (SP_MED_FIREBALL);
631 617
632 remove_contents (cauldron->inv, NULL); 618 remove_contents (cauldron->inv, NULL);
633 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);
634 fb->destroy (); 620 fb->destroy (true);
635 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);
636 return;
637
638 } 622 }
639 else if (level < 100) 623 else if (level < 100)
640 { /* WHAMMY the CAULDRON */ 624 { /* WHAMMY the CAULDRON */
641 if (!QUERY_FLAG (cauldron, FLAG_CURSED)) 625 if (!QUERY_FLAG (cauldron, FLAG_CURSED))
642 SET_FLAG (cauldron, FLAG_CURSED); 626 SET_FLAG (cauldron, FLAG_CURSED);
643 else 627 else
644 cauldron->magic--; 628 cauldron->magic--;
629
645 cauldron->magic -= random_roll (0, 4, op, PREFER_LOW); 630 cauldron->magic -= random_roll (0, 4, op, PREFER_LOW);
631
646 if (rndm (0, 1)) 632 if (rndm (0, 1))
647 { 633 {
648 remove_contents (cauldron->inv, NULL); 634 remove_contents (cauldron->inv, NULL);
649 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);
650 } 636 }
651 else 637 else
652 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);
653 return;
654
655 } 639 }
656 else if (level < 110) 640 else if (level < 110)
657 { /* SUMMON EVIL MONSTERS */ 641 { /* SUMMON EVIL MONSTERS */
658 object *tmp = get_random_mon (level / 5); 642 object *tmp = get_random_mon (level / 5);
659 643
660 remove_contents (cauldron->inv, NULL); 644 remove_contents (cauldron->inv, NULL);
645
661 if (!tmp) 646 if (!tmp)
662 alchemy_failure_effect (op, cauldron, rp, level); 647 alchemy_failure_effect (op, cauldron, rp, level);
663 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))
664 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 ());
665 return;
666
667 } 650 }
668 else if (level < 150) 651 else if (level < 150)
669 { /* COMBO EFFECT */ 652 { /* COMBO EFFECT */
670 int roll = rndm (1, 3); 653 int roll = rndm (1, 3);
671 654
672 while (roll) 655 while (roll)
673 { 656 {
674 alchemy_failure_effect (op, cauldron, rp, level - 39); 657 alchemy_failure_effect (op, cauldron, rp, level - 39);
675 roll--; 658 roll--;
676 } 659 }
677 return;
678 } 660 }
679 else if (level == 151) 661 else if (level == 151)
680 { /* CREATE RANDOM ARTIFACT */ 662 { /* CREATE RANDOM ARTIFACT */
681 object *tmp; 663 object *tmp;
682 664
693 { 675 {
694 remove_contents (cauldron->inv, tmp); 676 remove_contents (cauldron->inv, tmp);
695 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 ());
696 } 678 }
697 } 679 }
698 return;
699 } 680 }
700 else 681 else
701 { /* MANA STORM - watch out!! */ 682 { /* MANA STORM - watch out!! */
702 object *tmp = get_archetype (LOOSE_MANA); 683 object *tmp = get_archetype (LOOSE_MANA);
703 684
704 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!");
705 remove_contents (cauldron->inv, NULL); 686 remove_contents (cauldron->inv, NULL);
706 cast_magic_storm (op, tmp, level); 687 cast_magic_storm (op, tmp, level);
707 return;
708 } 688 }
709} 689}
710
711 690
712/* 691/*
713 * All but object "save_item" are elimentated from 692 * All but object "save_item" are elimentated from
714 * the container list. Note we have to becareful to remove the inventories 693 * the container list. Note we have to becareful to remove the inventories
715 * of objects in the cauldron inventory (ex icecube has stuff in it). 694 * of objects in the cauldron inventory (ex icecube has stuff in it).
716 */ 695 */
717
718void 696void
719remove_contents (object *first_ob, object *save_item) 697remove_contents (object *first_ob, object *save_item)
720{ 698{
699 // this cries for a cleaner rewrite, removing save_item first possibly
721 object *next, *tmp = first_ob; 700 object *next, *tmp = first_ob;
722 701
723 while (tmp) 702 while (tmp)
724 { 703 {
725 next = tmp->below; 704 next = tmp->below;
733 } 712 }
734 713
735 if (tmp->inv) 714 if (tmp->inv)
736 remove_contents (tmp->inv, NULL); 715 remove_contents (tmp->inv, NULL);
737 716
738 tmp->destroy (); 717 tmp->destroy (true);
739 tmp = next; 718 tmp = next;
740 } 719 }
741} 720}
742 721
743/** 722/**
744 *"Danger" level, will determine how bad the backfire 723 *"Danger" level, will determine how bad the backfire
745 * could be if the user fails to concoct a recipe properly. Factors include 724 * could be if the user fails to concoct a recipe properly. Factors include
746 * the number of ingredients, the length of the name of each ingredient, 725 * the number of ingredients, the length of the name of each ingredient,
747 * the user's effective level, the user's Int and the enchantment on the 726 * the user's effective level, the user's Int and the enchantment on the
748 * mixing device (aka "cauldron"). Higher values of 'danger' indicate more 727 * mixing device (aka "cauldron"). Higher values of 'danger' indicate more
749 * danger. Note that we assume that we have had the caster ready the alchemy 728 * danger. Note that we assume that we have had the caster ready the alchemy
750 * skill *before* this routine is called. (no longer auto-readies that skill) 729 * skill *before* this routine is called. (no longer auto-readies that skill)
751 * -b.t. 730 * -b.t.
752 */ 731 */
753
754int 732int
755calc_alch_danger (object *caster, object *cauldron, recipe *rp) 733calc_alch_danger (object *caster, object *cauldron, recipe *rp)
756{ 734{
757 object *item; 735 object *item;
758 char name[MAX_BUF]; 736 char name[MAX_BUF];
759 int danger = 0, nrofi = 0; 737 int danger = 0, nrofi = 0;
760 738
761 /* Knowing alchemy skill reduces yer risk */ 739 /* Knowing alchemy skill reduces yer risk */
762 danger -= caster->chosen_skill ? caster->chosen_skill->level : caster->level; 740 danger -= caster->chosen_skill ? caster->chosen_skill->level : caster->level;
741
742 if (!caster->chosen_skill)
743 LOG (llevError | logBacktrace, "calc_alch_danger called without a chosen skill, caster %s, cauldron %s\n",
744 caster->debug_desc (), cauldron->debug_desc ());
763 745
764 /* better cauldrons reduce risk */ 746 /* better cauldrons reduce risk */
765 danger -= cauldron->magic; 747 danger -= cauldron->magic;
766 748
767 /* Higher Int, lower the risk */ 749 /* Higher Int, lower the risk */
777 if (item->title) 759 if (item->title)
778 sprintf (name, "%s %s", &item->name, &item->title); 760 sprintf (name, "%s %s", &item->name, &item->title);
779 danger += (strtoint (name) / 1000) + 3; 761 danger += (strtoint (name) / 1000) + 3;
780 nrofi++; 762 nrofi++;
781 } 763 }
764
782 if (rp == NULL) 765 if (rp == NULL)
783 danger += 110; 766 danger += 110;
784 else 767 else
785 danger += rp->diff * 3; 768 danger += rp->diff * 3;
786 769
795#endif 778#endif
796 779
797 return danger; 780 return danger;
798} 781}
799 782
800/** 783/**
801 * Determines if ingredients in a container match the 784 * Determines if ingredients in a container match the
802 * proper ingredients for a recipe. 785 * proper ingredients for a recipe.
803 * 786 *
804 * rp is the recipe to check 787 * rp is the recipe to check
805 * cauldron is the container that holds the ingredients 788 * cauldron is the container that holds the ingredients
909 LOG (llevDebug, "looking for formula %d:\n", formula); 892 LOG (llevDebug, "looking for formula %d:\n", formula);
910#endif 893#endif
911 result = NULL; 894 result = NULL;
912 recipes_matching = 0; 895 recipes_matching = 0;
913 transmute_found = 0; 896 transmute_found = 0;
897
914 for (rp = fl->items; rp != NULL; rp = rp->next) 898 for (rp = fl->items; rp; rp = rp->next)
915 { 899 {
916 /* check if recipe matches at all */ 900 /* check if recipe matches at all */
917 if (formula % rp->index != 0) 901 if (formula % rp->index != 0)
918 { 902 {
919#ifdef EXTREME_ALCHEMY_DEBUG 903#ifdef EXTREME_ALCHEMY_DEBUG

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines