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.
19 # LUProfsSelection.py - Modular selection of proficiencies
22 from GUIDefines
import *
23 from ie_stats
import *
27 #the different types possible
28 LUPROFS_TYPE_LEVELUP
= 1
29 LUPROFS_TYPE_DUALCLASS
= 2
30 LUPROFS_TYPE_CHARGEN
= 4
32 #refs to the script calling this
36 #all our offsets for the various parts of the window
38 ProfsOffsetButton1
= 0
42 Profs2ndOffsetButton1
= Profs2ndOffsetStar
= Profs2ndOffsetLabel
= -1
55 # the table offset is used in bg2, since in the end they made it use different
56 # profs than in bg1, but left the table entries intact
60 # iwd1/bg1 table that holds the allowed proficiency <-> class mapping
61 ClassWeaponsTable
= None
65 def SetupProfsWindow (pc
, type, window
, callback
, level1
=[0,0,0], level2
=[1,1,1], classid
=0, scroll
=True, profTableOffset
=8):
66 """Opens the proficiency selection window.
68 type specifies the type of selection we are doing; choices are above.
69 window specifies the window to be updated.
70 callback specifies the function to call on changes.
71 classid is sent only during dualclassing to specify the new class."""
73 global ProfsOffsetSum
, ProfsOffsetButton1
, ProfsOffsetLabel
, ProfsOffsetStar
, OddIDs
74 global ProfsOffsetPress
, ProfsPointsLeft
, ProfsNumButtons
, ProfsTopIndex
75 global ProfsScrollBar
, ProfsTableOffset
, ProfsType
76 global ProfsWindow
, ProfsCallback
, ProfsTextArea
, ProfsColumn
, ProfsTable
, ProfCount
77 global Profs2ndOffsetButton1
, Profs2ndOffsetStar
, Profs2ndOffsetLabel
, ClassNameSave
, ClassWeaponsTable
79 # make sure we're within ranges
80 GemRB
.SetVar ("ProfsPointsLeft", 0)
81 if not window
or not callback
or len(level1
)!=len(level2
):
84 # save the values we'll point to
86 ProfsCallback
= callback
87 ProfsTableOffset
= profTableOffset
90 if type == LUPROFS_TYPE_CHARGEN
and GUICommon
.GameIsBG2(): #chargen
92 ProfsOffsetButton1
= 11
97 ProfsTextArea
= ProfsWindow
.GetControl (68)
98 ProfsTextArea
.SetText (9588)
100 ProfsScrollBar
= ProfsWindow
.GetControl (78)
101 elif type == LUPROFS_TYPE_CHARGEN
and GUICommon
.GameIsBG1(): #chargen
103 ProfsOffsetButton1
= 11
106 ProfsOffsetPress
= 69
108 ProfsTextArea
= ProfsWindow
.GetControl (68)
109 ProfsTextArea
.SetText (9588)
111 ProfsScrollBar
= ProfsWindow
.GetControl (78)
112 elif type == LUPROFS_TYPE_LEVELUP
and GUICommon
.GameIsBG2(): #levelup
114 ProfsOffsetButton1
= 1
116 ProfsOffsetLabel
= 24
117 ProfsOffsetPress
= 112
119 ProfsTextArea
= ProfsWindow
.GetControl (110)
120 ProfsScrollBar
= ProfsWindow
.GetControl (108)
121 elif type == LUPROFS_TYPE_LEVELUP
and GUICommon
.GameIsBG1(): #levelup
123 ProfsOffsetButton1
= 1
125 ProfsOffsetLabel
= 24
126 ProfsOffsetPress
= 17
128 ProfsTextArea
= ProfsWindow
.GetControl (42)
130 ProfsScrollBar
= ProfsWindow
.GetControl (108)
131 elif type == LUPROFS_TYPE_LEVELUP
and GUICommon
.GameIsIWD1(): #levelup
133 ProfsOffsetButton1
= 1
135 ProfsOffsetLabel
= 24
136 ProfsOffsetPress
= -1
137 ProfsNumButtons
= 15 # 8+7, the 7 are done with the following vars
138 Profs2ndOffsetButton1
= 150
139 Profs2ndOffsetStar
= 115
140 Profs2ndOffsetLabel
= 108
141 ProfsTextArea
= ProfsWindow
.GetControl (42)
143 ProfsScrollBar
= ProfsWindow
.GetControl (108)
145 elif type == LUPROFS_TYPE_DUALCLASS
and GUICommon
.GameIsIWD1(): #dualclass
147 ProfsOffsetButton1
= 50
149 ProfsOffsetLabel
= 41
150 ProfsOffsetPress
= -1 #66
152 Profs2ndOffsetButton1
= 78
153 Profs2ndOffsetStar
= 92
154 Profs2ndOffsetLabel
= 126
155 ProfsTextArea
= ProfsWindow
.GetControl (74)
156 ProfsTextArea
.SetText (9588)
158 ProfsScrollBar
= ProfsWindow
.GetControl (None)
160 elif type == LUPROFS_TYPE_DUALCLASS
and GUICommon
.GameIsBG1(): #dualclass
162 ProfsOffsetButton1
= 50
164 ProfsOffsetLabel
= 41
165 ProfsOffsetPress
= -1 #FIXME
167 ProfsTextArea
= ProfsWindow
.GetControl (74)
168 ProfsTextArea
.SetText (9588)
170 ProfsScrollBar
= ProfsWindow
.GetControl (None)
171 elif type == LUPROFS_TYPE_DUALCLASS
: #dualclass
173 ProfsOffsetButton1
= 50
175 ProfsOffsetLabel
= 41
176 ProfsOffsetPress
= 66
178 ProfsTextArea
= ProfsWindow
.GetControl (74)
179 ProfsTextArea
.SetText (9588)
181 ProfsScrollBar
= ProfsWindow
.GetControl (78)
185 #nullify internal variables
186 GemRB
.SetVar ("ProfsTopIndex", 0)
190 ProfsTable
= GemRB
.LoadTable ("profs")
191 if GUICommon
.GameIsIWD1() or GUICommon
.GameIsBG1():
192 ClassWeaponsTable
= GemRB
.LoadTable ("clasweap")
194 ClassWeaponsTable
= None
197 IsDual
= GUICommon
.IsDualClassed (pc
, 1)
198 if classid
: #for dual classes when we can't get the class dualing to
201 Class
= CommonTables
.Classes
.GetValue (IsDual
[2], 5)
203 Class
= GemRB
.GetPlayerStat (pc
, IE_CLASS
)
204 ClassName
= CommonTables
.Classes
.FindValue (5, Class
)
205 ClassName
= CommonTables
.Classes
.GetRowName (ClassName
)
206 if ClassName
== "SORCERER":
208 ClassNameSave
= ClassName
210 #find the class with the greatest prof potential
213 IsMulti
= GUICommon
.IsMultiClassed (pc
, 1)
215 for i
in range (1, IsMulti
[0]+1):
216 TmpRate
= ProfsTable
.GetValue (IsMulti
[i
]-1, 1)
217 if TmpRate
< ProfsRate
:
221 ProfsRate
= ProfsTable
.GetValue (Class
-1, 1)
223 #figure out how many prof points we have
224 if sum (level1
) == 0: #character is being generated (either chargen or dual)
225 ProfsPointsLeft
= ProfsTable
.GetValue (ClassName
, "FIRST_LEVEL")
227 #we need these 2 number to floor before subtracting
228 ProfsPointsLeft
+= level2
[FastestProf
]/ProfsRate
- level1
[FastestProf
]/ProfsRate
230 #setup prof vars for passing between functions
231 ProfsTable
= GemRB
.LoadTable ("weapprof")
233 # if we have the classweapons table, use it
234 if ClassWeaponsTable
:
235 ProfsColumn
= ClassWeaponsTable
.GetRowIndex (ClassName
)
237 Kit
= GUICommon
.GetKitIndex (pc
)
238 if Kit
and type != LUPROFS_TYPE_DUALCLASS
and IsMulti
[0]<2 and not IsDual
[0]:
239 #if we do kit with dualclass, we'll get the old kit
240 #also don't want to worry about kitted multis
241 ProfsColumn
= CommonTables
.KitList
.GetValue (Kit
, 5)
243 ProfsColumn
= ProfsTable
.GetColumnIndex (ClassName
)
245 #setup some basic counts
246 RowCount
= ProfsTable
.GetRowCount () - ProfsTableOffset
+ 1
247 ProfCount
= RowCount
-ProfsNumButtons
#decrease it with the number of controls
250 TwoWeapIndex
= ProfsTable
.GetRowIndex ("2WEAPON")
251 for i
in range(RowCount
):
252 ProfName
= ProfsTable
.GetValue (i
+ProfsTableOffset
, 1)
253 #decrease it with the number of invalid proficiencies
254 if ProfName
> 0x1000000 or ProfName
< 0:
257 #we only need the low 3 bits for profeciencies on levelup; otherwise
258 #we just set them all to 0
260 if type == LUPROFS_TYPE_LEVELUP
:
261 stat
= ProfsTable
.GetValue (i
+ProfsTableOffset
, 0)
262 if GUICommon
.GameIsBG1():
263 stat
= stat
+ IE_PROFICIENCYBASTARDSWORD
264 currentprof
= GemRB
.GetPlayerStat (pc
, stat
)&0x07
266 #rangers always get 2 points in 2 weapons style
267 if (i
+ProfsTableOffset
) == TwoWeapIndex
and "RANGER" in ClassName
.split("_"):
269 GemRB
.SetVar ("Prof "+str(i
), currentprof
)
270 GemRB
.SetVar ("ProfBase "+str(i
), currentprof
)
272 #see if we can assign to this prof
273 if ClassWeaponsTable
:
274 maxprof
= ClassWeaponsTable
.GetValue (ProfsColumn
, i
) # this table has profs as rows
276 maxprof
= ProfsTable
.GetValue(i
+ProfsTableOffset
, ProfsColumn
)
277 if maxprof
> currentprof
:
278 ProfsAssignable
+= maxprof
-currentprof
280 #correct the profs left if we can't assign that much
281 if ProfsPointsLeft
> ProfsAssignable
:
282 ProfsPointsLeft
= ProfsAssignable
283 GemRB
.SetVar ("ProfsPointsLeft", ProfsPointsLeft
)
285 # setup the +/- and info controls
286 for i
in range (ProfsNumButtons
):
287 if ProfsOffsetPress
!= -1:
288 Button
=ProfsWindow
.GetControl(i
+ProfsOffsetPress
)
289 Button
.SetVarAssoc("Prof", i
)
290 Button
.SetEvent(IE_GUI_BUTTON_ON_PRESS
, ProfsJustPress
)
292 cid
= i
*2+ProfsOffsetButton1
293 if Profs2ndOffsetButton1
!= -1 and i
> 7:
294 cid
= (i
-8)*2+Profs2ndOffsetButton1
296 Button
=ProfsWindow
.GetControl(cid
)
297 Button
.SetVarAssoc("Prof", i
)
298 Button
.SetEvent(IE_GUI_BUTTON_ON_PRESS
, ProfsLeftPress
)
300 Button
=ProfsWindow
.GetControl(cid
+1)
301 Button
.SetVarAssoc("Prof", i
)
302 Button
.SetEvent(IE_GUI_BUTTON_ON_PRESS
, ProfsRightPress
)
305 # proficiencies scrollbar
306 ProfsScrollBar
.SetEvent(IE_GUI_SCROLLBAR_ON_CHANGE
, ProfsScrollBarPress
)
307 ProfsScrollBar
.SetDefaultScrollBar ()
308 ProfsScrollBar
.SetVarAssoc ("ProfsTopIndex", ProfCount
)
312 def ProfsRedraw (first
=0):
313 """Redraws the proficiencies part of the window.
315 If first is true, it skips ahead to the first assignable proficiency."""
317 global ProfsTopIndex
, ProfsScrollBar
319 ProfSumLabel
= ProfsWindow
.GetControl(0x10000000+ProfsOffsetSum
)
320 ProfSumLabel
.SetText(str(ProfsPointsLeft
))
323 for i
in range(ProfsNumButtons
):
325 ProfName
= ProfsTable
.GetValue(Pos
+ProfsTableOffset
, 1) #we add the bg1 skill count offset
326 if ClassWeaponsTable
: # iwd
327 MaxProf
= ClassWeaponsTable
.GetValue (ClassNameSave
, ProfsTable
.GetRowName(Pos
))
329 MaxProf
= ProfsTable
.GetValue(Pos
+ProfsTableOffset
, ProfsColumn
)
331 cid
= i
*2+ProfsOffsetButton1
332 if Profs2ndOffsetButton1
!= -1 and i
> 7:
333 cid
= (i
-8)*2+Profs2ndOffsetButton1
334 Button1
=ProfsWindow
.GetControl (cid
)
335 Button2
=ProfsWindow
.GetControl (cid
+1)
337 Button1
.SetState(IE_GUI_BUTTON_DISABLED
)
338 Button2
.SetState(IE_GUI_BUTTON_DISABLED
)
339 Button1
.SetFlags(IE_GUI_BUTTON_NO_IMAGE
,OP_OR
)
340 Button2
.SetFlags(IE_GUI_BUTTON_NO_IMAGE
,OP_OR
)
341 if GUICommon
.GameIsBG2() and (i
==0 or ((i
-1) in SkipProfs
)):
344 Button1
.SetState(IE_GUI_BUTTON_ENABLED
)
345 Button2
.SetState(IE_GUI_BUTTON_ENABLED
)
346 Button1
.SetFlags(IE_GUI_BUTTON_NO_IMAGE
,OP_NAND
)
347 Button2
.SetFlags(IE_GUI_BUTTON_NO_IMAGE
,OP_NAND
)
349 cid
= 0x10000000 + ProfsOffsetLabel
+ i
350 if Profs2ndOffsetLabel
!= -1 and i
> 7:
352 cid
= 0x10000000 + Profs2ndOffsetLabel
+ 2*(i
- 8)
354 cid
= 0x10000000 + Profs2ndOffsetLabel
+ i
- 8
356 Label
=ProfsWindow
.GetControl (cid
)
357 Label
.SetText(ProfName
)
359 ActPoint
= GemRB
.GetVar("Prof "+str(Pos
) )
360 for j
in range(5): #5 is maximum distributable
361 cid
= i
*5 + j
+ ProfsOffsetStar
362 if Profs2ndOffsetStar
!= -1 and i
> 7:
363 cid
= (i
-8)*5 + j
+ Profs2ndOffsetStar
364 Star
=ProfsWindow
.GetControl (cid
)
365 Star
.SetSprites("GUIPFC", 0, 0, 0, 0, 0)
367 Star
.SetFlags(IE_GUI_BUTTON_NO_IMAGE
,OP_NAND
)
369 Star
.SetFlags(IE_GUI_BUTTON_NO_IMAGE
,OP_OR
)
371 if first
and len (SkipProfs
):
372 ProfsTopIndex
+= SkipProfs
[-1]+1
373 GemRB
.SetVar ("ProfsTopIndex", ProfsTopIndex
)
375 ProfsScrollBar
.SetVarAssoc ("ProfsTopIndex", ProfCount
)
379 def ProfsScrollBarPress():
380 """Scrolls the window by reassigning ProfsTopIndex."""
384 ProfsTopIndex
= GemRB
.GetVar ("ProfsTopIndex")
388 def ProfsJustPress():
389 """Updates the text area with a description of the proficiency."""
390 Pos
= GemRB
.GetVar ("Prof")+ProfsTopIndex
391 ProfsTextArea
.SetText (ProfsTable
.GetValue(Pos
+ProfsTableOffset
, 2) )
394 def ProfsRightPress():
395 """Decrease the current proficiency by one."""
397 global ProfsPointsLeft
399 Pos
= GemRB
.GetVar("Prof")+ProfsTopIndex
400 ProfsTextArea
.SetText(ProfsTable
.GetValue(Pos
+ProfsTableOffset
, 2) )
401 ActPoint
= GemRB
.GetVar("Prof "+str(Pos
) )
402 MinPoint
= GemRB
.GetVar ("ProfBase "+str(Pos
) )
403 if ActPoint
<= 0 or ActPoint
<= MinPoint
:
405 GemRB
.SetVar("Prof "+str(Pos
),ActPoint
-1)
407 GemRB
.SetVar ("ProfsPointsLeft", ProfsPointsLeft
)
412 def ProfsLeftPress():
413 """Increases the current proficiency by one."""
415 global ProfsPointsLeft
417 Pos
= GemRB
.GetVar("Prof")+ProfsTopIndex
418 ProfsTextArea
.SetText(ProfsTable
.GetValue(Pos
+ProfsTableOffset
, 2) )
419 if ProfsPointsLeft
== 0:
421 if GUICommon
.GameIsIWD1() or GUICommon
.GameIsBG1():
422 ProfMaxTable
= GemRB
.LoadTable ("profsmax")
423 MaxProf
= ProfMaxTable
.GetValue(ClassNameSave
, "OTHER_LEVELS")
425 MaxProf
= ProfsTable
.GetValue(Pos
+ProfsTableOffset
, ProfsColumn
)
428 # FIXME: use profsmax.2da (in all games? could be problematic for weapon styles)
429 #if (MaxProf>2) and GUICommon.GameIsBG1():
432 ActPoint
= GemRB
.GetVar("Prof "+str(Pos
) )
433 if ActPoint
>= MaxProf
:
435 GemRB
.SetVar("Prof "+str(Pos
),ActPoint
+1)
437 GemRB
.SetVar ("ProfsPointsLeft", ProfsPointsLeft
)
442 def ProfsSave (pc
, type=LUPROFS_TYPE_LEVELUP
):
443 """Updates the actor with the new proficiencies."""
445 ProfCount
= ProfsTable
.GetRowCount () - ProfsTableOffset
446 for i
in range(ProfCount
): # skip bg1 weapprof.2da proficiencies
447 ProfID
= ProfsTable
.GetValue (i
+ProfsTableOffset
, 0)
448 if GUICommon
.GameIsBG1():
449 ProfID
= ProfID
+ IE_PROFICIENCYBASTARDSWORD
450 SaveProf
= GemRB
.GetVar ("Prof "+str(i
))
452 if type == LUPROFS_TYPE_CHARGEN
and GUICommon
.GameIsBG2():
453 GemRB
.DispelEffect (pc
, "Proficiency", ProfID
)
455 if type != LUPROFS_TYPE_DUALCLASS
:
456 OldProf
= GemRB
.GetPlayerStat (pc
, ProfID
) & 0x38
457 SaveProf
= OldProf | SaveProf
458 else: # gotta move the old prof to the back for dual class
459 OldProf
= GemRB
.GetPlayerStat (pc
, ProfID
) & 0x07
460 SaveProf
= (OldProf
<< 3) | SaveProf
462 GemRB
.SetPlayerStat (pc
, ProfID
, SaveProf
)
463 if GUICommon
.GameIsBG2() and (type == LUPROFS_TYPE_LEVELUP
or type == LUPROFS_TYPE_CHARGEN
):
465 GemRB
.ApplyEffect (pc
, "Proficiency", SaveProf
, ProfID
)
469 """Resets all of the internal variables to 0."""
473 ProfsTable
= GemRB
.LoadTable ("weapprof")
474 for i
in range (ProfsTable
.GetRowCount()-ProfsTableOffset
+1): #skip bg1 profs
475 GemRB
.SetVar ("Prof "+str(i
), 0)
476 GemRB
.SetVar ("ProfBase "+str(i
), 0)