factored out the EFFv2 saving into EFFImporter
[gemrb.git] / gemrb / GUIScripts / Actor.py
blobfd2e2cbd8ff40408c755c21e7cbc917f90aa0168
1 # -*-python-*-
2 # GemRB - Infinity Engine Emulator
3 # Copyright (C) 2003 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 # Actor.py: Contains the actor class.
22 import GemRB
23 from GUIDefines import *
24 from ie_stats import *
25 #this import is primarily for the tables
26 import CommonTables
28 ##############################################################################
29 ## GLOBALS TO BE INITIALIZED ONCE
30 ##############################################################################
31 dualswap = None
32 classcount = None
33 levelslots = [IE_LEVEL, IE_LEVEL2, IE_LEVEL3]
35 class Actor:
36 """Holds information of a PC."""
38 def __init__ (self, pc):
39 """Load up basic information."""
41 #setup our basic Actor
42 self.Reset (pc)
44 #setup globals if they are blank
45 if dualswap == None:
46 self.__setup_globals ()
48 def __setup_globals (self):
49 """Initializes all globals used for quick referencing.
51 Will only be called by the first Actor created."""
53 global classcount, dualswap
54 classcount = CommonTables.Classes.GetRowCount ()
55 dualswap = [0]*classcount
57 for i in range(classcount):
58 classid = CommonTables.Classes.GetValue (i, 5)
59 classnames = CommonTables.Classes.GetRowName(i).split("_")
61 #set the MC_WAS_ID of the first class
62 if len(classnames) == 2:
63 dualswap[classid-1] = CommonTables.Classes.GetValue (i, 8)
65 def Classes (self):
66 """Returns a list with all the class IDs."""
68 if self.__classes == None:
69 #already reversed in ClassNames
70 self.__classes = [CommonTables.Classes.GetValue (name, "ID", 1) for name in self.ClassNames()]
71 return self.__classes
73 def ClassNames (self):
74 """Returns a list will all the class names."""
76 if self.__classnames == None:
77 self.__classnames = CommonTables.Classes.GetRowName (CommonTables.Classes.FindValue (5, self.classid) ).split("_")
78 if self.IsDualSwap():
79 self.__classnames.reverse()
80 return self.__classnames
82 def ClassTitle (self):
83 """Returns the class title as a displayable string."""
85 if self.__classtitle != None:
86 return self.__classtitle
88 self.__classtitle = GemRB.GetPlayerStat (self.pc, IE_TITLE1)
90 if self.__classtitle == 0:
91 if self.multiclass and self.isdual == 0:
92 self.__classtitle = CommonTables.Classes.GetValue (self.classindex, 2)
93 self.__classtitle = GemRB.GetString (self.__classtitle)
94 elif self.isdual:
95 # first (previous) kit or class of the dual class
96 self.Classes()
97 if self.KitIndex():
98 self.__classtitle = CommonTables.KitList.GetValue (self.__kitindex, 2)
99 else:
100 self.__classtitle = CommonTables.Classes.GetValue (CommonTables.Classes.FindValue \
101 (5, self.__classes[1]), 2)
102 self.__classtitle = GemRB.GetString (self.__classtitle) + " / " + \
103 GemRB.GetString (CommonTables.Classes.GetValue (CommonTables.Classes.FindValue \
104 (5, self.__classes[0]), 2) )
105 else: # ordinary class or kit
106 if self.KitIndex():
107 self.__classtitle = CommonTables.KitList.GetValue (self.__kitindex, 2)
108 else:
109 self.__classtitle = CommonTables.Classes.GetValue (self.classindex, 2)
110 self.__classtitle = GemRB.GetString (self.__classtitle)
112 if self.__classtitle == "*":
113 self.__classtitle = 0
114 return self.__classtitle
116 def IsDualSwap (self):
117 """Returns true if IE_LEVEL is opposite of expectations."""
119 if self.__dualswap == None:
120 self.__dualswap = (self.isdual & CommonTables.Classes.GetValue \
121 (self.ClassNames()[0], "MC_WAS_ID", 1)) > 0
122 return self.__dualswap
124 def KitIndex (self):
125 """Returns the kit index in relation to kitlist.2da."""
127 if self.__kitindex != None:
128 return self.__kitindex
130 Kit = GemRB.GetPlayerStat (self.pc, IE_KIT)
131 self.__kitindex = 0
133 if Kit & 0xc000 == 0x4000:
134 self.__kitindex = Kit & 0xfff
136 # carefully looking for kit by the usability flag
137 # since the barbarian kit id clashes with the no-kit value
138 if self.__kitindex == 0 and Kit != 0x4000:
139 self.__kitindex = CommonTables.KitList.FindValue (6, Kit)
140 if self.__kitindex == -1:
141 self.__kitindex = 0
143 return self.__kitindex
145 def LevelDiffs (self):
146 """Returns the differences between the current and next classes."""
147 return [(next-current) for current,next in zip(self.Levels(),
148 self.NextLevels())]
150 def Levels (self):
151 """Returns the current level of each class."""
152 if self.__levels == None:
153 self.__levels = [level for slot in levelslots for level \
154 in [GemRB.GetPlayerStat (self.pc, slot)] if level>0]
155 if self.IsDualSwap():
156 self.__levels.reverse()
157 return self.__levels
159 def NextLevelExp (self):
160 """Returns the experience required to level each class."""
162 #filtering the old dual class out seems unnecessary
163 #just be sure to use NumClasses() or isdual to check
164 return [CommonTables.NextLevel.GetValue (name, str(level+1)) for name,level \
165 in zip(self.ClassNames(), self.Levels())]
167 def NextLevels (self):
168 """Returns the next level for each class."""
170 if self.__nextlevels != None:
171 return self.__nextlevels
173 xp = GemRB.GetPlayerStat (self.pc, IE_XP) / self.NumClasses()
175 self.__nextlevels = []
176 for name, level in zip(self.ClassNames(), self.Levels() ):
177 next = level
179 #we only want the current level for the old part of a dual-class
180 if len(self.__nextlevels) < self.__numclasses:
181 for current in range(level+1, CommonTables.NextLevel.GetColumnCount () ):
182 if CommonTables.NextLevel.GetValue (name, str(current)) <= xp:
183 next = current
184 else:
185 break
186 self.__nextlevels.append(next)
188 return self.__nextlevels
190 def NumClasses (self):
191 """Returns the number of *active* classes."""
192 if self.__numclasses == None:
193 if self.isdual:
194 self.__numclasses = 1
195 else:
196 self.__numclasses = len(self.ClassNames() )
197 return self.__numclasses
200 def RaceName (self):
201 """Returns the race string."""
202 pass
204 def Reset (self, pc):
205 """Resets all internal variables.
207 This should be called after any fundemental changes to the pc.
208 This includes: dualclassing, leveling."""
210 #accessible variables
211 self.pc = pc
212 self.classid = GemRB.GetPlayerStat (self.pc, IE_CLASS)
213 self.classindex = CommonTables.Classes.FindValue (5, self.classid)
214 self.isdual = GemRB.GetPlayerStat (self.pc, IE_MC_FLAGS) & MC_WAS_ANY_CLASS
215 self.multiclass = CommonTables.Classes.GetValue (self.classindex, 4)
217 #internal variables - these are only intialized on the first
218 #call to their respective function, and stored thereafter
219 self.__classes = None
220 self.__classnames = None
221 self.__classtitle = None
222 self.__dualswap = None
223 self.__kitindex = None
224 self.__levels = None
225 self.__nextlevels = None
226 self.__numclasses = None