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 ########################################################
20 from equiption
import *
24 from statistic
import *
27 from utilities
import *
28 from struct
import pack
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
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'
45 jTree
= libxml2
.parseFile('./data/job/'+j
)
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
)
57 statTree
= fTree
.xpathEval("//stat")
58 for statElem
in statTree
:
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:
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
89 elementTree
= fTree
.xpathEval("//modifiers/element")
90 statusTree
= fTree
.xpathEval("//modifiers/status")
92 for elementNode
in elementTree
:
93 self
.__elemMod
.append((elementNode
.prop("name"),elementNode
.prop("mod")))
96 for statusNode
in statusTree
:
97 self
.__statusMod
.append((statusNode
.prop("name"),statusNode
.prop("chance")))
103 # for the sake of more legible code
106 part2
= binary
[40:120]
107 part3
= binary
[120:152]
108 part4
= binary
[152:159]
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
)
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')
127 self
.__equiption
= Equiption(head
.strip('\0'), body
.strip('\0'), left
.strip('\0'), right
.strip('\0'))
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))
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())
177 """Get fighter's name."""
180 def setName(self
, n
):
181 """Change fighter's name."""
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
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()
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():
230 if self
.getStat("tom").getCurrent() != currentTime
:
233 # Generate per-turn status transactions
234 for s
in self
.__status
:
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
)
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
)
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":
278 def receiveExp(self
,exp
):
279 """Fighter receives experience for leveling up."""
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()
291 print self
.getStat("exptnl").getCurrent()
292 print self
.getStat("exptnl").getMax()
295 while exptnl_s
.getCurrent() <= 0:
297 # Increase level number
298 level_s
= self
.getStat("level")
299 level_s
.setCurrent(level_s
.getCurrent() + 1)
305 hp
= self
.getStat("hp")
306 print hp
.getChance() * 100
307 if x
<= hp
.getChance() * 100:
309 hp
.setMax(hp
.getMax() + hp
.getPlus())
313 str = self
.getStat("str")
314 if x
<= str.getChance() * 100:
315 str.setMax(str.getMax() + str.getPlus())
316 str.setCurrent(str.getMax())
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?
328 dex
= self
.getStat("dex")
329 if x
<= dex
.getChance() * 100:
330 dex
.setMax(dex
.getMax() + dex
.getPlus())
331 dex
.setCurrent(dex
.getMax())
335 agl
= self
.getStat("agl")
336 if x
<= agl
.getChance() * 100:
337 agl
.setMax(agl
.getMax() + agl
.getPlus())
338 agl
.setCurrent(agl
.getMax())
342 wis
= self
.getStat("wis")
343 if x
<= wis
.getChance() * 100:
344 wis
.setMax(wis
.getMax() + wis
.getPlus())
345 wis
.setCurrent(wis
.getMax())
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]:
367 def getStatusModifier(self
,stat
):
368 for statusMod
in self
.__statusMod
:
369 if stat
== statusMod
[0]:
375 """Get status(es) of fighter."""
378 def setStatus(self
,s
):
379 """Set status(es) of fighter."""
382 def addStatus(self
,s
):
383 """Add a status to status list for fighter."""
385 for i
in self
.__status
:
392 self
.__status
.append(s
)
395 print 'ERROR: Status already in list!'
397 def removeStatus(self
,s
):
398 """Remove status s from status list for fighter."""
400 for i
in self
.__status
:
406 self
.__status
.remove(i
)
409 print 'ERROR: Status was not in list!'
411 def getStat(self
,statName
):
412 for stat
in self
.__stats
:
413 if stat
.getName() == statName
:
415 print 'ERROR: No such Fighter stat.'
417 def getAllStats(self
):
420 def setAllStats(self
,stats
):