2025/06/22 Update
Fixed Vow of Poverty. Fixed Vow of Poverty bonus feats not being restored onClientEnter. Added PRC option for spontaneous casters unlearning spells (@Rakiov) Gloura was double dipping caster level. Added NUI levelup spellpicker for most AMS classes (@Rakiov) Tweaked Tactical Insight. Updated ToB maneuver TLK entries to display correct prerequisites.
This commit is contained in:
parent
4ae73d0f45
commit
a882749366
@ -1,63 +1,63 @@
|
||||
2DA V2.0
|
||||
|
||||
Bonus
|
||||
0 0
|
||||
1 0
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
5 0
|
||||
6 0
|
||||
7 0
|
||||
8 0
|
||||
9 0
|
||||
10 0
|
||||
11 0
|
||||
12 0
|
||||
13 1
|
||||
14 0
|
||||
15 0
|
||||
16 0
|
||||
17 1
|
||||
18 0
|
||||
19 0
|
||||
20 0
|
||||
21 1
|
||||
22 0
|
||||
23 0
|
||||
24 0
|
||||
25 1
|
||||
26 0
|
||||
27 0
|
||||
28 0
|
||||
29 1
|
||||
30 0
|
||||
31 0
|
||||
32 0
|
||||
33 1
|
||||
34 0
|
||||
35 0
|
||||
36 0
|
||||
37 1
|
||||
38 0
|
||||
39 0
|
||||
40 0
|
||||
41 1
|
||||
42 0
|
||||
43 0
|
||||
44 0
|
||||
45 1
|
||||
46 0
|
||||
47 0
|
||||
48 0
|
||||
49 1
|
||||
50 0
|
||||
51 0
|
||||
52 0
|
||||
53 1
|
||||
54 0
|
||||
55 0
|
||||
56 0
|
||||
57 1
|
||||
58 0
|
||||
59 0
|
||||
Bonus
|
||||
0 0
|
||||
1 0
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
5 0
|
||||
6 0
|
||||
7 0
|
||||
8 0
|
||||
9 0
|
||||
10 0
|
||||
11 0
|
||||
12 1
|
||||
13 0
|
||||
14 0
|
||||
15 1
|
||||
16 0
|
||||
17 0
|
||||
18 1
|
||||
19 0
|
||||
20 0
|
||||
21 1
|
||||
22 0
|
||||
23 0
|
||||
24 1
|
||||
25 0
|
||||
26 0
|
||||
27 1
|
||||
28 0
|
||||
29 0
|
||||
30 1
|
||||
31 0
|
||||
32 0
|
||||
33 1
|
||||
34 0
|
||||
35 0
|
||||
36 1
|
||||
37 0
|
||||
38 0
|
||||
39 1
|
||||
40 0
|
||||
41 0
|
||||
42 1
|
||||
43 0
|
||||
44 0
|
||||
45 1
|
||||
46 0
|
||||
47 0
|
||||
48 1
|
||||
49 0
|
||||
50 0
|
||||
51 1
|
||||
52 0
|
||||
53 0
|
||||
54 1
|
||||
55 0
|
||||
56 0
|
||||
57 1
|
||||
58 0
|
||||
59 0
|
||||
|
@ -1,16 +1,302 @@
|
||||
2DA V2.0
|
||||
|
||||
FeatLabel FeatIndex List GrantedOnLevel OnMenu
|
||||
0 FEAT_EPIC_BLINDING_SPEED 491 0 -1 1
|
||||
1 DefArrow 8 0 -1 0
|
||||
2 TwoWeap 41 0 -1 0
|
||||
3 Ambidex 1 0 -1 0
|
||||
4 ETBL_ManeuverQuicksel 24125 3 1 1
|
||||
5 ETBL_Blade_Guide 24126 3 1 0
|
||||
6 ETBL_Eternal_Training 24127 3 1 1
|
||||
7 ETBL_Guided_Strike 24128 3 2 1
|
||||
8 ETBL_Armored_Uncanny_Dodge 24129 3 3 0
|
||||
9 ETBL_Eternal_Knowledge 24130 3 4 0
|
||||
10 ETBL_Defensive_Insight 24131 3 5 1
|
||||
11 ETBL_Tactical_Insight 24132 3 8 1
|
||||
12 ETBL_Island_In_Time 24133 3 10 1
|
||||
FeatLabel FeatIndex List GrantedOnLevel OnMenu
|
||||
0 ETBL_ManeuverQuicksel 24125 3 1 1
|
||||
1 ETBL_Blade_Guide 24126 3 1 0
|
||||
2 ETBL_Eternal_Training 24127 3 1 1
|
||||
3 ETBL_Guided_Strike 24128 3 2 1
|
||||
4 ETBL_Armored_Uncanny_Dodge 24129 3 3 0
|
||||
5 ETBL_Eternal_Knowledge 24130 3 4 0
|
||||
6 ETBL_Defensive_Insight 24131 3 5 1
|
||||
7 ETBL_Tactical_Insight 24132 3 8 1
|
||||
8 ETBL_Island_In_Time 24133 3 10 1
|
||||
9 FEAT_EPIC_ETERNAL_BLADE 25081 3 11 0
|
||||
10 FEAT_EPIC_BLINDING_SPEED 491 1 -1 1
|
||||
11 FEAT_EPIC_GREAT_STRENGTH_1 814 1 -1 0
|
||||
12 FEAT_EPIC_GREAT_STRENGTH_2 815 1 -1 0
|
||||
13 FEAT_EPIC_GREAT_STRENGTH_3 816 1 -1 0
|
||||
14 FEAT_EPIC_GREAT_STRENGTH_4 817 1 -1 0
|
||||
15 FEAT_EPIC_GREAT_STRENGTH_5 818 1 -1 0
|
||||
16 FEAT_EPIC_GREAT_STRENGTH_6 819 1 -1 0
|
||||
17 FEAT_EPIC_GREAT_STRENGTH_7 820 1 -1 0
|
||||
18 FEAT_EPIC_GREAT_STRENGTH_8 821 1 -1 0
|
||||
19 FEAT_EPIC_GREAT_STRENGTH_9 822 1 -1 0
|
||||
20 FEAT_EPIC_GREAT_STRENGTH_10 823 1 -1 0
|
||||
21 FEAT_EPIC_GREAT_INTELLIGENCE_1 794 1 -1 0
|
||||
22 FEAT_EPIC_GREAT_INTELLIGENCE_2 795 1 -1 0
|
||||
23 FEAT_EPIC_GREAT_INTELLIGENCE_3 796 1 -1 0
|
||||
24 FEAT_EPIC_GREAT_INTELLIGENCE_4 797 1 -1 0
|
||||
25 FEAT_EPIC_GREAT_INTELLIGENCE_5 798 1 -1 0
|
||||
26 FEAT_EPIC_GREAT_INTELLIGENCE_6 799 1 -1 0
|
||||
27 FEAT_EPIC_GREAT_INTELLIGENCE_7 800 1 -1 0
|
||||
28 FEAT_EPIC_GREAT_INTELLIGENCE_8 801 1 -1 0
|
||||
29 FEAT_EPIC_GREAT_INTELLIGENCE_9 802 1 -1 0
|
||||
30 FEAT_EPIC_GREAT_INTELLIGENCE_10 803 1 -1 0
|
||||
31 FEAT_EPIC_ARMOR_SKIN 490 1 -1 0
|
||||
32 FEAT_EPIC_DAMAGE_REDUCTION_3 492 1 -1 0
|
||||
33 FEAT_EPIC_DAMAGE_REDUCTION_6 493 1 -1 0
|
||||
34 FEAT_EPIC_DAMAGE_REDUCTION_9 494 1 -1 0
|
||||
35 FEAT_EPIC_DEVASTATING_CRITICAL_CLUB 495 1 -1 0
|
||||
36 FEAT_EPIC_DEVASTATING_CRITICAL_DAGGER 496 1 -1 0
|
||||
37 FEAT_EPIC_DEVASTATING_CRITICAL_DART 497 1 -1 0
|
||||
38 FEAT_EPIC_DEVASTATING_CRITICAL_HEAVYCROSSBOW 498 1 -1 0
|
||||
39 FEAT_EPIC_DEVASTATING_CRITICAL_LIGHTCROSSBOW 499 1 -1 0
|
||||
40 FEAT_EPIC_DEVASTATING_CRITICAL_LIGHTMACE 500 1 -1 0
|
||||
41 FEAT_EPIC_DEVASTATING_CRITICAL_MORNINGSTAR 501 1 -1 0
|
||||
42 FEAT_EPIC_DEVASTATING_CRITICAL_QUARTERSTAFF 502 1 -1 0
|
||||
43 FEAT_EPIC_DEVASTATING_CRITICAL_SHORTSPEAR 503 1 -1 0
|
||||
44 FEAT_EPIC_DEVASTATING_CRITICAL_SICKLE 504 1 -1 0
|
||||
45 FEAT_EPIC_DEVASTATING_CRITICAL_SLING 505 1 -1 0
|
||||
46 FEAT_EPIC_DEVASTATING_CRITICAL_UNARMED 506 1 -1 0
|
||||
47 FEAT_EPIC_DEVASTATING_CRITICAL_LONGBOW 507 1 -1 0
|
||||
48 FEAT_EPIC_DEVASTATING_CRITICAL_SHORTBOW 508 1 -1 0
|
||||
49 FEAT_EPIC_DEVASTATING_CRITICAL_SHORTSWORD 509 1 -1 0
|
||||
50 FEAT_EPIC_DEVASTATING_CRITICAL_RAPIER 510 1 -1 0
|
||||
51 FEAT_EPIC_DEVASTATING_CRITICAL_SCIMITAR 511 1 -1 0
|
||||
52 FEAT_EPIC_DEVASTATING_CRITICAL_LONGSWORD 512 1 -1 0
|
||||
53 FEAT_EPIC_DEVASTATING_CRITICAL_GREATSWORD 513 1 -1 0
|
||||
54 FEAT_EPIC_DEVASTATING_CRITICAL_HANDAXE 514 1 -1 0
|
||||
55 FEAT_EPIC_DEVASTATING_CRITICAL_THROWINGAXE 515 1 -1 0
|
||||
56 FEAT_EPIC_DEVASTATING_CRITICAL_BATTLEAXE 516 1 -1 0
|
||||
57 FEAT_EPIC_DEVASTATING_CRITICAL_GREATAXE 517 1 -1 0
|
||||
58 FEAT_EPIC_DEVASTATING_CRITICAL_HALBERD 518 1 -1 0
|
||||
59 FEAT_EPIC_DEVASTATING_CRITICAL_LIGHTHAMMER 519 1 -1 0
|
||||
60 FEAT_EPIC_DEVASTATING_CRITICAL_LIGHTFLAIL 520 1 -1 0
|
||||
61 FEAT_EPIC_DEVASTATING_CRITICAL_WARHAMMER 521 1 -1 0
|
||||
62 FEAT_EPIC_DEVASTATING_CRITICAL_HEAVYFLAIL 522 1 -1 0
|
||||
63 FEAT_EPIC_DEVASTATING_CRITICAL_KAMA 523 1 -1 0
|
||||
64 FEAT_EPIC_DEVASTATING_CRITICAL_KUKRI 524 1 -1 0
|
||||
65 FEAT_EPIC_DEVASTATING_CRITICAL_SHURIKEN 525 1 -1 0
|
||||
66 FEAT_EPIC_DEVASTATING_CRITICAL_SCYTHE 526 1 -1 0
|
||||
67 FEAT_EPIC_DEVASTATING_CRITICAL_KATANA 527 1 -1 0
|
||||
68 FEAT_EPIC_DEVASTATING_CRITICAL_BASTARDSWORD 528 1 -1 0
|
||||
69 FEAT_EPIC_DEVASTATING_CRITICAL_DIREMACE 529 1 -1 0
|
||||
70 FEAT_EPIC_DEVASTATING_CRITICAL_DOUBLEAXE 530 1 -1 0
|
||||
71 FEAT_EPIC_DEVASTATING_CRITICAL_TWOBLADEDSWORD 531 1 -1 0
|
||||
72 FEAT_EPIC_DEVASTATING_CRITICAL_TRIDENT 1075 1 -1 0
|
||||
73 DEVASTATING_CRITICAL_LIGHT_LANCE 24673 1 -1 0
|
||||
74 DEVASTATING_CRITICAL_HEAVY_PICK 24674 1 -1 0
|
||||
75 DEVASTATING_CRITICAL_LIGHT_PICK 24675 1 -1 0
|
||||
76 DEVASTATING_CRITICAL_SAI 24676 1 -1 0
|
||||
77 DEVASTATING_CRITICAL_NUNCHAKU 24677 1 -1 0
|
||||
78 DEVASTATING_CRITICAL_FALCHION 24678 1 -1 0
|
||||
79 DEVASTATING_CRITICAL_SAP 24679 1 -1 0
|
||||
80 DEVASTATING_CRITICAL_KATAR 24680 1 -1 0
|
||||
81 DEVASTATING_CRITICAL_HEAVY_MACE 24681 1 -1 0
|
||||
82 DEVASTATING_CRITICAL_MAUL 24682 1 -1 0
|
||||
83 DEVASTATING_CRITICAL_DBL_SCIMITAR 24683 1 -1 0
|
||||
84 DEVASTATING_CRITICAL_GOAD 24684 1 -1 0
|
||||
85 DEVASTATING_CRITICAL_ELVEN_LIGHTBLADE 24703 1 -1 0
|
||||
86 DEVASTATING_CRITICAL_ELVEN_THINBLADE 24711 1 -1 0
|
||||
87 DEVASTATING_CRITICAL_ELVEN_COURTBLADE 24719 1 -1 0
|
||||
88 FEAT_EPIC_PROWESS 584 1 -1 0
|
||||
89 FEAT_EPIC_WEAPON_FOCUS_CLUB 619 1 -1 0
|
||||
90 FEAT_EPIC_WEAPON_FOCUS_DAGGER 620 1 -1 0
|
||||
91 FEAT_EPIC_WEAPON_FOCUS_DART 621 1 -1 0
|
||||
92 FEAT_EPIC_WEAPON_FOCUS_HEAVYCROSSBOW 622 1 -1 0
|
||||
93 FEAT_EPIC_WEAPON_FOCUS_LIGHTCROSSBOW 623 1 -1 0
|
||||
94 FEAT_EPIC_WEAPON_FOCUS_LIGHTMACE 624 1 -1 0
|
||||
95 FEAT_EPIC_WEAPON_FOCUS_MORNINGSTAR 625 1 -1 0
|
||||
96 FEAT_EPIC_WEAPON_FOCUS_QUARTERSTAFF 626 1 -1 0
|
||||
97 FEAT_EPIC_WEAPON_FOCUS_SHORTSPEAR 627 1 -1 0
|
||||
98 FEAT_EPIC_WEAPON_FOCUS_SICKLE 628 1 -1 0
|
||||
99 FEAT_EPIC_WEAPON_FOCUS_SLING 629 1 -1 0
|
||||
100 FEAT_EPIC_WEAPON_FOCUS_UNARMED 630 1 -1 0
|
||||
101 FEAT_EPIC_WEAPON_FOCUS_LONGBOW 631 1 -1 0
|
||||
102 FEAT_EPIC_WEAPON_FOCUS_SHORTBOW 632 1 -1 0
|
||||
103 FEAT_EPIC_WEAPON_FOCUS_SHORTSWORD 633 1 -1 0
|
||||
104 FEAT_EPIC_WEAPON_FOCUS_RAPIER 634 1 -1 0
|
||||
105 FEAT_EPIC_WEAPON_FOCUS_SCIMITAR 635 1 -1 0
|
||||
106 FEAT_EPIC_WEAPON_FOCUS_LONGSWORD 636 1 -1 0
|
||||
107 FEAT_EPIC_WEAPON_FOCUS_GREATSWORD 637 1 -1 0
|
||||
108 FEAT_EPIC_WEAPON_FOCUS_HANDAXE 638 1 -1 0
|
||||
109 FEAT_EPIC_WEAPON_FOCUS_THROWINGAXE 639 1 -1 0
|
||||
110 FEAT_EPIC_WEAPON_FOCUS_BATTLEAXE 640 1 -1 0
|
||||
111 FEAT_EPIC_WEAPON_FOCUS_GREATAXE 641 1 -1 0
|
||||
112 FEAT_EPIC_WEAPON_FOCUS_HALBERD 642 1 -1 0
|
||||
113 FEAT_EPIC_WEAPON_FOCUS_LIGHTHAMMER 643 1 -1 0
|
||||
114 FEAT_EPIC_WEAPON_FOCUS_LIGHTFLAIL 644 1 -1 0
|
||||
115 FEAT_EPIC_WEAPON_FOCUS_WARHAMMER 645 1 -1 0
|
||||
116 FEAT_EPIC_WEAPON_FOCUS_HEAVYFLAIL 646 1 -1 0
|
||||
117 FEAT_EPIC_WEAPON_FOCUS_KAMA 647 1 -1 0
|
||||
118 FEAT_EPIC_WEAPON_FOCUS_KUKRI 648 1 -1 0
|
||||
119 FEAT_EPIC_WEAPON_FOCUS_SHURIKEN 649 1 -1 0
|
||||
120 FEAT_EPIC_WEAPON_FOCUS_SCYTHE 650 1 -1 0
|
||||
121 FEAT_EPIC_WEAPON_FOCUS_KATANA 651 1 -1 0
|
||||
122 FEAT_EPIC_WEAPON_FOCUS_BASTARDSWORD 652 1 -1 0
|
||||
123 FEAT_EPIC_WEAPON_FOCUS_DIREMACE 653 1 -1 0
|
||||
124 FEAT_EPIC_WEAPON_FOCUS_DOUBLEAXE 654 1 -1 0
|
||||
125 FEAT_EPIC_WEAPON_FOCUS_TWOBLADEDSWORD 655 1 -1 0
|
||||
126 EPIC_WEAPON_FOCUS_LANCE 24613 1 -1 0
|
||||
127 EPIC_WEAPON_FOCUS_HEAVY_PICK 24614 1 -1 0
|
||||
128 EPIC_WEAPON_FOCUS_LIGHT_PICK 24615 1 -1 0
|
||||
129 EPIC_WEAPON_FOCUS_SAI 24616 1 -1 0
|
||||
130 EPIC_WEAPON_FOCUS_NUNCHAKU 24617 1 -1 0
|
||||
131 EPIC_WEAPON_FOCUS_FALCHION 24618 1 -1 0
|
||||
132 EPIC_WEAPON_FOCUS_SAP 24619 1 -1 0
|
||||
133 EPIC_WEAPON_FOCUS_KATAR 24620 1 -1 0
|
||||
134 EPIC_WEAPON_FOCUS_HEAVY_MACE 24621 1 -1 0
|
||||
135 EPIC_WEAPON_FOCUS_MAUL 24622 1 -1 0
|
||||
136 EPIC_WEAPON_FOCUS_DBL_SCIMITAR 24623 1 -1 0
|
||||
137 EPIC_WEAPON_FOCUS_GOAD 24624 1 -1 0
|
||||
138 EPIC_WEAPON_FOCUS_ELVEN_LIGHTBLADE 24698 1 -1 0
|
||||
139 EPIC_WEAPON_FOCUS_ELVEN_THINBLADE 24706 1 -1 0
|
||||
140 EPIC_WEAPON_FOCUS_ELVEN_COURTBLADE 24714 1 -1 0
|
||||
141 FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB 657 1 -1 0
|
||||
142 FEAT_EPIC_WEAPON_SPECIALIZATION_DAGGER 658 1 -1 0
|
||||
143 FEAT_EPIC_WEAPON_SPECIALIZATION_DART 659 1 -1 0
|
||||
144 FEAT_EPIC_WEAPON_SPECIALIZATION_HEAVYCROSSBOW 660 1 -1 0
|
||||
145 FEAT_EPIC_WEAPON_SPECIALIZATION_LIGHTCROSSBOW 661 1 -1 0
|
||||
146 FEAT_EPIC_WEAPON_SPECIALIZATION_LIGHTMACE 662 1 -1 0
|
||||
147 FEAT_EPIC_WEAPON_SPECIALIZATION_MORNINGSTAR 663 1 -1 0
|
||||
148 FEAT_EPIC_WEAPON_SPECIALIZATION_QUARTERSTAFF 664 1 -1 0
|
||||
149 FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTSPEAR 665 1 -1 0
|
||||
150 FEAT_EPIC_WEAPON_SPECIALIZATION_SICKLE 666 1 -1 0
|
||||
151 FEAT_EPIC_WEAPON_SPECIALIZATION_SLING 667 1 -1 0
|
||||
152 FEAT_EPIC_WEAPON_SPECIALIZATION_UNARMED 668 1 -1 0
|
||||
153 FEAT_EPIC_WEAPON_SPECIALIZATION_LONGBOW 669 1 -1 0
|
||||
154 FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTBOW 670 1 -1 0
|
||||
155 FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTSWORD 671 1 -1 0
|
||||
156 FEAT_EPIC_WEAPON_SPECIALIZATION_RAPIER 672 1 -1 0
|
||||
157 FEAT_EPIC_WEAPON_SPECIALIZATION_SCIMITAR 673 1 -1 0
|
||||
158 FEAT_EPIC_WEAPON_SPECIALIZATION_LONGSWORD 674 1 -1 0
|
||||
159 FEAT_EPIC_WEAPON_SPECIALIZATION_GREATSWORD 675 1 -1 0
|
||||
160 FEAT_EPIC_WEAPON_SPECIALIZATION_HANDAXE 676 1 -1 0
|
||||
161 FEAT_EPIC_WEAPON_SPECIALIZATION_THROWINGAXE 677 1 -1 0
|
||||
162 FEAT_EPIC_WEAPON_SPECIALIZATION_BATTLEAXE 678 1 -1 0
|
||||
163 FEAT_EPIC_WEAPON_SPECIALIZATION_GREATAXE 679 1 -1 0
|
||||
164 FEAT_EPIC_WEAPON_SPECIALIZATION_HALBERD 680 1 -1 0
|
||||
165 FEAT_EPIC_WEAPON_SPECIALIZATION_LIGHTHAMMER 681 1 -1 0
|
||||
166 FEAT_EPIC_WEAPON_SPECIALIZATION_LIGHTFLAIL 682 1 -1 0
|
||||
167 FEAT_EPIC_WEAPON_SPECIALIZATION_WARHAMMER 683 1 -1 0
|
||||
168 FEAT_EPIC_WEAPON_SPECIALIZATION_HEAVYFLAIL 684 1 -1 0
|
||||
169 FEAT_EPIC_WEAPON_SPECIALIZATION_KAMA 685 1 -1 0
|
||||
170 FEAT_EPIC_WEAPON_SPECIALIZATION_KUKRI 686 1 -1 0
|
||||
171 FEAT_EPIC_WEAPON_SPECIALIZATION_SHURIKEN 687 1 -1 0
|
||||
172 FEAT_EPIC_WEAPON_SPECIALIZATION_SCYTHE 688 1 -1 0
|
||||
173 FEAT_EPIC_WEAPON_SPECIALIZATION_KATANA 689 1 -1 0
|
||||
174 FEAT_EPIC_WEAPON_SPECIALIZATION_BASTARDSWORD 690 1 -1 0
|
||||
175 FEAT_EPIC_WEAPON_SPECIALIZATION_DIREMACE 691 1 -1 0
|
||||
176 FEAT_EPIC_WEAPON_SPECIALIZATION_DOUBLEAXE 692 1 -1 0
|
||||
177 FEAT_EPIC_WEAPON_SPECIALIZATION_TWOBLADEDSWORD 693 1 -1 0
|
||||
178 EPIC_WEAPON_SPECIALIZATION_LIGHT_LANCE 24637 1 -1 0
|
||||
179 EPIC_WEAPON_SPECIALIZATION_HEAVY_PICK 24638 1 -1 0
|
||||
180 EPIC_WEAPON_SPECIALIZATION_LIGHT_PICK 24639 1 -1 0
|
||||
181 EPIC_WEAPON_SPECIALIZATION_SAI 24640 1 -1 0
|
||||
182 EPIC_WEAPON_SPECIALIZATION_NUNCHAKU 24641 1 -1 0
|
||||
183 EPIC_WEAPON_SPECIALIZATION_FALCHION 24642 1 -1 0
|
||||
184 EPIC_WEAPON_SPECIALIZATION_SAP 24643 1 -1 0
|
||||
185 EPIC_WEAPON_SPECIALIZATION_KATAR 24644 1 -1 0
|
||||
186 EPIC_WEAPON_SPECIALIZATION_HEAVY_MACE 24645 1 -1 0
|
||||
187 EPIC_WEAPON_SPECIALIZATION_MAUL 24646 1 -1 0
|
||||
188 EPIC_WEAPON_SPECIALIZATION_DBL_SCIMITAR 24647 1 -1 0
|
||||
189 EPIC_WEAPON_SPECIALIZATION_GOAD 24648 1 -1 0
|
||||
190 EPIC_WEAPON_SPECIALIZATION_ELVEN_LIGHTBLADE 24700 1 -1 0
|
||||
191 EPIC_WEAPON_SPECIALIZATION_ELVEN_THINBLADE 24708 1 -1 0
|
||||
192 EPIC_WEAPON_SPECIALIZATION_ELVEN_COURTBLADE 24716 1 -1 0
|
||||
193 FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB 709 1 -1 0
|
||||
194 FEAT_EPIC_OVERWHELMING_CRITICAL_DAGGER 710 1 -1 0
|
||||
195 FEAT_EPIC_OVERWHELMING_CRITICAL_DART 711 1 -1 0
|
||||
196 FEAT_EPIC_OVERWHELMING_CRITICAL_HEAVYCROSSBOW 712 1 -1 0
|
||||
197 FEAT_EPIC_OVERWHELMING_CRITICAL_LIGHTCROSSBOW 713 1 -1 0
|
||||
198 FEAT_EPIC_OVERWHELMING_CRITICAL_LIGHTMACE 714 1 -1 0
|
||||
199 FEAT_EPIC_OVERWHELMING_CRITICAL_MORNINGSTAR 715 1 -1 0
|
||||
200 FEAT_EPIC_OVERWHELMING_CRITICAL_QUARTERSTAFF 716 1 -1 0
|
||||
201 FEAT_EPIC_OVERWHELMING_CRITICAL_SHORTSPEAR 717 1 -1 0
|
||||
202 FEAT_EPIC_OVERWHELMING_CRITICAL_SICKLE 718 1 -1 0
|
||||
203 FEAT_EPIC_OVERWHELMING_CRITICAL_SLING 719 1 -1 0
|
||||
204 FEAT_EPIC_OVERWHELMING_CRITICAL_UNARMED 720 1 -1 0
|
||||
205 FEAT_EPIC_OVERWHELMING_CRITICAL_LONGBOW 721 1 -1 0
|
||||
206 FEAT_EPIC_OVERWHELMING_CRITICAL_SHORTBOW 722 1 -1 0
|
||||
207 FEAT_EPIC_OVERWHELMING_CRITICAL_SHORTSWORD 723 1 -1 0
|
||||
208 FEAT_EPIC_OVERWHELMING_CRITICAL_RAPIER 724 1 -1 0
|
||||
209 FEAT_EPIC_OVERWHELMING_CRITICAL_SCIMITAR 725 1 -1 0
|
||||
210 FEAT_EPIC_OVERWHELMING_CRITICAL_LONGSWORD 726 1 -1 0
|
||||
211 FEAT_EPIC_OVERWHELMING_CRITICAL_GREATSWORD 727 1 -1 0
|
||||
212 FEAT_EPIC_OVERWHELMING_CRITICAL_HANDAXE 728 1 -1 0
|
||||
213 FEAT_EPIC_OVERWHELMING_CRITICAL_THROWINGAXE 729 1 -1 0
|
||||
214 FEAT_EPIC_OVERWHELMING_CRITICAL_BATTLEAXE 730 1 -1 0
|
||||
215 FEAT_EPIC_OVERWHELMING_CRITICAL_GREATAXE 731 1 -1 0
|
||||
216 FEAT_EPIC_OVERWHELMING_CRITICAL_HALBERD 732 1 -1 0
|
||||
217 FEAT_EPIC_OVERWHELMING_CRITICAL_LIGHTHAMMER 733 1 -1 0
|
||||
218 FEAT_EPIC_OVERWHELMING_CRITICAL_LIGHTFLAIL 734 1 -1 0
|
||||
219 FEAT_EPIC_OVERWHELMING_CRITICAL_WARHAMMER 735 1 -1 0
|
||||
220 FEAT_EPIC_OVERWHELMING_CRITICAL_HEAVYFLAIL 736 1 -1 0
|
||||
221 FEAT_EPIC_OVERWHELMING_CRITICAL_KAMA 737 1 -1 0
|
||||
222 FEAT_EPIC_OVERWHELMING_CRITICAL_KUKRI 738 1 -1 0
|
||||
223 FEAT_EPIC_OVERWHELMING_CRITICAL_SHURIKEN 739 1 -1 0
|
||||
224 FEAT_EPIC_OVERWHELMING_CRITICAL_SCYTHE 740 1 -1 0
|
||||
225 FEAT_EPIC_OVERWHELMING_CRITICAL_KATANA 741 1 -1 0
|
||||
226 FEAT_EPIC_OVERWHELMING_CRITICAL_BASTARDSWORD 742 1 -1 0
|
||||
227 FEAT_EPIC_OVERWHELMING_CRITICAL_DIREMACE 743 1 -1 0
|
||||
228 FEAT_EPIC_OVERWHELMING_CRITICAL_DOUBLEAXE 744 1 -1 0
|
||||
229 FEAT_EPIC_OVERWHELMING_CRITICAL_TWOBLADEDSWORD 745 1 -1 0
|
||||
230 OVERWHELMING_CRITICAL_LIGHT_LANCE 24661 1 -1 0
|
||||
231 OVERWHELMING_CRITICAL_HEAVY_PICK 24662 1 -1 0
|
||||
232 OVERWHELMING_CRITICAL_LIGHT_PICK 24663 1 -1 0
|
||||
233 OVERWHELMING_CRITICAL_SAI 24664 1 -1 0
|
||||
234 OVERWHELMING_CRITICAL_NUNCHAKU 24665 1 -1 0
|
||||
235 OVERWHELMING_CRITICAL_FALCHION 24666 1 -1 0
|
||||
236 OVERWHELMING_CRITICAL_SAP 24667 1 -1 0
|
||||
237 OVERWHELMING_CRITICAL_KATAR 24668 1 -1 0
|
||||
238 OVERWHELMING_CRITICAL_HEAVY_MACE 24669 1 -1 0
|
||||
239 OVERWHELMING_CRITICAL_MAUL 24670 1 -1 0
|
||||
240 OVERWHELMING_CRITICAL_DBL_SCIMITAR 24671 1 -1 0
|
||||
241 OVERWHELMING_CRITICAL_GOAD 24672 1 -1 0
|
||||
242 OVERWHELMING_CRITICAL_ELVEN_LIGHTBLADE 24702 1 -1 0
|
||||
243 OVERWHELMING_CRITICAL_ELVEN_THINBLADE 24710 1 -1 0
|
||||
244 OVERWHELMING_CRITICAL_ELVEN_COURTBLADE 24718 1 -1 0
|
||||
245 FEAT_EPIC_TOUGHNESS_1 754 1 -1 0
|
||||
246 FEAT_EPIC_TOUGHNESS_2 755 1 -1 0
|
||||
247 FEAT_EPIC_TOUGHNESS_3 756 1 -1 0
|
||||
248 FEAT_EPIC_TOUGHNESS_4 757 1 -1 0
|
||||
249 FEAT_EPIC_TOUGHNESS_5 758 1 -1 0
|
||||
250 FEAT_EPIC_TOUGHNESS_6 759 1 -1 0
|
||||
251 FEAT_EPIC_TOUGHNESS_7 760 1 -1 0
|
||||
252 FEAT_EPIC_TOUGHNESS_8 761 1 -1 0
|
||||
253 FEAT_EPIC_TOUGHNESS_9 762 1 -1 0
|
||||
254 FEAT_EPIC_TOUGHNESS_10 763 1 -1 0
|
||||
255 FEAT_EPIC_DEVASTATING_CRITICAL_DWAXE 955 1 -1 0
|
||||
256 FEAT_EPIC_WEAPON_FOCUS_DWAXE 956 1 -1 0
|
||||
257 FEAT_EPIC_WEAPON_SPECIALIZATION_DWAXE 957 1 -1 0
|
||||
258 FEAT_EPIC_OVERWHELMING_CRITICAL_DWAXE 958 1 -1 0
|
||||
259 FEAT_EPIC_WEAPON_FOCUS_WHIP 997 1 -1 0
|
||||
260 FEAT_EPIC_DEVASTATING_CRITICAL_WHIP 996 1 -1 0
|
||||
261 FEAT_EPIC_OVERWHELMING_CRITICAL_WHIP 999 1 -1 0
|
||||
262 FEAT_EPIC_WEAPON_SPECIALIZATION_WHIP 998 1 -1 0
|
||||
263 FEAT_IMPROVED_WHIRLWIND 868 1 -1 0
|
||||
264 FEAT_EPIC_SUPERIOR_INITIATIVE 753 1 -1 0
|
||||
265 FEAT_EPIC_BLINDING_SPEED 491 1 -1 1
|
||||
266 OverWCrit_Mindblade 3615 1 -1 0
|
||||
267 DevCrit_Mindblade 3616 1 -1 0
|
||||
268 Epic_WeaponFocus_Mindblade 3618 1 -1 0
|
||||
269 Epic_WeaponSpecialization_Mindblade 3619 1 -1 0
|
||||
270 PERFECT_TWO_WEAPON_FIGHTING 4320 1 -1 0
|
||||
271 FEAT_EPIC_LEADERSHIP 4366 1 -1 0
|
||||
272 FEAT_LEGENDARY_COMMANDER 4367 1 -1 0
|
||||
273 Two-Weapon_Rend 3113 1 -1 0
|
||||
274 FEAT_EPIC_GREAT_CHARISMA_2 764 1 -1 0
|
||||
275 FEAT_EPIC_GREAT_CHARISMA_3 765 1 -1 0
|
||||
276 FEAT_EPIC_GREAT_CHARISMA_4 766 1 -1 0
|
||||
277 FEAT_EPIC_GREAT_CHARISMA_5 767 1 -1 0
|
||||
278 FEAT_EPIC_GREAT_CHARISMA_6 768 1 -1 0
|
||||
279 FEAT_EPIC_GREAT_CHARISMA_7 769 1 -1 0
|
||||
280 FEAT_EPIC_GREAT_CHARISMA_8 770 1 -1 0
|
||||
281 FEAT_EPIC_GREAT_CHARISMA_9 771 1 -1 0
|
||||
282 FEAT_EPIC_GREAT_CHARISMA_10 772 1 -1 0
|
||||
283 FEAT_EPIC_GREAT_CONSTITUTION_1 773 1 -1 0
|
||||
284 FEAT_EPIC_GREAT_CONSTITUTION_2 774 1 -1 0
|
||||
285 FEAT_EPIC_GREAT_CONSTITUTION_3 775 1 -1 0
|
||||
286 FEAT_EPIC_GREAT_CONSTITUTION_4 776 1 -1 0
|
||||
287 FEAT_EPIC_GREAT_CONSTITUTION_5 777 1 -1 0
|
||||
288 FEAT_EPIC_GREAT_CONSTITUTION_6 778 1 -1 0
|
||||
289 FEAT_EPIC_GREAT_CONSTITUTION_7 779 1 -1 0
|
||||
290 FEAT_EPIC_GREAT_CONSTITUTION_8 780 1 -1 0
|
||||
291 FEAT_EPIC_GREAT_CONSTITUTION_9 781 1 -1 0
|
||||
292 FEAT_EPIC_GREAT_CONSTITUTION_10 782 1 -1 0
|
||||
293 ExtraGrantedManeuver 4096 0 -1 0
|
||||
294 StonePower 5294 0 -1 1
|
||||
295 VitalRecovery 3636 0 -1 0
|
||||
296 DefArrow 8 0 -1 0
|
||||
297 TwoWeap 41 0 -1 0
|
||||
298 Ambidex 1 0 -1 0
|
||||
|
@ -3,13 +3,13 @@
|
||||
Label Name FeatIndex PreReq1 PreReq2 Con Wis Cha BAB Law
|
||||
0 FEAT_EXALTED_COMPANION "Exalted Companion" 4199 199 **** **** **** **** **** ****
|
||||
1 FEAT_EXALTED_TURNING "Exalted Turning" 3168 294 **** **** **** **** **** ****
|
||||
2 FEAT_FISTOFHEAVENS "Fist of Heavens" 26004 213 26002 **** 15 **** **** ****
|
||||
3 FEAT_GIFTOFFAITH "Gift of Faith" 26007 **** **** **** 13 **** **** ****
|
||||
4 FEAT_HOLYKISTRIKE "Holy Ki Strike" 26003 213 26002 **** **** 15 **** ****
|
||||
2 FEAT_FISTOFHEAVENS "Fist of Heavens" 26005 213 26003 **** 15 **** **** ****
|
||||
3 FEAT_GIFTOFFAITH "Gift of Faith" 26008 **** **** **** 13 **** **** ****
|
||||
4 FEAT_HOLYKISTRIKE "Holy Ki Strike" 26004 213 26003 **** **** 15 **** ****
|
||||
5 FEAT_HOLYRADIANCE "Holy Radiance" 3164 3165 **** **** **** 15 **** ****
|
||||
6 FEAT_INTUITIVE_ATTACK "Intuitive Attack" 3166 **** **** **** **** **** 1 ****
|
||||
7 FEAT_NIMBUSLIGHT "Nimbus of Light" 3165 **** **** **** **** **** 1 ****
|
||||
8 FEAT_SANCTIFYKISTRIKE "Sanctify Ki Strike" 26002 213 **** **** **** 15 **** ****
|
||||
8 FEAT_SANCTIFYKISTRIKE "Sanctify Ki Strike" 26003 213 **** **** **** 15 **** ****
|
||||
9 FEAT_SANCTIFY_MARTIAL_CLUB "Sanctify Martial Strike (Club)" 3194 43 **** **** **** 15 **** ****
|
||||
10 FEAT_SANCTIFY_MARTIAL_DAGGER "Sanctify Martial Strike (Dagger)" 3195 90 **** **** **** 15 **** ****
|
||||
11 FEAT_SANCTIFY_MARTIAL_DART "Sanctify Martial Strike (Dard)" 3227 91 **** **** **** 15 **** ****
|
||||
@ -24,7 +24,7 @@
|
||||
20 FEAT_SERVHEAVEN "Servant of the Heavens" 3355 **** **** **** **** **** **** ****
|
||||
21 FEAT_STIGMATA Stigmata 3163 3165 **** **** **** **** **** ****
|
||||
22 FEAT_RAVAGEGOLDENICE "Touch of Golden Ice" 3162 **** **** 13 **** **** **** ****
|
||||
23 FEAT_VOWABSTINENCE "Vow of Abstinence" 26005 **** **** **** **** **** **** ****
|
||||
24 FEAT_VOWCHASTITY "Vow of Chastity" 26006 **** **** **** **** **** **** ****
|
||||
23 FEAT_VOWABSTINENCE "Vow of Abstinence" 26006 **** **** **** **** **** **** ****
|
||||
24 FEAT_VOWCHASTITY "Vow of Chastity" 26007 **** **** **** **** **** **** ****
|
||||
25 FEAT_VOW_OBED "Vow of Obedience" 3389 **** **** **** **** **** **** 1
|
||||
26 FEAT_VOW_PURITY "Vow of Purity" 5360 **** **** **** **** **** **** ****
|
||||
|
@ -876,6 +876,8 @@ void CreateSwitchNameArray()
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_HARM);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_NEUTRALIZE_POISON);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_REMOVE_DISEASE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIO_UNLEARN);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_UNLEARN_SPELL_MAXNR);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TIMESTOP_BIOWARE_DURATION);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TIMESTOP_LOCAL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TIMESTOP_NO_HOSTILE);
|
||||
|
@ -1549,7 +1549,7 @@ const int FEAT_STIGMATA = 3163;
|
||||
const int FEAT_SERVHEAVEN = 3355;
|
||||
const int FEAT_RANGED_SMITE = 3356;
|
||||
const int FEAT_VOW_PURITY = 5360;
|
||||
const int FEAT_VOWOFPOVERTY = 26001;
|
||||
const int FEAT_VOWOFPOVERTY = 26002;
|
||||
|
||||
//Vile Feat
|
||||
const int FEAT_LICHLOVED = 3395;
|
||||
@ -1868,12 +1868,12 @@ const int FEAT_SANCTIFY_MARTIAL_SICKLE = 3169;
|
||||
const int FEAT_SANCTIFY_MARTIAL_MINDBLADE = 3623;
|
||||
const int FEAT_SANCTIFY_MARTIAL_WHIP = 3596;
|
||||
const int FEAT_SANCTIFY_MARTIAL_TRIDENT = 3597;
|
||||
const int FEAT_SANCTIFYKISTRIKE = 26002;
|
||||
const int FEAT_HOLYKISTRIKE = 26003;
|
||||
const int FEAT_FISTOFHEAVENS = 26004;
|
||||
const int FEAT_VOWABSTINENCE = 26005;
|
||||
const int FEAT_VOWCHASTITY = 26006;
|
||||
const int FEAT_GIFTOFFAITH = 26007;
|
||||
const int FEAT_SANCTIFYKISTRIKE = 26003;
|
||||
const int FEAT_HOLYKISTRIKE = 26004;
|
||||
const int FEAT_FISTOFHEAVENS = 26005;
|
||||
const int FEAT_VOWABSTINENCE = 26006;
|
||||
const int FEAT_VOWCHASTITY = 26007;
|
||||
const int FEAT_GIFTOFFAITH = 26008;
|
||||
|
||||
//heartwarder
|
||||
const int FEAT_CHARISMA_INC1 = 3230;
|
||||
|
@ -575,8 +575,8 @@ int PRCGetCasterLevel(object oCaster = OBJECT_SELF)
|
||||
iReturnLevel = GetLevelByClass(CLASS_TYPE_SHAPECHANGER);
|
||||
|
||||
}
|
||||
// Casting as a bard but don't have any levels in the class
|
||||
if(iCastingClass == CLASS_TYPE_BARD && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
|
||||
// Casting as a bard but don't have any levels in the class //:: Double-dipping?
|
||||
/* if(iCastingClass == CLASS_TYPE_BARD && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
|
||||
{
|
||||
int nRace = GetRacialType(oCaster);
|
||||
|
||||
@ -584,7 +584,7 @@ int PRCGetCasterLevel(object oCaster = OBJECT_SELF)
|
||||
//otherwise use RHD instead of bard levels
|
||||
if(nRace == RACIAL_TYPE_GLOURA)
|
||||
iReturnLevel = GetLevelByClass(CLASS_TYPE_FEY);
|
||||
}
|
||||
} */
|
||||
|
||||
//Spell Rage ability
|
||||
if(GetHasSpellEffect(SPELL_SPELL_RAGE, oCaster)
|
||||
@ -960,8 +960,10 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
}
|
||||
//:: End Bard Arcane PrC casting calculations
|
||||
|
||||
if(nCastingClass == CLASS_TYPE_BARD && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
|
||||
if(nCastingClass == CLASS_TYPE_BARD || nCastingClass == CLASS_TYPE_BARD && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_castlvl >> Found Fey RHD caster (not bard)");
|
||||
|
||||
if(GetHasFeat(FEAT_ABCHAMP_SPELLCASTING_FEY, oCaster))
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_ABJURANT_CHAMPION, oCaster);
|
||||
|
||||
@ -1065,7 +1067,10 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_UNSEEN_SEER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VIRTUOSO_SPELLCASTING_FEY, oCaster))
|
||||
{
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_VIRTUOSO, oCaster);
|
||||
if(DEBUG) DoDebug("prc_inc_castlvl >> Found Fey + Virtuoso PrC. Arcane caster level is "+IntToString(nArcane)+".");
|
||||
}
|
||||
|
||||
if(GetHasFeat(FEAT_WWOC_SPELLCASTING_FEY, oCaster))
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_WAR_WIZARD_OF_CORMYR, oCaster);
|
||||
|
@ -382,17 +382,17 @@ int GetPrCAdjustedClassLevel(int nClass, object oCaster = OBJECT_SELF)
|
||||
// is it arcane, divine or neither?
|
||||
if(GetIsArcaneClass(nClass, oCaster) && nClass != CLASS_TYPE_SUBLIME_CHORD)
|
||||
{
|
||||
if (GetPrimaryArcaneClass(oCaster) == nClass) // adjust for any PrCs
|
||||
if (GetPrimaryArcaneClass(oCaster) == nClass) // adjust for any PrCs
|
||||
iTemp = GetArcanePRCLevels(oCaster, nClass);
|
||||
}
|
||||
else if(GetIsDivineClass(nClass, oCaster))
|
||||
{
|
||||
if (GetPrimaryDivineClass(oCaster) == nClass) // adjust for any PrCs
|
||||
if (GetPrimaryDivineClass(oCaster) == nClass) // adjust for any PrCs
|
||||
iTemp = GetDivinePRCLevels(oCaster, nClass);
|
||||
}
|
||||
else // a non-caster class or a PrC
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
// add the caster class levels
|
||||
return iTemp += GetLevelByClass(nClass, oCaster);
|
||||
|
530
nwn/nwnprc/trunk/include/prc_nui_com_inc.nss
Normal file
530
nwn/nwnprc/trunk/include/prc_nui_com_inc.nss
Normal file
@ -0,0 +1,530 @@
|
||||
#include "prc_nui_consts"
|
||||
#include "inc_newspellbook"
|
||||
#include "psi_inc_psifunc"
|
||||
#include "inc_lookups"
|
||||
#include "nw_inc_nui"
|
||||
|
||||
//
|
||||
// GetCurrentSpellLevel
|
||||
// Gets the current spell level the class can achieve at the current
|
||||
// caster level (ranging from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
// nLevel:int the caster level
|
||||
//
|
||||
// Returns:
|
||||
// int the circle the class can achieve currently
|
||||
//
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel);
|
||||
|
||||
//
|
||||
// GetMaxSpellLevel
|
||||
// Gets the highest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest circle that can be achieved
|
||||
//
|
||||
int GetMaxSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetMinSpellLevel
|
||||
// Gets the lowest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the lowest circle that can be achieved
|
||||
//
|
||||
int GetMinSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetHighestLevelPossibleInClass
|
||||
// Given a class Id this will determine what the max level of a class can be
|
||||
// achieved
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest possible level the class can achieve
|
||||
//
|
||||
int GetHighestLevelPossibleInClass(int nClass);
|
||||
|
||||
//
|
||||
// GetClassSpellbookFile
|
||||
// Gets the class 2da spellbook/ability for the given class Id
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the classID
|
||||
//
|
||||
// Returns:
|
||||
// string the 2da file name for the spell/abilities of the ClassID
|
||||
//
|
||||
string GetClassSpellbookFile(int nClass);
|
||||
|
||||
//
|
||||
// GetBinderSpellToFeatDictionary
|
||||
// Sets up the Binder Spell Dictionary that is used to match a binder's vestige
|
||||
// to their feat. This is constructed based off the binder's known location of
|
||||
// their feat and spell ranges in the base 2das respectivly. After constructing
|
||||
// this it will be saved to the player locally as a cached result since we do
|
||||
// not need to call this again.
|
||||
//
|
||||
// Argument:
|
||||
// oPlayer:object the player
|
||||
//
|
||||
// Returns:
|
||||
// json:Dictionary<String,Int> a dictionary of mapping between the SpellID
|
||||
// and the FeatID of a vestige ability
|
||||
//
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF);
|
||||
|
||||
//
|
||||
// GetSpellLevelIcon
|
||||
// Takes the spell circle int and gets the icon appropriate for it (i.e. 0 turns
|
||||
// into "ir_cantrips"
|
||||
//
|
||||
// Arguments:
|
||||
// spellLevel:int the spell level we want the icon for
|
||||
//
|
||||
// Returns:
|
||||
// string the spell level icon
|
||||
//
|
||||
string GetSpellLevelIcon(int spellLevel);
|
||||
|
||||
//
|
||||
// GetSpellLevelToolTip
|
||||
// Gets the spell level tool tip text based on the int spell level provided (i.e.
|
||||
// 0 turns into "Cantrips")
|
||||
//
|
||||
// Arguments:
|
||||
// spellLevel:int the spell level we want the tooltip for
|
||||
//
|
||||
// Returns:
|
||||
// string the spell level toop tip
|
||||
//
|
||||
string GetSpellLevelToolTip(int spellLevel);
|
||||
|
||||
//
|
||||
// GetSpellIcon
|
||||
// Gets the spell icon based off the spellId, or featId supplied
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the class Id
|
||||
// featId:int the featId we can use the icon for
|
||||
// spellId:int the spell Id we want the icon for
|
||||
//
|
||||
// Returns:
|
||||
// json:String the string of the icon we want.
|
||||
//
|
||||
json GetSpellIcon(int spellId, int featId=0, int nClass=0);
|
||||
string GetSpellName(int spellId, int realSpellID=0, int featId=0, int nClass=0);
|
||||
|
||||
//
|
||||
// GreyOutButton
|
||||
// Takes NUI Button along with it's width and height and greys it out it with a drawn
|
||||
// colored rectangle to represent it's not been selected or not valid.
|
||||
//
|
||||
// Arguments:
|
||||
// jButton:json the NUI Button
|
||||
// w:float the width of the button
|
||||
// h:float the height of the button
|
||||
//
|
||||
// Returns:
|
||||
// json the NUI button greyed out
|
||||
//
|
||||
json GreyOutButton(json jButton, float w, float h);
|
||||
|
||||
//
|
||||
// CreateGreyOutRectangle
|
||||
// Creates a grey out rectangle for buttons
|
||||
//
|
||||
// Arguments:
|
||||
// w:float the width of the button
|
||||
// h:float the height of the button
|
||||
//
|
||||
// Returns:
|
||||
// json the transparant black rectangle
|
||||
//
|
||||
json CreateGreyOutRectangle(float w, float h);
|
||||
|
||||
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0);
|
||||
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF);
|
||||
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||
{
|
||||
int currentLevel = nLevel;
|
||||
|
||||
// ToB doesn't have a concept of spell levels, but still match up to it
|
||||
if(nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER)
|
||||
{
|
||||
return 9;
|
||||
}
|
||||
|
||||
|
||||
// Binders don't really have a concept of spell level
|
||||
if (nClass == CLASS_TYPE_BINDER
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN) // they can only reach 1st circle
|
||||
return 1;
|
||||
|
||||
//Shadowsmith has no concept of spell levels
|
||||
if (nClass == CLASS_TYPE_SHADOWSMITH)
|
||||
return 2;
|
||||
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
return 4;
|
||||
|
||||
// Spont casters have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
|
||||
int maxLevel = GetMaxSpellLevelForCasterLevel(nClass, currentLevel);
|
||||
return maxLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
string spellLevel2da = GetAMSKnownFileName(nClass);
|
||||
|
||||
currentLevel = nLevel - 1; // Level is 1 off of the row in the 2da
|
||||
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
currentLevel = GetManifesterLevel(OBJECT_SELF, nClass, TRUE) - 1;
|
||||
|
||||
int totalLevel = Get2DARowCount(spellLevel2da);
|
||||
|
||||
// in case we somehow go over bounds just don't :)
|
||||
if (currentLevel >= totalLevel)
|
||||
currentLevel = totalLevel - 1;
|
||||
|
||||
//Psionics have MaxPowerLevel as their column name
|
||||
string columnName = "MaxPowerLevel";
|
||||
|
||||
//Invokers have MaxInvocationLevel
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
columnName = "MaxInvocationLevel";
|
||||
|
||||
// Truenamers have 3 sets of utterances, ranging from 1-6, EvolvingMind covers the entire range
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
columnName = "EvolvingMind";
|
||||
spellLevel2da = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
columnName = "VestigeLvl";
|
||||
spellLevel2da = "cls_bind_binder";
|
||||
}
|
||||
|
||||
// ToB doesn't have a concept of this, but we don't care.
|
||||
|
||||
int maxLevel = StringToInt(Get2DACache(spellLevel2da, columnName, currentLevel));
|
||||
return maxLevel;
|
||||
}
|
||||
}
|
||||
|
||||
int GetMinSpellLevel(int nClass)
|
||||
{
|
||||
// again sponts have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
return GetMinSpellLevelForCasterLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND
|
||||
|| nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER
|
||||
|| nClass == CLASS_TYPE_SHADOWSMITH
|
||||
|| nClass == CLASS_TYPE_BINDER)
|
||||
return 1;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMaxSpellLevel(int nClass)
|
||||
{
|
||||
if (nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSION)
|
||||
return 9;
|
||||
if (nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
return 5;
|
||||
if (nClass == CLASS_TYPE_PSYWAR)
|
||||
return 6;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
|
||||
int GetHighestLevelPossibleInClass(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
|
||||
//sponts have their spells in the classes.2da
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
sFile = GetAMSKnownFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
sFile = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "cls_bind_binder";
|
||||
}
|
||||
}
|
||||
|
||||
return Get2DARowCount(sFile);
|
||||
}
|
||||
|
||||
string GetClassSpellbookFile(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
// Spontaneous casters use a specific file name structure
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = GetFileForClass(nClass);
|
||||
}
|
||||
// everyone else uses this structure
|
||||
else
|
||||
{
|
||||
sFile = GetAMSDefinitionFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "vestiges";
|
||||
}
|
||||
}
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
string GetSpellLevelIcon(int spellLevel)
|
||||
{
|
||||
switch (spellLevel)
|
||||
{
|
||||
case 0: return "ir_cantrips";
|
||||
case 1: return "ir_level1";
|
||||
case 2: return "ir_level2";
|
||||
case 3: return "ir_level3";
|
||||
case 4: return "ir_level4";
|
||||
case 5: return "ir_level5";
|
||||
case 6: return "ir_level6";
|
||||
case 7: return "ir_level789";
|
||||
case 8: return "ir_level789";
|
||||
case 9: return "ir_level789";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
string GetSpellLevelToolTip(int spellLevel)
|
||||
{
|
||||
switch (spellLevel)
|
||||
{
|
||||
case 0: return "Cantrips";
|
||||
case 1: return "Level 1";
|
||||
case 2: return "Level 2";
|
||||
case 3: return "Level 3";
|
||||
case 4: return "Level 4";
|
||||
case 5: return "Level 5";
|
||||
case 6: return "Level 6";
|
||||
case 7: return "Level 7";
|
||||
case 8: return "Level 8";
|
||||
case 9: return "Level 9";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
json GetSpellIcon(int spellId,int featId=0,int nClass=0)
|
||||
{
|
||||
// Binder's spells don't have the FeatID on the spells.2da, so we have to use
|
||||
// the mapping we constructed to get it.
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
json binderDict = GetBinderSpellToFeatDictionary();
|
||||
int nFeatID = JsonGetInt(JsonObjectGet(binderDict, IntToString(spellId)));
|
||||
return JsonString(Get2DACache("feat", "Icon", featId));
|
||||
}
|
||||
|
||||
if (featId)
|
||||
return JsonString(Get2DACache("feat", "Icon", featId));
|
||||
|
||||
int masterSpellID = StringToInt(Get2DACache("spells", "Master", spellId));
|
||||
|
||||
// if this is a sub radial spell, then we use spell's icon instead
|
||||
if (masterSpellID)
|
||||
return JsonString(Get2DACache("spells", "IconResRef", spellId));
|
||||
|
||||
// the FeatID holds the accurate spell icon, not the SpellID
|
||||
int nFeatID = StringToInt(Get2DACache("spells", "FeatID", spellId));
|
||||
|
||||
return JsonString(Get2DACache("feat", "Icon", nFeatID));
|
||||
}
|
||||
|
||||
string GetSpellName(int spellId, int realSpellID=0, int featId=0, int nClass=0)
|
||||
{
|
||||
if ((nClass == CLASS_TYPE_SHADOWSMITH
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER) && spellId)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||
if (nClass == CLASS_TYPE_TRUENAMER && featId)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", featId)));
|
||||
if (realSpellID)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", realSpellID)));
|
||||
if (spellId)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||
if (featId)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", featId)));
|
||||
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||
}
|
||||
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF)
|
||||
{
|
||||
// a dictionary of <SpellID, FeatID>
|
||||
json binderDict = GetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR);
|
||||
// if this hasn't been created, create it now.
|
||||
if (binderDict == JsonNull())
|
||||
binderDict = JsonObject();
|
||||
else
|
||||
return binderDict;
|
||||
|
||||
// the starting row for binder spells
|
||||
int spellIndex = 19070;
|
||||
// the starting row for binder feats
|
||||
int featIndex = 9030;
|
||||
//the end of the binder spells/feats
|
||||
while (spellIndex <= 19156 && featIndex <= 9104)
|
||||
{
|
||||
// get the SpellID tied to the feat
|
||||
int spellID = StringToInt(Get2DACache("feat", "SPELLID", featIndex));
|
||||
// if the spellID matches the current index, then this is the spell
|
||||
// attached to the feat
|
||||
if (spellID == spellIndex)
|
||||
{
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellID), JsonInt(featIndex));
|
||||
|
||||
// move to next spell/feat
|
||||
featIndex++;
|
||||
spellIndex++;
|
||||
}
|
||||
// else we have reached a subdial spell
|
||||
else
|
||||
{
|
||||
// loop through until we reach back at spellID
|
||||
while (spellIndex < spellID)
|
||||
{
|
||||
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellIndex));
|
||||
|
||||
// add the sub radial to the dict, tied to the master's FeatID
|
||||
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(masterSpell)));
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellIndex), JsonInt(featId));
|
||||
|
||||
spellIndex++;
|
||||
}
|
||||
|
||||
|
||||
// some feats overlap the same FeatID, can cause this to get stuck.
|
||||
// if it happens then move on
|
||||
if (spellIndex > spellID)
|
||||
featIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// cache the result
|
||||
SetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR, binderDict);
|
||||
return binderDict;
|
||||
}
|
||||
|
||||
json GreyOutButton(json jButton, float w, float h)
|
||||
{
|
||||
json retValue = jButton;
|
||||
|
||||
json jBorders = JsonArray();
|
||||
jBorders = JsonArrayInsert(jBorders, CreateGreyOutRectangle(w, h));
|
||||
|
||||
return NuiDrawList(jButton, JsonBool(FALSE), jBorders);
|
||||
}
|
||||
|
||||
json CreateGreyOutRectangle(float w, float h)
|
||||
{
|
||||
// set the points of the button shape
|
||||
json jPoints = JsonArray();
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(h));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(w));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(h));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(w));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
return NuiDrawListPolyLine(JsonBool(TRUE), NuiColor(0, 0, 0, 127), JsonBool(TRUE), JsonFloat(2.0), jPoints);
|
||||
}
|
||||
|
||||
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0)
|
||||
{
|
||||
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_FEATID_VAR, featID);
|
||||
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_SPELLID_VAR, spellId);
|
||||
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR, realSpellId);
|
||||
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR, nClass);
|
||||
ExecuteScript("prc_nui_dsc_view", oPlayer);
|
||||
}
|
||||
|
||||
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF)
|
||||
{
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_FEATID_VAR);
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_SPELLID_VAR);
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR);
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR);
|
||||
}
|
||||
|
@ -111,3 +111,48 @@ const string NUI_PRC_PA_TEXT_BIND = "nui_prc_pa_text_bind";
|
||||
const string NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND = "leftButtonEnabled";
|
||||
// Right Button Enabled Bind for Power Attack NUI
|
||||
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// //
|
||||
// NUI Level Up //
|
||||
// //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
const string NUI_LEVEL_UP_WINDOW_ID = "prcLevelUpNui";
|
||||
|
||||
const string NUI_LEVEL_UP_SPELL_CIRCLE_BUTTON_BASEID = "NuiLevelUpCircleButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_BUTTON_BASEID = "NuiLevelUpSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_CHOSEN_BUTTON_BASEID = "NuiLevelUpChosenSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_CHOSEN_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledChosenSpellButton_";
|
||||
const string NUI_LEVEL_UP_DONE_BUTTON = "NuiLevelUpDoneButton";
|
||||
const string NUI_LEVEL_UP_RESET_BUTTON = "NuiLevelUpResetButton";
|
||||
|
||||
const string NUI_LEVEL_UP_SELECTED_CLASS_VAR = "NUILevelUpSelectedClass";
|
||||
const string NUI_LEVEL_UP_SELECTED_CIRCLE_VAR = "NUILevelUpSelectedCircle";
|
||||
const string NUI_LEVEL_UP_KNOWN_SPELLS_VAR = "NUILevelUpKnownSpells";
|
||||
const string NUI_LEVEL_UP_CHOSEN_SPELLS_VAR = "NUILevelUpChosenSpells";
|
||||
const string NUI_LEVEL_UP_EXPANDED_KNOW_LIST_VAR = "NUILevelUpExpKnowList";
|
||||
const string NUI_LEVEL_UP_POWER_LIST_VAR = "NUILevelUpPowerList";
|
||||
const string NUI_LEVEL_UP_DISCIPLINE_INFO_VAR = "GetDisciplineInfoObjectCache_";
|
||||
const string NUI_LEVEL_UP_SPELLID_LIST_VAR = "NUILevelUpSpellIDList_";
|
||||
const string NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR = "NUIRemainingChoicesCache";
|
||||
const string NUI_LEVEL_UP_RELEARN_LIST_VAR = "NUILevelUpRelearnList";
|
||||
const string NUI_LEVEL_UP_ARCHIVIST_NEW_SPELLS_LIST_VAR = "NUILevelUpArchivistNewSpellsList";
|
||||
|
||||
const string NUI_LEVEL_UP_EXPANDED_CHOICES_VAR = "NUIExpandedChoices";
|
||||
const string NUI_LEVEL_UP_EPIC_EXPANDED_CHOICES_VAR = "NUIEpicExpandedChoices";
|
||||
|
||||
const int NUI_LEVEL_UP_MANEUVER_PREREQ_LIMIT = 6;
|
||||
|
||||
const string NUI_LEVEL_UP_MANEUVER_TOTAL = "ManeuverTotal";
|
||||
const string NUI_LEVEL_UP_STANCE_TOTAL = "StanceTotal";
|
||||
|
||||
const string NUI_LEVEL_UP_SPELLBOOK_OBJECT_CACHE_VAR = "GetSpellListObjectCache_";
|
||||
const string NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR = "GetInvokerKnownListObjectCache_";
|
||||
|
||||
const string NUI_SPELL_DESCRIPTION_FEATID_VAR = "NUISpellDescriptionFeatID";
|
||||
const string NUI_SPELL_DESCRIPTION_CLASSID_VAR = "NUISpellDescriptionClassID";
|
||||
const string NUI_SPELL_DESCRIPTION_SPELLID_VAR = "NUISpellDescriptionSpellID";
|
||||
const string NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR = "NUISpellDescriptionRealSpellID";
|
||||
|
||||
|
3336
nwn/nwnprc/trunk/include/prc_nui_lv_inc.nss
Normal file
3336
nwn/nwnprc/trunk/include/prc_nui_lv_inc.nss
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,10 +10,8 @@
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 24.05.2005
|
||||
//:://////////////////////////////////////////////
|
||||
#include "inc_newspellbook"
|
||||
#include "psi_inc_psifunc"
|
||||
#include "inc_lookups"
|
||||
#include "prc_nui_consts"
|
||||
|
||||
#include "prc_nui_com_inc"
|
||||
|
||||
//
|
||||
// GetSpellListForCircle
|
||||
@ -43,69 +41,6 @@ json GetSpellListForCircle(object oPlayer, int nClass, int circle);
|
||||
//
|
||||
json GetSupportedNUISpellbookClasses(object oPlayer);
|
||||
|
||||
//
|
||||
// GetCurrentSpellLevel
|
||||
// Gets the current spell level the class can achieve at the current
|
||||
// caster level (ranging from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
// nLevel:int the caster level
|
||||
//
|
||||
// Returns:
|
||||
// int the circle the class can achieve currently
|
||||
//
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel);
|
||||
|
||||
//
|
||||
// GetMaxSpellLevel
|
||||
// Gets the highest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest circle that can be achieved
|
||||
//
|
||||
int GetMaxSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetMinSpellLevel
|
||||
// Gets the lowest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the lowest circle that can be achieved
|
||||
//
|
||||
int GetMinSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetHighestLevelPossibleInClass
|
||||
// Given a class Id this will determine what the max level of a class can be
|
||||
// achieved
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest possible level the class can achieve
|
||||
//
|
||||
int GetHighestLevelPossibleInClass(int nClass);
|
||||
|
||||
//
|
||||
// GetClassSpellbookFile
|
||||
// Gets the class 2da spellbook/ability for the given class Id
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the classID
|
||||
//
|
||||
// Returns:
|
||||
// string the 2da file name for the spell/abilities of the ClassID
|
||||
//
|
||||
string GetClassSpellbookFile(int nClass);
|
||||
|
||||
//
|
||||
// IsSpellKnown
|
||||
// Returns whether the player with the given class, spell file, and spellbook id
|
||||
@ -234,23 +169,6 @@ json GetMetaMysteryFeatList();
|
||||
//
|
||||
int GetTrueClassIfRHD(object oPlayer, int nClass);
|
||||
|
||||
//
|
||||
// GetBinderSpellToFeatDictionary
|
||||
// Sets up the Binder Spell Dictionary that is used to match a binder's vestige
|
||||
// to their feat. This is constructed based off the binder's known location of
|
||||
// their feat and spell ranges in the base 2das respectivly. After constructing
|
||||
// this it will be saved to the player locally as a cached result since we do
|
||||
// not need to call this again.
|
||||
//
|
||||
// Argument:
|
||||
// oPlayer:object the player
|
||||
//
|
||||
// Returns:
|
||||
// json:Dictionary<String,Int> a dictionary of mapping between the SpellID
|
||||
// and the FeatID of a vestige ability
|
||||
//
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF);
|
||||
|
||||
//
|
||||
// ShouldAddSpell
|
||||
// Given a spellId and a class, determines if the spell should be added to the
|
||||
@ -318,6 +236,18 @@ json GetInvokerEssenceSpellList(int nClass, object oPlayer=OBJECT_SELF);
|
||||
//
|
||||
int JsonArrayContainsInt(json list, int item);
|
||||
|
||||
//
|
||||
// IsSpellbookNUIOpen
|
||||
// Checks to see if the Spellbook NUI is open on a given player.
|
||||
//
|
||||
// Arguments:
|
||||
// oPC:object the player
|
||||
//
|
||||
// Returns:
|
||||
// int:Boolean TRUE if window is open, FALSE otherwise
|
||||
//
|
||||
int IsSpellbookNUIOpen(object oPC);
|
||||
|
||||
json GetSpellListForCircle(object oPlayer, int nClass, int circle)
|
||||
{
|
||||
json retValue = JsonArray();
|
||||
@ -397,86 +327,6 @@ int ShouldAddSpell(int nClass, int spellId, object oPlayer=OBJECT_SELF)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF)
|
||||
{
|
||||
// a dictionary of <SpellID, FeatID>
|
||||
json binderDict = GetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR);
|
||||
// if this hasn't been created, create it now.
|
||||
if (binderDict == JsonNull())
|
||||
binderDict = JsonObject();
|
||||
else
|
||||
return binderDict;
|
||||
|
||||
// the starting row for binder spells
|
||||
int spellIndex = 19070;
|
||||
// the starting row for binder feats
|
||||
int featIndex = 9030;
|
||||
//the end of the binder spells/feats
|
||||
while (spellIndex <= 19156 && featIndex <= 9104)
|
||||
{
|
||||
// get the SpellID tied to the feat
|
||||
int spellID = StringToInt(Get2DACache("feat", "SPELLID", featIndex));
|
||||
// if the spellID matches the current index, then this is the spell
|
||||
// attached to the feat
|
||||
if (spellID == spellIndex)
|
||||
{
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellID), JsonInt(featIndex));
|
||||
|
||||
// move to next spell/feat
|
||||
featIndex++;
|
||||
spellIndex++;
|
||||
}
|
||||
// else we have reached a subdial spell
|
||||
else
|
||||
{
|
||||
// loop through until we reach back at spellID
|
||||
while (spellIndex < spellID)
|
||||
{
|
||||
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellIndex));
|
||||
|
||||
// add the sub radial to the dict, tied to the master's FeatID
|
||||
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(masterSpell)));
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellIndex), JsonInt(featId));
|
||||
|
||||
spellIndex++;
|
||||
}
|
||||
|
||||
|
||||
// some feats overlap the same FeatID, can cause this to get stuck.
|
||||
// if it happens then move on
|
||||
if (spellIndex > spellID)
|
||||
featIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// cache the result
|
||||
SetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR, binderDict);
|
||||
return binderDict;
|
||||
}
|
||||
|
||||
string GetClassSpellbookFile(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
// Spontaneous casters use a specific file name structure
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = GetFileForClass(nClass);
|
||||
}
|
||||
// everyone else uses this structure
|
||||
else
|
||||
{
|
||||
sFile = GetAMSDefinitionFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "vestiges";
|
||||
}
|
||||
}
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
json GetSupportedNUISpellbookClasses(object oPlayer)
|
||||
{
|
||||
json retValue = JsonArray();
|
||||
@ -526,167 +376,6 @@ int IsSpellKnown(object oPlayer, int nClass, int spellId)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||
{
|
||||
int currentLevel = nLevel;
|
||||
|
||||
// ToB doesn't have a concept of spell levels, but still match up to it
|
||||
if(nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER)
|
||||
{
|
||||
return 9;
|
||||
}
|
||||
|
||||
|
||||
// Binders don't really have a concept of spell level
|
||||
if (nClass == CLASS_TYPE_BINDER
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN) // they can only reach 1st circle
|
||||
return 1;
|
||||
|
||||
//Shadowsmith has no concept of spell levels
|
||||
if (nClass == CLASS_TYPE_SHADOWSMITH)
|
||||
return 2;
|
||||
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
return 4;
|
||||
|
||||
// Spont casters have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
|
||||
int maxLevel = GetMaxSpellLevelForCasterLevel(nClass, currentLevel);
|
||||
return maxLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
string spellLevel2da = GetAMSKnownFileName(nClass);
|
||||
|
||||
currentLevel = nLevel - 1; // Level is 1 off of the row in the 2da
|
||||
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
currentLevel = GetManifesterLevel(OBJECT_SELF, nClass, TRUE) - 1;
|
||||
|
||||
int totalLevel = Get2DARowCount(spellLevel2da);
|
||||
|
||||
// in case we somehow go over bounds just don't :)
|
||||
if (currentLevel >= totalLevel)
|
||||
currentLevel = totalLevel - 1;
|
||||
|
||||
//Psionics have MaxPowerLevel as their column name
|
||||
string columnName = "MaxPowerLevel";
|
||||
|
||||
//Invokers have MaxInvocationLevel
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
columnName = "MaxInvocationLevel";
|
||||
|
||||
// Truenamers have 3 sets of utterances, ranging from 1-6, EvolvingMind covers the entire range
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
columnName = "EvolvingMind";
|
||||
spellLevel2da = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
columnName = "VestigeLvl";
|
||||
spellLevel2da = "cls_bind_binder";
|
||||
}
|
||||
|
||||
// ToB doesn't have a concept of this, but we don't care.
|
||||
|
||||
int maxLevel = StringToInt(Get2DACache(spellLevel2da, columnName, currentLevel));
|
||||
return maxLevel;
|
||||
}
|
||||
}
|
||||
|
||||
int GetMinSpellLevel(int nClass)
|
||||
{
|
||||
// again sponts have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
return GetMinSpellLevelForCasterLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND
|
||||
|| nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER
|
||||
|| nClass == CLASS_TYPE_SHADOWSMITH
|
||||
|| nClass == CLASS_TYPE_BINDER)
|
||||
return 1;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMaxSpellLevel(int nClass)
|
||||
{
|
||||
if (nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSION)
|
||||
return 9;
|
||||
if (nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
return 5;
|
||||
if (nClass == CLASS_TYPE_PSYWAR)
|
||||
return 6;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
|
||||
int GetHighestLevelPossibleInClass(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
|
||||
//sponts have their spells in the classes.2da
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
sFile = GetAMSKnownFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
sFile = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "cls_bind_binder";
|
||||
}
|
||||
}
|
||||
|
||||
return Get2DARowCount(sFile);
|
||||
}
|
||||
|
||||
int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
|
||||
{
|
||||
// This controls who can use the Spellbook NUI, if for some reason you don't
|
||||
@ -1146,3 +835,14 @@ int JsonArrayContainsInt(json list, int item)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int IsSpellbookNUIOpen(object oPC)
|
||||
{
|
||||
int nPreviousToken = NuiFindWindow(oPC, PRC_SPELLBOOK_NUI_WINDOW_ID);
|
||||
if (nPreviousToken != 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ const string _MYSTERY_LIST_MISC_ARRAY = "_MysteriesKnownMiscArray";
|
||||
const string _MYSTERY_LIST_LEVEL_ARRAY = "_MysteriesKnownLevelArray_";
|
||||
const string _MYSTERY_LIST_GENERAL_ARRAY = "_MysteriesKnownGeneralArray";
|
||||
|
||||
#include "shd_inc_shdfunc"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function prototypes */
|
||||
|
@ -1441,8 +1441,9 @@ int CheckSecondaryPrC(object oPC = OBJECT_SELF)
|
||||
if (GetHasFeat(FEAT_WILDMAGE_SPELLCASTING_BARD)) return TRUE;
|
||||
if (GetHasFeat(FEAT_WWOC_SPELLCASTING_BARD)) return TRUE;
|
||||
}
|
||||
else if (bBeguiler)
|
||||
if (bBeguiler)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: CheckSecondaryPrC >>> Entering Beguiler", oPC);
|
||||
if (GetHasFeat(FEAT_ABCHAMP_SPELLCASTING_BEGUILER)) return TRUE;
|
||||
if (GetHasFeat(FEAT_AOTS_SPELLCASTING_BEGUILER)) return TRUE;
|
||||
if (GetHasFeat(FEAT_ALCHEM_SPELLCASTING_BEGUILER)) return TRUE;
|
||||
@ -1492,8 +1493,9 @@ int CheckSecondaryPrC(object oPC = OBJECT_SELF)
|
||||
|
||||
|
||||
}
|
||||
else if (bDuskblade)
|
||||
if (bDuskblade)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: CheckSecondaryPrC >>> Entering Dusblade", oPC);
|
||||
if (GetHasFeat(FEAT_ABCHAMP_SPELLCASTING_DUSKBLADE)) return TRUE;
|
||||
if (GetHasFeat(FEAT_AOTS_SPELLCASTING_DUSKBLADE)) return TRUE;
|
||||
if (GetHasFeat(FEAT_ALCHEM_SPELLCASTING_DUSKBLADE)) return TRUE;
|
||||
@ -1540,8 +1542,9 @@ int CheckSecondaryPrC(object oPC = OBJECT_SELF)
|
||||
|
||||
|
||||
}
|
||||
else if (bSorcerer)
|
||||
if (bSorcerer)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: CheckSecondaryPrC >>> Entering Sorcerer", oPC);
|
||||
if (GetHasFeat(FEAT_ABERRATION_SPELLCASTING_DRIDER)) return TRUE;
|
||||
if (GetHasFeat(FEAT_MONSTROUS_SPELLCASTING_ARKAMOI)) return TRUE;
|
||||
if (GetHasFeat(FEAT_MONSTROUS_SPELLCASTING_MARRUTACT)) return TRUE;
|
||||
@ -1599,8 +1602,9 @@ int CheckSecondaryPrC(object oPC = OBJECT_SELF)
|
||||
if (GetHasFeat(FEAT_WILDMAGE_SPELLCASTING_SORCERER)) return TRUE;
|
||||
if (GetHasFeat(FEAT_WWOC_SPELLCASTING_SORCERER)) return TRUE;
|
||||
}
|
||||
else if (bWarmage)
|
||||
if (bWarmage)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: CheckSecondaryPrC >>> Entering Warmage", oPC);
|
||||
if (GetHasFeat(FEAT_AOTS_SPELLCASTING_WARMAGE)) return TRUE;
|
||||
if (GetHasFeat(FEAT_ALCHEM_SPELLCASTING_WARMAGE)) return TRUE;
|
||||
if (GetHasFeat(FEAT_ANIMA_SPELLCASTING_WARMAGE)) return TRUE;
|
||||
@ -1662,14 +1666,71 @@ int BardSorcPrCCheck(object oCaster, int nCastingClass, object oSpellCastItem)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//check its a sorc spell
|
||||
//check its a sorcerer spell
|
||||
if(nCastingClass == CLASS_TYPE_SORCERER)
|
||||
{
|
||||
if (CheckSecondaryPrC(oCaster) == TRUE)
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> nCastingClass is Sorcerer.", oCaster);
|
||||
//no need to check further if new spellbooks are disabled
|
||||
if(GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK))
|
||||
{
|
||||
if (DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Sorcerer w/RHD found.", oCaster);
|
||||
if (DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> PRC_SORC_DISALLOW_NEWSPELLBOOK.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
//check they have sorcerer levels
|
||||
if(!GetLevelByClass(CLASS_TYPE_SORCERER, oCaster))
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Not a sorcerer.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
//check if they are casting via new spellbook
|
||||
if(GetLocalInt(oCaster, "NSB_Class") != CLASS_TYPE_SORCERER && GetLevelByClass(CLASS_TYPE_ULTIMATE_MAGUS, oCaster))
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> UltMagus using new spellbook.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
//check if they are casting via new spellbook
|
||||
if(GetLocalInt(oCaster, "NSB_Class") == CLASS_TYPE_SORCERER)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Using new spellbook.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
if(GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oCaster) > 0 && CheckSecondaryPrC(oCaster) == TRUE)
|
||||
{
|
||||
if (DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Sublime Chord w/RHD found.", oCaster);
|
||||
FloatingTextStringOnCreature("You must use the new spellbook on the class radial.", oCaster, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
if (CheckSecondaryPrC(oCaster) == TRUE)
|
||||
{
|
||||
if (DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Sorcerer w/RHD found.", oCaster);
|
||||
FloatingTextStringOnCreature("You must use the new spellbook on the class radial.", oCaster, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
//check they have arcane PrC or Draconic Arcane Grace/Breath
|
||||
if(!(GetArcanePRCLevels(oCaster, nCastingClass) - GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oCaster))
|
||||
&& !(GetHasFeat(FEAT_DRACONIC_GRACE, oCaster) || GetHasFeat(FEAT_DRACONIC_BREATH, oCaster)))
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> First Sublime Chord check.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//check they have sorcerer in first arcane slot
|
||||
//if(GetPrimaryArcaneClass() != CLASS_TYPE_SORCERER)
|
||||
if(GetPrCAdjustedCasterLevelByType(TYPE_ARCANE, oCaster, TRUE) != GetPrCAdjustedCasterLevelByType(CLASS_TYPE_SORCERER, oCaster, TRUE))
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> GetPrCAdjustedCasterLevelByType.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
//at this point, they must be using the bioware spellbook
|
||||
//from a class that adds to bard
|
||||
FloatingTextStringOnCreature("You must use the new spellbook on the class radial.", oCaster, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* //check its a sorc spell
|
||||
if(nCastingClass == CLASS_TYPE_SORCERER)
|
||||
{
|
||||
//no need to check further if new spellbooks are disabled
|
||||
if(GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK))
|
||||
return TRUE;
|
||||
@ -1708,7 +1769,7 @@ int BardSorcPrCCheck(object oCaster, int nCastingClass, object oSpellCastItem)
|
||||
//from a class that adds to sorc
|
||||
FloatingTextStringOnCreature("You must use the new spellbook on the class radial.", oCaster, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
} */
|
||||
|
||||
//check its a bard spell
|
||||
if(nCastingClass == CLASS_TYPE_BARD)
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "tob_inc_tobfunc"
|
||||
#include "shd_inc_shdfunc"
|
||||
#include "inv_inc_invfunc"
|
||||
#include "prc_nui_lv_inc"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function prototypes */
|
||||
@ -87,7 +88,7 @@ void CheckSpellbooks(object oPC)
|
||||
CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 3);
|
||||
}
|
||||
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_SORCERER))
|
||||
{
|
||||
{
|
||||
CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 3);
|
||||
}
|
||||
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_WARMAGE, oPC))
|
||||
@ -98,7 +99,7 @@ void CheckSpellbooks(object oPC)
|
||||
{
|
||||
CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 3);
|
||||
}
|
||||
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_BEGUILER, oPC))
|
||||
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_BEGUILER, oPC))
|
||||
{
|
||||
CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 3);
|
||||
}
|
||||
@ -134,9 +135,9 @@ void CheckSpellbooks(object oPC)
|
||||
|
||||
/* void CheckSpellbooks(object oPC)
|
||||
{
|
||||
if(GetIsRHDSorcerer(oPC) && CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9))
|
||||
if(GetIsRHDSorcerer(oPC) && CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9))
|
||||
return;
|
||||
if(GetIsRHDBard(oPC) && CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6))
|
||||
if(GetIsRHDBard(oPC) && CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6))
|
||||
return;
|
||||
if(!GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK) && CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6))
|
||||
return;
|
||||
@ -278,10 +279,15 @@ int CheckMissingPowers(object oPC, int nClass)
|
||||
|
||||
if(nCurrentPowers < nMaxPowers)
|
||||
{
|
||||
if (nClass <= 0)
|
||||
nClass = GetPrimaryPsionicClass(oPC);
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("psi_powconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@ -304,9 +310,15 @@ int CheckMissingInvocations(object oPC, int nClass)
|
||||
|
||||
if(nCurrentInvocations < nMaxInvocations)
|
||||
{
|
||||
if (nClass == CLASS_TYPE_INVALID || nClass == -2)
|
||||
nClass = GetPrimaryInvocationClass(oPC);
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain invocations and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("inv_invokeconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -364,7 +376,7 @@ int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
||||
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_OUTSIDER, oPC);
|
||||
|
||||
//:: Aranea cast as sorcerers
|
||||
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|
||||
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|
||||
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_SHAPECHANGER, oPC);
|
||||
|
||||
//::Arkamoi cast as sorcerers
|
||||
@ -400,7 +412,7 @@ int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
||||
if(!nLevel)
|
||||
return FALSE;
|
||||
|
||||
if(nClass == CLASS_TYPE_BARD || nClass == CLASS_TYPE_SORCERER)
|
||||
if(nClass == CLASS_TYPE_BARD || nClass == CLASS_TYPE_SORCERER)
|
||||
{
|
||||
if((GetLevelByClass(nClass, oPC) == nLevel) //no PrC
|
||||
&& !(GetHasFeat(FEAT_DRACONIC_GRACE, oPC) || GetHasFeat(FEAT_DRACONIC_BREATH, oPC))) //no Draconic feats that apply
|
||||
@ -411,29 +423,24 @@ int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
||||
int nLastGainLevel = GetPersistantLocalInt(oPC, "LastSpellGainLevel");
|
||||
nLevel = GetLevelByClass(CLASS_TYPE_ARCHIVIST, oPC);
|
||||
|
||||
|
||||
//add cleric spells known for level 0
|
||||
if(persistant_array_get_size(oPC, "Spellbook_Known_"+IntToString(CLASS_TYPE_ARCHIVIST)+"_0") < 5) // TODO: replace with GetSpellKnownCurrentCount
|
||||
{
|
||||
ActionDoCommand(AddSpellsForLevel(CLASS_TYPE_ARCHIVIST, 0));
|
||||
}
|
||||
if(nLastGainLevel < nLevel)
|
||||
{
|
||||
if(nLevel == 1)
|
||||
{
|
||||
//count the number of available at 1st level spells
|
||||
int nSpellsAvailable = 3 + GetAbilityModifier(ABILITY_INTELLIGENCE, oPC);
|
||||
SetLocalInt(oPC, "LrnLvlUp", nSpellsAvailable);
|
||||
}
|
||||
else if(nLevel > 1)
|
||||
//add additional 2 spells form cleric list
|
||||
SetLocalInt(oPC, "LrnLvlUp", 2);
|
||||
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_ARCHIVIST);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, TRUE, FALSE, oPC);
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
//add cleric spells known for level 0
|
||||
else if(persistant_array_get_size(oPC, "Spellbook_Known_"+IntToString(CLASS_TYPE_ARCHIVIST)+"_0") < 5) // TODO: replace with GetSpellKnownCurrentCount
|
||||
{
|
||||
ActionDoCommand(AddSpellsForLevel(CLASS_TYPE_ARCHIVIST, 0));
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
@ -458,12 +465,15 @@ int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", nClass);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "SpellbookMaxSpelllevel", nMaxLevel);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@ -474,20 +484,28 @@ int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
||||
int nALSpells = GetPersistantLocalInt(oPC, "AdvancedLearning_"+IntToString(nClass));
|
||||
if(nClass == CLASS_TYPE_BEGUILER && nALSpells < (nLevel+1)/4)//one every 4 levels starting at 3.
|
||||
{
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_BEGUILER);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "AdvancedLearning", 1);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
else if(nClass == CLASS_TYPE_DREAD_NECROMANCER && nALSpells < nLevel/4)//one every 4 levels
|
||||
{
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_DREAD_NECROMANCER);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "AdvancedLearning", 1);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
else if(nClass == CLASS_TYPE_WARMAGE)
|
||||
@ -502,11 +520,15 @@ int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
||||
(nLevel >= 6 && nLevel < 11 && nALSpells < 2) ||
|
||||
(nLevel >= 3 && nLevel < 6 && nALSpells < 1))
|
||||
{
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_WARMAGE);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "AdvancedLearning", 1);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@ -535,9 +557,13 @@ int CheckMissingUtterances(object oPC, int nClass, int nLexicon)
|
||||
|
||||
if(nCurrentUtterances < nMaxUtterances)
|
||||
{
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain Utterances and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("true_utterconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -557,9 +583,13 @@ int CheckMissingManeuvers(object oPC, int nClass)
|
||||
|
||||
if(nCurrentManeuvers < nMaxManeuvers || nCurrentStances < nMaxStances)
|
||||
{
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("tob_moveconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -577,10 +607,13 @@ int CheckMissingMysteries(object oPC, int nClass)
|
||||
|
||||
if(nCurrentMysteries < nMaxMysteries)
|
||||
{
|
||||
if (!IsLevelUpNUIOpen(oPC))
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
/*
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("shd_mystconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
@ -7,7 +7,7 @@
|
||||
10 MAR 09 by GC
|
||||
*/ /** @file
|
||||
|
||||
Although you may be young by the elve's reckoning,
|
||||
Although you may be young by the elves' reckoning,
|
||||
your blade guide lends you the experience and wisdom
|
||||
of one who has fought battles across countless fields.
|
||||
|
||||
@ -53,7 +53,7 @@ void main()
|
||||
effect eAC;
|
||||
int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE, oInitiator);
|
||||
if(nInt >= 1) eAC = EffectACDecrease(nInt);
|
||||
PerformAttackRound(oTarget, oInitiator, eAC, 6.0, 0, 0, 0, FALSE, "", "", FALSE, FALSE, TRUE);
|
||||
PerformAttackRound(oTarget, oInitiator, eAC, 6.0, 0, 0, 0, FALSE, "Tactical Insight: Hit!", "Tactical Insight: Miss!", FALSE, FALSE, TRUE);
|
||||
|
||||
// Expend ability
|
||||
SetLocalInt(oInitiator, "ETBL_Tactical_Insight_Expended", TRUE);
|
||||
|
@ -79,6 +79,7 @@ void RemoveUncannyDodge(object oInitiator)
|
||||
DeleteLocalInt(oInitiator, "ETBL_AUD_Applied");
|
||||
}
|
||||
}
|
||||
|
||||
void BladeGuide(object oInitiator, object oItem)
|
||||
{
|
||||
if (GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
|
||||
@ -176,11 +177,12 @@ void main()
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oInitiator);
|
||||
}
|
||||
|
||||
int nClass = CLASS_TYPE_ETERNAL_BLADE;
|
||||
int nLevel = GetLevelByClass(CLASS_TYPE_ETERNAL_BLADE, oInitiator);
|
||||
int nMoveTotal = GetKnownManeuversModifier(oInitiator, nClass, MANEUVER_TYPE_MANEUVER);
|
||||
int nStncTotal = GetKnownManeuversModifier(oInitiator, nClass, MANEUVER_TYPE_STANCE);
|
||||
int nRdyTotal = GetReadiedManeuversModifier(oInitiator, nClass);
|
||||
int nClass = CLASS_TYPE_ETERNAL_BLADE;
|
||||
int nLevel = GetLevelByClass(CLASS_TYPE_ETERNAL_BLADE, oInitiator);
|
||||
int nBladeClass = GetPrimaryBladeMagicClass(oInitiator);
|
||||
int nMoveTotal = GetKnownManeuversModifier(oInitiator, nBladeClass, MANEUVER_TYPE_MANEUVER);
|
||||
int nStncTotal = GetKnownManeuversModifier(oInitiator, nBladeClass, MANEUVER_TYPE_STANCE);
|
||||
int nRdyTotal = GetReadiedManeuversModifier(oInitiator, nBladeClass);
|
||||
|
||||
if(DEBUG) DoDebug("tob_eternalblade running, event: " + IntToString(nEvent));
|
||||
if(DEBUG) DoDebug("tob_eternalblade nMoveTotal: " + IntToString(nMoveTotal));
|
||||
@ -203,57 +205,109 @@ void main()
|
||||
// It's not pretty, but it works
|
||||
if (nLevel >= 1 && !GetPersistantLocalInt(oInitiator, "ToBEternalBlade1"))
|
||||
{
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 1");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 1: " + IntToString(++nMoveTotal));
|
||||
DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
nMoveTotal += 1;
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 1");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 1: " + IntToString(nMoveTotal));
|
||||
//DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
SetKnownManeuversModifier(oInitiator, nBladeClass, nMoveTotal, MANEUVER_TYPE_MANEUVER);
|
||||
SetPersistantLocalInt(oInitiator, "ToBEternalBlade1", TRUE);
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", 270);//DISCIPLINE_DEVOTED_SPIRIT + DISCIPLINE_DIAMOND_MIND + DISCIPLINE_IRON_HEART + DISCIPLINE_WHITE_RAVEN
|
||||
}
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", DISCIPLINE_DEVOTED_SPIRIT +
|
||||
DISCIPLINE_DIAMOND_MIND +
|
||||
DISCIPLINE_IRON_HEART +
|
||||
DISCIPLINE_WHITE_RAVEN); //:: (270)
|
||||
|
||||
if (DEBUG) DoDebug("Granted Maneuver at Level 1: total now " + IntToString(nMoveTotal));
|
||||
if (DEBUG) DoDebug(IntToString(nStncTotal) +" stances known");
|
||||
if (DEBUG) DoDebug("Readied maneuvers now: " + IntToString(nRdyTotal));
|
||||
}
|
||||
|
||||
if (nLevel >= 3 && !GetPersistantLocalInt(oInitiator, "ToBEternalBlade3"))
|
||||
{
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 3");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 3: " + IntToString(++nMoveTotal));
|
||||
SetReadiedManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nRdyTotal);
|
||||
DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
nMoveTotal += 1;
|
||||
nRdyTotal += 1;
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 3");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 3: " + IntToString(nMoveTotal));
|
||||
SetReadiedManeuversModifier(oInitiator, nBladeClass, nRdyTotal);
|
||||
//DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
SetKnownManeuversModifier(oInitiator, nBladeClass, nMoveTotal, MANEUVER_TYPE_MANEUVER);
|
||||
SetPersistantLocalInt(oInitiator, "ToBEternalBlade3", TRUE);
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", 270);//DISCIPLINE_DEVOTED_SPIRIT + DISCIPLINE_DIAMOND_MIND + DISCIPLINE_IRON_HEART + DISCIPLINE_WHITE_RAVEN
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", DISCIPLINE_DEVOTED_SPIRIT +
|
||||
DISCIPLINE_DIAMOND_MIND +
|
||||
DISCIPLINE_IRON_HEART +
|
||||
DISCIPLINE_WHITE_RAVEN); //:: (270)
|
||||
|
||||
if (DEBUG) DoDebug("Granted Maneuver at Level 3: total now " + IntToString(nMoveTotal));
|
||||
if (DEBUG) DoDebug(IntToString(nStncTotal) +" stances known");
|
||||
if (DEBUG) DoDebug("Readied maneuvers now: " + IntToString(nRdyTotal));
|
||||
}
|
||||
|
||||
if (nLevel >= 5 && !GetPersistantLocalInt(oInitiator, "ToBEternalBlade5"))
|
||||
{
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 5");
|
||||
nStncTotal += 1;
|
||||
nMoveTotal += 1;
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 5");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 5: " + IntToString(++nMoveTotal));
|
||||
DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nStncTotal, MANEUVER_TYPE_STANCE));
|
||||
DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
//DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), nStncTotal, MANEUVER_TYPE_STANCE));
|
||||
//DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
SetKnownManeuversModifier(oInitiator, nBladeClass, nStncTotal, MANEUVER_TYPE_STANCE);
|
||||
SetKnownManeuversModifier(oInitiator, nBladeClass, nMoveTotal, MANEUVER_TYPE_MANEUVER);
|
||||
SetPersistantLocalInt(oInitiator, "ToBEternalBlade5", TRUE);
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", 270);//DISCIPLINE_DEVOTED_SPIRIT + DISCIPLINE_DIAMOND_MIND + DISCIPLINE_IRON_HEART + DISCIPLINE_WHITE_RAVEN
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", DISCIPLINE_DEVOTED_SPIRIT +
|
||||
DISCIPLINE_DIAMOND_MIND +
|
||||
DISCIPLINE_IRON_HEART +
|
||||
DISCIPLINE_WHITE_RAVEN); //:: (270)
|
||||
|
||||
if (DEBUG) DoDebug("Granted Maneuver at Level 5: total now " + IntToString(nMoveTotal));
|
||||
if (DEBUG) DoDebug(IntToString(nStncTotal) +" stances known");
|
||||
if (DEBUG) DoDebug("Readied maneuvers now: " + IntToString(nRdyTotal));
|
||||
}
|
||||
|
||||
if (nLevel >= 6 && !GetPersistantLocalInt(oInitiator, "ToBEternalBlade6"))
|
||||
{
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 6");
|
||||
SetReadiedManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nRdyTotal);
|
||||
nRdyTotal += 1;
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 6");
|
||||
SetReadiedManeuversModifier(oInitiator, nBladeClass, nRdyTotal);
|
||||
SetPersistantLocalInt(oInitiator, "ToBEternalBlade6", TRUE);
|
||||
|
||||
if (DEBUG) DoDebug("Granted Maneuver at Level 6: total now " + IntToString(nMoveTotal));
|
||||
if (DEBUG) DoDebug(IntToString(nStncTotal) +" stances known");
|
||||
if (DEBUG) DoDebug("Readied maneuvers now: " + IntToString(nRdyTotal));
|
||||
}
|
||||
|
||||
if (nLevel >= 7 && !GetPersistantLocalInt(oInitiator, "ToBEternalBlade7"))
|
||||
{
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 7");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 7: " + IntToString(++nMoveTotal));
|
||||
DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
nMoveTotal += 1;
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 7");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 7: " + IntToString(nMoveTotal));
|
||||
DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, nBladeClass, nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
SetPersistantLocalInt(oInitiator, "ToBEternalBlade7", TRUE);
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", 270);//DISCIPLINE_DEVOTED_SPIRIT + DISCIPLINE_DIAMOND_MIND + DISCIPLINE_IRON_HEART + DISCIPLINE_WHITE_RAVEN
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", DISCIPLINE_DEVOTED_SPIRIT +
|
||||
DISCIPLINE_DIAMOND_MIND +
|
||||
DISCIPLINE_IRON_HEART +
|
||||
DISCIPLINE_WHITE_RAVEN); //:: (270)
|
||||
|
||||
if (DEBUG) DoDebug("Granted Maneuver at Level 7: total now " + IntToString(nMoveTotal));
|
||||
if (DEBUG) DoDebug(IntToString(nStncTotal) +" stances known");
|
||||
if (DEBUG) DoDebug("Readied maneuvers now: " + IntToString(nRdyTotal));
|
||||
}
|
||||
|
||||
if (nLevel >= 9 && !GetPersistantLocalInt(oInitiator, "ToBEternalBlade9"))
|
||||
{
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 9");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 9: " + IntToString(++nMoveTotal));
|
||||
SetReadiedManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nRdyTotal);
|
||||
DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, GetPrimaryBladeMagicClass(oInitiator), ++nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
nMoveTotal += 1;
|
||||
nRdyTotal += 1;
|
||||
if(DEBUG) DoDebug("tob_eternalblade: Adding Maneuver 9");
|
||||
if(DEBUG) DoDebug("tob_eternalblade SetKnownManeuversModifier 9: " + IntToString(nMoveTotal));
|
||||
SetReadiedManeuversModifier(oInitiator, nBladeClass, nRdyTotal);
|
||||
DelayCommand(0.0f, SetKnownManeuversModifier(oInitiator, nBladeClass, nMoveTotal, MANEUVER_TYPE_MANEUVER));
|
||||
SetPersistantLocalInt(oInitiator, "ToBEternalBlade9", TRUE);
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", 270);//DISCIPLINE_DEVOTED_SPIRIT + DISCIPLINE_DIAMOND_MIND + DISCIPLINE_IRON_HEART + DISCIPLINE_WHITE_RAVEN
|
||||
SetPersistantLocalInt(oInitiator, "AllowedDisciplines", DISCIPLINE_DEVOTED_SPIRIT +
|
||||
DISCIPLINE_DIAMOND_MIND +
|
||||
DISCIPLINE_IRON_HEART +
|
||||
DISCIPLINE_WHITE_RAVEN); //:: (270)
|
||||
|
||||
if (DEBUG) DoDebug("Granted Maneuver at Level 9: total now " + IntToString(nMoveTotal));
|
||||
if (DEBUG) DoDebug(IntToString(nStncTotal) +" stances known");
|
||||
if (DEBUG) DoDebug("Readied maneuvers now: " + IntToString(nRdyTotal));
|
||||
}
|
||||
|
||||
// Hook to OnLevelDown to remove the maneuver slots granted here
|
||||
|
@ -28,9 +28,9 @@ void main()
|
||||
int nStncTotal = GetKnownManeuversModifier(oInitiator, nClass, MANEUVER_TYPE_STANCE);
|
||||
int nRdyTotal = GetReadiedManeuversModifier(oInitiator, nClass);
|
||||
|
||||
DoDebug("nMoveTotal = "+IntToString(nMoveTotal));
|
||||
DoDebug("nStncTotal = "+IntToString(nStncTotal));
|
||||
DoDebug("nRdyTotal = "+IntToString(nRdyTotal));
|
||||
if (DEBUG) DoDebug("nMoveTotal = "+IntToString(nMoveTotal));
|
||||
if (DEBUG) DoDebug("nStncTotal = "+IntToString(nStncTotal));
|
||||
if (DEBUG) DoDebug("nRdyTotal = "+IntToString(nRdyTotal));
|
||||
|
||||
int nRubyLvl = GetLevelByClass(CLASS_TYPE_RUBY_VINDICATOR, oInitiator);
|
||||
int nRubyBonusMove = nRubyLvl / 2;
|
||||
@ -38,9 +38,9 @@ DoDebug("nRdyTotal = "+IntToString(nRdyTotal));
|
||||
if (nRubyLvl >= 6) nRubyBonusStance = 2;
|
||||
int nRubyBonusReady = nRubyLvl > 8 ? 2 : nRubyLvl > 4 ? 1 : 0;
|
||||
int nMod;
|
||||
DoDebug("nRubyBonusMove = "+IntToString(nRubyBonusMove));
|
||||
DoDebug("nRubyBonusStance = "+IntToString(nRubyBonusStance));
|
||||
DoDebug("nRubyBonusReady = "+IntToString(nRubyBonusReady));
|
||||
if (DEBUG) DoDebug("nRubyBonusMove = "+IntToString(nRubyBonusMove));
|
||||
if (DEBUG) DoDebug("nRubyBonusStance = "+IntToString(nRubyBonusStance));
|
||||
if (DEBUG) DoDebug("nRubyBonusReady = "+IntToString(nRubyBonusReady));
|
||||
|
||||
// We aren't being called from any event, instead from EvalPRCFeats
|
||||
if(nEvent == FALSE)
|
||||
|
@ -85,11 +85,11 @@ void main()
|
||||
if(nPreReq1>0 && !GetHasFeat(nPreReq1, oPC)) nAllPreReq = 0;
|
||||
if(nPreReq1==213 && GetLevelByClass(CLASS_TYPE_MONK, oPC) >= 1) nAllPreReq = 1; //for Ki Strike and monks
|
||||
if(nPreReq2>0 && !GetHasFeat(nPreReq2, oPC)) nAllPreReq = 0;
|
||||
if(nCon>0 && !GetAbilityScore(oPC,ABILITY_CONSTITUTION) >= nCon) nAllPreReq = 0;
|
||||
if(nWis>0 && !GetAbilityScore(oPC,ABILITY_CONSTITUTION) >= nWis) nAllPreReq = 0;
|
||||
if(nCha>0 && !GetAbilityScore(oPC,ABILITY_CONSTITUTION) >= nCha) nAllPreReq = 0;
|
||||
if(nBAB>0 && !GetBaseAttackBonus(oPC) >= nBAB) nAllPreReq = 0;
|
||||
if(nLaw>0 && !GetAlignmentLawChaos(oPC) == ALIGNMENT_LAWFUL) nAllPreReq = 0;
|
||||
if(nCon>0 && GetAbilityScore(oPC,ABILITY_CONSTITUTION, TRUE) < nCon) nAllPreReq = 0;
|
||||
if(nWis>0 && GetAbilityScore(oPC,ABILITY_WISDOM, TRUE) < nWis) nAllPreReq = 0;
|
||||
if(nCha>0 && GetAbilityScore(oPC,ABILITY_CHARISMA, TRUE) < nCha) nAllPreReq = 0;
|
||||
if(nBAB>0 && GetBaseAttackBonus(oPC) < nBAB) nAllPreReq = 0;
|
||||
if(nLaw>0 && !(GetAlignmentLawChaos(oPC) == ALIGNMENT_LAWFUL)) nAllPreReq = 0;
|
||||
|
||||
if (!GetHasFeat(nFeat, oPC) && !GetLocalInt(oPC, "VoPFeat"+IntToString(nFeat)) && nAllPreReq == 1) AddChoice(sName, nFeat, oPC);
|
||||
}
|
||||
@ -122,6 +122,9 @@ void main()
|
||||
{
|
||||
SetPersistantLocalInt(oPC, "VoPFeat"+IntToString(nLevel),1); //Register the choice was made
|
||||
|
||||
// Store the feat ID for recalling onClientEnter
|
||||
SetPersistantLocalInt(oPC, "VoPFeatID" + IntToString(nChoice), 1);
|
||||
|
||||
//If it was not cancelled, give chosen feat to PC (as EffectBonusFeat)
|
||||
if(nChoice > 0)
|
||||
{
|
||||
|
27
nwn/nwnprc/trunk/scripts/prc_nui_dsc_evnt.nss
Normal file
27
nwn/nwnprc/trunk/scripts/prc_nui_dsc_evnt.nss
Normal file
@ -0,0 +1,27 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC Spell Description NUI Events
|
||||
//:: prc_nui_dsc_evnt
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the event logic used for the spell description nui
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 20.06.2005
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_nui_consts"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPlayer = NuiGetEventPlayer();
|
||||
int nToken = NuiGetEventWindow();
|
||||
string sEvent = NuiGetEventType();
|
||||
string sElement = NuiGetEventElement();
|
||||
string sWindowId = NuiGetWindowId(oPlayer, nToken);
|
||||
|
||||
// if the OK button was clicked then we close the window.
|
||||
if (sElement == NUI_SPELL_DESCRIPTION_OK_BUTTON)
|
||||
DelayCommand(0.1f, NuiDestroy(oPlayer, nToken));
|
||||
}
|
||||
|
90
nwn/nwnprc/trunk/scripts/prc_nui_dsc_view.nss
Normal file
90
nwn/nwnprc/trunk/scripts/prc_nui_dsc_view.nss
Normal file
@ -0,0 +1,90 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC Spellbook Description NUI
|
||||
//:: prc_nui_dsc_view
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the view for the Spell Description NUI
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 29.05.2005
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "nw_inc_nui"
|
||||
#include "prc_nui_consts"
|
||||
#include "inc_2dacache"
|
||||
#include "prc_nui_com_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
int featID = GetLocalInt(OBJECT_SELF, NUI_SPELL_DESCRIPTION_FEATID_VAR);
|
||||
int spellId = GetLocalInt(OBJECT_SELF, NUI_SPELL_DESCRIPTION_SPELLID_VAR);
|
||||
int realSpellId = GetLocalInt(OBJECT_SELF, NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR);
|
||||
int nClass = GetLocalInt(OBJECT_SELF, NUI_SPELL_DESCRIPTION_CLASSID_VAR);
|
||||
|
||||
// look for existing window and destroy
|
||||
int nPreviousToken = NuiFindWindow(OBJECT_SELF, NUI_SPELL_DESCRIPTION_WINDOW_ID);
|
||||
if(nPreviousToken != 0)
|
||||
{
|
||||
NuiDestroy(OBJECT_SELF, nPreviousToken);
|
||||
}
|
||||
|
||||
// in order of accuracy for names it goes RealSpellID > SpellID > FeatID
|
||||
string spellName = GetSpellName(spellId, realSpellId, featID, nClass);
|
||||
// Descriptions and Icons are accuratly stored on the feat
|
||||
string spellDesc = GetStringByStrRef(StringToInt(Get2DACache("feat", "DESCRIPTION", featID)));
|
||||
string spellIcon = Get2DACache("feat", "ICON", featID);
|
||||
|
||||
json jRoot = JsonArray();
|
||||
json jGroup = JsonArray();
|
||||
|
||||
json jRow = JsonArray();
|
||||
|
||||
json jImage = NuiImage(JsonString(spellIcon), JsonInt(NUI_ASPECT_EXACT), JsonInt(NUI_HALIGN_LEFT), JsonInt(NUI_VALIGN_TOP));
|
||||
jImage = NuiWidth(jImage, 32.0f);
|
||||
jRow = JsonArrayInsert(jRow, jImage);
|
||||
jRow = NuiCol(jRow);
|
||||
jGroup = JsonArrayInsert(jGroup, jRow);
|
||||
|
||||
jRow = JsonArray();
|
||||
json jText = NuiText(JsonString(spellDesc), FALSE, NUI_SCROLLBARS_AUTO);
|
||||
jRow = JsonArrayInsert(jRow, jText);
|
||||
jRow = NuiCol(jRow);
|
||||
jGroup = JsonArrayInsert(jGroup, jRow);
|
||||
|
||||
jGroup = NuiRow(jGroup);
|
||||
jGroup = NuiGroup(jGroup, TRUE, NUI_SCROLLBARS_NONE);
|
||||
jRoot = JsonArrayInsert(jRoot, jGroup);
|
||||
|
||||
jRow = JsonArray();
|
||||
jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
json jButton = NuiId(NuiButton(JsonString("OK")), NUI_SPELL_DESCRIPTION_OK_BUTTON);
|
||||
jButton = NuiWidth(jButton, 175.0f);
|
||||
jButton = NuiHeight(jButton, 48.0f);
|
||||
jRow = JsonArrayInsert(jRow, jButton);
|
||||
jRow = NuiRow(jRow);
|
||||
|
||||
jRoot = JsonArrayInsert(jRoot, jRow);
|
||||
jRoot = NuiCol(jRoot);
|
||||
|
||||
|
||||
// This is the main window with jRoot as the main pane. It includes titles and parameters (more on those later)
|
||||
json nui = NuiWindow(jRoot, JsonString(spellName), NuiBind("geometry"), NuiBind("resizable"), JsonBool(FALSE), NuiBind("closable"), NuiBind("transparent"), NuiBind("border"));
|
||||
|
||||
// finally create it and it'll return us a non-zero token.
|
||||
int nToken = NuiCreate(OBJECT_SELF, nui, NUI_SPELL_DESCRIPTION_WINDOW_ID);
|
||||
|
||||
// get the geometry of the window in case we opened this before and have a
|
||||
// preference for location
|
||||
json geometry = NuiRect(-1.0f,-1.0f, 426.0f, 446.0f);
|
||||
|
||||
// Set the binds to their default values
|
||||
NuiSetBind(OBJECT_SELF, nToken, "geometry", geometry);
|
||||
NuiSetBind(OBJECT_SELF, nToken, "resizable", JsonBool(FALSE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "closable", JsonBool(FALSE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "transparent", JsonBool(FALSE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "border", JsonBool(TRUE));
|
||||
|
||||
ClearSpellDescriptionNUI();
|
||||
}
|
||||
|
158
nwn/nwnprc/trunk/scripts/prc_nui_lv_event.nss
Normal file
158
nwn/nwnprc/trunk/scripts/prc_nui_lv_event.nss
Normal file
@ -0,0 +1,158 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC Level Up NUI Events
|
||||
//:: prc_nui_lv_event
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the logic that handles the events for the Level Up NUI
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 20.06.2005
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_nui_lv_inc"
|
||||
|
||||
void SetupAndCallSpellDescriptionNUI(object oPlayer, int spellbookId, int classId)
|
||||
{
|
||||
string sFile = GetClassSpellbookFile(classId);
|
||||
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
||||
int spellId = StringToInt(Get2DACache(sFile, "SpellID", spellbookId));
|
||||
int realSpellId = StringToInt(Get2DACache(sFile, "RealSpellID", spellbookId));
|
||||
|
||||
CreateSpellDescriptionNUI(oPlayer, featId, spellId, realSpellId, classId);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPlayer = NuiGetEventPlayer();
|
||||
int nToken = NuiGetEventWindow();
|
||||
string sEvent = NuiGetEventType();
|
||||
string sElement = NuiGetEventElement();
|
||||
string sWindowId = NuiGetWindowId(oPlayer, nToken);
|
||||
|
||||
// Not a mouseup event, nothing to do.
|
||||
if (sEvent != "mouseup")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we clicked a spell circle, set the selected circle to the new one and refresh the window
|
||||
if (FindSubString(sElement, NUI_LEVEL_UP_SPELL_CIRCLE_BUTTON_BASEID) >= 0)
|
||||
{
|
||||
int selectedCircle = StringToInt(RegExpReplace(NUI_LEVEL_UP_SPELL_CIRCLE_BUTTON_BASEID, sElement, ""));
|
||||
SetLocalInt(oPlayer, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR, selectedCircle);
|
||||
CloseNUILevelUpWindow(oPlayer);
|
||||
ExecuteScript("prc_nui_lv_view", oPlayer);
|
||||
return;
|
||||
}
|
||||
|
||||
json jPayload = NuiGetEventPayload();
|
||||
int nButton = JsonGetInt(JsonObjectGet(jPayload, "mouse_btn"));
|
||||
|
||||
if (FindSubString(sElement, NUI_LEVEL_UP_SPELL_DISABLED_BUTTON_BASEID) >= 0)
|
||||
{
|
||||
int spellbookId = StringToInt(RegExpReplace(NUI_LEVEL_UP_SPELL_DISABLED_BUTTON_BASEID, sElement, ""));
|
||||
int classId = GetLocalInt(oPlayer, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||
|
||||
// we right clicked a disabled button, tell what the spell is
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_RIGHT_CLICK)
|
||||
{
|
||||
SetupAndCallSpellDescriptionNUI(oPlayer, spellbookId, classId);
|
||||
return;
|
||||
}
|
||||
// we left clicked a disabled button, tell why it was disables
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_LEFT_CLICK)
|
||||
{
|
||||
SendMessageToPC(oPlayer, ReasonForDisabledSpell(classId, spellbookId, oPlayer));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (FindSubString(sElement, NUI_LEVEL_UP_SPELL_CHOSEN_DISABLED_BUTTON_BASEID) >= 0)
|
||||
{
|
||||
int spellbookId = StringToInt(RegExpReplace(NUI_LEVEL_UP_SPELL_CHOSEN_DISABLED_BUTTON_BASEID, sElement, ""));
|
||||
int classId = GetLocalInt(oPlayer, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||
|
||||
// we right clicked a disabled button, tell what the spell is
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_RIGHT_CLICK)
|
||||
{
|
||||
SetupAndCallSpellDescriptionNUI(oPlayer, spellbookId, classId);
|
||||
return;
|
||||
}
|
||||
// we left clicked a disabled button, tell why it was disabled
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_LEFT_CLICK)
|
||||
{
|
||||
SendMessageToPC(oPlayer, ReasonForDisabledChosen(classId, spellbookId, oPlayer));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (FindSubString(sElement, NUI_LEVEL_UP_SPELL_BUTTON_BASEID) >= 0)
|
||||
{
|
||||
int spellbookId = StringToInt(RegExpReplace(NUI_LEVEL_UP_SPELL_BUTTON_BASEID, sElement, ""));
|
||||
int classId = GetLocalInt(oPlayer, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||
|
||||
// If right click, open the Spell Description NUI
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_RIGHT_CLICK)
|
||||
{
|
||||
SetupAndCallSpellDescriptionNUI(oPlayer, spellbookId, classId);
|
||||
return;
|
||||
}
|
||||
// we are adding the spell to the chosen spell list then refreshing the window
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_LEFT_CLICK)
|
||||
{
|
||||
int chosenCircle = GetLocalInt(oPlayer, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR);
|
||||
|
||||
AddSpellToChosenList(classId, spellbookId, chosenCircle, oPlayer);
|
||||
CloseNUILevelUpWindow(oPlayer);
|
||||
ExecuteScript("prc_nui_lv_view", oPlayer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (FindSubString(sElement, NUI_LEVEL_UP_SPELL_CHOSEN_BUTTON_BASEID) >= 0)
|
||||
{
|
||||
int spellbookId = StringToInt(RegExpReplace(NUI_LEVEL_UP_SPELL_CHOSEN_BUTTON_BASEID, sElement, ""));
|
||||
int classId = GetLocalInt(oPlayer, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||
|
||||
|
||||
json jPayload = NuiGetEventPayload();
|
||||
int nButton = JsonGetInt(JsonObjectGet(jPayload, "mouse_btn"));
|
||||
|
||||
// If right click, open the Spell Description NUI
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_RIGHT_CLICK)
|
||||
{
|
||||
SetupAndCallSpellDescriptionNUI(oPlayer, spellbookId, classId);
|
||||
return;
|
||||
}
|
||||
// we are removing a chosen spell from the chosen list then refreshing the window
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_LEFT_CLICK)
|
||||
{
|
||||
int chosenCircle = GetLocalInt(oPlayer, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR);
|
||||
|
||||
RemoveSpellFromChosenList(classId, spellbookId, chosenCircle, oPlayer);
|
||||
CloseNUILevelUpWindow(oPlayer);
|
||||
ExecuteScript("prc_nui_lv_view", oPlayer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// we are resetting our choices
|
||||
if (sElement == NUI_LEVEL_UP_RESET_BUTTON)
|
||||
{
|
||||
ResetChoices(oPlayer);
|
||||
CloseNUILevelUpWindow(oPlayer);
|
||||
ExecuteScript("prc_nui_lv_view", oPlayer);
|
||||
return;
|
||||
}
|
||||
// finalize all our choices
|
||||
if (sElement == NUI_LEVEL_UP_DONE_BUTTON)
|
||||
{
|
||||
int classId = GetLocalInt(oPlayer, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||
FinishLevelUp(classId, oPlayer);
|
||||
CloseNUILevelUpWindow(oPlayer);
|
||||
ExecuteScript("prc_amagsys_gain", oPlayer);
|
||||
DelayCommand(0.2f, ExecuteScript("prc_nui_sb_view", oPlayer));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
353
nwn/nwnprc/trunk/scripts/prc_nui_lv_view.nss
Normal file
353
nwn/nwnprc/trunk/scripts/prc_nui_lv_view.nss
Normal file
@ -0,0 +1,353 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC Level Up NUI View
|
||||
//:: prc_nui_lv_view
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the logic that handles the view for the Level Up NUI
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 20.06.2005
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "nw_inc_nui"
|
||||
#include "prc_nui_consts"
|
||||
#include "prc_inc_function"
|
||||
#include "prc_nui_lv_inc"
|
||||
|
||||
//
|
||||
// CreateCircleButtons
|
||||
// Creates the spell circle buttons for the given class Id
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// json the NUI spell circle buttons
|
||||
//
|
||||
json CreateCircleButtons(int nClass)
|
||||
{
|
||||
json jRow = JsonArray();
|
||||
// get the spell list for the class
|
||||
json spellList = GetSpellListObject(nClass);
|
||||
|
||||
// get the keys which are circles
|
||||
json circleList = JsonObjectKeys(spellList);
|
||||
int totalCircles = JsonGetLength(circleList);
|
||||
int selectedCircle = GetLocalInt(OBJECT_SELF, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
json jCircle;
|
||||
// some classes have less than 10 circles, build buttons for circles
|
||||
// we have, leave the rest blank
|
||||
if (i < totalCircles)
|
||||
{
|
||||
int spellLevel = StringToInt(JsonGetString(JsonArrayGet(circleList, i)));
|
||||
// in case this isn't set, and we start at a spot higher than 0.
|
||||
// OR we switched classes and the selected circle is higher than possible
|
||||
// we set the value
|
||||
if ((selectedCircle == -1)
|
||||
&& (GetRemainingSpellChoices(nClass, spellLevel) || (i+1 == totalCircles)))
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR, spellLevel);
|
||||
selectedCircle = spellLevel;
|
||||
}
|
||||
|
||||
jCircle = NuiId(NuiButtonImage(JsonString(GetSpellLevelIcon(spellLevel))), NUI_LEVEL_UP_SPELL_CIRCLE_BUTTON_BASEID + IntToString(spellLevel));
|
||||
jCircle = NuiTooltip(jCircle, JsonString(GetSpellLevelToolTip(spellLevel)));
|
||||
|
||||
if (selectedCircle != spellLevel)
|
||||
jCircle = GreyOutButton(jCircle, 36.0f, 36.0f);
|
||||
}
|
||||
else
|
||||
jCircle = NuiText(JsonString(""), TRUE, NUI_SCROLLBARS_NONE);
|
||||
jCircle = NuiWidth(jCircle, 36.0f);
|
||||
jCircle = NuiHeight(jCircle, 36.0f);
|
||||
jCircle = NuiMargin(jCircle, 0.0f);
|
||||
jRow = JsonArrayInsert(jRow, jCircle);
|
||||
}
|
||||
|
||||
jRow = NuiRow(jRow);
|
||||
jRow = NuiMargin(jRow, 0.0f);
|
||||
return jRow;
|
||||
}
|
||||
|
||||
json CreateSpellButtons(int nClass, int selectedCircle)
|
||||
{
|
||||
json jRow = JsonArray();
|
||||
|
||||
json spellList = GetSpellListObject(nClass);
|
||||
json currentList = JsonObjectGet(spellList, IntToString(selectedCircle));
|
||||
int totalSpells = JsonGetLength(currentList);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < totalSpells; i++)
|
||||
{
|
||||
int spellbookId = JsonGetInt(JsonArrayGet(currentList, i));
|
||||
if (ShouldAddSpellToSpellButtons(nClass, spellbookId))
|
||||
{
|
||||
string sFile = GetClassSpellbookFile(nClass);
|
||||
string sRealSpellID = Get2DACache(sFile, "RealSpellID", spellbookId);
|
||||
int nRealSpellID = StringToInt(sRealSpellID);
|
||||
int spellId = StringToInt(Get2DACache(sFile, "SpellID", spellbookId));
|
||||
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
||||
|
||||
string spellName = GetSpellName(spellId, nRealSpellID, featId, nClass);
|
||||
|
||||
int enabled = ShouldSpellButtonBeEnabled(nClass, selectedCircle, spellbookId);
|
||||
json jSpellButton;
|
||||
if (enabled)
|
||||
jSpellButton = NuiId(NuiButton(JsonString("")), NUI_LEVEL_UP_SPELL_BUTTON_BASEID + IntToString(spellbookId));
|
||||
else
|
||||
jSpellButton = NuiId(NuiButton(JsonString("")), NUI_LEVEL_UP_SPELL_DISABLED_BUTTON_BASEID + IntToString(spellbookId));
|
||||
|
||||
json jIcons = JsonArray();
|
||||
json jIconLeft = NuiDrawListImage(JsonBool(TRUE), GetSpellIcon(spellId, featId), NuiRect(5.0f,5.0f,32.0f,32.0f), JsonInt(NUI_ASPECT_FIT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE), NUI_DRAW_LIST_ITEM_ORDER_AFTER);
|
||||
json jIconRight = NuiDrawListImage(JsonBool(TRUE), JsonString("nui_shld_right"), NuiRect(299.0f,8.0f,26.0f,26.0f), JsonInt(NUI_ASPECT_FIT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE), NUI_DRAW_LIST_ITEM_ORDER_AFTER);
|
||||
json jText = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 255), NuiRect(40.0f, 12.0f, 290.0f, 32.0f), JsonString(spellName));
|
||||
jIcons = JsonArrayInsert(jIcons, jIconLeft);
|
||||
jIcons = JsonArrayInsert(jIcons, jIconRight);
|
||||
jIcons = JsonArrayInsert(jIcons, jText);
|
||||
if (!enabled)
|
||||
jIcons = JsonArrayInsert(jIcons, CreateGreyOutRectangle(335.0f, 42.0f));
|
||||
jSpellButton = NuiDrawList(jSpellButton, JsonBool(FALSE), jIcons);
|
||||
jSpellButton = NuiWidth(jSpellButton, 335.0f);
|
||||
jSpellButton = NuiHeight(jSpellButton, 42.0f);
|
||||
jSpellButton = NuiMargin(jSpellButton, 0.0f);
|
||||
|
||||
jRow = JsonArrayInsert(jRow, jSpellButton);
|
||||
}
|
||||
}
|
||||
jRow = NuiCol(jRow);
|
||||
jRow = NuiGroup(jRow, TRUE, NUI_SCROLLBARS_Y);
|
||||
jRow = NuiWidth(jRow, 360.0f);
|
||||
jRow = NuiHeight(jRow, 360.0f);
|
||||
jRow = NuiMargin(jRow, 0.0f);
|
||||
|
||||
return jRow;
|
||||
}
|
||||
|
||||
json CreateChosenButtons(int nClass, int selectedCircle)
|
||||
{
|
||||
json jRow = JsonArray();
|
||||
|
||||
json selectedList = GetChosenSpellListObject(nClass);
|
||||
json currentList = JsonObjectGet(selectedList, IntToString(selectedCircle));
|
||||
if (currentList != JsonNull())
|
||||
{
|
||||
int totalSpells = JsonGetLength(currentList);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < totalSpells; i++)
|
||||
{
|
||||
int spellbookId = JsonGetInt(JsonArrayGet(currentList, i));
|
||||
|
||||
string sFile = GetClassSpellbookFile(nClass);
|
||||
string sRealSpellID = Get2DACache(sFile, "RealSpellID", spellbookId);
|
||||
int nRealSpellID = StringToInt(sRealSpellID);
|
||||
int spellId = StringToInt(Get2DACache(sFile, "SpellID", spellbookId));
|
||||
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
||||
|
||||
int enabled = EnableChosenButton(nClass, spellbookId, selectedCircle);
|
||||
|
||||
string spellName = GetSpellName(spellId, nRealSpellID, featId, nClass);
|
||||
|
||||
json jSpellButton;
|
||||
if (enabled)
|
||||
jSpellButton = NuiId(NuiButton(JsonString("")), NUI_LEVEL_UP_SPELL_CHOSEN_BUTTON_BASEID + IntToString(spellbookId));
|
||||
else
|
||||
jSpellButton = NuiId(NuiButton(JsonString("")), NUI_LEVEL_UP_SPELL_CHOSEN_DISABLED_BUTTON_BASEID + IntToString(spellbookId));
|
||||
|
||||
json jIcons = JsonArray();
|
||||
json jIconLeft = NuiDrawListImage(JsonBool(TRUE), GetSpellIcon(spellId, featId), NuiRect(5.0f,5.0f,32.0f,32.0f), JsonInt(NUI_ASPECT_FIT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE), NUI_DRAW_LIST_ITEM_ORDER_AFTER);
|
||||
json jIconRight = NuiDrawListImage(JsonBool(TRUE), JsonString("nui_shld_left"), NuiRect(299.0f,8.0f,26.0f,26.0f), JsonInt(NUI_ASPECT_FIT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE), NUI_DRAW_LIST_ITEM_ORDER_AFTER);
|
||||
json jText = NuiDrawListText(JsonBool(TRUE), NuiColor(255, 255, 255), NuiRect(40.0f, 12.0f, 290.0f, 32.0f), JsonString(spellName));
|
||||
jIcons = JsonArrayInsert(jIcons, jIconLeft);
|
||||
jIcons = JsonArrayInsert(jIcons, jIconRight);
|
||||
jIcons = JsonArrayInsert(jIcons, jText);
|
||||
if (!enabled)
|
||||
jIcons = JsonArrayInsert(jIcons, CreateGreyOutRectangle(335.0f, 42.0f));
|
||||
jSpellButton = NuiDrawList(jSpellButton, JsonBool(FALSE), jIcons);
|
||||
jSpellButton = NuiWidth(jSpellButton, 335.0f);
|
||||
jSpellButton = NuiHeight(jSpellButton, 42.0f);
|
||||
jSpellButton = NuiMargin(jSpellButton, 0.0f);
|
||||
|
||||
jRow = JsonArrayInsert(jRow, jSpellButton);
|
||||
}
|
||||
}
|
||||
|
||||
jRow = NuiCol(jRow);
|
||||
jRow = NuiGroup(jRow, TRUE, NUI_SCROLLBARS_Y);
|
||||
jRow = NuiWidth(jRow, 360.0f);
|
||||
jRow = NuiHeight(jRow, 360.0f);
|
||||
jRow = NuiMargin(jRow, 0.0f);
|
||||
|
||||
return jRow;
|
||||
}
|
||||
|
||||
string GetRemainingText(int nClass, int selectedCircle)
|
||||
{
|
||||
if (GetIsBladeMagicClass(nClass))
|
||||
{
|
||||
string remainingMan = IntToString(GetRemainingManeuverChoices(nClass));
|
||||
string remainingStance = IntToString(GetRemainingStanceChoices(nClass));
|
||||
|
||||
return remainingMan + " Remaining Maneuevers / " + remainingStance + " Remaining Stances";
|
||||
}
|
||||
|
||||
if (GetIsTruenamingClass(nClass))
|
||||
return IntToString(GetRemainingTruenameChoices(nClass, LEXICON_EVOLVING_MIND)) + " EM / "
|
||||
+ IntToString(GetRemainingTruenameChoices(nClass, LEXICON_CRAFTED_TOOL)) + " CT / "
|
||||
+ IntToString(GetRemainingTruenameChoices(nClass, LEXICON_PERFECTED_MAP)) + " PM";
|
||||
|
||||
int remainingSpellChoices = GetRemainingSpellChoices(nClass, selectedCircle, OBJECT_SELF);
|
||||
|
||||
if (GetIsInvocationClass(nClass))
|
||||
return IntToString(remainingSpellChoices) + " Remaining Invocations";
|
||||
if (GetIsShadowMagicClass(nClass))
|
||||
return IntToString(remainingSpellChoices) + " Remaining Mysteries";
|
||||
if (GetIsPsionicClass(nClass))
|
||||
return IntToString(remainingSpellChoices) + " Remaining Powers";
|
||||
return IntToString(remainingSpellChoices) + " Remaining Spells";
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
int nClass = GetLocalInt(OBJECT_SELF, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||
if (!IsClassAllowedToUseLevelUpNUI(nClass))
|
||||
{
|
||||
string name = GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", nClass)));
|
||||
SendMessageToPC(OBJECT_SELF, "The class " + name + " is not allowed to use the Level Up NUI!");
|
||||
DeleteLocalInt(OBJECT_SELF, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||
return;
|
||||
}
|
||||
|
||||
// First we look for any previous windows, if found (ie, non-zero) we destory them so we can start fresh.
|
||||
if (IsLevelUpNUIOpen())
|
||||
{
|
||||
// this is already rendered
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
///////////////
|
||||
// LEFT SIDE //
|
||||
///////////////
|
||||
|
||||
json jRoot = JsonArray();
|
||||
json jLeftSide = JsonArray();
|
||||
json jRightSide = JsonArray();
|
||||
|
||||
// Title
|
||||
|
||||
json jRow = JsonArray();
|
||||
json jTitle = NuiText(JsonString("Available/Known"), TRUE, NUI_SCROLLBARS_NONE);
|
||||
jTitle = NuiHeight(jTitle, 26.0f);
|
||||
jTitle = NuiWidth(jTitle, 360.0f);
|
||||
jTitle = NuiMargin(jTitle, 0.0f);
|
||||
jRow = JsonArrayInsert(jRow, jTitle);
|
||||
jRow = NuiRow(jRow);
|
||||
jRow = NuiMargin(jRow, 0.0f);
|
||||
jLeftSide = JsonArrayInsert(jLeftSide, jRow);
|
||||
|
||||
// Circles
|
||||
|
||||
jRow = CreateCircleButtons(nClass);
|
||||
jLeftSide = JsonArrayInsert(jLeftSide, jRow);
|
||||
|
||||
int selectedCircle = GetLocalInt(OBJECT_SELF, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR);
|
||||
|
||||
// Spells
|
||||
|
||||
jRow = CreateSpellButtons(nClass, selectedCircle);
|
||||
jLeftSide = JsonArrayInsert(jLeftSide, jRow);
|
||||
jLeftSide = NuiCol(jLeftSide);
|
||||
|
||||
////////////////
|
||||
// RIGHT SIDE //
|
||||
////////////////
|
||||
|
||||
// Title
|
||||
|
||||
jRow = JsonArray();
|
||||
|
||||
jTitle = NuiText(JsonString("Selected/Prepared"), TRUE, NUI_SCROLLBARS_NONE);
|
||||
jTitle = NuiHeight(jTitle, 26.0f);
|
||||
jTitle = NuiWidth(jTitle, 360.0f);
|
||||
jTitle = NuiMargin(jTitle, 0.0f);
|
||||
jRow = JsonArrayInsert(jRow, jTitle);
|
||||
jRow = NuiRow(jRow);
|
||||
jRow = NuiMargin(jRow, 0.0f);
|
||||
jRightSide = JsonArrayInsert(jRightSide, jRow);
|
||||
|
||||
// Remaining Choice
|
||||
|
||||
jRow = JsonArray();
|
||||
json jAmountLeft = NuiText(JsonString(GetRemainingText(nClass, selectedCircle)), TRUE, NUI_SCROLLBARS_NONE);
|
||||
jAmountLeft = NuiHeight(jAmountLeft, 36.0f);
|
||||
jAmountLeft = NuiWidth(jAmountLeft, 360.0f);
|
||||
jAmountLeft = NuiMargin(jAmountLeft, 0.0f);
|
||||
jRow = JsonArrayInsert(jRow, jAmountLeft);
|
||||
jRow = NuiRow(jRow);
|
||||
jRow = NuiMargin(jRow, 0.0f);
|
||||
jRightSide = JsonArrayInsert(jRightSide, jRow);
|
||||
|
||||
// Selected Choices
|
||||
|
||||
jRow = CreateChosenButtons(nClass, selectedCircle);
|
||||
jRightSide = JsonArrayInsert(jRightSide, jRow);
|
||||
jRightSide = NuiCol(jRightSide);
|
||||
|
||||
// Make each side
|
||||
|
||||
json tempRow = JsonArray();
|
||||
tempRow = JsonArrayInsert(tempRow, jLeftSide);
|
||||
tempRow = JsonArrayInsert(tempRow, jRightSide);
|
||||
tempRow = NuiRow(tempRow);
|
||||
|
||||
jRoot = JsonArrayInsert(jRoot, tempRow);
|
||||
|
||||
// Done button
|
||||
|
||||
jRow = JsonArray();
|
||||
json jResetButton = NuiId(NuiButton(JsonString("Reset")), NUI_LEVEL_UP_RESET_BUTTON);
|
||||
jResetButton = NuiWidth(jResetButton, 118.0f);
|
||||
jResetButton = NuiHeight(jResetButton, 50.0f);
|
||||
json jDoneButton = NuiId(NuiButton(JsonString("Done")), NUI_LEVEL_UP_DONE_BUTTON);
|
||||
jDoneButton = NuiWidth(jDoneButton, 118.0f);
|
||||
jDoneButton = NuiHeight(jDoneButton, 50.0f);
|
||||
if (!AllSpellsAreChosen(nClass, OBJECT_SELF))
|
||||
jDoneButton = NuiEnabled(jDoneButton, JsonBool(FALSE));
|
||||
jRow = JsonArrayInsert(jRow, NuiSpacer());
|
||||
jRow = JsonArrayInsert(jRow, jResetButton);
|
||||
jRow = JsonArrayInsert(jRow, jDoneButton);
|
||||
jRow = NuiRow(jRow);
|
||||
jRoot = JsonArrayInsert(jRoot, jRow);
|
||||
|
||||
jRoot = NuiCol(jRoot);
|
||||
|
||||
string className = GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", nClass)));
|
||||
string title = className + " Level Up";
|
||||
|
||||
// This is the main window with jRoot as the main pane. It includes titles and parameters (more on those later)
|
||||
json nui = NuiWindow(jRoot, JsonString(title), NuiBind("geometry"), NuiBind("resizable"), JsonBool(FALSE), NuiBind("closable"), NuiBind("transparent"), NuiBind("border"));
|
||||
|
||||
// finally create it and it'll return us a non-zero token.
|
||||
int nToken = NuiCreate(OBJECT_SELF, nui, NUI_LEVEL_UP_WINDOW_ID);
|
||||
|
||||
// get the geometry of the window in case we opened this before and have a
|
||||
// preference for location
|
||||
json geometry = NuiRect(-1.0f,-1.0f, 748.0f, 535.0f);
|
||||
|
||||
// Set the binds to their default values
|
||||
NuiSetBind(OBJECT_SELF, nToken, "geometry", geometry);
|
||||
NuiSetBind(OBJECT_SELF, nToken, "resizable", JsonBool(FALSE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "closable", JsonBool(FALSE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "transparent", JsonBool(FALSE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "border", JsonBool(TRUE));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC Spellbook NUI Events
|
||||
//:: prc_nui_sc_event
|
||||
//:: prc_nui_sb_event
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the event script for the PRC Spellbook NUI that handles button presses
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
#include "prc_nui_consts"
|
||||
#include "prc_nui_sb_inc"
|
||||
#include "prc_nui_sbd_inc"
|
||||
|
||||
//
|
||||
// SetWindowGeometry
|
||||
@ -75,18 +74,9 @@ void main()
|
||||
string sElement = NuiGetEventElement();
|
||||
string sWindowId = NuiGetWindowId(oPlayer, nToken);
|
||||
|
||||
// if this was the Spell Description NUI and the OK button was clicked
|
||||
// then we close the window.
|
||||
if (sWindowId == NUI_SPELL_DESCRIPTION_WINDOW_ID)
|
||||
{
|
||||
if (sElement == NUI_SPELL_DESCRIPTION_OK_BUTTON)
|
||||
NuiDestroy(oPlayer, nToken);
|
||||
return;
|
||||
}
|
||||
|
||||
// if the window is closed, save the geometry
|
||||
if (sEvent == "close")
|
||||
if (sEvent == "watch" && sElement == "geometry")
|
||||
{
|
||||
// Save the geometry
|
||||
SetWindowGeometry(oPlayer, nToken);
|
||||
return;
|
||||
}
|
||||
@ -97,9 +87,6 @@ void main()
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the geometry first
|
||||
SetWindowGeometry(oPlayer, nToken);
|
||||
|
||||
int spellId;
|
||||
int featId;
|
||||
int realSpellId;
|
||||
@ -192,7 +179,8 @@ void main()
|
||||
// If right click, open the Spell Description NUI
|
||||
if (nButton == NUI_PAYLOAD_BUTTON_RIGHT_CLICK)
|
||||
{
|
||||
CreateSpellDescriptionNUI(oPlayer, featId, spellId, realSpellId);
|
||||
int classId = GetLocalInt(oPlayer, PRC_SPELLBOOK_SELECTED_CLASSID_VAR);
|
||||
CreateSpellDescriptionNUI(oPlayer, featId, spellId, realSpellId, classId);
|
||||
DeleteLocalInt(oPlayer, NUI_SPELLBOOK_SELECTED_SUBSPELL_SPELLID_VAR);
|
||||
return;
|
||||
}
|
||||
@ -209,7 +197,7 @@ void main()
|
||||
if (sRange == "P")
|
||||
{
|
||||
SetLocalInt(oPlayer, NUI_SPELLBOOK_ON_TARGET_IS_PERSONAL_FEAT, 1);
|
||||
ExecuteScript("prc_nui_sc_trggr", oPlayer);
|
||||
ExecuteScript("prc_nui_sb_trggr", oPlayer);
|
||||
}
|
||||
// otherwise enter targetting mode
|
||||
else
|
||||
@ -228,7 +216,7 @@ void main()
|
||||
|
||||
SetEnterTargetingModeData(oPlayer, iShape, fSizeX, fSizeY, nFlags, fRange);
|
||||
EnterTargetingMode(oPlayer, iTargetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
//:: Created On: 24.05.2005
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "nw_inc_nui"
|
||||
//#include "nw_inc_nui_insp"
|
||||
#include "prc_nui_sb_inc"
|
||||
#include "prc_nui_consts"
|
||||
@ -80,60 +79,6 @@ json CreateMetaMagicFeatButtons(int nClass);
|
||||
//
|
||||
json CreateMetaFeatButtonRow(json spellList);
|
||||
|
||||
//
|
||||
// GetSpellLevelIcon
|
||||
// Takes the spell circle int and gets the icon appropriate for it (i.e. 0 turns
|
||||
// into "ir_cantrips"
|
||||
//
|
||||
// Arguments:
|
||||
// spellLevel:int the spell level we want the icon for
|
||||
//
|
||||
// Returns:
|
||||
// string the spell level icon
|
||||
//
|
||||
string GetSpellLevelIcon(int spellLevel);
|
||||
|
||||
//
|
||||
// GetSpellLevelToolTip
|
||||
// Gets the spell level tool tip text based on the int spell level provided (i.e.
|
||||
// 0 turns into "Cantrips")
|
||||
//
|
||||
// Arguments:
|
||||
// spellLevel:int the spell level we want the tooltip for
|
||||
//
|
||||
// Returns:
|
||||
// string the spell level toop tip
|
||||
//
|
||||
string GetSpellLevelToolTip(int spellLevel);
|
||||
|
||||
//
|
||||
// GetSpellIcon
|
||||
// Gets the spell icon based off the spellId by using the FeatID instead
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the class Id
|
||||
// spellId:int the spell Id we want the icon for
|
||||
//
|
||||
// Returns:
|
||||
// json:String the string of the icon we want.
|
||||
//
|
||||
json GetSpellIcon(int spellId, int nClass=0);
|
||||
|
||||
//
|
||||
// HighlightButton
|
||||
// Takes NUI Button along with it's width and height and heighlights it with a drawn
|
||||
// colored rectangle to represent it's been selected.
|
||||
//
|
||||
// Arguments:
|
||||
// jButton:json the NUI Button
|
||||
// w:float the width of the button
|
||||
// h:float the height of the button
|
||||
//
|
||||
// Returns:
|
||||
// json the NUI button highlighted
|
||||
//
|
||||
json HighlightButton(json jButton, float w, float h);
|
||||
|
||||
void main()
|
||||
{
|
||||
// look for existing window and destroy
|
||||
@ -200,7 +145,7 @@ void main()
|
||||
// Default to put this near the middle and let the person adjust its location
|
||||
if (geometry == JsonNull())
|
||||
{
|
||||
geometry = NuiRect(893.0f,346.0f, 489.0f, 351.0f);
|
||||
geometry = NuiRect(-1.0f,-1.0f, 489.0f, 351.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -216,6 +161,8 @@ void main()
|
||||
NuiSetBind(OBJECT_SELF, nToken, "closable", JsonBool(TRUE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "transparent", JsonBool(TRUE));
|
||||
NuiSetBind(OBJECT_SELF, nToken, "border", JsonBool(FALSE));
|
||||
|
||||
NuiSetBindWatch(OBJECT_SELF, nToken, "geometry", TRUE);
|
||||
}
|
||||
|
||||
json CreateSpellBookClassButtons()
|
||||
@ -243,8 +190,8 @@ json CreateSpellBookClassButtons()
|
||||
float height = 32.0f;
|
||||
// Get the class icon from the classes.2da
|
||||
json jClassButton = NuiId(NuiButtonImage(JsonString(Get2DACache("classes", "Icon", classId))), PRC_SPELLBOOK_NUI_CLASS_BUTTON_BASEID + IntToString(classId));
|
||||
if (classId == selectedClassId)
|
||||
jClassButton = HighlightButton(jClassButton, width, height);
|
||||
if (classId != selectedClassId)
|
||||
jClassButton = GreyOutButton(jClassButton, width, height);
|
||||
jClassButton = NuiWidth(jClassButton, width);
|
||||
jClassButton = NuiHeight(jClassButton, height);
|
||||
// Get the class name from the classes.2da and set it to the tooltip
|
||||
@ -272,8 +219,6 @@ json CreateSpellbookCircleButtons(int nClass)
|
||||
|
||||
if (minSpellLevel >= 0)
|
||||
{
|
||||
// get what is the highest circle the class can cast at
|
||||
int currentMaxSpellLevel = GetCurrentSpellLevel(nClass, casterLevel);
|
||||
|
||||
// Get what the max circle the class can reach at is
|
||||
int totalMaxSpellLevel = GetMaxSpellLevel(nClass);
|
||||
@ -288,9 +233,9 @@ json CreateSpellbookCircleButtons(int nClass)
|
||||
|
||||
// conversily if it is higher than the max the class has (possibly due to
|
||||
// switching classes) then set it to that.
|
||||
if (currentCircle > currentMaxSpellLevel)
|
||||
if (currentCircle > totalMaxSpellLevel)
|
||||
{
|
||||
currentCircle = currentMaxSpellLevel;
|
||||
currentCircle = totalMaxSpellLevel;
|
||||
SetLocalInt(OBJECT_SELF, PRC_SPELLBOOK_SELECTED_CIRCLE_VAR, currentCircle);
|
||||
}
|
||||
|
||||
@ -306,13 +251,10 @@ json CreateSpellbookCircleButtons(int nClass)
|
||||
|
||||
// if the current circle is selected or if the person can't cast at
|
||||
// that circle yet then disable the button.
|
||||
if (i > currentMaxSpellLevel)
|
||||
enabled = JsonBool(FALSE);
|
||||
else
|
||||
enabled = JsonBool(TRUE);
|
||||
jButton = NuiEnabled(jButton, enabled);
|
||||
if (i == currentCircle)
|
||||
jButton = HighlightButton(jButton, width, height);
|
||||
|
||||
if (i != currentCircle)
|
||||
jButton = GreyOutButton(jButton, width, height);
|
||||
|
||||
|
||||
jRow = JsonArrayInsert(jRow, jButton);
|
||||
}
|
||||
@ -340,22 +282,27 @@ json CreateSpellbookSpellButtons(int nClass, int circle)
|
||||
for (i = 0; i < JsonGetLength(spellListAtCircle); i++)
|
||||
{
|
||||
int spellbookId = JsonGetInt(JsonArrayGet(spellListAtCircle, i));
|
||||
int featId;
|
||||
int spellId;
|
||||
// Binders don't have a spellbook, so spellbookId is actually SpellID
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
spellId = spellbookId;
|
||||
featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
|
||||
}
|
||||
else
|
||||
{
|
||||
spellId = StringToInt(Get2DACache(sFile, "SpellID", spellbookId));
|
||||
featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
||||
}
|
||||
|
||||
json jSpellButton = NuiId(NuiButtonImage(GetSpellIcon(spellId, nClass)), PRC_SPELLBOOK_NUI_SPELL_BUTTON_BASEID + IntToString(spellbookId));
|
||||
json jSpellButton = NuiId(NuiButtonImage(GetSpellIcon(spellId, featId, nClass)), PRC_SPELLBOOK_NUI_SPELL_BUTTON_BASEID + IntToString(spellbookId));
|
||||
jSpellButton = NuiWidth(jSpellButton, 38.0f);
|
||||
jSpellButton = NuiHeight(jSpellButton, 38.0f);
|
||||
|
||||
// the RealSpellID has the accurate descriptions for the spells/abilities
|
||||
int realSpellId = StringToInt(Get2DACache(sFile, "RealSpellID", spellbookId));
|
||||
if (!realSpellId)
|
||||
realSpellId = spellId;
|
||||
jSpellButton = NuiTooltip(jSpellButton, JsonString(GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", realSpellId)))));
|
||||
jSpellButton = NuiTooltip(jSpellButton, JsonString(GetSpellName(spellId, realSpellId, featId, nClass)));
|
||||
|
||||
// if the row limit has been reached, make a new row
|
||||
tempRow = JsonArrayInsert(tempRow, jSpellButton);
|
||||
@ -465,12 +412,23 @@ json CreateMetaFeatButtonRow(json spellList)
|
||||
else
|
||||
featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
|
||||
|
||||
int selectedFeatId = featId;
|
||||
if (featId == FEAT_EXTEND_SPELL_ABILITY)
|
||||
selectedFeatId = FEAT_EXTEND_SPELL;
|
||||
if (featId == FEAT_EMPOWER_SPELL_ABILITY)
|
||||
selectedFeatId = FEAT_EMPOWER_SPELL;
|
||||
if (featId == FEAT_MAXIMIZE_SPELL_ABILITY)
|
||||
selectedFeatId = FEAT_MAXIMIZE_SPELL;
|
||||
if (featId == FEAT_QUICKEN_SPELL_ABILITY)
|
||||
selectedFeatId = FEAT_QUICKEN_SPELL;
|
||||
if (featId == FEAT_STILL_SPELL_ABILITY)
|
||||
selectedFeatId = FEAT_STILL_SPELL;
|
||||
|
||||
if (GetHasFeat(featId, OBJECT_SELF, TRUE))
|
||||
if (GetHasFeat(selectedFeatId, OBJECT_SELF, TRUE))
|
||||
{
|
||||
string featName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||
|
||||
json jMetaButton = NuiId(NuiButtonImage(GetSpellIcon(spellId)), PRC_SPELLBOOK_NUI_META_BUTTON_BASEID + IntToString(spellId));
|
||||
json jMetaButton = NuiId(NuiButtonImage(GetSpellIcon(spellId, featId)), PRC_SPELLBOOK_NUI_META_BUTTON_BASEID + IntToString(spellId));
|
||||
jMetaButton = NuiWidth(jMetaButton, 32.0f);
|
||||
jMetaButton = NuiHeight(jMetaButton, 32.0f);
|
||||
jMetaButton = NuiTooltip(jMetaButton, JsonString(featName));
|
||||
@ -482,91 +440,3 @@ json CreateMetaFeatButtonRow(json spellList)
|
||||
return jRow;
|
||||
}
|
||||
|
||||
json GetSpellIcon(int spellId,int nClass=0)
|
||||
{
|
||||
// Binder's spells don't have the FeatID on the spells.2da, so we have to use
|
||||
// the mapping we constructed to get it.
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
json binderDict = GetBinderSpellToFeatDictionary();
|
||||
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(spellId)));
|
||||
return JsonString(Get2DACache("feat", "Icon", featId));
|
||||
}
|
||||
|
||||
int masterSpellID = StringToInt(Get2DACache("spells", "Master", spellId));
|
||||
|
||||
// if this is a sub radial spell, then we use spell's icon instead
|
||||
if (masterSpellID)
|
||||
return JsonString(Get2DACache("spells", "IconResRef", spellId));
|
||||
|
||||
// the FeatID holds the accurate spell icon, not the SpellID
|
||||
int featId = StringToInt(Get2DACache("spells", "FeatID", spellId));
|
||||
|
||||
return JsonString(Get2DACache("feat", "Icon", featId));
|
||||
}
|
||||
|
||||
json HighlightButton(json jButton, float w, float h)
|
||||
{
|
||||
json retValue = jButton;
|
||||
|
||||
json jBorders = JsonArray();
|
||||
|
||||
// set the points of the button shape
|
||||
json jPoints = JsonArray();
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(h));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(w));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(h));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(w));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
jBorders = JsonArrayInsert(jBorders, NuiDrawListPolyLine(JsonBool(TRUE), NuiColor(71, 140, 32), JsonBool(FALSE), JsonFloat(2.0), jPoints));
|
||||
|
||||
return NuiDrawList(jButton, JsonBool(FALSE), jBorders);
|
||||
}
|
||||
|
||||
string GetSpellLevelIcon(int spellLevel)
|
||||
{
|
||||
switch (spellLevel)
|
||||
{
|
||||
case 0: return "ir_cantrips";
|
||||
case 1: return "ir_level1";
|
||||
case 2: return "ir_level2";
|
||||
case 3: return "ir_level3";
|
||||
case 4: return "ir_level4";
|
||||
case 5: return "ir_level5";
|
||||
case 6: return "ir_level6";
|
||||
case 7: return "ir_level789";
|
||||
case 8: return "ir_level789";
|
||||
case 9: return "ir_level789";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
string GetSpellLevelToolTip(int spellLevel)
|
||||
{
|
||||
switch (spellLevel)
|
||||
{
|
||||
case 0: return "Cantrips";
|
||||
case 1: return "Level 1";
|
||||
case 2: return "Level 2";
|
||||
case 3: return "Level 3";
|
||||
case 4: return "Level 4";
|
||||
case 5: return "Level 5";
|
||||
case 6: return "Level 6";
|
||||
case 7: return "Level 7";
|
||||
case 8: return "Level 8";
|
||||
case 9: return "Level 9";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
@ -217,6 +217,11 @@ void main()
|
||||
// through the .2da's, the entering player already meets.
|
||||
ExecuteScript("prc_prereq", oPC);
|
||||
ExecuteScript("prc_psi_ppoints", oPC);
|
||||
if (GetHasFeat(FEAT_VOWOFPOVERTY, oPC) == TRUE)
|
||||
{
|
||||
ExecuteScript("prc_vop_feats_oe", oPC);
|
||||
}
|
||||
|
||||
ResetTouchOfVitality(oPC);
|
||||
DelayCommand(0.15, DeleteLocalInt(oPC,"ONENTER"));
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
A OnChat script that parses what is said and
|
||||
uses any commands or NUI associated with
|
||||
commands.
|
||||
uses any commands or NUI associated with
|
||||
commands.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Updated By: Rakiov
|
||||
@ -28,6 +28,7 @@ OR:
|
||||
#include "prc_string_inc"
|
||||
#include "prc_nui_sb_inc"
|
||||
#include "prc_nui_consts"
|
||||
#include "prc_nui_lv_inc"
|
||||
|
||||
const string CHAT_COMMAND_INDICATOR_1 = "~~";
|
||||
const string CHAT_COMMAND_INDICATOR_2 = "..";
|
||||
@ -135,19 +136,31 @@ void main()
|
||||
|
||||
// clear message from chat
|
||||
SetPCChatMessage();
|
||||
return;
|
||||
}
|
||||
// If the first word is /sb then we open the Spellbook NUI
|
||||
if(firstWord == "/sb")
|
||||
{
|
||||
ExecuteScript("prc_nui_sc_view", oPC);
|
||||
ExecuteScript("prc_nui_sb_view", oPC);
|
||||
|
||||
// clear message from chat
|
||||
SetPCChatMessage();
|
||||
return;
|
||||
}
|
||||
if (firstWord == "/lvl")
|
||||
{
|
||||
if (JsonGetLength(sCommandSplit) >= 2)
|
||||
{
|
||||
int classPos = StringToInt(JsonGetString(JsonArrayGet(sCommandSplit, 1)));
|
||||
int nClass = GetClassByPosition(classPos, oPC);
|
||||
OpenNUILevelUpWindow(nClass, oPC);
|
||||
SetPCChatMessage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Execute scripts hooked to this event for the player triggering it
|
||||
ExecuteAllScriptsHookedToEvent(oPC, EVENT_ONPLAYERCHAT);
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This handles any NUI events and sends them to
|
||||
appropriate NUI Event handler depending on the
|
||||
window Id
|
||||
appropriate NUI Event handler depending on the
|
||||
window Id
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Rakiov
|
||||
@ -22,16 +22,18 @@ void main()
|
||||
|
||||
// Open the Power Attack NUI
|
||||
if(sWindowId == NUI_PRC_POWER_ATTACK_WINDOW)
|
||||
{
|
||||
ExecuteScript("prc_nui_pa_event");
|
||||
}
|
||||
|
||||
// Open the Spellbook NUI
|
||||
if(sWindowId == PRC_SPELLBOOK_NUI_WINDOW_ID
|
||||
|| sWindowId == NUI_SPELL_DESCRIPTION_WINDOW_ID)
|
||||
{
|
||||
ExecuteScript("prc_nui_sc_event");
|
||||
}
|
||||
if(sWindowId == PRC_SPELLBOOK_NUI_WINDOW_ID)
|
||||
ExecuteScript("prc_nui_sb_event");
|
||||
|
||||
if (sWindowId == NUI_SPELL_DESCRIPTION_WINDOW_ID)
|
||||
ExecuteScript("prc_nui_dsc_evnt");
|
||||
|
||||
if (sWindowId == NUI_LEVEL_UP_WINDOW_ID)
|
||||
ExecuteScript("prc_nui_lv_event");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the OnTarget event used set up spell
|
||||
attacks with the selected spell from the PRC
|
||||
Spellbook NUI
|
||||
attacks with the selected spell from the PRC
|
||||
Spellbook NUI
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Updated By: Rakiov
|
||||
@ -20,7 +20,7 @@ void DoJump(object oPC, location lTarget, int bDoKnockdown);
|
||||
// DoSpellbookAction
|
||||
// This is a OnTarget event action handling the use of the NUI Spellbook's spell.
|
||||
// All this should do is take the manual targeting information and send it to the
|
||||
// prc_nui_sc_trggr to handle the use of the spell.
|
||||
// prc_nui_sb_trggr to handle the use of the spell.
|
||||
//
|
||||
// Arguments:
|
||||
// oPC:object the player executing the action
|
||||
@ -85,7 +85,7 @@ void DoSpellbookAction(object oPC, object oTarget, location lTarget)
|
||||
SetLocalLocation(oPC, "TARGETING_POSITION", lTarget);
|
||||
}
|
||||
|
||||
ExecuteScript("prc_nui_sc_trggr", oPC);
|
||||
ExecuteScript("prc_nui_sb_trggr", oPC);
|
||||
ClearEventVariables(oPC);
|
||||
}
|
||||
|
||||
|
@ -1054,15 +1054,57 @@ void TomeOfBattle(object oPC = OBJECT_SELF)
|
||||
//Master of Nine
|
||||
SetLocalInt(oPC, "PRC_PrereqMoNine", 1);
|
||||
// Needs 6 maneuvers, so check the persistent locals
|
||||
int i, nCount, nSkills;
|
||||
int nCount = 0;
|
||||
int nTotal = 0;
|
||||
|
||||
int nDesert = _CheckPrereqsByDiscipline(oPC, DISCIPLINE_DESERT_WIND);
|
||||
if (nDesert > 0) nCount += 1;
|
||||
|
||||
int nDevoted = _CheckPrereqsByDiscipline(oPC, DISCIPLINE_DEVOTED_SPIRIT);
|
||||
if (nDevoted > 0) nCount += 1;
|
||||
|
||||
int nDiamond = _CheckPrereqsByDiscipline(oPC, DISCIPLINE_DIAMOND_MIND);
|
||||
if (nDiamond > 0) nCount += 1;
|
||||
|
||||
int nTiger = _CheckPrereqsByDiscipline(oPC, DISCIPLINE_TIGER_CLAW);
|
||||
if (nTiger > 0) nCount += 1;
|
||||
|
||||
int nShadow = _CheckPrereqsByDiscipline(oPC, DISCIPLINE_SHADOW_HAND);
|
||||
if (nShadow > 0) nCount += 1;
|
||||
|
||||
int nStone = _CheckPrereqsByDiscipline(oPC, DISCIPLINE_STONE_DRAGON);
|
||||
if (nStone > 0) nCount += 1;
|
||||
|
||||
int nSun = _CheckPrereqsByDiscipline(oPC, DISCIPLINE_SETTING_SUN);
|
||||
if (nSun > 0) nCount += 1;
|
||||
|
||||
int nRaven = _CheckPrereqsByDiscipline(oPC, DISCIPLINE_WHITE_RAVEN);
|
||||
if (nRaven > 0) nCount += 1;
|
||||
|
||||
nTotal = nDevoted + nDiamond + nTiger + nShadow + nStone + nSun + nRaven + nDesert;
|
||||
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nDevoted)+" Devoted Spirit Maneuvers");
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nDiamond)+" Diamond Mind Maneuvers");
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nTiger)+" Tiger Claw Maneuvers");
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nShadow)+" Shadow Hand Maneuvers");
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nStone)+" Stone Dragon Maneuvers");
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nSun)+" Setting Sun Maneuvers");
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nRaven)+" White Raven Maneuvers");
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nDesert)+" Desert Wind Maneuvers");
|
||||
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nTotal)+" total Maneuvers from "+IntToString(nCount)+" Disciplines.");
|
||||
|
||||
// Needs 6 maneuvers, so check the persistent locals
|
||||
/* int i, nCount, nSkills;
|
||||
for(i = 1; i <= 256; i <<= 1)
|
||||
{
|
||||
// Loop over all disciplines, and total up how many he knows
|
||||
if(_CheckPrereqsByDiscipline(oPC, i))
|
||||
nCount++;
|
||||
}
|
||||
} */
|
||||
|
||||
// Base ranks only
|
||||
int nSkills = 0;
|
||||
// Base ranks only
|
||||
if(GetSkillRank(SKILL_TUMBLE, oPC, TRUE) >= 10) nSkills += 1;
|
||||
if(GetSkillRank(SKILL_INTIMIDATE, oPC, TRUE) >= 10) nSkills += 1;
|
||||
if(GetSkillRank(SKILL_CONCENTRATION, oPC, TRUE) >= 10) nSkills += 1;
|
||||
@ -1072,6 +1114,8 @@ void TomeOfBattle(object oPC = OBJECT_SELF)
|
||||
if(GetSkillRank(SKILL_JUMP, oPC, TRUE) >= 10) nSkills += 1;
|
||||
if(GetSkillRank(SKILL_PERSUADE, oPC, TRUE) >= 10) nSkills += 1;
|
||||
|
||||
if (DEBUG) DoDebug("You have "+IntToString(nSkills)+" total Skills over 10 ranks.");
|
||||
|
||||
if(nCount >= 6 && nSkills >= 4)
|
||||
SetLocalInt(oPC, "PRC_PrereqMoNine", 0);
|
||||
|
||||
|
85
nwn/nwnprc/trunk/scripts/prc_vop_feats_oe.nss
Normal file
85
nwn/nwnprc/trunk/scripts/prc_vop_feats_oe.nss
Normal file
@ -0,0 +1,85 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Restore VoP Bonus Feats OnClientEnter
|
||||
//:: Uses prc_vop_feats.2da
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_inc_function"
|
||||
#include "inc_debug"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
if (!GetIsPC(oPC) || GetIsDM(oPC)) return;
|
||||
|
||||
int nRow = 0;
|
||||
int nFeat;
|
||||
string sFeatTag;
|
||||
|
||||
int nRows = Get2DARowCount("prc_vop_feats");
|
||||
if (DEBUG) DoDebug("[VoPRestore] Checking " + IntToString(nRows) + " exalted feats...");
|
||||
|
||||
while (nRow < nRows)
|
||||
{
|
||||
string sIndex = Get2DAString("prc_vop_feats", "FeatIndex", nRow);
|
||||
|
||||
if (sIndex != "****" && sIndex != "")
|
||||
{
|
||||
nFeat = StringToInt(sIndex);
|
||||
sFeatTag = "VoPFeatID" + IntToString(nFeat);
|
||||
|
||||
if (GetPersistantLocalInt(oPC, sFeatTag) == 1)
|
||||
{
|
||||
if (DEBUG) DoDebug("[VoPRestore] Restoring feat ID " + IntToString(nFeat));
|
||||
|
||||
effect eFeat = EffectBonusFeat(nFeat);
|
||||
eFeat = UnyieldingEffect(eFeat);
|
||||
eFeat = TagEffect(eFeat, "VoPFeat" + IntToString(nFeat));
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eFeat, oPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only uncomment this line if you want to see *every* non-match
|
||||
// SendMessageToPC(oPC, "[VoPRestore] Not set: " + sFeatTag);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DEBUG) DoDebug("[VoPRestore] Invalid FeatIndex at row " + IntToString(nRow));
|
||||
}
|
||||
|
||||
nRow++;
|
||||
}
|
||||
|
||||
if (DEBUG) DoDebug("[VoPRestore] Done.");
|
||||
}
|
||||
|
||||
|
||||
/* void main()
|
||||
{
|
||||
object oPC = GetEnteringObject();
|
||||
if (!GetIsPC(oPC) || GetIsDM(oPC)) return;
|
||||
|
||||
int nRow = 0;
|
||||
int nFeat;
|
||||
string sFeatTag;
|
||||
|
||||
int nRows = Get2DARowCount("prc_vop_feats");
|
||||
while (nRow < nRows)
|
||||
{
|
||||
// Read the feat index from the 2DA
|
||||
nFeat = StringToInt(Get2DACache("prc_vop_feats", "FeatIndex", nRow));
|
||||
sFeatTag = "VoPFeat" + IntToString(nFeat);
|
||||
|
||||
// If the PC has a persistent variable set for this feat, reapply the effect
|
||||
if (GetPersistantLocalInt(oPC, sFeatTag) == 1)
|
||||
{
|
||||
effect eFeat = EffectBonusFeat(nFeat);
|
||||
eFeat = UnyieldingEffect(eFeat);
|
||||
eFeat = TagEffect(eFeat, sFeatTag);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eFeat, oPC);
|
||||
}
|
||||
|
||||
nRow++;
|
||||
}
|
||||
} */
|
Binary file not shown.
@ -35992,6 +35992,7 @@ This is a supernatural maneuver.</entry>
|
||||
<entry id="52589" lang="en" sex="m">Fire Riposte</entry>
|
||||
<entry id="52590" lang="en" sex="m">Desert Wind (Counter)
|
||||
Level: Swordsage 2
|
||||
Prerequisite: One Desert Wind maneuver
|
||||
Initiation Action: 1 Immediate Action
|
||||
Range: Personal.
|
||||
Target: You.
|
||||
@ -36344,7 +36345,7 @@ This makes you flat-footed for the rest of the round.</entry>
|
||||
<entry id="52645" lang="en" sex="m">Doom Charge</entry>
|
||||
<entry id="52646" lang="en" sex="m">Devoted Spirit (Strike) [Evil]
|
||||
Level: Crusader 5
|
||||
Prerequisite: One Devoted Spirit maneuver
|
||||
Prerequisite: One Devoted Spirit maneuver, evil alignment
|
||||
Initiation Action: 1 Full-round action
|
||||
Range: Melee
|
||||
Target: One creature
|
||||
@ -36401,7 +36402,7 @@ Any creature you threaten takes a -4 penalty on attacks against allies.</entry>
|
||||
<entry id="52655" lang="en" sex="m">Law Bearer</entry>
|
||||
<entry id="52656" lang="en" sex="m">Devoted Spirit (Strike) [Law]
|
||||
Level: Crusader 5
|
||||
Prerequisite: One Devoted Spirit maneuver
|
||||
Prerequisite: One Devoted Spirit maneuver, lawful alignment
|
||||
Initiation Action: 1 Full-round action
|
||||
Range: Melee
|
||||
Target: One creature
|
||||
@ -36424,7 +36425,7 @@ Whenever you successfully strike a creature, you or your ally within 30 feet hea
|
||||
<entry id="52659" lang="en" sex="m">Radiant Charge</entry>
|
||||
<entry id="52660" lang="en" sex="m">Devoted Spirit (Strike) [Good]
|
||||
Level: Crusader 5
|
||||
Prerequisite: One Devoted Spirit maneuver
|
||||
Prerequisite: One Devoted Spirit maneuver, good alignment
|
||||
Initiation Action: 1 Full-round action
|
||||
Range: Melee
|
||||
Target: One creature
|
||||
@ -36469,7 +36470,7 @@ Your grant your ally a +4 shield bonus against the next attack made against him.
|
||||
<entry id="52667" lang="en" sex="m">Shield Counter</entry>
|
||||
<entry id="52668" lang="en" sex="m">Devoted Spirit (Counter)
|
||||
Level: Crusader 2
|
||||
Prerequisite: 2 Devoted Spirit maneuvers
|
||||
Prerequisite: Two Devoted Spirit maneuvers
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: Melee Attack
|
||||
Target: One Creature
|
||||
@ -36503,7 +36504,7 @@ Any creature who attempts to move near you provokes an AoO.</entry>
|
||||
<entry id="52673" lang="en" sex="m">Tide Of Chaos</entry>
|
||||
<entry id="52674" lang="en" sex="m">Devoted Spirit (Strike) [Chaos]
|
||||
Level: Crusader 5
|
||||
Prerequisite: One Devoted Spirit maneuver
|
||||
Prerequisite: One Devoted Spirit maneuver, chaotic alignment
|
||||
Initiation Action: 1 Full-round action
|
||||
Range: Melee
|
||||
Target: One creature
|
||||
@ -37101,6 +37102,15 @@ A creature strikes, but you turn the blow straight back at it.
|
||||
|
||||
Make an opposed attack roll against the targeted creature. If you succeed, he damages himself rather than you.</entry>
|
||||
<entry id="52779" lang="en" sex="m">Ghostly Defense</entry>
|
||||
<entry id="52780" land="en" sex="m">Setting Sun (Stance)
|
||||
Level: Swordsage 8
|
||||
Prerequisite: Three Setting Sun maneuvers
|
||||
Initiation Action: 1 swift action
|
||||
Range: Personal
|
||||
Target : You
|
||||
Duration: Stance
|
||||
|
||||
You are a ghost in the mist, capable of turning a foe against her allies. By gauging your opponent?s fighting stance, timing your dodge correctly, and placing yourself in the right position, you can lead her into attacking one of her allies rather than you. When your foe strikes, you duck out of the way. As she follows through with her attack, she inadvertently attacks an ally.</entry>
|
||||
<entry id="52781" lang="en" sex="m">Giant Killing Style</entry>
|
||||
<entry id="52782" lang="en" sex="m">Setting Sun (Stance)
|
||||
Level: Swordsage 3
|
||||
@ -37159,6 +37169,7 @@ Make an opposed attack roll against the targeted creature. If you succeed, he da
|
||||
<entry id="52791" lang="en" sex="m">Shifting Defense</entry>
|
||||
<entry id="52792" lang="en" sex="m">Setting Sun (Stance)
|
||||
Level: Swordsage 5
|
||||
Prerequisite: Two Setting Sun maneuvers
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: Personal
|
||||
Target: You
|
||||
@ -37240,6 +37251,7 @@ You gain +2d6 Sneak Attack.</entry>
|
||||
<entry id="52805" lang="en" sex="m">Balance On The Sky</entry>
|
||||
<entry id="52806" lang="en" sex="m">Shadow Hand (Stance)
|
||||
Level: Swordsage 8
|
||||
Prerequisite: Three Shadow Hand maneuvers.
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: Personal.
|
||||
Target: You.
|
||||
@ -37321,6 +37333,7 @@ This maneuver functions only against a flat-footed opponent. As part of this man
|
||||
<entry id="52819" lang="en" sex="m">Drain Vitality</entry>
|
||||
<entry id="52820" lang="en" sex="m">Shadow Hand (Strike)
|
||||
Level: Swordsage 2
|
||||
Prerequisite: One Shadow Hand maneuver
|
||||
Initiation Action: 1 Standard Action
|
||||
Range: Melee Attack
|
||||
Target: One Creatures
|
||||
@ -37414,6 +37427,7 @@ This is a supernatural maneuver.</entry>
|
||||
<entry id="52833" lang="en" sex="m">One With Shadow</entry>
|
||||
<entry id="52834" lang="en" sex="m">Shadow Hand (Counter)
|
||||
Level: Swordsage 8
|
||||
Prerequisite: Three Shadow Hand maneuvers
|
||||
Initiation Action: 1 Immediate Action
|
||||
Range: Personal
|
||||
Target: You
|
||||
@ -37443,7 +37457,6 @@ This maneuver functions as the shadow jaunt maneuver, except that it can be init
|
||||
<entry id="52839" lang="en" sex="m">Shadow Garrote</entry>
|
||||
<entry id="52840" lang="en" sex="m">Shadow Hand (Strike)
|
||||
Level: Swordsage 3
|
||||
Prerequisite: One Shadow Hand maneuver
|
||||
Initiation Action: 1 Standard Action
|
||||
Range: 60'
|
||||
Target: One Living Creature
|
||||
@ -37616,6 +37629,7 @@ As part of this maneuver, you make a melee attack. This attack deals an extra 4d
|
||||
<entry id="52869" lang="en" sex="m">Crushing Weight Of The Mountain</entry>
|
||||
<entry id="52870" lang="en" sex="m">Stone Dragon (Stance)
|
||||
Level: Crusader 3, Swordsage 3, Warblade 3
|
||||
Prerequisite: One Stone Dragon maneuver
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: Personal
|
||||
Target: You
|
||||
@ -37756,6 +37770,7 @@ You gain DR 5/adamantium (+5) for 1 round.</entry>
|
||||
<entry id="52893" lang="en" sex="m">Stone Dragon's Fury</entry>
|
||||
<entry id="52894" lang="en" sex="m">Stone Dragon (Strike)
|
||||
Level: Crusader 3, Swordsage 3, Warblade 3
|
||||
Prerequisite: One Stone Dragon maneuver
|
||||
Initiation Action: 1 Standard Action
|
||||
Range: Melee Attack
|
||||
Target: One Creature
|
||||
@ -37788,6 +37803,7 @@ You gain a +2 bonus on Strength checks, and a +2 AC bonus against creatures larg
|
||||
<entry id="52899" lang="en" sex="m">White Raven Tactics</entry>
|
||||
<entry id="52900" lang="en" sex="m">White Raven (Boost)
|
||||
Level: Crusader 3, Warblade 3
|
||||
Prerequisite: One White Raven maneuver
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: 10 ft.
|
||||
Target: One ally
|
||||
@ -37832,6 +37848,7 @@ While you are in this stance, you focus your efforts on preventing any devastati
|
||||
<entry id="52907" lang="en" sex="m">Blood In The Water</entry>
|
||||
<entry id="52908" lang="en" sex="m">Tiger Claw (Stance)
|
||||
Level: Swordsage 1, Warblade 1
|
||||
Prerequisite: One Tiger Claw maneuver
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: Personal.
|
||||
Target: You.
|
||||
@ -37843,6 +37860,7 @@ Whenever you successfully critical hit a creature, you gain a +1 Attack and Dama
|
||||
<entry id="52909" lang="en" sex="m">Claw At The Moon</entry>
|
||||
<entry id="52910" lang="en" sex="m">Tiger Claw (Strike)
|
||||
Level: Swordsage 2, Warblade 2
|
||||
Prerequisite: Two Tiger Claw maneuvers
|
||||
Initiation Action: 1 Standard Action
|
||||
Range: Melee Attack
|
||||
Target: One Creature
|
||||
@ -37889,6 +37907,7 @@ If your Jump check fails, you can make a singe attack normally. The maneuver is
|
||||
<entry id="52917" lang="en" sex="m">Flesh Ripper</entry>
|
||||
<entry id="52918" lang="en" sex="m">Tiger Claw (Strike)
|
||||
Level: Swordsage 3, Warblade 3
|
||||
Prerequisite: Two Tiger Claw maneuvers
|
||||
Initiation Action: 1 Standard Action
|
||||
Range: Melee Attack
|
||||
Target: One Creature
|
||||
@ -37950,6 +37969,7 @@ As part of this maneuver, you make a single melee attack. If this attack hits, i
|
||||
<entry id="52925" lang="en" sex="m">Hunter's Sense</entry>
|
||||
<entry id="52926" lang="en" sex="m">Tiger Claw (Stance)
|
||||
Level: Swordsage 1, Warblade 1
|
||||
Prerequisite: One Tiger Claw maneuver
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: Personal.
|
||||
Target: You.
|
||||
@ -38028,6 +38048,7 @@ You make a flurry of deadly attacks. After initiating this boost, you can make t
|
||||
<entry id="52939" lang="en" sex="m">Soaring Raptor Strike</entry>
|
||||
<entry id="52940" lang="en" sex="m">Tiger Claw (Strike)
|
||||
Level: Swordsage 3, Warblade 3
|
||||
Prerequisite: One Tiger Claw maneuver
|
||||
Initiation Action: 1 Standard Action
|
||||
Range: Melee Attack
|
||||
Target: One Creature
|
||||
@ -38039,6 +38060,7 @@ This must be used on a creature larger than you are.</entry>
|
||||
<entry id="52941" lang="en" sex="m">Sudden Leap</entry>
|
||||
<entry id="52942" lang="en" sex="m">Tiger Claw (Boost)
|
||||
Level: Swordsage 1, Warblade 1
|
||||
Prerequisite: One Tiger Claw maneuver
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: Personal.
|
||||
Target: You.
|
||||
@ -38097,6 +38119,7 @@ While you are in this stance, you gain a 5 foot bonus to movement for every succ
|
||||
<entry id="52951" lang="en" sex="m">Wolverine Stance</entry>
|
||||
<entry id="52952" lang="en" sex="m">Tiger Claw (Stance)
|
||||
Level: Swordsage 3, Warblade 3
|
||||
Prerequisite: One Tiger Claw maneuver
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: Personal.
|
||||
Target: You.
|
||||
@ -38108,6 +38131,7 @@ You may use any weapon in a grapple, and do not take the -4 penalty to attack. I
|
||||
<entry id="52953" lang="en" sex="m">Battle Leader's Charge</entry>
|
||||
<entry id="52954" lang="en" sex="m">White Raven (Strike)
|
||||
Level: Crusader 2, Warblade 2
|
||||
Prerequisite: One White Raven maneuver
|
||||
Initiation Action: 1 Full-round Action
|
||||
Range: Melee Attack
|
||||
Target: One Creature
|
||||
@ -38185,6 +38209,7 @@ If your strike hits, your target suffers a -4 penalty to AC.</entry>
|
||||
<entry id="52967" lang="en" sex="m">Lion's Roar</entry>
|
||||
<entry id="52968" lang="en" sex="m">White Raven (Boost)
|
||||
Level: Crusader 3, Warblade 3
|
||||
Prerequisite: One White Raven maneuver
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: 60'
|
||||
Target: You
|
||||
@ -38242,6 +38267,7 @@ If you strike your foe, all allies in melee range make a single attack against t
|
||||
<entry id="52977" lang="en" sex="m">Tactical Strike</entry>
|
||||
<entry id="52978" lang="en" sex="m">White Raven (Strike)
|
||||
Level: Crusader 2, Warblade 2
|
||||
Prerequisite: One White Raven maneuver
|
||||
Initiation Action: 1 Standard Action
|
||||
Range: Melee Attack
|
||||
Target: One Creature
|
||||
@ -38252,6 +38278,7 @@ Make a single melee attack. If you successfully hit the creature, all allies gai
|
||||
<entry id="52979" lang="en" sex="m">Tactics Of The Wolf</entry>
|
||||
<entry id="52980" lang="en" sex="m">White Raven (Stance)
|
||||
Level: Crusader 3, Warblade 3
|
||||
Prerequisite: One White Raven maneuver
|
||||
Initiation Action: 1 Swift Action
|
||||
Range: 10ft.
|
||||
Area: 10 ft radius centred on you.
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user