factored out the EFFv2 saving into EFFImporter
[gemrb.git] / gemrb / GUIScripts / LevelUp.py
blob7ba2bcab10f421101a671e92627ba75c304a7e47
1 # -*-python-*-
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
21 import GemRB
22 from GUIDefines import *
23 from ie_stats import *
24 from ie_restype import RES_2DA
25 import GUICommon
26 import CommonTables
27 import LUSpellSelection
28 import LUCommon
29 if GUICommon.HasTOB():
30 import LUHLASelection
31 import LUProfsSelection
32 import LUSkillsSelection
33 import Actor
35 LevelUpWindow = None
36 DoneButton = 0
37 TextAreaControl = 0
38 InfoCounter = 1
39 NewProfPoints = 0
40 NewSkillPoints = 0
41 LevelDiff = 0
42 Level = 0
43 Classes = 0
44 NumClasses = 0
45 DualSwap = 0
46 KitName = 0
47 IsDual = 0
48 IsMulti = 0
49 pc = 0
50 ClassName = 0
51 actor = 0
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."""
67 import GUIREC
69 global LevelUpWindow, TextAreaControl, NewProfPoints, actor
70 global DoneButton
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)
92 # name
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():
99 # armorclass
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)
107 # hp now
108 Label = LevelUpWindow.GetControl (0x10000058)
109 Label.SetText (str (GemRB.GetPlayerStat (pc, IE_HITPOINTS)))
110 Label.SetTooltip (17184)
112 # hp max
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)
121 for i in range (5):
122 OldSaves[i] = GemRB.GetPlayerStat (pc, IE_SAVEVSDEATH+i, 1)
124 # class
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")
134 # kit
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
146 if Kit == 0:
147 KitName = ClassName
148 else:
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
157 IsDual = 0
158 DualSwap = 0
160 # not multi, check dual
161 if not IsMulti:
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
167 NumClasses = 1
169 # not dual, must be single
170 if IsDual[0] == 0:
171 Classes = [Class]
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)
175 else: # class
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()
183 Level = [0]*3
184 LevelDiff = [0]*3
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)
188 if IsDual:
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
197 if DualSwap:
198 Level[1] = GemRB.GetPlayerStat (pc, IE_LEVEL)
199 else:
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
205 hp = 0
206 HaveCleric = 0
207 # clear some globals, since we may get called multiple times with different classes
208 DeltaWSpells = 0
209 DeltaDSpells = 0
210 OldDSpells = [0]*7
211 OldWSpells = [0]*9
212 NewDSpells = [0]*7
213 NewWSpells = [0]*9
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
219 # get the next level
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)
227 if i == 0:
228 if DualSwap:
229 LevelDiff[i] = Level[i] - GemRB.GetPlayerStat (pc, IE_LEVEL2)
230 else:
231 LevelDiff[i] = Level[i] - GemRB.GetPlayerStat (pc, IE_LEVEL)
232 elif i == 1:
233 LevelDiff[i] = Level[i] - GemRB.GetPlayerStat (pc, IE_LEVEL2)
234 elif i == 2:
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
247 if MageTable != "*":
248 # we get 1 extra spell per level if we're a specialist
249 Specialist = 0
250 if CommonTables.KitList.GetValue (Kit, 7) == 1: # see if we're a kitted mage
251 Specialist = 1
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)
267 HaveCleric = 1
268 # same as above
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)
275 if HaveCleric == 0:
276 #use MXSPLPRS if we can't find the resource (SoA fix)
277 if not GemRB.HasResource (DruidTable, RES_2DA):
278 DruidTable = "MXSPLPRS"
280 # check druid spells
281 DruidTable = GemRB.LoadTable (DruidTable)
282 # same as above
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
309 HLACount = 0
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)
313 if actor.multiclass:
314 print "Actor HLA Names:",["MULTI"+str(actor.NumClasses())+name \
315 for name in actor.ClassNames()]
316 else:
317 print "Actor HLA Names:",actor.ClassNames()
319 for i in range (NumClasses):
320 if IsMulti:
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
325 else:
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:
331 HLACount = 0
332 break
334 if (Level[i] - LevelDiff[i]) < FirstLevel:
335 # count only from FirstLevel up
336 HLACount += (Level[i] - FirstLevel + 1)
337 else:
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)
345 if HLACount:
346 HLAButton.SetText (4954)
347 HLAButton.SetEvent (IE_GUI_BUTTON_ON_PRESS, LevelUpHLAPress)
348 else:
349 HLAButton.SetFlags (IE_GUI_BUTTON_DISABLED, OP_OR)
351 # setup our profs
352 Level1 = []
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)
357 else:
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
362 for i in range (4):
363 HideSkills (i)
364 if GUICommon.GameIsBG2():
365 LUSkillsSelection.SetupSkillsWindow (pc, LUSkillsSelection.LUSKILLS_TYPE_LEVELUP, LevelUpWindow, RedrawSkills, Level1, Level)
366 else:
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())
373 else:
374 TextAreaControl = LevelUpWindow.GetControl(42)
375 TextAreaControl.SetText(GUIREC.GetStatOverview(pc, LevelDiff))
377 RedrawSkills()
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])
385 def HideSkills(i):
386 """Hides the given skill label from view."""
387 global LevelUpWindow
389 Label = LevelUpWindow.GetControl (0x10000000+32+i)
390 Label.SetText ("")
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)
398 Label.SetText("")
400 def RedrawSkills():
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)
421 else:
422 DoneButton.SetState (IE_GUI_BUTTON_DISABLED)
423 return
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
433 if IsDual:
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)
442 LOHGain = 0
443 BackstabMult = 0
445 for i in range(NumClasses):
446 # get the class name
447 TmpClassName = CommonTables.Classes.FindValue (5, Classes[i])
448 TmpClassName = CommonTables.Classes.GetRowName (TmpClassName)
450 # backstab
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])
460 # lay on hands
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])
470 # saving throws
471 # 5277 death
472 # 5278 wand
473 # 5279 polymorph
474 # 5282 breath
475 # 5292 spell
476 # include in news if the save is updated
477 Changed = 0
478 for i in range (5):
479 CurrentSave = GemRB.GetPlayerStat (pc, IE_SAVEVSDEATH+i, 1)
480 SaveString = 5277+i
481 if i == 3:
482 SaveString = 5282
483 elif i == 4:
484 SaveString = 5292
486 if CurrentSave < OldSaves[i]:
487 News += GemRB.GetString (SaveString) + ": " + str(OldSaves[i]-CurrentSave) + '\n'
488 Changed = 1
489 if Changed:
490 News += '\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'
498 # new spell slots
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:
507 continue
508 GemRB.SetToken("level", str(i+1))
509 News += GemRB.GetString(61269)+": " + str(NewDSpells[i]-OldDSpells[i]) + '\n'
510 News += '\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:
516 continue
517 GemRB.SetToken("level", str(i+1))
518 News += GemRB.GetString(61269)+": " + str(NewWSpells[i]-OldWSpells[i]) + '\n'
519 News += '\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)
524 if (BSGain > 0):
525 News += GemRB.GetString (5375) + ": " + str(BSGain) + '\n\n'
527 # 5376 - Lay on Hands increased
528 if LOHGain > 0:
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'
546 return News
548 def LevelUpInfoPress():
549 """Displays new abilites gained on level up.
551 Alternates between overall and modified stats."""
552 import GUIREC
553 global LevelUpWindow, TextAreaControl, InfoCounter, LevelDiff
555 if InfoCounter % 2:
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))
559 else:
560 TextAreaControl.SetText(GetLevelUpNews())
561 InfoCounter += 1
562 return
564 # save the results
565 def LevelUpDonePress():
566 """Updates the PC with the new choices.
568 Closes the window when finished."""
569 import GUICommonWindows
570 import GUIREC
571 global SkillTable
573 # proficiencies
574 LUProfsSelection.ProfsSave (pc)
576 # skills
577 LUSkillsSelection.SkillsSave (pc)
579 # level
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])
583 else:
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
591 if DeltaWSpells > 0:
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)):
600 # get each update
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)
610 continue
611 elif IsCleric == "*": # druid spells
612 ClassFlag = 0x8000
613 else: # cleric spells
614 ClassFlag = 0x4000
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])
621 # hlas
622 # level, xp and other stuff by the core?
624 # 5261 - Regained abilities from inactive class
625 if IsDual: # we're dual classed
626 print "activation?"
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 ()
631 if LevelUpWindow:
632 LevelUpWindow.Unload()
633 GUICommonWindows.UpdatePortraitWindow ()
634 GUIREC.UpdateRecordsWindow()
636 GemRB.SetRepeatClickFlags (GEM_RK_DISABLE, OP_OR)
637 return
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)
647 RedrawSkills ()
648 GemRB.SetVar ("HLACount", TmpCount)
650 LUHLASelection.OpenHLAWindow (pc, NumClasses, Classes, Level)
651 return
653 def ReactivateBaseClass ():
654 """Regains all abilities of the base dual-class.
656 Proficiencies, THACO, saves, spells, and innate abilites,
657 most noteably."""
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")
665 ProfsTableOffset = 0
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
678 print "Value:",Value
679 if GUICommon.GameIsBG2():
680 GemRB.ApplyEffect (pc, "Proficiency", Value, ProfID )
681 else:
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)
693 for i in range (5):
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])
704 for i in range (9):
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])
713 ClassMask = 0x4000
714 else: # druidic spells
715 if not GameRB.HasResource(SpellTables[0], RES_2DA):
716 SpellTables[0] = "MXSPLPRS"
717 SpellTable = GemRB.LoadTable (SpellTables[0])
718 ClassMask = 0x8000
720 # loop through each spell level
721 for i in range (7):
722 # update if we can cast more spells at this level
723 NumSpells = SpellTable.GetValue (str(Level[1]), str(i+1), 1)
724 if not NumSpells:
725 continue
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")
742 else: # kit
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