diff --git a/nwn/nwnprc/trunk/2das/classes.2da b/nwn/nwnprc/trunk/2das/classes.2da index 2f01b1e8..4b444a3c 100644 --- a/nwn/nwnprc/trunk/2das/classes.2da +++ b/nwn/nwnprc/trunk/2das/classes.2da @@ -237,7 +237,7 @@ 233 Sohei 16790716 16827429 16827430 16827431 16827432 IR_FIGHTER 10 CLS_ATK_2 CLS_FEAT_SOHEI CLS_SAVTHR_CLER CLS_SKILL_SOHEI CLS_BFEAT_SOHEI 2 CLS_SPGN_SOHEI **** 1 1 16 10 13 14 13 10 STR 0X05 0X1 0 CLASS_TYPE_SOHEI 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_SOHEI 0 1 0 0 -1 6 0 **** 1 0 0 0 0 0 0 WIS Sohei 1 4 255 0 0 234 Crusader 16790717 16829702 16829703 16829704 16829705 IR_CRUSADER 10 CLS_ATK_1 CLS_FEAT_CRUSDR CLS_SAVTHR_FIGHT CLS_SKILL_CRUSDR CLS_BFEAT_CRUSDR 4 **** **** 1 0 16 14 14 10 12 10 STR 0X1E 0X3 1 CLASS_TYPE_CRUSADER 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_CRUSDR 0 1 0 0 -1 715 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 235 Swordsage 16790718 16829706 16829707 16829708 16829709 IR_MONK 8 CLS_ATK_2 CLS_FEAT_SWDSGE CLS_SAVTHR_BARD CLS_SKILL_SWDSGE CLS_BFEAT_SWDSGE 6 **** **** 1 0 16 14 14 10 12 10 STR 0X00 0X0 0 CLASS_TYPE_SWORDSAGE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_SWDSGE 0 1 0 0 -1 5 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** -236 Warblade 16790719 16829710 16829711 16829712 16829713 IR_FIGHTER 12 CLS_ATK_1 CLS_FEAT_WARBLD CLS_SAVTHR_FIGHT CLS_SKILL_WARBLD CLS_BFEAT_WARBLD 4 **** **** 1 0 16 14 14 10 12 10 STR 0X00 0X0 0 CLASS_TYPE_WARBLADE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_WARBLD 0 1 0 0 -1 5 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** +236 Warblade 16790719 16829710 16829711 16829712 16829713 IR_FIGHTER 12 CLS_ATK_1 CLS_FEAT_WARBLD CLS_SAVTHR_FIGHT CLS_SKILL_WARBLD CLS_BFEAT_WARBLD 4 **** **** 1 0 16 14 14 10 12 10 STR 0X00 0X0 0 CLASS_TYPE_WARBLADE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_WARBLD 0 1 0 0 -1 860 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 237 Warmage 16790720 16827604 16827605 16827606 16827607 IR_HAVOCMAGE 6 CLS_ATK_3 CLS_FEAT_WRMAGE CLS_SAVTHR_WIZ CLS_SKILL_WRMAGE CLS_BFEAT_WRMAGE 2 CLS_SPGN_WRMAGE CLS_SPKN_WRMAGE 1 1 10 14 12 10 14 16 INT 0X00 0X0 0 CLASS_TYPE_WARMAGE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_WRMAGE 0 1 0 0 -1 10 130 **** **** **** **** **** **** **** **** **** Warmage **** **** **** **** **** 238 Knight 16790721 16827632 16827633 16827634 16827635 IR_PALADIN 12 CLS_ATK_1 CLS_FEAT_KNIGHT CLS_SAVTHR_WIZ CLS_SKILL_KNIGHT CLS_BFEAT_KNIGHT 2 **** **** 1 0 16 10 16 10 10 12 STR 0X05 0X1 0 CLASS_TYPE_KNIGHT 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_KNIGHT 20 1 0 0 -1 765 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 239 FistOfDalQuor 16790722 16827033 16827034 16827035 16827036 IR_SHOUDISC 10 CLS_ATK_2 CLS_FEAT_DALQUR CLS_SAVTHR_CLER CLS_SKILL_DALQUR CLS_BFEAT_DALQUR 2 **** **** 1 0 12 16 14 8 14 12 DEX 0X00 0X0 0 CLASS_TYPE_FIST_DAL_QUOR 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_DALQUR 5 0 0 0 5 4 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** diff --git a/nwn/nwnprc/trunk/2das/feat.2da b/nwn/nwnprc/trunk/2das/feat.2da index f11ef594..55940ed0 100644 --- a/nwn/nwnprc/trunk/2das/feat.2da +++ b/nwn/nwnprc/trunk/2das/feat.2da @@ -21227,7 +21227,7 @@ 21223 Psion_EvadeBurst 16848023 16823883 fot_imprhaste **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 14667 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** SWIFT_ACTION **** 0 **** **** **** **** **** 0 21224 Psion_Insanity 16848024 16823843 fot_Confusion **** **** **** **** **** **** **** **** **** **** **** **** **** 1 **** 14668 **** **** **** **** 0 **** **** **** **** **** **** **** **** **** **** **** 1 **** **** **** **** **** 0 21225 Psion_Mind_BlankPersonal 16848025 16823845 fot_spelldeflect **** **** **** **** **** **** **** **** **** **** **** **** **** 9 **** 14669 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 -21226 Psion_MomentOfPrescience_RadialMaster 16848026 16823887 fot_oracle **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 14670 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 +21226 Psion_MomentOfPrescience_RadialMaster 16848026 16823887 fot_oracle **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 14670 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** SWIFT_ACTION **** 0 **** **** **** **** **** 0 21227 Psion_OakBody 16848031 16823847 fot_holypower **** **** **** **** **** **** **** **** **** **** **** **** **** 1 **** 14675 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 21228 Psion_Reddopsi 16848032 16824148 fot_powersilence **** **** **** **** **** **** **** **** 3555 **** **** **** **** 12 **** 14676 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 21229 Psion_Sequester 16848033 16827004 fot_sequester **** **** **** **** **** **** **** **** **** **** **** **** **** 9 **** 14677 **** **** **** **** 0 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 @@ -21594,7 +21594,7 @@ 21590 Wilder_EvadeBurst 16848554 16823883 fot_imprhaste **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 15198 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** SWIFT_ACTION **** 0 **** **** **** **** **** 0 21591 Wilder_Insanity 16848555 16823843 fot_Confusion **** **** **** **** **** **** **** **** **** **** **** **** **** 1 **** 15199 **** **** **** **** 0 **** **** **** **** **** **** **** **** **** **** **** 1 **** **** **** **** **** 0 21592 Wilder_Mind_BlankPersonal 16848556 16823845 fot_spelldeflect **** **** **** **** **** **** **** **** **** **** **** **** **** 9 **** 15200 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 -21593 Wilder_MomentOfPrescience_RadialMaster 16848557 16823887 fot_oracle **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 15201 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 +21593 Wilder_MomentOfPrescience_RadialMaster 16848557 16823887 fot_oracle **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 15201 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** SWIFT_ACTION **** 0 **** **** **** **** **** 0 21594 Wilder_OakBody 16848562 16823847 fot_holypower **** **** **** **** **** **** **** **** **** **** **** **** **** 1 **** 15206 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 21595 Wilder_Reddopsi 16848563 16824148 fot_powersilence **** **** **** **** **** **** **** **** **** **** **** **** **** 12 **** 15207 **** **** **** **** 1 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 21596 Wilder_Sequester 16848564 16827004 fot_sequester **** **** **** **** **** **** **** **** **** **** **** **** **** 9 **** 15208 **** **** **** **** 0 **** **** **** **** **** **** **** **** **** **** **** 0 **** **** **** **** **** 0 diff --git a/nwn/nwnprc/trunk/2das/packages.2da b/nwn/nwnprc/trunk/2das/packages.2da index 0c4bf171..fa5a7cc2 100644 --- a/nwn/nwnprc/trunk/2das/packages.2da +++ b/nwn/nwnprc/trunk/2das/packages.2da @@ -861,12 +861,12 @@ 857 Truenamer3 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 858 Truenamer4 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 859 Truenamer5 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** -860 Warblade1 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** +860 Warblade_Default 16988933 16988934 236 STR 20 **** **** **** **** **** packftwb1 packskwb1 packeqwb1 0 1 861 Warblade2 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 862 Warblade3 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 863 Warblade4 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 864 Warblade5 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** -865 Warlock_Blaster 16988943 1698894 112 CHA 50 **** **** **** **** **** packftwr1 packftwr1 packeqwr1 0 1 +865 Warlock_Blaster 16988943 1698894 112 CHA 50 **** **** **** **** **** packftwr1 packskwr1 packeqwr1 0 1 866 Warlock_RESERVE2 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 867 Warlock_RESERVE3 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** 868 Warlock_RESERVE4 **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** diff --git a/nwn/nwnprc/trunk/Craft2das/packeqwb1.2da b/nwn/nwnprc/trunk/Craft2das/packeqwb1.2da new file mode 100644 index 00000000..03782d97 --- /dev/null +++ b/nwn/nwnprc/trunk/Craft2das/packeqwb1.2da @@ -0,0 +1,14 @@ +2DA V2.0 + + Label Name +0 NW_ASHLW001 LargeShield_AC2 +1 NW_WSWLS001 Longsword_1d8 +2 NW_WBWSH001 Shortbow_1d6 +3 NW_AARCL003 ScaleMail_AC4 +4 NW_IT_TORCH001 Torch +5 NW_IT_MEDKIT001 Healer's_Kit_+1 +6 NW_IT_MEDKIT001 Healer's_Kit_+1 +7 NW_IT_MEDKIT001 Healer's_Kit_+1 +8 NW_WAMAR001 Arrows +9 NW_WAMAR001 Arrows +10 NW_WAMAR001 Arrows diff --git a/nwn/nwnprc/trunk/Craft2das/packftwb1.2da b/nwn/nwnprc/trunk/Craft2das/packftwb1.2da new file mode 100644 index 00000000..1e5ca304 --- /dev/null +++ b/nwn/nwnprc/trunk/Craft2das/packftwb1.2da @@ -0,0 +1,385 @@ +2DA V2.0 + + FeatIndex Label +0 657 FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB +1 658 FEAT_EPIC_WEAPON_SPECIALIZATION_DAGGER +2 659 FEAT_EPIC_WEAPON_SPECIALIZATION_DART +3 660 FEAT_EPIC_WEAPON_SPECIALIZATION_HEAVYCROSSBOW +4 661 FEAT_EPIC_WEAPON_SPECIALIZATION_LIGHTCROSSBOW +5 662 FEAT_EPIC_WEAPON_SPECIALIZATION_LIGHTMACE +6 663 FEAT_EPIC_WEAPON_SPECIALIZATION_MORNINGSTAR +7 664 FEAT_EPIC_WEAPON_SPECIALIZATION_QUARTERSTAFF +8 665 FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTSPEAR +9 666 FEAT_EPIC_WEAPON_SPECIALIZATION_SICKLE +10 667 FEAT_EPIC_WEAPON_SPECIALIZATION_SLING +11 668 FEAT_EPIC_WEAPON_SPECIALIZATION_UNARMED +12 669 FEAT_EPIC_WEAPON_SPECIALIZATION_LONGBOW +13 670 FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTBOW +14 671 FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTSWORD +15 672 FEAT_EPIC_WEAPON_SPECIALIZATION_RAPIER +16 673 FEAT_EPIC_WEAPON_SPECIALIZATION_SCIMITAR +17 674 FEAT_EPIC_WEAPON_SPECIALIZATION_LONGSWORD +18 675 FEAT_EPIC_WEAPON_SPECIALIZATION_GREATSWORD +19 676 FEAT_EPIC_WEAPON_SPECIALIZATION_HANDAXE +20 677 FEAT_EPIC_WEAPON_SPECIALIZATION_THROWINGAXE +21 678 FEAT_EPIC_WEAPON_SPECIALIZATION_BATTLEAXE +22 679 FEAT_EPIC_WEAPON_SPECIALIZATION_GREATAXE +23 680 FEAT_EPIC_WEAPON_SPECIALIZATION_HALBERD +24 681 FEAT_EPIC_WEAPON_SPECIALIZATION_LIGHTHAMMER +25 682 FEAT_EPIC_WEAPON_SPECIALIZATION_LIGHTFLAIL +26 683 FEAT_EPIC_WEAPON_SPECIALIZATION_WARHAMMER +27 684 FEAT_EPIC_WEAPON_SPECIALIZATION_HEAVYFLAIL +28 685 FEAT_EPIC_WEAPON_SPECIALIZATION_KAMA +29 686 FEAT_EPIC_WEAPON_SPECIALIZATION_KUKRI +30 687 FEAT_EPIC_WEAPON_SPECIALIZATION_SHURIKEN +31 688 FEAT_EPIC_WEAPON_SPECIALIZATION_SCYTHE +32 689 FEAT_EPIC_WEAPON_SPECIALIZATION_KATANA +33 690 FEAT_EPIC_WEAPON_SPECIALIZATION_BASTARDSWORD +34 691 FEAT_EPIC_WEAPON_SPECIALIZATION_DIREMACE +35 692 FEAT_EPIC_WEAPON_SPECIALIZATION_DOUBLEAXE +36 693 FEAT_EPIC_WEAPON_SPECIALIZATION_TWOBLADEDSWORD +37 1077 FEAT_EPIC_WEAPON_SPECIALIZATION_TRIDENT +38 619 FEAT_EPIC_WEAPON_FOCUS_CLUB +39 620 FEAT_EPIC_WEAPON_FOCUS_DAGGER +40 621 FEAT_EPIC_WEAPON_FOCUS_DART +41 622 FEAT_EPIC_WEAPON_FOCUS_HEAVYCROSSBOW +42 623 FEAT_EPIC_WEAPON_FOCUS_LIGHTCROSSBOW +43 624 FEAT_EPIC_WEAPON_FOCUS_LIGHTMACE +44 625 FEAT_EPIC_WEAPON_FOCUS_MORNINGSTAR +45 626 FEAT_EPIC_WEAPON_FOCUS_QUARTERSTAFF +46 627 FEAT_EPIC_WEAPON_FOCUS_SHORTSPEAR +47 628 FEAT_EPIC_WEAPON_FOCUS_SICKLE +48 629 FEAT_EPIC_WEAPON_FOCUS_SLING +49 630 FEAT_EPIC_WEAPON_FOCUS_UNARMED +50 631 FEAT_EPIC_WEAPON_FOCUS_LONGBOW +51 632 FEAT_EPIC_WEAPON_FOCUS_SHORTBOW +52 633 FEAT_EPIC_WEAPON_FOCUS_SHORTSWORD +53 634 FEAT_EPIC_WEAPON_FOCUS_RAPIER +54 635 FEAT_EPIC_WEAPON_FOCUS_SCIMITAR +55 636 FEAT_EPIC_WEAPON_FOCUS_LONGSWORD +56 637 FEAT_EPIC_WEAPON_FOCUS_GREATSWORD +57 638 FEAT_EPIC_WEAPON_FOCUS_HANDAXE +58 639 FEAT_EPIC_WEAPON_FOCUS_THROWINGAXE +59 640 FEAT_EPIC_WEAPON_FOCUS_BATTLEAXE +60 641 FEAT_EPIC_WEAPON_FOCUS_GREATAXE +61 642 FEAT_EPIC_WEAPON_FOCUS_HALBERD +62 643 FEAT_EPIC_WEAPON_FOCUS_LIGHTHAMMER +63 644 FEAT_EPIC_WEAPON_FOCUS_LIGHTFLAIL +64 645 FEAT_EPIC_WEAPON_FOCUS_WARHAMMER +65 646 FEAT_EPIC_WEAPON_FOCUS_HEAVYFLAIL +66 647 FEAT_EPIC_WEAPON_FOCUS_KAMA +67 648 FEAT_EPIC_WEAPON_FOCUS_KUKRI +68 649 FEAT_EPIC_WEAPON_FOCUS_SHURIKEN +69 650 FEAT_EPIC_WEAPON_FOCUS_SCYTHE +70 651 FEAT_EPIC_WEAPON_FOCUS_KATANA +71 652 FEAT_EPIC_WEAPON_FOCUS_BASTARDSWORD +72 653 FEAT_EPIC_WEAPON_FOCUS_DIREMACE +73 654 FEAT_EPIC_WEAPON_FOCUS_DOUBLEAXE +74 655 FEAT_EPIC_WEAPON_FOCUS_TWOBLADEDSWORD +75 1076 FEAT_EPIC_WEAPON_FOCUS_TRIDENT +76 709 FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB +77 710 FEAT_EPIC_OVERWHELMING_CRITICAL_DAGGER +78 711 FEAT_EPIC_OVERWHELMING_CRITICAL_DART +79 712 FEAT_EPIC_OVERWHELMING_CRITICAL_HEAVYCROSSBOW +80 713 FEAT_EPIC_OVERWHELMING_CRITICAL_LIGHTCROSSBOW +81 714 FEAT_EPIC_OVERWHELMING_CRITICAL_LIGHTMACE +82 715 FEAT_EPIC_OVERWHELMING_CRITICAL_MORNINGSTAR +83 716 FEAT_EPIC_OVERWHELMING_CRITICAL_QUARTERSTAFF +84 717 FEAT_EPIC_OVERWHELMING_CRITICAL_SHORTSPEAR +85 718 FEAT_EPIC_OVERWHELMING_CRITICAL_SICKLE +86 719 FEAT_EPIC_OVERWHELMING_CRITICAL_SLING +87 720 FEAT_EPIC_OVERWHELMING_CRITICAL_UNARMED +88 721 FEAT_EPIC_OVERWHELMING_CRITICAL_LONGBOW +89 722 FEAT_EPIC_OVERWHELMING_CRITICAL_SHORTBOW +90 723 FEAT_EPIC_OVERWHELMING_CRITICAL_SHORTSWORD +91 724 FEAT_EPIC_OVERWHELMING_CRITICAL_RAPIER +92 725 FEAT_EPIC_OVERWHELMING_CRITICAL_SCIMITAR +93 726 FEAT_EPIC_OVERWHELMING_CRITICAL_LONGSWORD +94 727 FEAT_EPIC_OVERWHELMING_CRITICAL_GREATSWORD +95 728 FEAT_EPIC_OVERWHELMING_CRITICAL_HANDAXE +96 729 FEAT_EPIC_OVERWHELMING_CRITICAL_THROWINGAXE +97 730 FEAT_EPIC_OVERWHELMING_CRITICAL_BATTLEAXE +98 731 FEAT_EPIC_OVERWHELMING_CRITICAL_GREATAXE +99 732 FEAT_EPIC_OVERWHELMING_CRITICAL_HALBERD +100 733 FEAT_EPIC_OVERWHELMING_CRITICAL_LIGHTHAMMER +101 734 FEAT_EPIC_OVERWHELMING_CRITICAL_LIGHTFLAIL +102 735 FEAT_EPIC_OVERWHELMING_CRITICAL_WARHAMMER +103 736 FEAT_EPIC_OVERWHELMING_CRITICAL_HEAVYFLAIL +104 737 FEAT_EPIC_OVERWHELMING_CRITICAL_KAMA +105 738 FEAT_EPIC_OVERWHELMING_CRITICAL_KUKRI +106 739 FEAT_EPIC_OVERWHELMING_CRITICAL_SHURIKEN +107 740 FEAT_EPIC_OVERWHELMING_CRITICAL_SCYTHE +108 741 FEAT_EPIC_OVERWHELMING_CRITICAL_KATANA +109 742 FEAT_EPIC_OVERWHELMING_CRITICAL_BASTARDSWORD +110 743 FEAT_EPIC_OVERWHELMING_CRITICAL_DIREMACE +111 744 FEAT_EPIC_OVERWHELMING_CRITICAL_DOUBLEAXE +112 745 FEAT_EPIC_OVERWHELMING_CRITICAL_TWOBLADEDSWORD +113 1078 FEAT_EPIC_OVERWHELMING_CRITICAL_TRIDENT +114 495 FEAT_EPIC_DEVASTATING_CRITICAL_CLUB +115 496 FEAT_EPIC_DEVASTATING_CRITICAL_DAGGER +116 497 FEAT_EPIC_DEVASTATING_CRITICAL_DART +117 498 FEAT_EPIC_DEVASTATING_CRITICAL_HEAVYCROSSBOW +118 499 FEAT_EPIC_DEVASTATING_CRITICAL_LIGHTCROSSBOW +119 500 FEAT_EPIC_DEVASTATING_CRITICAL_LIGHTMACE +120 501 FEAT_EPIC_DEVASTATING_CRITICAL_MORNINGSTAR +121 502 FEAT_EPIC_DEVASTATING_CRITICAL_QUARTERSTAFF +122 503 FEAT_EPIC_DEVASTATING_CRITICAL_SHORTSPEAR +123 504 FEAT_EPIC_DEVASTATING_CRITICAL_SICKLE +124 505 FEAT_EPIC_DEVASTATING_CRITICAL_SLING +125 506 FEAT_EPIC_DEVASTATING_CRITICAL_UNARMED +126 507 FEAT_EPIC_DEVASTATING_CRITICAL_LONGBOW +127 508 FEAT_EPIC_DEVASTATING_CRITICAL_SHORTBOW +128 509 FEAT_EPIC_DEVASTATING_CRITICAL_SHORTSWORD +129 510 FEAT_EPIC_DEVASTATING_CRITICAL_RAPIER +130 511 FEAT_EPIC_DEVASTATING_CRITICAL_SCIMITAR +131 512 FEAT_EPIC_DEVASTATING_CRITICAL_LONGSWORD +132 513 FEAT_EPIC_DEVASTATING_CRITICAL_GREATSWORD +133 514 FEAT_EPIC_DEVASTATING_CRITICAL_HANDAXE +134 515 FEAT_EPIC_DEVASTATING_CRITICAL_THROWINGAXE +135 516 FEAT_EPIC_DEVASTATING_CRITICAL_BATTLEAXE +136 517 FEAT_EPIC_DEVASTATING_CRITICAL_GREATAXE +137 518 FEAT_EPIC_DEVASTATING_CRITICAL_HALBERD +138 519 FEAT_EPIC_DEVASTATING_CRITICAL_LIGHTHAMMER +139 520 FEAT_EPIC_DEVASTATING_CRITICAL_LIGHTFLAIL +140 521 FEAT_EPIC_DEVASTATING_CRITICAL_WARHAMMER +141 522 FEAT_EPIC_DEVASTATING_CRITICAL_HEAVYFLAIL +142 523 FEAT_EPIC_DEVASTATING_CRITICAL_KAMA +143 524 FEAT_EPIC_DEVASTATING_CRITICAL_KUKRI +144 525 FEAT_EPIC_DEVASTATING_CRITICAL_SHURIKEN +145 526 FEAT_EPIC_DEVASTATING_CRITICAL_SCYTHE +146 527 FEAT_EPIC_DEVASTATING_CRITICAL_KATANA +147 528 FEAT_EPIC_DEVASTATING_CRITICAL_BASTARDSWORD +148 529 FEAT_EPIC_DEVASTATING_CRITICAL_DIREMACE +149 530 FEAT_EPIC_DEVASTATING_CRITICAL_DOUBLEAXE +150 531 FEAT_EPIC_DEVASTATING_CRITICAL_TWOBLADEDSWORD +151 1075 FEAT_EPIC_DEVASTATING_CRITICAL_TRIDENT +152 867 FEAT_WHIRLWIND_ATTACK +153 868 FEAT_IMPROVED_WHIRLWIND +154 584 FEAT_EPIC_PROWESS +155 814 FEAT_EPIC_GREAT_STRENGTH_1 +156 815 FEAT_EPIC_GREAT_STRENGTH_2 +157 816 FEAT_EPIC_GREAT_STRENGTH_3 +158 490 FEAT_EPIC_ARMOR_SKIN +159 491 FEAT_EPIC_BLINDING_SPEED +160 753 FEAT_EPIC_SUPERIOR_INITIATIVE +161 817 FEAT_EPIC_GREAT_STRENGTH_4 +162 818 FEAT_EPIC_GREAT_STRENGTH_5 +163 819 FEAT_EPIC_GREAT_STRENGTH_6 +164 754 FEAT_EPIC_TOUGHNESS_1 +165 755 FEAT_EPIC_TOUGHNESS_2 +166 756 FEAT_EPIC_TOUGHNESS_3 +167 820 FEAT_EPIC_GREAT_STRENGTH_7 +168 821 FEAT_EPIC_GREAT_STRENGTH_8 +169 822 FEAT_EPIC_GREAT_STRENGTH_9 +170 823 FEAT_EPIC_GREAT_STRENGTH_10 +171 757 FEAT_EPIC_TOUGHNESS_4 +172 758 FEAT_EPIC_TOUGHNESS_5 +173 759 FEAT_EPIC_TOUGHNESS_6 +174 492 FEAT_EPIC_DAMAGE_REDUCTION_3 +175 493 FEAT_EPIC_DAMAGE_REDUCTION_6 +176 494 FEAT_EPIC_DAMAGE_REDUCTION_9 +177 760 FEAT_EPIC_TOUGHNESS_7 +178 761 FEAT_EPIC_TOUGHNESS_8 +179 762 FEAT_EPIC_TOUGHNESS_9 +180 763 FEAT_EPIC_TOUGHNESS_10 +181 695 FEAT_EPIC_WILL +182 774 FEAT_EPIC_GREAT_CONSTITUTION_1 +183 775 FEAT_EPIC_GREAT_CONSTITUTION_2 +184 776 FEAT_EPIC_GREAT_CONSTITUTION_3 +185 777 FEAT_EPIC_GREAT_CONSTITUTION_4 +186 778 FEAT_EPIC_GREAT_CONSTITUTION_5 +187 779 FEAT_EPIC_GREAT_CONSTITUTION_6 +188 780 FEAT_EPIC_GREAT_CONSTITUTION_7 +189 781 FEAT_EPIC_GREAT_CONSTITUTION_8 +190 782 FEAT_EPIC_GREAT_CONSTITUTION_9 +191 783 FEAT_EPIC_GREAT_CONSTITUTION_10 +192 784 FEAT_EPIC_GREAT_DEXTERITY_1 +193 785 FEAT_EPIC_GREAT_DEXTERITY_2 +194 786 FEAT_EPIC_GREAT_DEXTERITY_3 +195 787 FEAT_EPIC_GREAT_DEXTERITY_4 +196 788 FEAT_EPIC_GREAT_DEXTERITY_5 +197 789 FEAT_EPIC_GREAT_DEXTERITY_6 +198 790 FEAT_EPIC_GREAT_DEXTERITY_7 +199 791 FEAT_EPIC_GREAT_DEXTERITY_8 +200 792 FEAT_EPIC_GREAT_DEXTERITY_9 +201 793 FEAT_EPIC_GREAT_DEXTERITY_10 +202 106 WeapFocLSw +203 377 ImpInit +204 6 Cleave +205 391 GreatCleave +206 408 BlindFight +207 28 PowerAtk +208 68 ImpCritLSw +209 144 WeapSpeLSw +210 3831 BladeMeditation_IronHeart +211 3990 IronheartAura +212 10 Dodge +213 40 Toughness +214 26 Mobility +215 392 SpringAttack +216 9 Disarm +217 14 GreatFort +218 22 IronWill +219 24 LightngRef +220 389 Expertise +221 425 DirtyFighting +222 27 PBShot +223 30 RapidShot +224 107 WeapFocGSw +225 69 ImpCritGSw +226 145 WeapSpeGSw +227 1 Ambidex +228 41 TwoWeap +229 16 ImpDis +230 19 ImpPower +231 20 ImpTwo +232 390 ImpExpertise +233 0 Alertness +234 42 WeapFinesse +235 32 Shield +236 39 StunFist +237 8 DefArrow +238 427 ResistEnergyCold +239 428 ResistEnergyAcid +240 429 ResistEnergyFire +241 430 ResistEnergyElectrical +242 431 ResistEnergySonic +243 43 WeapFocClub +244 15 ImpCritClub +245 57 ImpCritMorn +246 58 ImpCritStaff +247 59 ImpCritSpear +248 60 ImpCritSickle +249 61 ImpCritSling +250 62 ImpCritUnArm +251 63 ImpCritLongBow +252 64 ImpCritShortBow +253 65 ImpCritShortSwor +254 66 ImpCritRapier +255 67 ImpCritScim +256 70 ImpCritHAxe +257 71 ImpCritTAxe +258 72 ImpCritBAxe +259 73 ImpCritGAxe +260 74 ImpCritHalb +261 75 ImpCritLgHam +262 76 ImpCritLgFlail +263 77 ImpCritWHam +264 78 ImpCritHFlail +265 79 ImpCritKama +266 80 ImpCritKukri +267 82 ImpCritShur +268 83 ImpCritScy +269 84 ImpCritKatana +270 85 ImpCritBSw +271 87 ImpCritDMace +272 88 ImpCritDAxe +273 89 ImpCrit2Sw +274 1074 FEAT_IMPROVED_CRITICAL_TRIDENT +275 90 WeapFocDagger +276 91 WeapFocDart +277 92 WeapFocHXBow +278 93 WeapFocLgXBow +279 94 WeapFocLgMace +280 95 WeapFocMorn +281 96 WeapFocStaff +282 97 WeapFocSpear +283 98 WeapFocSickle +284 99 WeapFocSling +285 100 WeapFocUnArm +286 101 WeapFocLongBow +287 102 WeapFocShortBow +288 103 WeapFocShortSwor +289 104 WeapFocRapier +290 105 WeapFocScim +291 108 WeapFocHAxe +292 109 WeapFocTAxe +293 110 WeapFocBAxe +294 111 WeapFocGAxe +295 112 WeapFocHalb +296 113 WeapFocLgHam +297 114 WeapFocLgFlail +298 115 WeapFocWHam +299 116 WeapFocHFlail +300 117 WeapFocKama +301 118 WeapFocKukri +302 120 WeapFocShur +303 121 WeapFocScy +304 122 WeapFocKatana +305 123 WeapFocBSw +306 125 WeapFocDMace +307 126 WeapFocDAxe +308 127 WeapFoc2Sw +309 1072 FEAT_WEAPON_FOCUS_TRIDENT +310 128 WeapSpeDagger +311 129 WeapSpeDart +312 130 WeapSpeHXBow +313 131 WeapSpeLgXBow +314 132 WeapSpeLgMace +315 133 WeapSpeMorn +316 134 WeapSpeStaff +317 135 WeapSpeSpear +318 136 WeapSpeSickle +319 137 WeapSpeSling +320 138 WeapSpeUnArm +321 139 WeapSpeLongBow +322 140 WeapSpeShortBow +323 141 WeapSpeShortSwor +324 142 WeapSpeRapier +325 143 WeapSpeScim +326 146 WeapSpeHAxe +327 147 WeapSpeTAxe +328 148 WeapSpeBAxe +329 149 WeapSpeGAxe +330 150 WeapSpeHalb +331 151 WeapSpeLgHam +332 152 WeapSpeLgFlail +333 153 WeapSpeWHam +334 154 WeapSpeHFlail +335 155 WeapSpeKama +336 156 WeapSpeKukri +337 158 WeapSpeShur +338 159 WeapSpeScy +339 160 WeapSpeKatana +340 161 WeapSpeBSw +341 163 WeapSpeDMace +342 164 WeapSpeDAxe +343 165 WeapSpe2Sw +344 1073 FEAT_WEAPON_SPECIALIZATION_TRIDENT +345 166 SpellFocusCon +346 167 SpellFocusDiv +347 168 SpellFocusEnc +348 169 SpellFocusEvo +349 170 SpellFocusIll +350 171 SpellFocusNec +351 172 SpellFocusTra +352 173 SkillFocusConc +353 174 SkillFocusDisa +354 175 SkillFocusGrip +355 177 SkillFocusHeal +356 178 SkillFocusHide +357 179 SkillFocusList +358 180 SkillFocusLore +359 181 SkillFocusMove +360 182 SkillFocusOpen +361 183 SkillFocusParr +362 184 SkillFocusPerf +363 185 SkillFocusPers +364 186 SkillFocusPick +365 187 SkillFocusSearch +366 188 SkillFocusSet +367 189 SkillFocusSpell +368 190 SkillFocusSpot +369 192 SkillFocusTaunt +370 193 SkillFocusDevi +371 35 SpellFocusAbj +372 36 SpellPen +373 37 StillSpell +374 25 MaxSpell +375 7 CmbtCast +376 29 Quicken +377 34 SkillFocusAnim +378 33 Silent +379 11 Empower +380 12 ExtSpell +381 13 ExtTurn diff --git a/nwn/nwnprc/trunk/Craft2das/packskwb1.2da b/nwn/nwnprc/trunk/Craft2das/packskwb1.2da new file mode 100644 index 00000000..7affba55 --- /dev/null +++ b/nwn/nwnprc/trunk/Craft2das/packskwb1.2da @@ -0,0 +1,26 @@ +2DA V2.0 + + SkillIndex Label +0 1 Concentration +1 28 Jump +2 32 Balance +3 12 Persuade +4 24 Intimidate +5 31 Martial_Lore +6 37 Climb +7 7 Lore +8 17 Spot +9 27 Ride +10 4 Heal +11 26 CraftWeapon +12 25 CraftArmor +13 16 Spellcraft +14 30 SenseMotive +15 19 UseMagicDevice +16 8 MoveSilently +17 5 Hide +18 23 Bluff +19 14 Search +20 24 Intimidate +21 35 CraftPoison +22 38 GraftGeneral diff --git a/nwn/nwnprc/trunk/include/true_inc_trufunc.nss b/nwn/nwnprc/trunk/include/true_inc_trufunc.nss index ad010b35..3b3e7d52 100644 --- a/nwn/nwnprc/trunk/include/true_inc_trufunc.nss +++ b/nwn/nwnprc/trunk/include/true_inc_trufunc.nss @@ -781,6 +781,8 @@ int CheckTrueSpeechSkill(object oTrueSpeaker) else if (GetLevelByClass(CLASS_TYPE_BEREFT, oTrueSpeaker) > 0) return FALSE; // And this one else if (GetLevelByClass(CLASS_TYPE_BRIMSTONE_SPEAKER, oTrueSpeaker) > 0) return FALSE; + // Factotums have every skill as a class skill. + else if (GetLevelByClass(CLASS_TYPE_FACTOTUM, oTrueSpeaker) > 0) return FALSE; // If they have the feat, no relevel else if(GetHasFeat(FEAT_TRUENAME_TRAINING, oTrueSpeaker)) return FALSE; // Now we check the values. If they have too many ranks, relevel. @@ -837,4 +839,7 @@ int GetCadenceCount(object oTrueSpeaker) // Return total return nCount; -} \ No newline at end of file +} + +// +void main (){} \ No newline at end of file diff --git a/nwn/nwnprc/trunk/newspellbook/inf_armor_enh.nss b/nwn/nwnprc/trunk/newspellbook/inf_armor_enh.nss new file mode 100644 index 00000000..fe36b48e --- /dev/null +++ b/nwn/nwnprc/trunk/newspellbook/inf_armor_enh.nss @@ -0,0 +1,849 @@ +// inf_armor_enh.nss +/* +Armor Enhancement, Lesser +Transmutation +Level: Artificer 1 +Components: S, M +Casting Time: 1 minute +Range: Touch +Target: Armor or shield touched +Duration: 10 min./level +Saving Throw: None (object) +Spell Resistance: No (object) + +The armor or shield you touch temporarily gains a special ability +commonly found on magic armor or shields. +You can choose any special ability whose market price is equivalent to + a +1 bonus or up to 5,000 gp, such as light fortification or shadow. + The armor or shield does not need to have an existing enhancement + bonus, nor does it gain one when you imbue it with this infusion. +Material Component: An ointment made from rare spices and minerals, +costing 10 gp. + +Armor Enhancement +Transmutation +Level: Artificer 2 + +As lesser armor enhancement, but you can choose any special ability +whose market price is equivalent to a bonus of up to +3 or up to +35,000 gp, such as ghost touch or acid resistance. +Material Component: An ointment costing 50 gp. + +Armor Enhancement, Greater +Transmutation +Level: Artificer 3 + +As lesser armor enhancement, but you can choose any special ability +whose market price is equivalent to a bonus of up to +5 or up to +100,000 gp, such as etherealness or greater fire resistance. +Material Component: An ointment costing 100 gp. + */ + +#include "inc_debug" +#include "prc_craft_inc" +#include "inc_dynconv" + +// Placeholder magic numbers for spell IDs +const int ARMOR_ENH_LESS = 5001; +const int ARMOR_ENH = 5002; +const int ARMOR_ENH_GREATER = 5003; + +// Dynamic conversation stages +const int STAGE_PROPERTY_SELECTION = 0; +const int STAGE_CONFIRMATION = 1; + + +void HandleConversation(object oPC, object oArmor, int nMaxEnhancement, int nMaxCost, string sLocalVar, int nSpellID, int nCasterLevel) +{ + int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE); + int nStage = GetStage(oPC); + + if(nValue == 0) return; + + if(nValue == DYNCONV_SETUP_STAGE) + { + if(!GetIsStageSetUp(nStage, oPC)) + { + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Set header first + SetHeader("Select an armor enhancement:"); + + // Initialize default tokens BEFORE adding choices + SetDefaultTokens(); + + // Read directly from craft_armour.2da + int nFileEnd = PRCGetFileEnd("craft_armour"); + int nChoice = 1; + int i; + + for(i = 0; i <= nFileEnd; i++) + { + // Get enhancement and cost for this specific line + int nEnhancement = StringToInt(Get2DACache("craft_armour", "Enhancement", i)); + int nAdditionalCost = StringToInt(Get2DACache("craft_armour", "AdditionalCost", i)); + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", i))); + + // Debug output + SendMessageToPC(oPC, "Line " + IntToString(i) + ": " + sName + " (Enh:" + IntToString(nEnhancement) + ", Cost:" + IntToString(nAdditionalCost) + ")"); + + // Check if this property is within limits + if(nEnhancement <= nMaxEnhancement && nAdditionalCost <= nMaxCost) + { + AddChoice(sName, i, oPC); + nChoice++; + } + } + + MarkStageSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty"); + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", nPropertyLine))); + + SetHeader("Apply " + sName + " to the armor?"); + + AddChoice("Yes", TRUE, oPC); + AddChoice("No", FALSE, oPC); + + MarkStageSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetupTokens(); + } + else if(nValue == DYNCONV_EXITED) + { + // Cleanup + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + } + else if(nValue == DYNCONV_ABORTED) + { + // Cleanup + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + } + else + { + int nChoice = GetChoice(oPC); + + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Store selection and go to confirmation + SetLocalInt(oPC, "ArmorEnh_SelectedProperty", nChoice); + nStage = STAGE_CONFIRMATION; + MarkStageNotSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + if(nChoice == TRUE) // User confirmed + { + // Apply the property + object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET"); + int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty"); + int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel"); + + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + // Debug output + SendMessageToPC(oPC, "Duration: " + FloatToString(fDuration) + " seconds"); + + // Add fallback for very small durations + if (fDuration <= 1.0) fDuration = 30.0f; + + SendMessageToPC(oPC, "Fallback Duration: " + FloatToString(fDuration) + " seconds"); + + // Create property directly + itemproperty ip; +/* if(nPropertyLine == 0) + { + // +1 Enhancement + ip = ConstructIP(ITEM_PROPERTY_AC_BONUS, 0, 1, 0); + } + else + { */ + // Read property data from 2DA and construct + string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + //} + + // Apply with proper duration + ip = TagItemProperty(ip, "ArmorEnhInfusion"); + IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + // Clean up and exit + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + + AllowExit(DYNCONV_EXIT_FORCE_EXIT); + } + else // User cancelled + { + // Go back to property selection + nStage = STAGE_PROPERTY_SELECTION; + MarkStageNotSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetStage(nStage, oPC); + } +} + +void main() +{ + object oPC = GetPCSpeaker(); + if(!GetIsObjectValid(oPC)) oPC = OBJECT_SELF; + + // Check if we're in conversation mode + if(GetLocalInt(oPC, "ArmorEnh_ConvMode")) + { + // Retrieve parameters for conversation + object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET"); + int nMaxEnhancement = GetLocalInt(oPC, "ArmorEnh_MaxEnh"); + int nMaxCost = GetLocalInt(oPC, "ArmorEnh_MaxCost"); + string sLocalVar = GetLocalString(oPC, "ArmorEnh_LocalVar"); + int nSpellID = GetLocalInt(oPC, "ArmorEnh_SpellID"); + int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel"); + + HandleConversation(oPC, oArmor, nMaxEnhancement, nMaxCost, sLocalVar, nSpellID, nCasterLevel); + return; + } + + // Normal spell execution + PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION); + if (!X2PreSpellCastCode()) return; + + object oCaster = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + int nCasterLevel = PRCGetCasterLevel(oCaster); + int nSpellID = PRCGetSpellId(); + + // Declare variables + int nGoldCost, nMaxEnhancement, nMaxCost; + string sLocalVar; + + // Set parameters based on spell level + switch(nSpellID) + { + case ARMOR_ENH_LESS: + nGoldCost = 10; + nMaxEnhancement = 1; + nMaxCost = 5000; + sLocalVar = "ARMOR_ENH_LESS_PROPERTY"; + break; + case ARMOR_ENH: + nGoldCost = 50; + nMaxEnhancement = 3; + nMaxCost = 35000; + sLocalVar = "ARMOR_ENH_PROPERTY"; + break; + case ARMOR_ENH_GREATER: + nGoldCost = 100; + nMaxEnhancement = 5; + nMaxCost = 100000; + sLocalVar = "ARMOR_ENH_GREATER_PROPERTY"; + break; + default: + // Default to lesser version for testing + nGoldCost = 10; + nMaxEnhancement = 1; + nMaxCost = 5000; + sLocalVar = "ARMOR_ENH_LESS_PROPERTY"; + break; + } + + // Check material component + if(GetGold(oCaster) < nGoldCost) + { + FloatingTextStringOnCreature("You need " + IntToString(nGoldCost) + "gp worth of rare spices and minerals.", oCaster, FALSE); + return; + } + + // Get targeted armor or shield + object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCaster); + //object oArmor = IPGetTargetedOrEquippedArmor(TRUE); <- don't delete + if(!GetIsObjectValid(oArmor)) + { + FloatingTextStrRefOnCreature(83826, oCaster, FALSE); // "Invalid target" + return; + } + + // Check if returning from conversation with a selection + int nPropertyLine = GetLocalInt(oCaster, sLocalVar); + if(nPropertyLine > 0) + { + // Apply the property + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + if (fDuration <= 1.0) fDuration = 30.0f; + + // Create property directly + itemproperty ip; + + // Read property data from 2DA and construct + string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + + // Apply with proper duration + ip = TagItemProperty(ip, "ArmorEnhInfusion"); + IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + DeleteLocalInt(oCaster, sLocalVar); + return; + } + + // Store parameters for conversation and start it + SetLocalInt(oPC, "ArmorEnh_ConvMode", 1); + SetLocalObject(oPC, "ARMOR_ENH_TARGET", oArmor); + SetLocalInt(oPC, "ArmorEnh_MaxEnh", nMaxEnhancement); + SetLocalInt(oPC, "ArmorEnh_MaxCost", nMaxCost); + SetLocalString(oPC, "ArmorEnh_LocalVar", sLocalVar); + SetLocalInt(oPC, "ArmorEnh_SpellID", nSpellID); + SetLocalInt(oPC, "ArmorEnh_CasterLevel", nCasterLevel); + + // Start the dynamic conversation using this same script + StartDynamicConversation("inf_armor_enh", oPC, 0, FALSE, TRUE); +} + + +/* void HandleConversation(object oPC, object oArmor, int nMaxEnhancement, int nMaxCost, string sLocalVar, int nSpellID, int nCasterLevel) +{ + int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE); + int nStage = GetStage(oPC); + + if(nValue == 0) return; + + if(nValue == DYNCONV_SETUP_STAGE) + { + if(!GetIsStageSetUp(nStage, oPC)) + { + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Set header first + SetHeader("Select an armor enhancement:"); + + // Initialize default tokens BEFORE adding choices + SetDefaultTokens(); + + // Read directly from craft_armour.2da + int nFileEnd = PRCGetFileEnd("craft_armour"); + int nChoice = 1; + int i; + + for(i = 0; i <= nFileEnd; i++) + { + // Get enhancement and cost for this specific line + int nEnhancement = StringToInt(Get2DACache("craft_armour", "Enhancement", i)); + int nAdditionalCost = StringToInt(Get2DACache("craft_armour", "AdditionalCost", i)); + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", i))); + + // Debug output + SendMessageToPC(oPC, "Line " + IntToString(i) + ": " + sName + " (Enh:" + IntToString(nEnhancement) + ", Cost:" + IntToString(nAdditionalCost) + ")"); + + // Check if this property is within limits + if(nEnhancement <= nMaxEnhancement && nAdditionalCost <= nMaxCost) + { + AddChoice(sName, i, oPC); + nChoice++; + } + } + + MarkStageSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty"); + + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", nPropertyLine))); + + SetHeader("Apply " + sName + " to the armor?"); + + AddChoice("Yes", TRUE, oPC); + AddChoice("No", FALSE, oPC); + + MarkStageSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetupTokens(); + } + else if(nValue == DYNCONV_EXITED) + { + // Cleanup + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + } + else if(nValue == DYNCONV_ABORTED) + { + // Cleanup + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + } + else + { + int nChoice = GetChoice(oPC); + + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Store selection and go to confirmation + SetLocalInt(oPC, "ArmorEnh_SelectedProperty", nChoice); + nStage = STAGE_CONFIRMATION; + MarkStageNotSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + if(nChoice == TRUE) // User confirmed + { + // Apply the property + object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET"); + int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty"); + int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel"); + + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + // Debug output + SendMessageToPC(oPC, "Duration: " + FloatToString(fDuration) + " seconds"); + + // Add fallback for very small durations + if (fDuration <= 1.0) fDuration = 30.0f; + + // Create property directly + itemproperty ip; + if(nPropertyLine == 0) + { + // +1 Enhancement + ip = ConstructIP(ITEM_PROPERTY_AC_BONUS, 0, 1, 0); + } + else + { + // Read property data from 2DA and construct + string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + } + + // Apply with proper duration + ip = TagItemProperty(ip, "ArmorEnhInfusion"); + IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + // Clean up and exit + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + + AllowExit(DYNCONV_EXIT_FORCE_EXIT); + return; + } + else // User cancelled + { + // Go back to property selection + nStage = STAGE_PROPERTY_SELECTION; + MarkStageNotSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetStage(nStage, oPC); + } +} + +void main() +{ + object oPC = GetPCSpeaker(); + if(!GetIsObjectValid(oPC)) oPC = OBJECT_SELF; + + // Check if we're in conversation mode + if(GetLocalInt(oPC, "ArmorEnh_ConvMode")) + { + // Retrieve parameters for conversation + object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET"); + int nMaxEnhancement = GetLocalInt(oPC, "ArmorEnh_MaxEnh"); + int nMaxCost = GetLocalInt(oPC, "ArmorEnh_MaxCost"); + string sLocalVar = GetLocalString(oPC, "ArmorEnh_LocalVar"); + int nSpellID = GetLocalInt(oPC, "ArmorEnh_SpellID"); + int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel"); + + HandleConversation(oPC, oArmor, nMaxEnhancement, nMaxCost, sLocalVar, nSpellID, nCasterLevel); + return; + } + + // Normal spell execution + PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION); + if (!X2PreSpellCastCode()) return; + + object oCaster = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + int nCasterLevel = PRCGetCasterLevel(oCaster); + //int nSpellID = PRCGetSpellId(); + int nSpellID = ARMOR_ENH_GREATER; + + // Declare variables + int nGoldCost, nMaxEnhancement, nMaxCost; + string sLocalVar; + + // Set parameters based on spell level + switch(nSpellID) + { + case ARMOR_ENH_LESS: + nGoldCost = 10; + nMaxEnhancement = 1; + nMaxCost = 5000; + sLocalVar = "ARMOR_ENH_LESS_PROPERTY"; + break; + case ARMOR_ENH: + nGoldCost = 50; + nMaxEnhancement = 3; + nMaxCost = 35000; + sLocalVar = "ARMOR_ENH_PROPERTY"; + break; + case ARMOR_ENH_GREATER: + nGoldCost = 100; + nMaxEnhancement = 5; + nMaxCost = 100000; + sLocalVar = "ARMOR_ENH_GREATER_PROPERTY"; + break; + default: + // Default to lesser version for testing + nGoldCost = 10; + nMaxEnhancement = 1; + nMaxCost = 5000; + sLocalVar = "ARMOR_ENH_LESS_PROPERTY"; + break; + } + + // Check material component + if(GetGold(oCaster) < nGoldCost) + { + FloatingTextStringOnCreature("You need " + IntToString(nGoldCost) + "gp worth of rare spices and minerals.", oCaster, FALSE); + return; + } + + // Get targeted armor or shield + object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCaster); + if(!GetIsObjectValid(oArmor)) + { + FloatingTextStrRefOnCreature(83826, oCaster, FALSE); // "Invalid target" + return; + } + + // Store parameters for conversation and start it + SetLocalInt(oPC, "ArmorEnh_ConvMode", 1); + SetLocalObject(oPC, "ARMOR_ENH_TARGET", oArmor); + SetLocalInt(oPC, "ArmorEnh_MaxEnh", nMaxEnhancement); + SetLocalInt(oPC, "ArmorEnh_MaxCost", nMaxCost); + SetLocalString(oPC, "ArmorEnh_LocalVar", sLocalVar); + SetLocalInt(oPC, "ArmorEnh_SpellID", nSpellID); + SetLocalInt(oPC, "ArmorEnh_CasterLevel", nCasterLevel); + + // Start the dynamic conversation using this same script + DelayCommand(0.1f, StartDynamicConversation("inf_armor_enh", oPC, 0, FALSE, TRUE)); +} */ + + + +/* void HandleConversation(object oPC, object oArmor, int nMaxEnhancement, int nMaxCost, string sLocalVar, int nSpellID, int nCasterLevel) +{ + int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE); + int nStage = GetStage(oPC); + + if(nValue == 0) return; + + if(nValue == DYNCONV_SETUP_STAGE) + { + if(!GetIsStageSetUp(nStage, oPC)) + { + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Set header first + SetHeader("Select an armor enhancement:"); + + // Initialize default tokens BEFORE adding choices + SetDefaultTokens(); + + // Read directly from craft_armour.2da + int nFileEnd = PRCGetFileEnd("craft_armour"); + int nChoice = 1; + int i; + + AddChoice("Enhancement +1", 0, oPC); + + for(i = 1; i <= nFileEnd; i++) + { + // Get enhancement and cost for this specific line + int nEnhancement = StringToInt(Get2DACache("craft_armour", "Enhancement", i)); + int nAdditionalCost = StringToInt(Get2DACache("craft_armour", "AdditionalCost", i)); + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", i))); + + // Debug output + SendMessageToPC(oPC, "Line " + IntToString(i) + ": " + sName + " (Enh:" + IntToString(nEnhancement) + ", Cost:" + IntToString(nAdditionalCost) + ")"); + + // Check if this property is within limits + if(nEnhancement <= nMaxEnhancement && nAdditionalCost <= nMaxCost) + { + AddChoice(sName, i, oPC); + nChoice++; + } + } + + MarkStageSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty"); + string sName; + + if(nPropertyLine == 0) + sName = "Enhancement +1"; + else + sName = GetStringByStrRef(StringToInt(Get2DACache("craft_armour", "Name", nPropertyLine))); + + SetHeader("Apply " + sName + " to the armor?"); + + AddChoice("Yes", TRUE, oPC); + AddChoice("No", FALSE, oPC); + + MarkStageSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetupTokens(); + } + else if(nValue == DYNCONV_EXITED) + { + // Cleanup + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + } + else if(nValue == DYNCONV_ABORTED) + { + // Cleanup + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + } + else + { + int nChoice = GetChoice(oPC); + + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Store selection and go to confirmation + SetLocalInt(oPC, "ArmorEnh_SelectedProperty", nChoice); + nStage = STAGE_CONFIRMATION; + MarkStageNotSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + if(nChoice == TRUE) // User confirmed + { + // Apply the property + object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET"); + int nPropertyLine = GetLocalInt(oPC, "ArmorEnh_SelectedProperty"); + int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel"); + + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + // Debug output + SendMessageToPC(oPC, "Duration: " + FloatToString(fDuration) + " seconds"); + + // Add fallback for very small durations + if (fDuration <= 1.0) fDuration = 30.0f; + + // Create property directly + itemproperty ip; + if(nPropertyLine == 0) + { + // +1 Enhancement + ip = ConstructIP(ITEM_PROPERTY_AC_BONUS, 0, 1, 0); + } + else + { + // Read property data from 2DA and construct + string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + } + + // Apply with proper duration + ip = TagItemProperty(ip, "ArmorEnhInfusion"); + IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + // Clean up and exit + DeleteLocalInt(oPC, "ArmorEnh_ConvMode"); + DeleteLocalObject(oPC, "ARMOR_ENH_TARGET"); + DeleteLocalInt(oPC, "ArmorEnh_SelectedProperty"); + + AllowExit(DYNCONV_EXIT_FORCE_EXIT); + } + else // User cancelled + { + // Go back to property selection + nStage = STAGE_PROPERTY_SELECTION; + MarkStageNotSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetStage(nStage, oPC); + } +} + +void main() +{ + object oPC = GetPCSpeaker(); + if(!GetIsObjectValid(oPC)) oPC = OBJECT_SELF; + + // Check if we're in conversation mode + if(GetLocalInt(oPC, "ArmorEnh_ConvMode")) + { + // Retrieve parameters for conversation + object oArmor = GetLocalObject(oPC, "ARMOR_ENH_TARGET"); + int nMaxEnhancement = GetLocalInt(oPC, "ArmorEnh_MaxEnh"); + int nMaxCost = GetLocalInt(oPC, "ArmorEnh_MaxCost"); + string sLocalVar = GetLocalString(oPC, "ArmorEnh_LocalVar"); + int nSpellID = GetLocalInt(oPC, "ArmorEnh_SpellID"); + int nCasterLevel = GetLocalInt(oPC, "ArmorEnh_CasterLevel"); + + HandleConversation(oPC, oArmor, nMaxEnhancement, nMaxCost, sLocalVar, nSpellID, nCasterLevel); + return; + } + + // Normal spell execution + PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION); + if (!X2PreSpellCastCode()) return; + + object oCaster = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + int nCasterLevel = PRCGetCasterLevel(oCaster); + int nSpellID = PRCGetSpellId(); + + // Declare variables + int nGoldCost, nMaxEnhancement, nMaxCost; + string sLocalVar; + + // Set parameters based on spell level + switch(nSpellID) + { + case ARMOR_ENH_LESS: + nGoldCost = 10; + nMaxEnhancement = 1; + nMaxCost = 5000; + sLocalVar = "ARMOR_ENH_LESS_PROPERTY"; + break; + case ARMOR_ENH: + nGoldCost = 50; + nMaxEnhancement = 3; + nMaxCost = 35000; + sLocalVar = "ARMOR_ENH_PROPERTY"; + break; + case ARMOR_ENH_GREATER: + nGoldCost = 100; + nMaxEnhancement = 5; + nMaxCost = 100000; + sLocalVar = "ARMOR_ENH_GREATER_PROPERTY"; + break; + default: + // Default to lesser version for testing + nGoldCost = 10; + nMaxEnhancement = 1; + nMaxCost = 5000; + sLocalVar = "ARMOR_ENH_LESS_PROPERTY"; + break; + } + + // Check material component + if(GetGold(oCaster) < nGoldCost) + { + FloatingTextStringOnCreature("You need " + IntToString(nGoldCost) + "gp worth of rare spices and minerals.", oCaster, FALSE); + return; + } + + // Get targeted armor or shield + object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCaster); + if(!GetIsObjectValid(oArmor)) + { + FloatingTextStrRefOnCreature(83826, oCaster, FALSE); // "Invalid target" + return; + } + + // Check if item already has an infusion + itemproperty ipExisting = GetFirstItemProperty(oArmor); + while(GetIsItemPropertyValid(ipExisting)) + { + if(GetItemPropertyTag(ipExisting) == "ArmorEnhInfusion") + { + FloatingTextStringOnCreature("This armor already has an armor enhancement infusion.", oCaster, FALSE); + return; + } + ipExisting = GetNextItemProperty(oArmor); + } + + // Check if returning from conversation with a selection + int nPropertyLine = GetLocalInt(oCaster, sLocalVar); + if(nPropertyLine > 0) + { + // Apply the property + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + if (fDuration <= 1.0) fDuration = 30.0f; + + // Create property directly + itemproperty ip; + if(nPropertyLine == 0) + { + // +1 Enhancement + ip = ConstructIP(ITEM_PROPERTY_AC_BONUS, 0, 1, 0); + } + else + { + // Read property data from 2DA and construct + string sIPData = Get2DACache("craft_armour", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + } + + // Apply with proper duration + ip = TagItemProperty(ip, "ArmorEnhInfusion"); + IPSafeAddItemProperty(oArmor, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + DeleteLocalInt(oCaster, sLocalVar); + return; + } + + // Store parameters for conversation and start it + SetLocalInt(oPC, "ArmorEnh_ConvMode", 1); + SetLocalObject(oPC, "ARMOR_ENH_TARGET", oArmor); + SetLocalInt(oPC, "ArmorEnh_MaxEnh", nMaxEnhancement); + SetLocalInt(oPC, "ArmorEnh_MaxCost", nMaxCost); + SetLocalString(oPC, "ArmorEnh_LocalVar", sLocalVar); + SetLocalInt(oPC, "ArmorEnh_SpellID", nSpellID); + SetLocalInt(oPC, "ArmorEnh_CasterLevel", nCasterLevel); + + // Start the dynamic conversation using this same script + StartDynamicConversation("inf_armor_enh", oPC, 0, FALSE, TRUE); +} + + */ \ No newline at end of file diff --git a/nwn/nwnprc/trunk/newspellbook/inf_energy_alt.nss b/nwn/nwnprc/trunk/newspellbook/inf_energy_alt.nss new file mode 100644 index 00000000..ccf9608f --- /dev/null +++ b/nwn/nwnprc/trunk/newspellbook/inf_energy_alt.nss @@ -0,0 +1,158 @@ +// inf_energy_alt.nss +#include "prc_sp_func" +#include "prc_inc_spells" +#include "psi_inc_enrgypow" +#include "prc_craft_inc" // Add this for item property serialization + +const int SPELL_ENERGY_ALTERATION_COLD = 9000; +const int SPELL_ENERGY_ALTERATION_ELEC = 9001; +const int SPELL_ENERGY_ALTERATION_FIRE = 9002; +const int SPELL_ENERGY_ALTERATION_SONIC = 9003; + +// Forward declarations +void StoreOriginalProperties(object oItem); +void RestoreOriginalProperties(object oItem); +int ConvertDamageTypeToIPConst(int nDamageType); + +// Convert DAMAGE_TYPE_* to IP_CONST_DAMAGETYPE_* +int ConvertDamageTypeToIPConst(int nDamageType) +{ + switch(nDamageType) + { + case DAMAGE_TYPE_ACID: return IP_CONST_DAMAGETYPE_ACID; + case DAMAGE_TYPE_COLD: return IP_CONST_DAMAGETYPE_COLD; + case DAMAGE_TYPE_ELECTRICAL: return IP_CONST_DAMAGETYPE_ELECTRICAL; + case DAMAGE_TYPE_FIRE: return IP_CONST_DAMAGETYPE_FIRE; + case DAMAGE_TYPE_SONIC: return IP_CONST_DAMAGETYPE_SONIC; + default: return IP_CONST_DAMAGETYPE_ACID; + } + return IP_CONST_DAMAGETYPE_ACID; // Add explicit return for compiler +} + +void ApplyEnergyAlteration(object oItem, int nSpellID, int nCasterLvl) +{ + struct energy_adjustments enAdj = EvaluateEnergy( + nSpellID, + SPELL_ENERGY_ALTERATION_COLD, + SPELL_ENERGY_ALTERATION_ELEC, + SPELL_ENERGY_ALTERATION_FIRE, + SPELL_ENERGY_ALTERATION_SONIC + ); + + // Modify existing energy properties + itemproperty ip = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ip)) + { + int nType = GetItemPropertyType(ip); + + // Replace damage bonus properties + if(nType == ITEM_PROPERTY_DAMAGE_BONUS) + { + int nDamageType = GetItemPropertySubType(ip); + if(nDamageType == DAMAGE_TYPE_ACID || nDamageType == DAMAGE_TYPE_COLD || + nDamageType == DAMAGE_TYPE_ELECTRICAL || nDamageType == DAMAGE_TYPE_FIRE || + nDamageType == DAMAGE_TYPE_SONIC) + { + RemoveItemProperty(oItem, ip); + itemproperty ipNew = ItemPropertyDamageBonus(enAdj.nDamageType, GetItemPropertyCostTableValue(ip)); + AddItemProperty(DURATION_TYPE_TEMPORARY, ipNew, oItem, RoundsToSeconds(nCasterLvl * 10)); + SetLocalInt(oItem, "EnergyAlter_Temp_" + IntToString(ITEM_PROPERTY_DAMAGE_BONUS), TRUE); + } + } + + // Replace resistance properties + if(nType == ITEM_PROPERTY_DAMAGE_RESISTANCE) + { + int nResistType = GetItemPropertySubType(ip); + if(nResistType == IP_CONST_DAMAGETYPE_ACID || nResistType == IP_CONST_DAMAGETYPE_COLD || + nResistType == IP_CONST_DAMAGETYPE_ELECTRICAL || nResistType == IP_CONST_DAMAGETYPE_FIRE || + nResistType == IP_CONST_DAMAGETYPE_SONIC) + { + RemoveItemProperty(oItem, ip); + int nNewType = ConvertDamageTypeToIPConst(enAdj.nDamageType); + itemproperty ipNew = ItemPropertyDamageResistance(nNewType, GetItemPropertyCostTableValue(ip)); + AddItemProperty(DURATION_TYPE_TEMPORARY, ipNew, oItem, RoundsToSeconds(nCasterLvl * 10)); + SetLocalInt(oItem, "EnergyAlter_Temp_" + IntToString(ITEM_PROPERTY_DAMAGE_RESISTANCE), TRUE); + } + } + + ip = GetNextItemProperty(oItem); + } + + // Schedule restoration + DelayCommand(RoundsToSeconds(nCasterLvl * 10), RestoreOriginalProperties(oItem)); +} + +// Store original properties with PRC persistent backup +void StoreOriginalProperties(object oItem) +{ + string sItemID = GetObjectUUID(oItem); + itemproperty ip = GetFirstItemProperty(oItem); + + while(GetIsItemPropertyValid(ip)) + { + string sPropData = GetItemPropertyString(ip); // Use PRC's function + SetLocalString(oItem, "EnergyAlter_Original_" + IntToString(GetItemPropertyType(ip)), sPropData); + + // PRC persistence for crash recovery + SetPersistantLocalString(oItem, "EnergyAlter_" + sItemID + "_" + IntToString(GetItemPropertyType(ip)), sPropData); + ip = GetNextItemProperty(oItem); + } + + SetLocalInt(oItem, "EnergyAlter_Active", TRUE); + SetLocalString(oItem, "EnergyAlter_ItemID", sItemID); +} + +// Restore properties with cleanup +void RestoreOriginalProperties(object oItem) +{ + string sItemID = GetLocalString(oItem, "EnergyAlter_ItemID"); + + // Remove temporary properties + itemproperty ip = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ip)) + { + if(GetLocalInt(oItem, "EnergyAlter_Temp_" + IntToString(GetItemPropertyType(ip)))) + RemoveItemProperty(oItem, ip); + ip = GetNextItemProperty(oItem); + } + + // Restore original properties + int nType; + for(nType = 0; nType < 100; nType++) + { + string sPropData = GetPersistantLocalString(oItem, "EnergyAlter_" + sItemID + "_" + IntToString(nType)); + if(sPropData != "") + { + struct ipstruct ipData = GetIpStructFromString(sPropData); + itemproperty ipOriginal = ConstructIP(ipData.type, ipData.subtype, ipData.costtablevalue, ipData.param1value); + AddItemProperty(DURATION_TYPE_PERMANENT, ipOriginal, oItem); + } + } + + // Cleanup - clear PRC persistent variables + DeletePersistantLocalString(oItem, "EnergyAlter_" + sItemID); + DeleteLocalInt(oItem, "EnergyAlter_Active"); +} + +void main() +{ + if(!X2PreSpellCastCode()) return; + + object oCaster = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + int nSpellID = PRCGetSpellId(); + int nCasterLvl = PRCGetCasterLevel(oCaster); + + // Material component validation (remove for testing) + // if(!GetIsObjectValid(GetItemPossessedBy(oCaster, "energy_alter_ointment"))) + // { + // FloatingTextStringOnCreature("You need an alchemical ointment (50 gp) to cast this spell.", oCaster, FALSE); + // return; + // } + // DestroyObject(GetItemPossessedBy(oCaster, "energy_alter_ointment")); + + // Store original properties and apply alteration + StoreOriginalProperties(oTarget); + ApplyEnergyAlteration(oTarget, nSpellID, nCasterLvl); +} \ No newline at end of file diff --git a/nwn/nwnprc/trunk/newspellbook/inf_resist_item.nss b/nwn/nwnprc/trunk/newspellbook/inf_resist_item.nss new file mode 100644 index 00000000..c50fba12 --- /dev/null +++ b/nwn/nwnprc/trunk/newspellbook/inf_resist_item.nss @@ -0,0 +1,213 @@ +// inf_resist_item.nss + +/* +Resistance Item +Abjuration +Level: Artificer 1 +Components: S, M +Casting Time: 1 round +Range: Touch +Target: Item touched +Duration: 10 min./level +Saving Throw: None +Spell Resistance: No + +A nonmagical item imbued with this infusion grants a + 1 resistance +bonus on saving throws to a character who wears or wields it. This +bonus increases by 1 for every four caster levels (to +2 at 4th level, + +3 at 8th level, +4 at 12th level, and so forth). +Material Component: Oil mixed with various spices and minerals. +*/ + +#include "prc_craft_inc" +#include "inc_dynconv" + +// Spell constants for subradials +const int RESISTANCE_ITEM_FORTITUDE = 6001; +const int RESISTANCE_ITEM_REFLEX = 6002; +const int RESISTANCE_ITEM_WILL = 6003; + +// Check if item is magical +int GetIsItemMagical(object oItem) +{ + if(!GetIsObjectValid(oItem)) return FALSE; + + // Skip plot items + if(GetPlotFlag(oItem)) return TRUE; + + int bIsMagical = FALSE; + itemproperty ipCheck = GetFirstItemProperty(oItem); + while (GetIsItemPropertyValid(ipCheck)) + { + string sTag = GetItemPropertyTag(ipCheck); + int nType = GetItemPropertyType(ipCheck); + + // Check for protected properties + if(sTag == "Tag_PRC_OnHitKeeper" || + sTag == "Quality_Masterwork" || + sTag == "Material_Mithral" || + sTag == "Material_Adamantine" || + sTag == "Material_Darkwood" || + sTag == "Material_ColdIron" || + sTag == "Material_MundaneCrystal" || + sTag == "Material_DeepCrystal" || + nType == ITEM_PROPERTY_MATERIAL) // All material properties + { + // Protected property - skip, don't set bIsMagical + } + else + { + // Check for helmet carveout: +1 Concentration only + if(GetBaseItemType(oItem) == BASE_ITEM_HELMET && + GetItemPropertyType(ipCheck) == ITEM_PROPERTY_SKILL_BONUS && + GetItemPropertySubType(ipCheck) == SKILL_CONCENTRATION && + GetItemPropertyCostTableValue(ipCheck) == 1) + { + // This is a +1 Concentration helmet with no other properties, allow it + bIsMagical = FALSE; + break; + } + else + { + bIsMagical = TRUE; + break; + } + } + ipCheck = GetNextItemProperty(oItem); + } + + return bIsMagical; +} + +// Find first non-magical item on creature +object GetFirstNonMagicalItem(object oCreature) +{ + // Check equipped items first + int nSlot; + for(nSlot = 0; nSlot < NUM_INVENTORY_SLOTS; nSlot++) + { + object oItem = GetItemInSlot(nSlot, oCreature); + if(GetIsObjectValid(oItem) && !GetIsItemMagical(oItem)) + return oItem; + } + + // Check inventory + object oItem = GetFirstItemInInventory(oCreature); + while(GetIsObjectValid(oItem)) + { + if(!GetIsItemMagical(oItem)) + return oItem; + oItem = GetNextItemInInventory(oCreature); + } + + return OBJECT_INVALID; +} + +void main() +{ + PRCSetSchool(SPELL_SCHOOL_ABJURATION); + if (!X2PreSpellCastCode()) return; + + object oCaster = OBJECT_SELF; + //object oTarget = PRCGetSpellTargetObject(); + object oTarget = OBJECT_SELF; //:: for testing + + int nCasterLevel = PRCGetCasterLevel(oCaster); + //int nSpellID = PRCGetSpellId(); + int nSpellID = RESISTANCE_ITEM_FORTITUDE; + + // Calculate resistance bonus: +1 +1 per 4 caster levels + int nBonus = 1 + (nCasterLevel / 4); + + // Calculate duration: 10 minutes per level + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + // Add fallback for very small durations + if (fDuration <= 1.0) fDuration = 30.0f; // 30 seconds is fine for testing + + // Determine save type based on infusion spellID + int nSaveType; + string sSaveName; + + switch(nSpellID) + { + case RESISTANCE_ITEM_FORTITUDE: + nSaveType = SAVING_THROW_FORT; + sSaveName = "Fortitude"; + break; + case RESISTANCE_ITEM_REFLEX: + nSaveType = SAVING_THROW_REFLEX; + sSaveName = "Reflex"; + break; + case RESISTANCE_ITEM_WILL: + nSaveType = SAVING_THROW_WILL; + sSaveName = "Will"; + break; + default: + FloatingTextStringOnCreature("Invalid resistance spell type.", oCaster, FALSE); + return; + } + + object oItem; + + // Handle targeting + if(GetObjectType(oTarget) == OBJECT_TYPE_ITEM) + { + oItem = oTarget; + } + else if(GetObjectType(oTarget) == OBJECT_TYPE_CREATURE) + { + oItem = GetFirstNonMagicalItem(oTarget); + if(!GetIsObjectValid(oItem)) + { + FloatingTextStringOnCreature(GetName(oTarget) + " has no non-magical items to infuse.", oCaster, FALSE); + return; + } + } + else + { + FloatingTextStringOnCreature("Invalid target. Must target an item or creature.", oCaster, FALSE); + return; + } + + // Validate item + if(!GetIsObjectValid(oItem)) + { + FloatingTextStringOnCreature("Invalid item target.", oCaster, FALSE); + return; + } + + if(GetPlotFlag(oItem)) + { + FloatingTextStringOnCreature("Cannot infuse plot items.", oCaster, FALSE); + return; + } + + if(GetIsItemMagical(oItem)) + { + FloatingTextStringOnCreature(GetName(oItem) + " is already magical. Can only infuse non-magical items.", oCaster, FALSE); + return; + } + + // Check for existing resistance infusion to prevent stacking + itemproperty ipExisting = GetFirstItemProperty(oItem); + while(GetIsItemPropertyValid(ipExisting)) + { + if(GetItemPropertyTag(ipExisting) == "ResistanceInfusion") + { + FloatingTextStringOnCreature(GetName(oItem) + " already has a resistance infusion.", oCaster, FALSE); + return; + } + ipExisting = GetNextItemProperty(oItem); + } + + // Create and apply the resistance bonus property + itemproperty ip = ItemPropertyBonusSavingThrow(nSaveType, nBonus); + ip = TagItemProperty(ip, "ResistanceInfusion"); + IPSafeAddItemProperty(oItem, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + FloatingTextStringOnCreature(sSaveName + " resistance +" + IntToString(nBonus) + " applied to " + GetName(oItem) + ".", oCaster, FALSE); +} \ No newline at end of file diff --git a/nwn/nwnprc/trunk/newspellbook/inf_weapon_aug.nss b/nwn/nwnprc/trunk/newspellbook/inf_weapon_aug.nss new file mode 100644 index 00000000..d3b65552 --- /dev/null +++ b/nwn/nwnprc/trunk/newspellbook/inf_weapon_aug.nss @@ -0,0 +1,709 @@ +// inf_weapon_aug.nss +/* +Weapon Augmentation, Personal +Transmutation +Level: Artificer 1 +Components: S, M +Casting Time: 1 minute +Range: Touch +Target: Weapon touched +Duration: 10 min./level +Saving Throw: None (object) +Spell Resistance: No (object) + +The weapon you touch temporarily gains a special ability commonly +found on magic weapons. You can choose any special ability whose +market price is equivalent to a +1 bonus or up to 10,000 gp, such as +flaming or keen. The weapon does not have to have an existing +enhancement bonus, nor does it gain one when you imbue it with this +infusion. The weapon gains the benefit of the infusion only if you +wield, throw, or fire it. + +Material Component: A patch of rabbit's fur. + +Weapon Augmentation, Lesser +Transmutation +Level: Artificer 2 +Duration: 10 min./level + +Target: One weapon or fifty projectiles, all of which must be in +contact with each other at the time of casting As personal weapon +augmentation, but any character can wield the weapon you augment. +Alternatively, you can affect as many as fifty arrows, bolts, or +bullets. The projectiles must be of the same kind, and they have to be +together (in the same quiver or other container). Projectiles, but +not thrown weapons, lose their transmutation when used. (Treat +shuriken as projectiles rather than thrown weapons for the purpose of +this spell.) + +Material Component: An ointment made from rare spices and minerals, costing 20 gp. + + + +Weapon Augmentation +Transmutation +Level: Artificer 4 + +As lesser weapon augmentation, but you can choose any special ability +whose market price is equivalent to a bonus of up to +3 or up to +70,000 gp, such as speed. + +Material Component: An ointment costing 100 gp. + +*/ +#include "inc_debug" +#include "prc_craft_inc" +#include "inc_dynconv" + +// Placeholder magic numbers for spell IDs +const int WEAPON_AUG_PER = 6001; +const int WEAPON_AUG_LESS = 6002; +const int WEAPON_AUG = 6003; +const int WEAPON_AUG_GREATER = 6004; + +// Define constants (these are standard in the crafting system) +const int CHOICE_BACK = -1; + +// Dynamic conversation stages +const int STAGE_PROPERTY_SELECTION = 0; +const int STAGE_BANE = 1; // Match crafting system naming +const int STAGE_CONFIRMATION = 2; + +// Helper functions for sorted lists +void AddToTempList(object oPC, string sChoice, int nChoice) +{ + // Simple implementation - just add directly + AddChoice(sChoice, nChoice, oPC); +} + +void TransferTempList(object oPC) +{ + // No-op for simple implementation +} + +//Adds names to a list based on sTable (2da), delayed recursion to avoid TMI +void PopulateList(object oPC, int MaxValue, int bSort, string sTable, int i = 0) +{ + if(GetLocalInt(oPC, "DynConv_Waiting") == FALSE) + return; + + if(i <= MaxValue) + { + string sTemp = Get2DACache(sTable, "Name", i); + if(sTemp != "") + { + if(bSort) + AddToTempList(oPC, ActionString(GetStringByStrRef(StringToInt(sTemp))), i); + else + AddChoice(ActionString(GetStringByStrRef(StringToInt(sTemp))), i, oPC); + } + + if(!(i % 100) && i) //i != 0, i % 100 == 0 + FloatingTextStringOnCreature("*Tick*", oPC, FALSE); + } + else + { + if(bSort) TransferTempList(oPC); + DeleteLocalInt(oPC, "DynConv_Waiting"); + FloatingTextStringOnCreature("*Done*", oPC, FALSE); + return; + } + DelayCommand(0.01, PopulateList(oPC, MaxValue, bSort, sTable, i + 1)); +} + + + +void HandleConversation(object oPC, object oWeapon, int nMaxEnhancement, int nMaxCost, string sLocalVar, int nSpellID, int nCasterLevel) +{ + int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE); + int nStage = GetStage(oPC); + + if(nValue == 0) return; + + if(nValue == DYNCONV_SETUP_STAGE) + { + if(!GetIsStageSetUp(nStage, oPC)) + { + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Set header first + SetHeader("Select a weapon augmentation:"); + + // Initialize default tokens BEFORE adding choices + SetDefaultTokens(); + + int nFileEnd = PRCGetFileEnd("craft_weapon"); + int nChoice = 1; + int i; + + for(i = 0; i <= nFileEnd; i++) + { + // Get enhancement and cost for this specific line + int nEnhancement = StringToInt(Get2DACache("craft_weapon", "Enhancement", i)); + int nAdditionalCost = StringToInt(Get2DACache("craft_weapon", "AdditionalCost", i)); + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_weapon", "Name", i))); + + // Debug output + SendMessageToPC(oPC, "Line " + IntToString(i) + ": " + sName + " (Enh:" + IntToString(nEnhancement) + ", Cost:" + IntToString(nAdditionalCost) + ")"); + + // Check if this property is within limits + if(nEnhancement <= nMaxEnhancement && nAdditionalCost <= nMaxCost) + { + AddChoice(sName, i, oPC); + nChoice++; + } + } + + MarkStageSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_BANE) + { + // Exact copy from crafting system + SetHeader("Select a racial type."); + AllowExit(DYNCONV_EXIT_NOT_ALLOWED, FALSE, oPC); + AddChoice(ActionString("Back"), CHOICE_BACK, oPC); + SetLocalInt(oPC, "DynConv_Waiting", TRUE); + PopulateList(oPC, PRCGetFileEnd("racialtypes"), TRUE, "racialtypes"); + MarkStageSetUp(nStage); + } + else if(nStage == STAGE_CONFIRMATION) + { + int nPropertyLine = GetLocalInt(oPC, "WeaponAug_SelectedProperty"); + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_weapon", "Name", nPropertyLine))); + + SetHeader("Apply " + sName + " to the weapon?"); + + AddChoice("Yes", TRUE, oPC); + AddChoice("No", FALSE, oPC); + + MarkStageSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetupTokens(); + } + else if(nValue == DYNCONV_EXITED) + { + // Cleanup + DeleteLocalInt(oPC, "WeaponAug_ConvMode"); + DeleteLocalObject(oPC, "WEAPON_AUG_TARGET"); + DeleteLocalInt(oPC, "WeaponAug_SelectedProperty"); + DeleteLocalInt(oPC, PRC_CRAFT_SPECIAL_BANE_RACE); + } + else if(nValue == DYNCONV_ABORTED) + { + // Cleanup + DeleteLocalInt(oPC, "WeaponAug_ConvMode"); + DeleteLocalObject(oPC, "WEAPON_AUG_TARGET"); + DeleteLocalInt(oPC, "WeaponAug_SelectedProperty"); + DeleteLocalInt(oPC, PRC_CRAFT_SPECIAL_BANE_RACE); + } + else + { + int nChoice = GetChoice(oPC); + + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Store selection and check if Bane/Dread + SetLocalInt(oPC, "WeaponAug_SelectedProperty", nChoice); + if(nChoice == 26 || nChoice == 27) // Bane or Dread + { + nStage = STAGE_BANE; + } + else + { + nStage = STAGE_CONFIRMATION; + } + MarkStageNotSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_BANE) + { + // Exact copy from crafting system logic + if(nChoice == CHOICE_BACK) + nStage = STAGE_PROPERTY_SELECTION; + else + { + nStage = STAGE_CONFIRMATION; + SetLocalInt(oPC, PRC_CRAFT_SPECIAL_BANE_RACE, nChoice); + } + MarkStageNotSetUp(nStage, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + if(nChoice == TRUE) // User confirmed + { + // Apply the property + object oWeapon = GetLocalObject(oPC, "WEAPON_AUG_TARGET"); + int nPropertyLine = GetLocalInt(oPC, "WeaponAug_SelectedProperty"); + int nCasterLevel = GetLocalInt(oPC, "WeaponAug_CasterLevel"); + + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + // Debug output + SendMessageToPC(oPC, "Duration: " + FloatToString(fDuration) + " seconds"); + + // Add fallback for very small durations + if (fDuration <= 1.0) fDuration = 30.0f; + + SendMessageToPC(oPC, "Fallback Duration: " + FloatToString(fDuration) + " seconds"); + + // Create property with special handling for Bane/Dread + itemproperty ip; + if(nPropertyLine == 26 || nPropertyLine == 27) // Bane or Dread + { + // Use the special handling function from the crafting system + ip = PropSpecialHandling(oWeapon, "craft_weapon", nPropertyLine, 1); + } + else + { + // Standard property construction + string sIPData = Get2DACache("craft_weapon", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + } + + // Apply with proper duration + ip = TagItemProperty(ip, "WeaponAugInfusion"); + IPSafeAddItemProperty(oWeapon, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + // Clean up and exit + DeleteLocalInt(oPC, "WeaponAug_ConvMode"); + DeleteLocalObject(oPC, "WEAPON_AUG_TARGET"); + DeleteLocalInt(oPC, "WeaponAug_SelectedProperty"); + DeleteLocalInt(oPC, PRC_CRAFT_SPECIAL_BANE_RACE); + + AllowExit(DYNCONV_EXIT_FORCE_EXIT); + } + else // User cancelled + { + // Go back to property selection or BANE stage + if(GetLocalInt(oPC, PRC_CRAFT_SPECIAL_BANE_RACE)) + { + nStage = STAGE_BANE; + DeleteLocalInt(oPC, PRC_CRAFT_SPECIAL_BANE_RACE); + } + else + { + nStage = STAGE_PROPERTY_SELECTION; + } + MarkStageNotSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetStage(nStage, oPC); + } +} + +void main() +{ + object oPC = GetPCSpeaker(); + if(!GetIsObjectValid(oPC)) oPC = OBJECT_SELF; + + // Check if we're in conversation mode + if(GetLocalInt(oPC, "WeaponAug_ConvMode")) + { + // Retrieve parameters for conversation + object oWeapon = GetLocalObject(oPC, "WEAPON_AUG_TARGET"); + int nMaxEnhancement = GetLocalInt(oPC, "WeaponAug_MaxEnh"); + int nMaxCost = GetLocalInt(oPC, "WeaponAug_MaxCost"); + string sLocalVar = GetLocalString(oPC, "WeaponAug_LocalVar"); + int nSpellID = GetLocalInt(oPC, "WeaponAug_SpellID"); + int nCasterLevel = GetLocalInt(oPC, "WeaponAug_CasterLevel"); + + HandleConversation(oPC, oWeapon, nMaxEnhancement, nMaxCost, sLocalVar, nSpellID, nCasterLevel); + return; + } + + // Normal spell execution + PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION); + if (!X2PreSpellCastCode()) return; + + object oCaster = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + int nCasterLevel = PRCGetCasterLevel(oCaster); + int nSpellID = PRCGetSpellId(); + + // Declare variables + int nGoldCost, nMaxEnhancement, nMaxCost; + string sLocalVar; + + // Set parameters based on spell level + switch(nSpellID) + { + case WEAPON_AUG_PER: + nGoldCost = 0; + nMaxEnhancement = 1; + nMaxCost = 10000; + sLocalVar = "WEAPON_AUG_PER_PROPERTY"; + break; + case WEAPON_AUG_LESS: + nGoldCost = 20; + nMaxEnhancement = 1; + nMaxCost = 10000; + sLocalVar = "WEAPON_AUG_LESS_PROPERTY"; + break; + case WEAPON_AUG: + nGoldCost = 100; + nMaxEnhancement = 3; + nMaxCost = 70000; + sLocalVar = "WEAPON_AUG_PROPERTY"; + break; + case WEAPON_AUG_GREATER: + nGoldCost = 200; + nMaxEnhancement = 5; + nMaxCost = 200000; + sLocalVar = "WEAPON_AUG_GREATER_PROPERTY"; + break; + default: + // Default to lesser version for testing + nGoldCost = 20; + nMaxEnhancement = 1; + nMaxCost = 10000; + sLocalVar = "WEAPON_AUG_LESS_PROPERTY"; + break; + } + + // Check material component + if(GetGold(oCaster) < nGoldCost) + { + FloatingTextStringOnCreature("You need " + IntToString(nGoldCost) + "gp worth of rare ointments.", oCaster, FALSE); + return; + } + + // Get targeted weapon + object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCaster); + //object oWeapon = IPGetTargetedOrEquippedArmor(TRUE); <- don't delete + if(!GetIsObjectValid(oWeapon)) + { + FloatingTextStrRefOnCreature(83826, oCaster, FALSE); // "Invalid target" + return; + } + + // Check if returning from conversation with a selection + int nPropertyLine = GetLocalInt(oCaster, sLocalVar); + if(nPropertyLine > 0) + { + // Apply the property + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + if (fDuration <= 1.0) fDuration = 30.0f; + + // Read property data from 2DA and construct + string sIPData = Get2DACache("craft_weapon", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + itemproperty ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + + + // Apply with proper duration + ip = TagItemProperty(ip, "WeaponAugInfusion"); + IPSafeAddItemProperty(oWeapon, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + DeleteLocalInt(oCaster, sLocalVar); + return; + } + + // Store parameters for conversation and start it + SetLocalInt(oPC, "WeaponAug_ConvMode", 1); + SetLocalObject(oPC, "WEAPON_AUG_TARGET", oWeapon); + SetLocalInt(oPC, "WeaponAug_MaxEnh", nMaxEnhancement); + SetLocalInt(oPC, "WeaponAugh_MaxCost", nMaxCost); + SetLocalString(oPC, "WeaponAug_LocalVar", sLocalVar); + SetLocalInt(oPC, "WeaponAug_SpellID", nSpellID); + SetLocalInt(oPC, "WeaponAug_CasterLevel", nCasterLevel); + + // Start the dynamic conversation using this same script + StartDynamicConversation("inf_weapon_aug", oPC, 0, FALSE, TRUE); +} + + + + + + + + + + + + +/* #include "inc_debug" +#include "prc_craft_inc" +#include "inc_dynconv" + +// Placeholder magic numbers for spell IDs +const int WEAPON_AUG_PER = 6001; +const int WEAPON_AUG_LESS = 6002; +const int WEAPON_AUG = 6003; +const int WEAPON_AUG_GREATER = 6004; + + +// Dynamic conversation stages +const int STAGE_PROPERTY_SELECTION = 0; +const int STAGE_CONFIRMATION = 1; + + +void HandleConversation(object oPC, object oWeapon, int nMaxEnhancement, int nMaxCost, string sLocalVar, int nSpellID, int nCasterLevel) +{ + int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE); + int nStage = GetStage(oPC); + + if(nValue == 0) return; + + if(nValue == DYNCONV_SETUP_STAGE) + { + if(!GetIsStageSetUp(nStage, oPC)) + { + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Set header first + SetHeader("Select a weapon augmentation:"); + + // Initialize default tokens BEFORE adding choices + SetDefaultTokens(); + + int nFileEnd = PRCGetFileEnd("craft_weapon"); + int nChoice = 1; + int i; + + for(i = 0; i <= nFileEnd; i++) + { + // Get enhancement and cost for this specific line + int nEnhancement = StringToInt(Get2DACache("craft_weapon", "Enhancement", i)); + int nAdditionalCost = StringToInt(Get2DACache("craft_weapon", "AdditionalCost", i)); + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_weapon", "Name", i))); + + // Debug output + SendMessageToPC(oPC, "Line " + IntToString(i) + ": " + sName + " (Enh:" + IntToString(nEnhancement) + ", Cost:" + IntToString(nAdditionalCost) + ")"); + + // Check if this property is within limits + if(nEnhancement <= nMaxEnhancement && nAdditionalCost <= nMaxCost) + { + AddChoice(sName, i, oPC); + nChoice++; + } + } + + MarkStageSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + int nPropertyLine = GetLocalInt(oPC, "WeaponAug_SelectedProperty"); + string sName = GetStringByStrRef(StringToInt(Get2DACache("craft_weapon", "Name", nPropertyLine))); + + SetHeader("Apply " + sName + " to the weapon?"); + + AddChoice("Yes", TRUE, oPC); + AddChoice("No", FALSE, oPC); + + MarkStageSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetupTokens(); + } + else if(nValue == DYNCONV_EXITED) + { + // Cleanup + DeleteLocalInt(oPC, "WeaponAug_ConvMode"); + DeleteLocalObject(oPC, "WEAPON_AUG_TARGET"); + DeleteLocalInt(oPC, "WeaponAug_SelectedProperty"); + } + else if(nValue == DYNCONV_ABORTED) + { + // Cleanup + DeleteLocalInt(oPC, "WeaponAug_ConvMode"); + DeleteLocalObject(oPC, "WEAPON_AUG_TARGET"); + DeleteLocalInt(oPC, "WeaponAug_SelectedProperty"); + } + else + { + int nChoice = GetChoice(oPC); + + if(nStage == STAGE_PROPERTY_SELECTION) + { + // Store selection and go to confirmation + SetLocalInt(oPC, "WeaponAug_SelectedProperty", nChoice); + nStage = STAGE_CONFIRMATION; + MarkStageNotSetUp(STAGE_PROPERTY_SELECTION, oPC); + } + else if(nStage == STAGE_CONFIRMATION) + { + if(nChoice == TRUE) // User confirmed + { + // Apply the property + object oWeapon = GetLocalObject(oPC, "WEAPON_AUG_TARGET"); + int nPropertyLine = GetLocalInt(oPC, "WeaponAug_SelectedProperty"); + int nCasterLevel = GetLocalInt(oPC, "WeaponAug_CasterLevel"); + + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + // Debug output + SendMessageToPC(oPC, "Duration: " + FloatToString(fDuration) + " seconds"); + + // Add fallback for very small durations + if (fDuration <= 1.0) fDuration = 30.0f; + + SendMessageToPC(oPC, "Fallback Duration: " + FloatToString(fDuration) + " seconds"); + + // Create property directly + itemproperty ip; + // Read property data from 2DA and construct + string sIPData = Get2DACache("craft_weapon", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + + // Apply with proper duration + ip = TagItemProperty(ip, "WeaponAugInfusion"); + IPSafeAddItemProperty(oWeapon, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + // Clean up and exit + DeleteLocalInt(oPC, "WeaponAug_ConvMode"); + DeleteLocalObject(oPC, "WEAPON_AUG_TARGET"); + DeleteLocalInt(oPC, "WeaponAug_SelectedProperty"); + + AllowExit(DYNCONV_EXIT_FORCE_EXIT); + } + else // User cancelled + { + // Go back to property selection + nStage = STAGE_PROPERTY_SELECTION; + MarkStageNotSetUp(STAGE_CONFIRMATION, oPC); + } + } + + SetStage(nStage, oPC); + } +} + +void main() +{ + object oPC = GetPCSpeaker(); + if(!GetIsObjectValid(oPC)) oPC = OBJECT_SELF; + + // Check if we're in conversation mode + if(GetLocalInt(oPC, "WeaponAug_ConvMode")) + { + // Retrieve parameters for conversation + object oWeapon = GetLocalObject(oPC, "WEAPON_AUG_TARGET"); + int nMaxEnhancement = GetLocalInt(oPC, "WeaponAug_MaxEnh"); + int nMaxCost = GetLocalInt(oPC, "WeaponAug_MaxCost"); + string sLocalVar = GetLocalString(oPC, "WeaponAug_LocalVar"); + int nSpellID = GetLocalInt(oPC, "WeaponAug_SpellID"); + int nCasterLevel = GetLocalInt(oPC, "WeaponAug_CasterLevel"); + + HandleConversation(oPC, oWeapon, nMaxEnhancement, nMaxCost, sLocalVar, nSpellID, nCasterLevel); + return; + } + + // Normal spell execution + PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION); + if (!X2PreSpellCastCode()) return; + + object oCaster = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + int nCasterLevel = PRCGetCasterLevel(oCaster); + int nSpellID = PRCGetSpellId(); + + // Declare variables + int nGoldCost, nMaxEnhancement, nMaxCost; + string sLocalVar; + + // Set parameters based on spell level + switch(nSpellID) + { + case WEAPON_AUG_PER: + nGoldCost = 0; + nMaxEnhancement = 1; + nMaxCost = 10000; + sLocalVar = "WEAPON_AUG_PER_PROPERTY"; + break; + case WEAPON_AUG_LESS: + nGoldCost = 20; + nMaxEnhancement = 1; + nMaxCost = 10000; + sLocalVar = "WEAPON_AUG_LESS_PROPERTY"; + break; + case WEAPON_AUG: + nGoldCost = 100; + nMaxEnhancement = 3; + nMaxCost = 70000; + sLocalVar = "WEAPON_AUG_PROPERTY"; + break; + case WEAPON_AUG_GREATER: + nGoldCost = 200; + nMaxEnhancement = 5; + nMaxCost = 200000; + sLocalVar = "WEAPON_AUG_GREATER_PROPERTY"; + break; + default: + // Default to lesser version for testing + nGoldCost = 20; + nMaxEnhancement = 1; + nMaxCost = 10000; + sLocalVar = "WEAPON_AUG_LESS_PROPERTY"; + break; + } + + // Check material component + if(GetGold(oCaster) < nGoldCost) + { + FloatingTextStringOnCreature("You need " + IntToString(nGoldCost) + "gp worth of rare ointments.", oCaster, FALSE); + return; + } + + // Get targeted weapon + object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCaster); + //object oWeapon = IPGetTargetedOrEquippedArmor(TRUE); <- don't delete + if(!GetIsObjectValid(oWeapon)) + { + FloatingTextStrRefOnCreature(83826, oCaster, FALSE); // "Invalid target" + return; + } + + // Check if returning from conversation with a selection + int nPropertyLine = GetLocalInt(oCaster, sLocalVar); + if(nPropertyLine > 0) + { + // Apply the property + float fDuration = TurnsToSeconds(nCasterLevel * 10); + int nMetaMagic = PRCGetMetaMagicFeat(); + if(nMetaMagic & METAMAGIC_EXTEND) + fDuration *= 2; + + if (fDuration <= 1.0) fDuration = 30.0f; + + // Read property data from 2DA and construct + string sIPData = Get2DACache("craft_weapon", "IP1", nPropertyLine); + struct ipstruct iptemp = GetIpStructFromString(sIPData); + itemproperty ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value); + + + // Apply with proper duration + ip = TagItemProperty(ip, "WeaponAugInfusion"); + IPSafeAddItemProperty(oWeapon, ip, fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); + + DeleteLocalInt(oCaster, sLocalVar); + return; + } + + // Store parameters for conversation and start it + SetLocalInt(oPC, "WeaponAug_ConvMode", 1); + SetLocalObject(oPC, "WEAPON_AUG_TARGET", oWeapon); + SetLocalInt(oPC, "WeaponAug_MaxEnh", nMaxEnhancement); + SetLocalInt(oPC, "WeaponAugh_MaxCost", nMaxCost); + SetLocalString(oPC, "WeaponAug_LocalVar", sLocalVar); + SetLocalInt(oPC, "WeaponAug_SpellID", nSpellID); + SetLocalInt(oPC, "WeaponAug_CasterLevel", nCasterLevel); + + // Start the dynamic conversation using this same script + StartDynamicConversation("inf_weapon_aug", oPC, 0, FALSE, TRUE); +} */ \ No newline at end of file diff --git a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk index 4b410525..5fa2c724 100644 Binary files a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk and b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk differ diff --git a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml index 88d29676..e32706b7 100644 --- a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml +++ b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml @@ -76267,8 +76267,19 @@ Throwing Axes Truenamer4 Truenamer5 Truenamer5 - Warblade1 - Warblade1 + Warblade (Default) + (STARTING PACKAGE) + +The default package focuses on improving strength and proficiency with the longsword.. + +Equipment: +Torch +Scale Armor +Large Shield +Longsword +Shortbow +(3) sets of arrows +(3) Healer's Kits Warblade2 Warblade2 Warblade3 diff --git a/nwn/nwnprc/trunk/tlk/prc_consortium.tlk b/nwn/nwnprc/trunk/tlk/prc_consortium.tlk index 4b410525..5fa2c724 100644 Binary files a/nwn/nwnprc/trunk/tlk/prc_consortium.tlk and b/nwn/nwnprc/trunk/tlk/prc_consortium.tlk differ diff --git a/nwn/nwnprc/trunk/users/Jaysyn/artificer_infusions.csv b/nwn/nwnprc/trunk/users/Jaysyn/artificer_infusions.csv new file mode 100644 index 00000000..741db0a7 --- /dev/null +++ b/nwn/nwnprc/trunk/users/Jaysyn/artificer_infusions.csv @@ -0,0 +1,35 @@ +Name,Infusion Level,Spell School,Components,Description, +Ablative Armor,Artificer 1,Abjuration,"S, M (shard of scrap metal)","Infuses armor to absorb 5 damage from the next attack (like DR 5/-), increasing by 1 per caster level (to a maximum of 15)", +"Armor Enhancement, Lesser",Artificer 1,Transmutation,"S, M (ointment of rare spices, 10 gp)",Grants a suit of armor or shield resistance 10 to one energy type (as with Protection from Energy) for 10 min/level when worn by a construct:contentReference, +Energy Alteration,Artificer 1,Transmutation,An alchemical ointment formed from materials representing all five energy types and costing 50 gp.,"You alter an item that employs an energy type or grants protection from an energy type, to employ or protect against a different energy type. ", +Enhancement Alteration,Artificer 1,Transmutation,,, +Identify,Artificer 1,,,, +Indisputable Possession,Artificer 1,Conjuration (Teleportation),"V, S","Creates a bond to a touched object: if it leaves your possession, you can call it back to your hand as a move action (a creature holding it gets a Will save to resist)", +Pending Potion,Artificer 1,Transmutation,"S, M (needles from an evergreen tree)",Destroys a prepared potion to delay its effect; the potion’s effect occurs up to 1 minute later when the caster speaks its name, +"Weapon Augmentation, Personal",Artificer 1,Transmutation,"S, M (ivy leaves and berries)","Gives a weapon one special ability up to +1 bonus (such as Flaming or Keen) for 10 min/level, only uable by caster.", +Lucky Blade,Artificer 2,Abjuration,"S, M (two-headed coin)",Imbues a weapon to let its wielder once reroll an attack roll (or critical confirmation) and must take the new result, +Reinforce Construct,Artificer 2,Transmutation,"V, S",Grants a target construct 1d6+1 temporary hit points per level (max +10) that last until the end of the next round, +Suppress Dragonmark,Artificer 2,Abjuration,"S, F (25 gp inversely charged Siberys shard)","An inversely attuned Siberys shard absorbs a creature’s dragonmark energy, preventing that target from using any dragonmark spell-like abilities for 24 hours (Will negates)", +"Weapon Augmentation, Lesser",Artificer 2,Transmutation,"S, M (ivy leaves and berries)",Gives a weapon one special ability up to +1 bonus (such as Flaming or Keen) for 10 min/level, +Adamantine Weapon,Artificer 3,Transmutation,"S, M (powdered adamantine)","Temporarily turns a metal weapon into adamantine for 10 min/level, letting it bypass hardness and ignore other special materials", +"Armor Enhancement, Greater",Artificer 3,Transmutation,"S, M (ointment of rare spices, 50 gp)","Grants a suit of armor or shield one special quality (equivalent to a +1 enhancement, e.g. light fortification) for 10 min/level", +Blast Rod,Artificer 3,Evocation,"S, F (rod to be infused)","Stores up to 1d8 per level of energy (max 10d8) in a rod, which can later be released as one or more ranged touch attack blasts", +Construct Energy Ward,Artificer 3,Abjuration,"S, M (ointment, 100 gp)",Grants a construct resistance 10 to a specified energy type for 10 min/level (as with Protection from that energy), +Lucky Cape,Artificer 3,Abjuration,"S, M (two-headed coin)",Imbues a cloak to let its wearer once reroll a saving throw and must take the new result, +Spell Snare,Artificer 3,Abjuration,"S, M (Eberron dragonshard 25 gp)",Enchants a dragonshard to absorb the next spell or spell-like ability of 3rd level or lower targeting its bearer; the spell is negated and the shard is destroyed., +Total Repair,Artificer 3,Conjuration (Healing),"V, S",Repairs 10 points per level of damage to a construct (as if casting Repair Serious Damage multiple times), +Censure Elementals,Artificer 4,Abjuration,"S, M (kiln-hardened mud)",Imbues a held item so that all elementals within 20 ft take 2d4+1/level damage each round while it is wielded (Will halves; max +15), +Concurrent Infusions,Artificer 4,Transmutation,"S, M (oak twig with three forks)",Allows you to imbue an object with three chosen 1st-level infusions at once; these do not count against your daily infusion uses, +"Construct Energy Ward, Greater",Artificer 4,Abjuration,"S, M (ointment, 100 gp)","As lesser ward, but also grants one chosen special ability (up to +5 bonus value, e.g. etherealness) to the construct", +Repair Serious Damage,Artificer 4,Conjuration (Healing),"V, S",Restores 3d8+1 per level (max +15) hit points to a construct:contentReference[oaicite:22]{index=22}., +Stone Construct,Artificer 4,Transmutation,"V, S",Turns a target into a living stone construct: it gains DR 10/adamantine and other construct traits, +Suppress Requirement,Artificer 4,Transmutation,"V, S","Removes a specific prerequisite (class, race, alignment, etc.) from an item so it functions fully without it.", +"Weapon Augmentation, Greater",Artificer 4,Transmutation,"S, M (ointment, 200 gp)",Gives a weapon one special ability up to +5 bonus (such as Vorpal) for 10 min/level:contentReference., +Hardening,Artificer 5,Transmutation,"V, S",Increases an item’s hardness by 1 for every 2 caster levels of the infusion:contentReference, +Iron Construct,Artificer 5,Transmutation,"V, S",Enhances a construct: it gains DR 15/adamantine and takes only half normal damage from acid and fire, +Item Alteration,Artificer 5,Transmutation,"V, S",Changes an item’s granted bonus type: the item provides one type of bonus instead of another of equal value (e.g. a Strength bonus instead of a Dexterity bonus), +Slaying Arrow,Artificer 5,Transmutation,"S, M (drop of viper blood)","Imbues an arrow or bolt keyed to a chosen creature type: it gains +1 enhancement bonus, and a creature of that type struck must make a Fortitude save or be slain (undead/construct are also affected)", +Repair Critical Damage,Artificer 6,Conjuration (Healing),"V, S",Restores 4d8+1 per level (max +20) hit points to a construct:contentReference, +Rusting Grasp,Artificer 6,Transmutation,"V, S",Your touch causes metal to corrode: hit metal weapons or armor take 1d6 acid damage and may be destroyed on contact, +"Shield of Faith, Legions",Artificer 6,Abjuration,"V, S",Grants all allies within 30 feet a +3 sacred bonus to Armor Class, +"Spell Snare, Greater",Artificer 6,Abjuration,"S, M (Eberron dragonshard 100 gp)","As Spell Snare, but absorbs spells or abilities up to 6th level",