Some more debuging mostly. Got it to where you can play several battles in a row...
[asgard.git] / fighter.py
blob7df10b62124455bfe4fc877252b15c525c7eb417
1 ########################################################
2 #Copyright (c) 2006 Russ Adams, Sean Eubanks, Asgard Contributors
3 #This file is part of Asgard.
5 #Asgard is free software; you can redistribute it and/or modify
6 #it under the terms of the GNU General Public License as published by
7 #the Free Software Foundation; either version 2 of the License, or
8 #(at your option) any later version.
10 #Asgard 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 Asgard; if not, write to the Free Software
17 #Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 ########################################################
19 from random import *
20 from equiption import *
21 from event import *
22 from status import *
23 from stat import *
24 from statistic import *
25 import libxml2
26 import struct
27 from utilities import *
28 from struct import pack
29 class Fighter:
31 def __init__(self,fTree=None,binary=None):
32 """ Construct a Fighter object from a job type XML tree and either a fighter type XML tree or packed binary data. """
34 # If there was a fighter tree specified
35 if fTree != None:
36 # Fighter members
37 self.__name = fTree.xpathEval("//name")[0].content
38 self.__playable = (fTree.xpathEval("//playable")[0].content == "True")
39 self.__jobType = fTree.xpathEval("//job")[0].content
41 # Find correct job XML file
42 j = fTree.xpathEval("//job")[0].content + '.xml'
44 # Create Job XML Tree
45 jTree = libxml2.parseFile('./data/job/'+j)
48 # Equiption
49 head = fTree.xpathEval("//equiption/head")[0].content
50 body = fTree.xpathEval("//equiption/body")[0].content
51 left = fTree.xpathEval("//equiption/left")[0].content
52 right = fTree.xpathEval("//equiption/right")[0].content
53 self.__equiption = Equiption(head,body,left,right)
55 #Statistics
56 self.__stats = []
57 statTree = fTree.xpathEval("//stat")
58 for statElem in statTree:
60 current = 0
61 afterBattle = False
63 # The following might should be moved to the Statistics Constructor in the future
64 sname = statElem.prop("name")
66 afterBattle = (statElem.prop("afterbattle") == "True")
68 if statElem.prop("current") != None:
69 current = int(statElem.prop("current"))
71 if statElem.prop("max") != None:
72 max = int(statElem.prop("max"))
74 if afterBattle == False and statElem.prop("current") == None:
75 current = max
77 (plus,chance,growthRate) = jobStatQuery(jTree, sname)
79 stat = Statistic(sname,current,max,afterBattle,plus,chance,growthRate)
80 self.__stats.append(stat)
82 spd = self.getStat("spd").getCurrent()
83 tom = round((1/float(spd)*100))
84 self.__stats.append(Statistic("tom",tom,tom,False,0,0,0))
86 # Initialize the status list
87 self.__status = []
89 elementTree = fTree.xpathEval("//modifiers/element")
90 statusTree = fTree.xpathEval("//modifiers/status")
91 self.__elemMod = []
92 for elementNode in elementTree:
93 self.__elemMod.append((elementNode.prop("name"),elementNode.prop("mod")))
95 self.__statusMod = []
96 for statusNode in statusTree:
97 self.__statusMod.append((statusNode.prop("name"),statusNode.prop("chance")))
99 jTree.freeDoc()
100 fTree.freeDoc()
101 elif binary != None:
103 # for the sake of more legible code
104 # break it up
105 part1 = binary[:40]
106 part2 = binary[40:120]
107 part3 = binary[120:152]
108 part4 = binary[152:159]
110 # unpack data
111 (name,job) = struct.unpack("20s20s",part1)
112 (head,body,left,right) = struct.unpack("20s20s20s20s",part2)
113 (level,exp,exptnl_current,exptnl_max,hp_current,hp_max,mp_current,mp_max) = struct.unpack("B7I",part3)
114 (str,dex,agl,spd,wil,wis) = struct.unpack("6B",part4)
116 # Meta Data
117 self.__name = name.strip('\0')
118 self.__jobType = job.strip('\0')
119 self.__playable = True
121 print len(self.__jobType)
122 print'./data/job/'+self.__jobType+'.xml'
123 # Create Job XML Tree
124 jTree = libxml2.parseFile('./data/job/'+self.__jobType+'.xml')
126 # Equiption
127 self.__equiption = Equiption(head.strip('\0'), body.strip('\0'), left.strip('\0'), right.strip('\0'))
129 #Stats
130 self.__stats = []
131 (plus,chance,growthRate) = self.jobStatQuery(jTree, "level")
132 self.__stats.append(Statistic("level",level,level,False,plus,chance,growthRate))
134 (plus,chance,growthRate) = self.jobStatQuery(jTree, "exp")
135 self.__stats.append(Statistic("exp",level,level,False,plus,chance,growthRate))
137 (plus,chance,growthRate) = self.jobStatQuery(jTree, "exptnl")
138 self.__stats.append(Statistic("exptnl",exptnl_current,exptnl_max,True,plus,chance,growthRate))
140 (plus,chance,growthRate) = self.jobStatQuery(jTree, "hp")
141 self.__stats.append(Statistic("hp",hp_current,hp_max,True,plus,chance,growthRate))
143 (plus,chance,growthRate) = self.jobStatQuery(jTree, "mp")
144 self.__stats.append(Statistic("mp",mp_current,mp_max,True,plus,chance,growthRate))
146 (plus,chance,growthRate) = self.jobStatQuery(jTree, "str")
147 self.__stats.append(Statistic("str",str,str,False,plus,chance,growthRate))
149 (plus,chance,growthRate) = self.jobStatQuery(jTree, "dex")
150 self.__stats.append(Statistic("dex",dex,dex,False,plus,chance,growthRate))
152 (plus,chance,growthRate) = self.jobStatQuery(jTree, "agl")
153 self.__stats.append(Statistic("agl",agl,agl,False,plus,chance,growthRate))
155 (plus,chance,growthRate) = self.jobStatQuery(jTree, "spd")
156 self.__stats.append(Statistic("spd",spd,spd,False,plus,chance,growthRate))
158 (plus,chance,growthRate) = self.jobStatQuery(jTree, "wis")
159 self.__stats.append(Statistic("wis",wis,wis,False,plus,chance,growthRate))
161 (plus,chance,growthRate) = self.jobStatQuery(jTree, "wil")
162 self.__stats.append(Statistic("wil",wis,wis,False,plus,chance,growthRate))
164 spd = self.getStat("spd").getCurrent()
165 tom = round((1/float(spd)*100))
166 self.__stats.append(Statistic("tom",tom,tom,False,0,0,0))
167 self.__status = []
168 jTree.freeDoc()
170 def toBinaryString(self):
171 """Convert Fighter data to binary string."""
173 binStr = pack("20s20s20s20s20s20sB7I6B",self.__name,self.__jobType,self.__equiption.getHead(),self.__equiption.getArmor(),self.__equiption.getRight(),self.__equiption.getLeft(),self.getStat("level").getMax(),self.getStat("exp").getCurrent(),self.getStat("exptnl").getCurrent(),self.getStat("exptnl").getMax(),self.getStat("hp").getCurrent(),self.getStat("hp").getMax(),self.getStat("mp").getCurrent,self.getStat("mp").getMax(),self.getStat("str").getMax(),self.getStat("dex").getMax(),self.getStat("agl").getMax(),self.getStat("spd").getMax(),self.getStat("wis").getMax(),self.getStat("wil").getMax())
174 return binStr
176 def getName(self):
177 """Get fighter's name."""
178 return self.__name
180 def setName(self, n):
181 """Change fighter's name."""
182 self.__name = n
184 def getJobType(self):
185 """Get Fighter's job type"""
186 return self.__jobType
188 def setJobType(self,jobType):
189 """ Set Fighter's job type"""
190 self.__jobType = jobType
192 def getEquiption(self):
193 """Get equiption for fighter."""
194 return self.__equiption
196 def setEquiption(self, eq):
197 """Set equiption for fighter."""
198 self.__equiption = eq
200 def getPlayable(self):
201 """Is fighter playable?"""
202 return self.__playable
204 def setPlayable(self, plyble):
205 """Set fighter's playability."""
206 self.__playable = plyble
208 def getAttack(self):
209 """Compute value of attack."""
210 return self.getStat("str").getCurrent() + self.__equiption.computeAtkMod()
212 def getDefense(self):
213 """Compute value of defense."""
214 return self.__equiption.computeDefMod()
216 def getEvade(self):
217 """Compute value of evade."""
218 return self.getStat("agl").getCurrent() + self.__equiption.computeEvaMod()
221 def makeEvent(self, eparty, fparty, currentTime, cont):
222 """ Check if ready to make move.
224 If so, select random fighter from enemy party and return.
227 if not self.isAlive():
228 return None
230 if self.getStat("tom").getCurrent() != currentTime:
231 return None
233 # Generate per-turn status transactions
234 for s in self.__status:
235 s.genPerTurn()
237 d = []
239 # Playable fighters have battle menu
240 if self.getPlayable():
241 # Show battle menu and choose event from battle menu
242 command = cont.getBattleCommand(eparty,fparty,self)
243 d.append(command[0])
244 t = command[1]
246 # Nonplayable fighters
247 elif currentTime >= self.getStat("tom").getCurrent():
248 x = randint(0,eparty.sizeOfParty()-1)
249 while not eparty.getFighter(x).isAlive():
250 x = randint(0,eparty.sizeOfParty()-1)
252 d.append(eparty.getFighter(x))
254 x = randint(0,len(self.getEventTypes())-1)
255 t = cont.getBattle().getEventType(self.getEventTypes()[x])
257 self.getStat("tom").setCurrent(self.getStat("tom").getMax() + round((1/float(self.getStat("spd").getMax()))*100))
258 self.getStat("tom").setMax(self.getStat("tom").getCurrent())
259 return Event(self,d,[],t)
261 def isAlive(self):
262 """If hp is greater than 0... return true"""
263 return (self.getStat("hp").getCurrent() > 0)
265 def getEventTypes(self):
266 """Return list of events available to fighter."""
267 if self.__jobType == "blackmage":
268 return ["attack","fire1","ice1","fog","poison","quit"]
269 elif self.__jobType == "swordsman":
270 return ["attack","cure1","heal","quit"]
271 elif self.__name == "Roc":
272 return ["attack","ice1"]
273 elif self.__name == "Imp":
274 return ["attack"]
275 else:
276 return ["attack"]
278 def receiveExp(self,exp):
279 """Fighter receives experience for leveling up."""
280 # Add on exp
281 exp_s = self.getStat("exp")
282 exp_s.setCurrent(exp_s.getCurrent() + exp)
283 exp_s.setMax(exp_s.getCurrent())
285 # Tax off exp from expTillNextLevel
286 exptnl_s = self.getStat("exptnl")
287 exptnl_s.setCurrent(exptnl_s.getCurrent() - exp)
289 print self.getStat("level").getCurrent()
290 print exp
291 print self.getStat("exptnl").getCurrent()
292 print self.getStat("exptnl").getMax()
294 # Level up?
295 while exptnl_s.getCurrent() <= 0:
296 print "hello!"
297 # Increase level number
298 level_s = self.getStat("level")
299 level_s.setCurrent(level_s.getCurrent() + 1)
301 ## Increase stats...
303 # Increase hp?
304 x = randint(1,100)
305 hp = self.getStat("hp")
306 print hp.getChance() * 100
307 if x <= hp.getChance() * 100:
308 print "test1"
309 hp.setMax(hp.getMax() + hp.getPlus())
311 # Increase strength?
312 x = randint(1,100)
313 str = self.getStat("str")
314 if x <= str.getChance() * 100:
315 str.setMax(str.getMax() + str.getPlus())
316 str.setCurrent(str.getMax())
319 # Increase speed?
320 x = randint(1,100)
321 spd = self.getStat("spd")
322 if x <= spd.getChance() * 100:
323 spd.setMax(spd.getMax() + spd.getPlus())
324 spd.setCurrent(spd.getMax())
326 # Increase dexterity?
327 x = randint(1,100)
328 dex = self.getStat("dex")
329 if x <= dex.getChance() * 100:
330 dex.setMax(dex.getMax() + dex.getPlus())
331 dex.setCurrent(dex.getMax())
333 # Increase agility?
334 x = randint(1,100)
335 agl = self.getStat("agl")
336 if x <= agl.getChance() * 100:
337 agl.setMax(agl.getMax() + agl.getPlus())
338 agl.setCurrent(agl.getMax())
340 # Increase wisdom?
341 x = randint(1,100)
342 wis = self.getStat("wis")
343 if x <= wis.getChance() * 100:
344 wis.setMax(wis.getMax() + wis.getPlus())
345 wis.setCurrent(wis.getMax())
347 # Increase will?
348 x = randint(1,100)
349 wil = self.getStat("wil")
350 if x <= wil.getChance() * 100:
351 wil.setMax(wil.getMax() + wil.getPlus())
352 wil.setCurrent(wil.getMax())
354 # Set new exp till next level maximum
355 exptnl_s.setMax(int(exptnl_s.getMax() * (1 + exptnl_s.getGrowthRate())))
357 # Carry over any experience that didn't go towards getting the last level
358 exptnl_s.setCurrent(int(exptnl_s.getMax() + exptnl_s.getCurrent()))
360 def getElemModifier(self,elem):
361 for elemMod in self.__elemMod:
362 if elem == elemMod[0]:
363 return elemMod[1]
365 return 0.0
367 def getStatusModifier(self,stat):
368 for statusMod in self.__statusMod:
369 if stat == statusMod[0]:
370 return statusMod[1]
372 return 1.0
374 def getStatus(self):
375 """Get status(es) of fighter."""
376 return self.__status
378 def setStatus(self,s):
379 """Set status(es) of fighter."""
380 self.__status = s
382 def addStatus(self,s):
383 """Add a status to status list for fighter."""
384 found = False
385 for i in self.__status:
386 if i == s:
387 found = True
388 break
390 print s
391 if not found:
392 self.__status.append(s)
393 s.genEntrance()
394 else:
395 print 'ERROR: Status already in list!'
397 def removeStatus(self,s):
398 """Remove status s from status list for fighter."""
399 found = False
400 for i in self.__status:
401 if i.getName() == s:
402 found = True
403 break
405 if found == True:
406 self.__status.remove(i)
407 i.genExit()
408 else:
409 print 'ERROR: Status was not in list!'
411 def getStat(self,statName):
412 for stat in self.__stats:
413 if stat.getName() == statName:
414 return stat
415 print 'ERROR: No such Fighter stat.'
417 def getAllStats(self):
418 return self.__stats
420 def setAllStats(self,stats):
421 self.__stats = stats