2 # GemRB - Infinity Engine Emulator
3 # Copyright (C) 2003-2004 The GemRB Project
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 # LevelUp.py - scripts to control the level up functionality and windows
22 from GUIDefines
import *
23 from ie_stats
import *
24 from ie_restype
import RES_2DA
27 import LUSpellSelection
29 if GUICommon
.HasTOB():
31 import LUProfsSelection
32 import LUSkillsSelection
53 # old values (so we don't add too much)
54 OldHPMax
= 0 # << old maximum hitpoints
55 OldSaves
= [0]*5 # << old saves
56 OldThaco
= 0 # << old thac0 value
57 OldLore
= 0 # << old lore value
58 OldDSpells
= [0]*7 # << old divine spells per level
59 OldWSpells
= [0]*9 # << old wizard spells per level
60 NewDSpells
= [0]*7 # << new divine spells per level
61 NewWSpells
= [0]*9 # << new wizard spells per level
62 DeltaDSpells
= 0 # << total new divine spells
63 DeltaWSpells
= 0 # << total new wizard spells
65 def OpenLevelUpWindow():
66 """Sets up the level up window."""
69 global LevelUpWindow
, TextAreaControl
, NewProfPoints
, actor
71 global NewSkillPoints
, KitName
, LevelDiff
72 global Level
, Classes
, NumClasses
, DualSwap
, IsMulti
73 global OldHPMax
, OldSaves
, OldLore
, OldThaco
, DeltaDSpells
, DeltaWSpells
74 global NewDSpells
, NewWSpells
, OldDSpells
, OldWSpells
, pc
, HLACount
, ClassName
, IsDual
76 LevelUpWindow
= GemRB
.LoadWindow (3)
78 if GUICommon
.GameIsBG2():
79 InfoButton
= LevelUpWindow
.GetControl (125)
80 InfoButton
.SetText (13707)
81 InfoButton
.SetEvent (IE_GUI_BUTTON_ON_PRESS
, LevelUpInfoPress
)
83 DoneButton
= LevelUpWindow
.GetControl (0)
84 DoneButton
.SetText (11962)
85 DoneButton
.SetEvent (IE_GUI_BUTTON_ON_PRESS
, LevelUpDonePress
)
86 DoneButton
.SetState (IE_GUI_BUTTON_DISABLED
)
87 DoneButton
.SetFlags (IE_GUI_BUTTON_DEFAULT
, OP_OR
)
89 # hide "Character Generation"
90 Label
= LevelUpWindow
.CreateLabel (0x1000007e, 0,0,0,0,"NUMBER","",1)
93 pc
= GemRB
.GameGetSelectedPCSingle ()
94 actor
= Actor
.Actor(pc
)
95 Label
= LevelUpWindow
.GetControl (0x10000000+90)
96 Label
.SetText (GemRB
.GetPlayerName (pc
))
98 if GUICommon
.GameIsBG1() or GUICommon
.GameIsIWD1():
100 Label
= LevelUpWindow
.GetControl (0x10000057)
101 ac
= GemRB
.GetPlayerStat (pc
, IE_ARMORCLASS
)
102 #This is a temporary solution, the core engine should set the stat correctly!
103 ac
+= GemRB
.GetAbilityBonus (IE_DEX
, 2, GemRB
.GetPlayerStat (pc
, IE_DEX
) )
104 Label
.SetText (str (ac
))
105 Label
.SetTooltip (17183)
108 Label
= LevelUpWindow
.GetControl (0x10000058)
109 Label
.SetText (str (GemRB
.GetPlayerStat (pc
, IE_HITPOINTS
)))
110 Label
.SetTooltip (17184)
113 Label
= LevelUpWindow
.GetControl (0x10000059)
114 Label
.SetText (str (GemRB
.GetPlayerStat (pc
, IE_MAXHITPOINTS
)))
115 Label
.SetTooltip (17378)
117 # some current values
118 OldHPMax
= GemRB
.GetPlayerStat (pc
, IE_MAXHITPOINTS
, 1)
119 OldThaco
= GemRB
.GetPlayerStat (pc
, IE_TOHIT
, 1)
120 OldLore
= GemRB
.GetPlayerStat (pc
, IE_LORE
, 1)
122 OldSaves
[i
] = GemRB
.GetPlayerStat (pc
, IE_SAVEVSDEATH
+i
, 1)
125 Label
= LevelUpWindow
.GetControl (0x10000000+106)
126 Label
.SetText (GUICommon
.GetActorClassTitle (pc
))
127 print "Title:",GUICommon
.GetActorClassTitle (pc
),"\tActor Title:",actor
.ClassTitle()
129 Class
= GemRB
.GetPlayerStat (pc
, IE_CLASS
)
130 print "Class:",Class
,"\tActor Class:",actor
.classid
131 ClassIndex
= CommonTables
.Classes
.FindValue (5, Class
)
132 SkillTable
= GemRB
.LoadTable("skills")
135 ClassName
= CommonTables
.Classes
.GetRowName(ClassIndex
)
136 Kit
= GUICommon
.GetKitIndex (pc
)
137 print "Kit:", Kit
, "\tActor Kit:",actor
.KitIndex()
138 print "ClassName:",ClassName
,"\tActor ClassNames:",actor
.ClassNames()
140 # need this for checking gnomes
141 RaceName
= GemRB
.GetPlayerStat (pc
, IE_RACE
, 1)
142 RaceName
= CommonTables
.Races
.FindValue (3, RaceName
)
143 RaceName
= CommonTables
.Races
.GetRowName (RaceName
)
145 # figure our our proficiency table and index
149 #rowname is just a number, the kitname is the first data column
150 KitName
= CommonTables
.KitList
.GetValue(Kit
, 0)
152 # our multiclass variables
153 IsMulti
= GUICommon
.IsMultiClassed (pc
, 1)
154 Classes
= [IsMulti
[1], IsMulti
[2], IsMulti
[3]]
155 NumClasses
= IsMulti
[0] # 2 or 3 if IsMulti; 0 otherwise
156 IsMulti
= NumClasses
> 1
160 # not multi, check dual
162 # check if we're dual classed
163 IsDual
= GUICommon
.IsDualClassed (pc
, 1)
164 Classes
= [IsDual
[2], IsDual
[1]] # make sure the new class is first
166 # either dual or single only care about 1 class
169 # not dual, must be single
172 else: # make sure Classes[1] is a class, not a kit
173 if IsDual
[0] == 1: # kit
174 Classes
[1] = CommonTables
.KitList
.GetValue (IsDual
[1], 7)
176 Classes
[1] = CommonTables
.Classes
.GetValue (Classes
[1], 5)
178 # store a boolean for IsDual
179 IsDual
= IsDual
[0] > 0
181 print "NumClasses:",NumClasses
,"\tActor NumClasses:",actor
.NumClasses()
186 # reorganize the leves if we're dc so the one we want to use is in Level[0]
187 # and the old one is in Level[1] (used to regain old class abilities)
189 # convert the classes from indicies to class id's
190 DualSwap
= GUICommon
.IsDualSwap (pc
)
191 ClassName
= CommonTables
.Classes
.GetRowName (Classes
[0])
192 KitName
= ClassName
# for simplicity throughout the code
193 Classes
[0] = CommonTables
.Classes
.GetValue (Classes
[0], 5)
194 # Class[1] is taken care of above
196 # we need the old level as well
198 Level
[1] = GemRB
.GetPlayerStat (pc
, IE_LEVEL
)
200 Level
[1] = GemRB
.GetPlayerStat (pc
, IE_LEVEL2
)
202 print "Classes:",Classes
,"\tActor Classes:",actor
.Classes()
203 print "IsDual:",IsDual
>0,"\tActor IsDual",actor
.isdual
207 # clear some globals, since we may get called multiple times with different classes
215 # get a bunch of different things each level
216 for i
in range(NumClasses
):
217 # print "Class:",Classes[i]
218 # we don't care about the current level, but about the to-be-achieved one
220 Level
[i
] = LUCommon
.GetNextLevelFromExp (GemRB
.GetPlayerStat (pc
, IE_XP
)/NumClasses
, Classes
[i
])
221 TmpIndex
= CommonTables
.Classes
.FindValue (5, Classes
[i
])
222 TmpName
= CommonTables
.Classes
.GetRowName (TmpIndex
)
224 # print "Name:",TmpName
226 # find the level diff for each classes (3 max, obviously)
229 LevelDiff
[i
] = Level
[i
] - GemRB
.GetPlayerStat (pc
, IE_LEVEL2
)
231 LevelDiff
[i
] = Level
[i
] - GemRB
.GetPlayerStat (pc
, IE_LEVEL
)
233 LevelDiff
[i
] = Level
[i
] - GemRB
.GetPlayerStat (pc
, IE_LEVEL2
)
235 LevelDiff
[i
] = Level
[i
] - GemRB
.GetPlayerStat (pc
, IE_LEVEL3
)
237 # print "Level (",i,"):",Level[i]
238 # print "Level Diff (",i,"):",LevelDiff[i]
240 # save our current and next spell amounts
241 StartLevel
= Level
[i
] - LevelDiff
[i
]
242 DruidTable
= CommonTables
.ClassSkills
.GetValue (Classes
[i
], 0, 0)
243 ClericTable
= CommonTables
.ClassSkills
.GetValue (Classes
[i
], 1, 0)
244 MageTable
= CommonTables
.ClassSkills
.GetValue (Classes
[i
], 2, 0)
246 # see if we have mage spells
248 # we get 1 extra spell per level if we're a specialist
250 if CommonTables
.KitList
.GetValue (Kit
, 7) == 1: # see if we're a kitted mage
252 MageTable
= GemRB
.LoadTable (MageTable
)
253 # loop through each spell level and save the amount possible to cast (current)
254 for j
in range (MageTable
.GetColumnCount ()):
255 NewWSpells
[j
] = MageTable
.GetValue (str(Level
[i
]), str(j
+1), 1)
256 OldWSpells
[j
] = MageTable
.GetValue (str(StartLevel
), str(j
+1), 1)
257 if NewWSpells
[j
] > 0: # don't want specialist to get 1 in levels they should have 0
258 NewWSpells
[j
] += Specialist
259 if OldWSpells
[j
] > 0:
260 OldWSpells
[j
] += Specialist
261 DeltaWSpells
= sum(NewWSpells
)-sum(OldWSpells
)
262 elif ClericTable
!= "*":
263 # check for cleric spells
264 if not GemRB
.HasResource(ClericTable
, RES_2DA
, 1):
265 ClericTable
= "MXSPLPRS" # iwd1 doesn't have a DRUIDSPELL column in the table
266 ClericTable
= GemRB
.LoadTable (ClericTable
)
269 for j
in range (ClericTable
.GetColumnCount ()):
270 NewDSpells
[j
] = ClericTable
.GetValue (str(Level
[i
]), str(j
+1), 1)
271 OldDSpells
[j
] = ClericTable
.GetValue (str(StartLevel
), str(j
+1), 1)
272 DeltaDSpells
= sum(NewDSpells
)-sum(OldDSpells
)
273 elif DruidTable
!= "*":
274 # clerics have precedence in multis (ranger/cleric)
276 #use MXSPLPRS if we can't find the resource (SoA fix)
277 if not GemRB
.HasResource (DruidTable
, RES_2DA
):
278 DruidTable
= "MXSPLPRS"
281 DruidTable
= GemRB
.LoadTable (DruidTable
)
283 for j
in range (DruidTable
.GetColumnCount ()):
284 NewDSpells
[j
] = DruidTable
.GetValue (str(Level
[i
]), str(j
+1), 1)
285 OldDSpells
[j
] = DruidTable
.GetValue (str(StartLevel
), str(j
+1), 1)
286 DeltaDSpells
= sum(NewDSpells
)-sum(OldDSpells
)
288 # setup class bonuses for this class
289 if IsMulti
or IsDual
or Kit
== 0:
290 ABTable
= CommonTables
.ClassSkills
.GetValue (TmpName
, "ABILITIES")
291 else: # single-classed with a kit
292 ABTable
= CommonTables
.KitList
.GetValue (str(Kit
), "ABILITIES")
294 # add the abilites if we have a table to ref
295 if ABTable
!= "*" and GemRB
.HasResource (ABTable
, RES_2DA
, 1):
296 GUICommon
.AddClassAbilities (pc
, ABTable
, Level
[i
], LevelDiff
[i
])
298 print "Actor CurrentLevels:",actor
.Levels()
299 print "Levels:",Level
,"Actor NextLevels:",actor
.NextLevels()
300 print "LevelDiffs:",LevelDiff
,"Actor LevelDiffs:",actor
.LevelDiffs()
302 #update our saves, thaco, hp and lore
303 LUCommon
.SetupSavingThrows (pc
, Level
)
304 LUCommon
.SetupThaco (pc
, Level
)
305 LUCommon
.SetupLore (pc
, LevelDiff
)
306 LUCommon
.SetupHP (pc
, Level
, LevelDiff
)
308 # use total levels for HLAs
310 if GUICommon
.HasTOB(): # make sure SoA doesn't try to get it
311 HLATable
= GemRB
.LoadTable("lunumab")
312 # we need to check each level against a multi value (this is kinda screwy)
314 print "Actor HLA Names:",["MULTI"+str(actor
.NumClasses())+name \
315 for name
in actor
.ClassNames()]
317 print "Actor HLA Names:",actor
.ClassNames()
319 for i
in range (NumClasses
):
321 # get the row name for lookup ex. MULTI2FIGHTER, MULTI3THIEF
322 MultiName
= CommonTables
.Classes
.FindValue (5, Classes
[i
])
323 MultiName
= CommonTables
.Classes
.GetRowName (MultiName
)
324 MultiName
= "MULTI" + str(NumClasses
) + MultiName
326 MultiName
= ClassName
328 # if we can't learn for this class, we can't learn at all
329 FirstLevel
= HLATable
.GetValue (MultiName
, "FIRST_LEVEL", 1)
330 if Level
[i
] < FirstLevel
:
334 if (Level
[i
] - LevelDiff
[i
]) < FirstLevel
:
335 # count only from FirstLevel up
336 HLACount
+= (Level
[i
] - FirstLevel
+ 1)
338 HLACount
+= LevelDiff
[i
]
340 # set values required by the hla level up code
341 HLACount
= HLACount
/ HLATable
.GetValue (ClassName
, "RATE", 1)
342 GemRB
.SetVar ("HLACount", HLACount
)
343 if GUICommon
.GameIsBG2():
344 HLAButton
= LevelUpWindow
.GetControl (126)
346 HLAButton
.SetText (4954)
347 HLAButton
.SetEvent (IE_GUI_BUTTON_ON_PRESS
, LevelUpHLAPress
)
349 HLAButton
.SetFlags (IE_GUI_BUTTON_DISABLED
, OP_OR
)
353 for i
in range (len (Level
)):
354 Level1
.append (Level
[i
]-LevelDiff
[i
])
355 if GUICommon
.GameIsBG2():
356 LUProfsSelection
.SetupProfsWindow (pc
, LUProfsSelection
.LUPROFS_TYPE_LEVELUP
, LevelUpWindow
, RedrawSkills
, Level1
, Level
)
358 LUProfsSelection
.SetupProfsWindow (pc
, LUProfsSelection
.LUPROFS_TYPE_LEVELUP
, LevelUpWindow
, RedrawSkills
, Level1
, Level
, 0, False, 0)
359 NewProfPoints
= GemRB
.GetVar ("ProfsPointsLeft")
361 #we autohide the skills and let SetupSkillsWindow show them if needbe
364 if GUICommon
.GameIsBG2():
365 LUSkillsSelection
.SetupSkillsWindow (pc
, LUSkillsSelection
.LUSKILLS_TYPE_LEVELUP
, LevelUpWindow
, RedrawSkills
, Level1
, Level
)
367 LUSkillsSelection
.SetupSkillsWindow (pc
, LUSkillsSelection
.LUSKILLS_TYPE_LEVELUP
, LevelUpWindow
, RedrawSkills
, Level1
, Level
, 0, False)
368 NewSkillPoints
= GemRB
.GetVar ("SkillPointsLeft")
370 if GUICommon
.GameIsBG2():
371 TextAreaControl
= LevelUpWindow
.GetControl(110)
372 TextAreaControl
.SetText(GetLevelUpNews())
374 TextAreaControl
= LevelUpWindow
.GetControl(42)
375 TextAreaControl
.SetText(GUIREC
.GetStatOverview(pc
, LevelDiff
))
378 GemRB
.SetRepeatClickFlags (GEM_RK_DISABLE
, OP_NAND
)
379 LevelUpWindow
.ShowModal (MODAL_SHADOW_GRAY
)
381 # if we have a sorcerer who can learn spells, we need to do spell selection
382 if (Classes
[0] == 19) and (DeltaWSpells
> 0): # open our sorc spell selection window
383 LUSpellSelection
.OpenSpellsWindow (pc
, "SPLSRCKN", Level
[0], LevelDiff
[0])
386 """Hides the given skill label from view."""
389 Label
= LevelUpWindow
.GetControl (0x10000000+32+i
)
391 Button1
= LevelUpWindow
.GetControl(i
*2+17)
392 Button1
.SetState(IE_GUI_BUTTON_DISABLED
)
393 Button1
.SetFlags(IE_GUI_BUTTON_NO_IMAGE
,OP_OR
)
394 Button2
= LevelUpWindow
.GetControl(i
*2+18)
395 Button2
.SetState(IE_GUI_BUTTON_DISABLED
)
396 Button2
.SetFlags(IE_GUI_BUTTON_NO_IMAGE
,OP_OR
)
397 Label
= LevelUpWindow
.GetControl(0x10000000+43+i
)
401 """Redraws the entire window.
403 Called whenever a state changes, such as a proficiency or skill being
404 added or taken away."""
406 global DoneButton
, LevelUpWindow
, HLACount
408 # we need to disable the HLA button if we don't have any HLAs left
409 HLACount
= GemRB
.GetVar ("HLACount")
410 if GUICommon
.GameIsBG2() and HLACount
== 0:
411 # turn the HLA button off
412 HLAButton
= LevelUpWindow
.GetControl (126)
413 HLAButton
.SetState(IE_GUI_BUTTON_DISABLED
)
415 # enable the done button if they've allocated all points
416 # sorcerer spell selection (if applicable) comes after hitting the done button
417 ProfPointsLeft
= GemRB
.GetVar ("ProfsPointsLeft")
418 SkillPointsLeft
= GemRB
.GetVar ("SkillPointsLeft")
419 if ProfPointsLeft
== 0 and SkillPointsLeft
== 0 and HLACount
== 0:
420 DoneButton
.SetState (IE_GUI_BUTTON_ENABLED
)
422 DoneButton
.SetState (IE_GUI_BUTTON_DISABLED
)
425 def GetLevelUpNews():
426 """Returns a string containing improvements gain on level up.
428 These include: HP, spells per level, and lore, among others."""
430 News
= GemRB
.GetString (5259) + '\n\n'
432 # display if our class has been reactivated
434 if (Level
[0] - LevelDiff
[0]) <= Level
[1] and Level
[0] > Level
[1]:
435 News
= GemRB
.GetString (5261) + '\n\n'
437 # 5271 - Additional weapon proficiencies
438 if NewProfPoints
> 0:
439 News
+= GemRB
.GetString (5271) + ": " + str(NewProfPoints
) + '\n\n'
441 # temps to compare all our new saves against (we get the best of our saving throws)
445 for i
in range(NumClasses
):
447 TmpClassName
= CommonTables
.Classes
.FindValue (5, Classes
[i
])
448 TmpClassName
= CommonTables
.Classes
.GetRowName (TmpClassName
)
451 # NOTE: Stalkers and assassins should get the correct mods at the correct levels based
452 # on AP_SPCL332 in their respective CLAB files.
453 # APND: Stalkers appear to get the correct mod at the correct levels; however, because they start
454 # at backstab multi x1, they are x1 too many at their respective levels.
455 if Classes
[i
] == 4 and GemRB
.GetPlayerStat (pc
, IE_BACKSTABDAMAGEMULTIPLIER
, 1) > 1: # we have a thief who can backstab (2 at level 1)
456 # save the backstab multiplier if we have a thief
457 BackstabTable
= GemRB
.LoadTable ("BACKSTAB")
458 BackstabMult
= BackstabTable
.GetValue (0, Level
[i
])
461 if (CommonTables
.ClassSkills
.GetValue (Classes
[i
], 6) != "*"):
462 # inquisitors and undead hunters don't get lay on hands out the chute, whereas cavaliers
463 # and unkitted paladins do; therefore, we check for the existence of lay on hands to ensure
464 # the character should get the new value; LoH is defined in GA_SPCL211 if anyone wants to
465 # make a pally kit with LoH
466 if (GUICommon
.HasSpell (pc
, IE_SPELL_TYPE_INNATE
, 0, "SPCL211") >= 0):
467 LOHTable
= GemRB
.LoadTable ("layhands")
468 LOHGain
= LOHTable
.GetValue (0, Level
[i
]) - LOHTable
.GetValue (0, Level
[i
]-LevelDiff
[i
])
476 # include in news if the save is updated
479 CurrentSave
= GemRB
.GetPlayerStat (pc
, IE_SAVEVSDEATH
+i
, 1)
486 if CurrentSave
< OldSaves
[i
]:
487 News
+= GemRB
.GetString (SaveString
) + ": " + str(OldSaves
[i
]-CurrentSave
) + '\n'
492 # 5305 - THAC0 Reduced by
493 # only output if there is a change in thaco
494 NewThaco
= GemRB
.GetPlayerStat (pc
, IE_TOHIT
, 1)
495 if (NewThaco
< OldThaco
):
496 News
+= GemRB
.GetString (5305) + ": " + str(OldThaco
-NewThaco
) + '\n\n'
499 # 5373 - Additional Priest Spells
500 # 5374 - Additional Mage Spells
501 # 61269 - Level <LEVEL> Spells
502 if DeltaDSpells
> 0: # new divine spells
503 News
+= GemRB
.GetString (5373) + '\n'
504 for i
in range (len (NewDSpells
)):
505 # only display classes with new spells
506 if (NewDSpells
[i
]-OldDSpells
[i
]) == 0:
508 GemRB
.SetToken("level", str(i
+1))
509 News
+= GemRB
.GetString(61269)+": " + str(NewDSpells
[i
]-OldDSpells
[i
]) + '\n'
511 if DeltaWSpells
> 0: # new wizard spells
512 News
+= GemRB
.GetString (5374) + '\n'
513 for i
in range (len (NewWSpells
)):
514 # only display classes with new spells
515 if (NewWSpells
[i
]-OldWSpells
[i
]) == 0:
517 GemRB
.SetToken("level", str(i
+1))
518 News
+= GemRB
.GetString(61269)+": " + str(NewWSpells
[i
]-OldWSpells
[i
]) + '\n'
521 # 5375 - Backstab Multiplier Increased by
522 # this auto-updates... we just need to inform of the update
523 BSGain
= BackstabMult
- GemRB
.GetPlayerStat (pc
, IE_BACKSTABDAMAGEMULTIPLIER
, 1)
525 News
+= GemRB
.GetString (5375) + ": " + str(BSGain
) + '\n\n'
527 # 5376 - Lay on Hands increased
529 News
+= GemRB
.GetString (5376) + ": " + str(LOHGain
) + '\n\n'
531 # 5293 - HP increased by
532 if (OldHPMax
!= GemRB
.GetPlayerStat (pc
, IE_MAXHITPOINTS
, 1)):
533 News
+= GemRB
.GetString (5293) + ": " + str(GemRB
.GetPlayerStat (pc
, IE_MAXHITPOINTS
, 1) - OldHPMax
) + '\n'
535 # 5377 - Lore Increased by
536 # add the lore gain if we haven't done so already
537 NewLore
= GemRB
.GetPlayerStat (pc
, IE_LORE
, 1)
538 if NewLore
> OldLore
:
539 News
+= GemRB
.GetString (5377) + ": " + str(NewLore
-OldLore
) + '\n\n'
541 # 5378 - Additional Skill Points
542 # ranger and bard skill(point) gain is not mentioned here in the original
543 if NewSkillPoints
> 0:
544 News
+= GemRB
.GetString (5378) + ": " + str(NewSkillPoints
) + '\n'
548 def LevelUpInfoPress():
549 """Displays new abilites gained on level up.
551 Alternates between overall and modified stats."""
553 global LevelUpWindow
, TextAreaControl
, InfoCounter
, LevelDiff
556 # call GetStatOverview with the new levels, so the future overview is shown
557 # TODO: show only xp, levels, thac0, #att, lore, reputation, backstab, saving throws
558 TextAreaControl
.SetText(GUIREC
.GetStatOverview(pc
, LevelDiff
))
560 TextAreaControl
.SetText(GetLevelUpNews())
565 def LevelUpDonePress():
566 """Updates the PC with the new choices.
568 Closes the window when finished."""
569 import GUICommonWindows
574 LUProfsSelection
.ProfsSave (pc
)
577 LUSkillsSelection
.SkillsSave (pc
)
580 if DualSwap
: # swap the IE_LEVELs around if a backward dual
581 GemRB
.SetPlayerStat (pc
, IE_LEVEL2
, Level
[0])
582 GemRB
.SetPlayerStat (pc
, IE_LEVEL
, Level
[1])
584 GemRB
.SetPlayerStat (pc
, IE_LEVEL
, Level
[0])
585 GemRB
.SetPlayerStat (pc
, IE_LEVEL2
, Level
[1])
586 GemRB
.SetPlayerStat (pc
, IE_LEVEL3
, Level
[2])
588 print "Levels:",Level
[0],"/",Level
[1],"/",Level
[2]
590 # save our number of memorizable spells per level
592 # loop through each wizard spell level
593 for i
in range(len(NewWSpells
)):
594 if NewWSpells
[i
] > 0: # we have new spells, so update
595 GemRB
.SetMemorizableSpellsCount(pc
, NewWSpells
[i
], IE_SPELL_TYPE_WIZARD
, i
)
597 # save our number of memorizable priest spells
598 if DeltaDSpells
> 0: # druids and clerics count
599 for i
in range (len(NewDSpells
)):
601 if NewDSpells
[i
] > 0:
602 GemRB
.SetMemorizableSpellsCount (pc
, NewDSpells
[i
], IE_SPELL_TYPE_PRIEST
, i
)
604 # learn all the spells we're given, but don't have, up to our given casting level
605 if GemRB
.GetMemorizableSpellsCount (pc
, IE_SPELL_TYPE_PRIEST
, i
, 1) > 0: # we can memorize spells of this level
606 for j
in range(NumClasses
): # loop through each class
607 IsDruid
= CommonTables
.ClassSkills
.GetValue (Classes
[j
], 0, 0)
608 IsCleric
= CommonTables
.ClassSkills
.GetValue (Classes
[j
], 1, 0)
609 if IsCleric
== "*" and IsDruid
== "*": # no divine spells (so mage/cleric multis don't screw up)
611 elif IsCleric
== "*": # druid spells
613 else: # cleric spells
616 Learnable
= GUICommon
.GetLearnablePriestSpells(ClassFlag
, GemRB
.GetPlayerStat (pc
, IE_ALIGNMENT
), i
+1)
617 for k
in range(len(Learnable
)): # loop through all the learnable spells
618 if GUICommon
.HasSpell (pc
, IE_SPELL_TYPE_PRIEST
, i
, Learnable
[k
]) < 0: # only write it if we don't yet know it
619 GemRB
.LearnSpell(pc
, Learnable
[k
])
622 # level, xp and other stuff by the core?
624 # 5261 - Regained abilities from inactive class
625 if IsDual
: # we're dual classed
627 if (Level
[0] - LevelDiff
[0]) <= Level
[1] and Level
[0] > Level
[1]: # our new classes now surpasses our old class
628 print "reactivating base class"
629 ReactivateBaseClass ()
632 LevelUpWindow
.Unload()
633 GUICommonWindows
.UpdatePortraitWindow ()
634 GUIREC
.UpdateRecordsWindow()
636 GemRB
.SetRepeatClickFlags (GEM_RK_DISABLE
, OP_OR
)
639 def LevelUpHLAPress ():
640 """Opens the HLA selection window."""
642 # we can turn the button off and temporarily set HLACount to 0
643 # because there is no cancel button on the HLA window; therefore,
644 # it's guaranteed to come back as 0
645 TmpCount
= GemRB
.GetVar ("HLACount")
646 GemRB
.SetVar ("HLACount", 0)
648 GemRB
.SetVar ("HLACount", TmpCount
)
650 LUHLASelection
.OpenHLAWindow (pc
, NumClasses
, Classes
, Level
)
653 def ReactivateBaseClass ():
654 """Regains all abilities of the base dual-class.
656 Proficiencies, THACO, saves, spells, and innate abilites,
659 ClassIndex
= CommonTables
.Classes
.FindValue (5, Classes
[1])
660 ClassName
= CommonTables
.Classes
.GetRowName (ClassIndex
)
661 KitIndex
= GUICommon
.GetKitIndex (pc
)
663 # reactivate all our proficiencies
664 TmpTable
= GemRB
.LoadTable ("weapprof")
666 if GUICommon
.GameIsBG2 ():
667 ProfsTableOffset
= 8 # skip bg1 weapprof.2da proficiencies
668 ProfCount
= TmpTable
.GetRowCount () - ProfsTableOffset
669 for i
in range(ProfCount
):
670 ProfID
= TmpTable
.GetValue (i
+ProfsTableOffset
, 0)
671 if GUICommon
.GameIsBG1():
672 ProfID
= ProfID
+ IE_PROFICIENCYBASTARDSWORD
673 Value
= GemRB
.GetPlayerStat (pc
, ProfID
)
674 OldProf
= (Value
& 0x38) >> 3
675 NewProf
= Value
& 0x07
676 if OldProf
> NewProf
:
677 Value
= (OldProf
<< 3) | OldProf
679 if GUICommon
.GameIsBG2():
680 GemRB
.ApplyEffect (pc
, "Proficiency", Value
, ProfID
)
682 GemRB
.SetPlayerStat (pc
, ProfID
, Value
)
684 # see if this thac0 is lower than our current thac0
685 ThacoTable
= GemRB
.LoadTable ("THAC0")
686 TmpThaco
= ThacoTable
.GetValue(Classes
[1]-1, Level
[1]-1, 1)
687 if TmpThaco
< GemRB
.GetPlayerStat (pc
, IE_TOHIT
, 1):
688 GemRB
.SetPlayerStat (pc
, IE_TOHIT
, TmpThaco
)
690 # see if all our saves are lower than our current saves
691 SavesTable
= CommonTables
.Classes
.GetValue (ClassIndex
, 3, 0)
692 SavesTable
= GemRB
.LoadTable (SavesTable
)
694 # see if this save is lower than our old save
695 TmpSave
= SavesTable
.GetValue (i
, Level
[1]-1)
696 if TmpSave
< GemRB
.GetPlayerStat (pc
, IE_SAVEVSDEATH
+i
, 1):
697 GemRB
.SetPlayerStat (pc
, IE_SAVEVSDEATH
+i
, TmpSave
)
699 # see if we're a caster
700 SpellTables
= [CommonTables
.ClassSkills
.GetValue (Classes
[1], 0, 0), CommonTables
.ClassSkills
.GetValue (Classes
[1], 1, 0), CommonTables
.ClassSkills
.GetValue (Classes
[1], 2, 0)]
701 if SpellTables
[2] != "*": # casts mage spells
702 # set up our memorizations
703 SpellTable
= GemRB
.LoadTable (SpellTables
[2])
705 # if we can cast more spells at this level (should be always), then update
706 NumSpells
= SpellTable
.GetValue (Level
[1]-1, i
)
707 if NumSpells
> GemRB
.GetMemorizableSpellsCount (pc
, IE_SPELL_TYPE_WIZARD
, i
, 1):
708 GemRB
.SetMemorizableSpellsCount (pc
, NumSpells
, IE_SPELL_TYPE_WIZARD
, i
)
709 elif SpellTables
[1] != "*" or SpellTables
[0] != "*": # casts priest spells
710 # get the correct table and mask
711 if SpellTables
[1] != "*": # clerical spells
712 SpellTable
= GemRB
.LoadTable (SpellTables
[1])
714 else: # druidic spells
715 if not GameRB
.HasResource(SpellTables
[0], RES_2DA
):
716 SpellTables
[0] = "MXSPLPRS"
717 SpellTable
= GemRB
.LoadTable (SpellTables
[0])
720 # loop through each spell level
722 # update if we can cast more spells at this level
723 NumSpells
= SpellTable
.GetValue (str(Level
[1]), str(i
+1), 1)
726 if NumSpells
> GemRB
.GetMemorizableSpellsCount (pc
, IE_SPELL_TYPE_PRIEST
, i
, 1):
727 GemRB
.SetMemorizableSpellsCount (pc
, NumSpells
, IE_SPELL_TYPE_PRIEST
, i
)
729 # also re-learn the spells if we have to
730 # WARNING: this fixes the error whereby rangers dualed to clerics still got all druid spells
731 # they will now only get druid spells up to the level they could cast
732 # this should probably be noted somewhere (ranger/cleric multis still function the same,
733 # but that could be remedied if desired)
734 Learnable
= GUICommon
.GetLearnablePriestSpells(ClassMask
, GemRB
.GetPlayerStat (pc
, IE_ALIGNMENT
), i
+1)
735 for k
in range (len (Learnable
)): # loop through all the learnable spells
736 if GUICommon
.HasSpell (pc
, IE_SPELL_TYPE_PRIEST
, i
, Learnable
[k
]) < 0: # only write it if we don't yet know it
737 GemRB
.LearnSpell(pc
, Learnable
[k
])
739 # setup class bonuses for this class
740 if KitIndex
== 0: # no kit
741 ABTable
= CommonTables
.ClassSkills
.GetValue (ClassName
, "ABILITIES")
743 ABTable
= CommonTables
.KitList
.GetValue (KitIndex
, 4, 0)
744 print "ABTable:",ABTable
746 # add the abilites if we have a table to ref
747 if ABTable
!= "*" and GemRB
.HasResource (ABTable
, RES_2DA
, 1):
748 GUICommon
.AddClassAbilities (pc
, ABTable
, Level
[1], Level
[1]) # relearn class abilites