Mercurial > traipse
comparison orpg/gametree/nodehandlers/dnd3e.py @ 0:4385a7d0efd1 grumpy-goblin
Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author | sirebral |
---|---|
date | Tue, 14 Jul 2009 16:41:58 -0500 |
parents | |
children | 265b987cce4f |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4385a7d0efd1 |
---|---|
1 # Copyright (C) 2000-2001 The OpenRPG Project | |
2 # | |
3 # openrpg-dev@lists.sourceforge.net | |
4 # | |
5 # This program 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. | |
9 # | |
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. | |
14 # | |
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., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 # -- | |
19 # | |
20 # File: dnd3e.py | |
21 # Author: Chris Davis & Digitalxero | |
22 # Maintainer: leadb | |
23 # Version: | |
24 # $Id: dnd3e.py,v 1.33 2006/11/04 21:24:21 digitalxero Exp $ | |
25 # | |
26 # Description: The file contains code for the dnd3e nodehanlers | |
27 # | |
28 # qpatch by lead.b. All modified lines denoted by # 1.500x[or] as below | |
29 # 1.5001r fix for unable to update misc modifier for saves | |
30 # 1.5002r fix for dnd_globals not scoping 1 character's data from another -or | |
31 # causing abends or other problems due to lack of intialization from | |
32 # char abilities. getCharacterProp function added. | |
33 # This includes fix for "total on saves", making "rclick" on skill | |
34 # work to send roll to window,"total on skill rolls", | |
35 # 1.5004r getting ac mod for | |
36 # those skill which have armour class adjustments was broken. | |
37 # 1.5005r perhaps no lines marked. Under dnd3eattacks, the misc. value for | |
38 # both Melee and Ranged do not get re-displayed if the panel is closed | |
39 # and re-opened, tho the adjustment still seems to be in total... perhap | |
40 # total just isn't getting recalculated? | |
41 # 1.5006r on rclick on a weapon, on first attack roll is generated, additional | |
42 # crash,terminating the sequence. | |
43 # 1.5008r extended bonuses for "extra" attacks don't include all items. | |
44 # 1.5009r while 1.5008 is "resolved", not sure it is correct for special monk | |
45 # attacks. I'm pretty sure I fixed this. | |
46 # 1.5014r powerpoints are broken. | |
47 # 1.5017r if you bring up the entire character in edit mode (dlclick on | |
48 # top node of character), and click | |
49 # "Money and Inventory" tab, then change the amount of "plat" a | |
50 # character has, the name on the tree will be updated to match | |
51 # the "plat" entry. | |
52 # 1.5019r if str bonus was 0, forgot + for aStrengthMod. | |
53 # ---v 1.6 cut. above corrected by 1.6. | |
54 # -- items marked 1.5xxx were found prior 1.6 but not added (enhancements) | |
55 # or corrected (bugs, default if not stated) at that cut point | |
56 # 1.5003r this is currently just a "this is busted" flag, this is an rclick on | |
57 # on the saves node (above the fort/wil/ref saves) itself. It throws an | |
58 # error message into the python window, then nothing... Not even sure what | |
59 # it is -supposed- to do. set to do nothing, which I think is fine. | |
60 # 1.5011r enhancement. Damage for thrown weapon should get str adder. | |
61 # Don't think this is accounted for. Remember, JUST damage, not to-hit. | |
62 # included into 1.6002, marking resolved to simplify list. | |
63 # 1.5012r enhancement. str penalty to dam for bow/slings should be applied. | |
64 # but it's not. Remember, this is just for damage, not to-hit. | |
65 # 1.5015r if you bring up the entire character in edit mode (dlclick on | |
66 # top node of character), and click | |
67 # "Spells and Powers" tab, then "Psionic Powers", push the "Refresh | |
68 # Powers" button, the powers are refreshed but if you select the | |
69 # "PowerPoints" tab, the update is not reflected there. Must close | |
70 # and reopen edit session for refresh. (Already corrected misspelling of | |
71 # "Pionic" -> "Psionic") | |
72 # 1.6000r eliminate misc debug items, include things like getCharacterProp which | |
73 # never got used. Documenting for completeness. Minor changes for clarity | |
74 # 1.6001r bug, melee weapons, such as dagger, which have a range are currently | |
75 # being treated simply as ranged weapons... this mean dex bonuses | |
76 # are being applied for to-hit Vs strength. Melee thrown are treated | |
77 # different than ranged. | |
78 # 1.6003r bug, if double weapon handle damage specified as 1d8/1d6 as 1d8 | |
79 # for single weapon usage. The correct usage for double weapon will | |
80 # for short term at least remove requirement to have to update | |
81 # memorized list. - med priority | |
82 # 1.6008r C:\Program Files\openrpg1\orpg\templates\nodes\dnd3e.xml minor | |
83 # typos corrected, added comment on psionics. Remember to replace! | |
84 # 1.6009r tohtml fails, thus send to chat fails and pretty print fails. | |
85 # 1.6010r tohtml for power points needs some clean up. | |
86 # 1.6011r if multiple weapons are chosen for deletion from character inventory, | |
87 # at least one wrong weapons will be deleted. | |
88 # 1.6012r flurry attack negative only applied to med monk, applies to all. | |
89 # 1.6013r penalties on stats on tohtml showed +-3, instead of just -3. | |
90 # 1.6014r rclick on "Skills" node above actual skills throws an error msg to | |
91 # python window. | |
92 # 1.6015r rclick on "Attacks" or "Abilities Score" node throws an error msg to | |
93 # python window. | |
94 # 1.6016r enhancement add comment to rclick footnotes to get footnote details. | |
95 # 1.6018r resolve saves not updating on panel if open when ability scores change | |
96 # change | |
97 # 1.6021r didn't roll extra monk attacks if base to it bonus was 0. | |
98 # 1.6022r monks always got d20 damage, reversed order of checks to fix. | |
99 # v1.8 cut. | |
100 # -- items marked 1.6xxx were found prior 1.8 but not added (enhancements) | |
101 # or corrected (bugs, default if not stated) at that cut point | |
102 # 1.5007o enhancement. str bows not accounted for correctly. | |
103 # thoughts: use new element tag to indicate strBow(3). | |
104 # 1.5010r proposed enhancement. Adding character name to frames around stuff. | |
105 # - marking resolved... determined to not do. | |
106 # 1.5013o enhancement. this is for all "off-hand" attacks stuff. Eg: str bonus | |
107 # only 1/2 for "off-hand" for both to-hit and damage (unless penalty! ;-) | |
108 # Probably other things, as I see nothing in here to account for them. | |
109 # 1.5016o enhancement. swim check does not reflect weight check. | |
110 # 1.5018o enhancement. actual psionic abilities list. | |
111 # 1.6002o enhancement. modify code to take advanage of new footnote field for | |
112 # indicating which weapons are Thrown, as opposed to improvised thrown | |
113 # weapons; which are treated differently. Allow for throwing of melee | |
114 # weapons (with 1.6001 all melee are unthrowable) recast of 1.5011, | |
115 # which I'm marking resolved. | |
116 # 1.6004o feature request from 541659 Ability to remove skills, at least those | |
117 # that can't be used untrained. This would also require ability to re-add | |
118 # skills later. Short term solution may be to ability to clearly mark | |
119 # skill which can't be used yet. - low priority. | |
120 # 1.6005o feature request from 541659 Custom feats, without the need to edit | |
121 # data/dnd3e/dnd3efeats.xml Note, while standard feats may be affecting | |
122 # how tool will generate rolls, etc; it is unlikely that custom feats will | |
123 # will be able to do this; but should be able to be include from a | |
124 # complete "character sheet" perspective. - low priority (since | |
125 # dnd3efeats can be edited to add feats) | |
126 # 1.6006o feature request from 541659 Do sorcerer and bard spells right; | |
127 # for short term at least remove requirement to have to update | |
128 # memorized list. - med priority | |
129 # 1.6007o feature request from 541659 Make tabs optional to be able to remove | |
130 # tabs which are unused by a particular character. Would need ability | |
131 # to add them back in, since character might later add a class which | |
132 # would need them. - very low priority | |
133 # 1.6017o enhancement when editing footnotes for weapons, | |
134 # provide full table of footnotes in companion window to help. | |
135 # 1.6019o enhancement Forum request to add "flatfooted" to ac matrix | |
136 # 1.6020o enh add column to skills to allow tracking of skill points allocated. | |
137 # 1.9000r clean up of excess comments from 1.6 and earlier. | |
138 # 1.9001r if str or dex changes, Melee/Ranged combat ability does not update | |
139 # until refreshed by a change. | |
140 # 1.9002r depending on what subwindows were open, changing stat scores could | |
141 # crash out entire orpg environment. | |
142 # | |
143 # r- resolved | |
144 # o- open | |
145 # | |
146 import orpg.tools.orpg_settings | |
147 import orpg.minidom | |
148 from core import * | |
149 from containers import * | |
150 from string import * #a 1.6003 | |
151 from inspect import * #a 1.9001 | |
152 dnd3e_EXPORT = wx.NewId() | |
153 ############Global Stuff############## | |
154 | |
155 HP_CUR = wx.NewId() | |
156 HP_MAX = wx.NewId() | |
157 PP_CUR = wx.NewId() | |
158 PP_MAX = wx.NewId() | |
159 PP_FRE = wx.NewId() | |
160 PP_MFRE = wx.NewId() | |
161 HOWTO_MAX = wx.NewId() | |
162 | |
163 def getRoot (node): # a 1.5002 this whole function is new. | |
164 root = None | |
165 target = node | |
166 while target != None: | |
167 root = target | |
168 target = target.hparent | |
169 return root | |
170 #o 1.5002 (this whole comment block) | |
171 # if a method runs getRoot for its instance and assigns the | |
172 # value returned to self.root, you can get to instances X via Y | |
173 # instance handle via invocation | |
174 # --------------- --- ----------- | |
175 # classes via self.root.classes | |
176 # abilities via self.root.abilities | |
177 # pp via self.root.pp | |
178 # general via self.root.general | |
179 # saves via self.root.saves | |
180 # attacks via self.root.attacks | |
181 # ac via self.root.ac | |
182 # feats via self.root.feats | |
183 # spells via self.root.spells | |
184 # divine via self.root.divine | |
185 # powers via self.root.powers | |
186 # inventory via self.root.inventory | |
187 # hp via self.root.hp | |
188 # skills via self.root.skills | |
189 #... if other instances are needed and the instance exists uniquely, | |
190 # add to the instance you need access to in the __init__ section the following: | |
191 # self.hparent = parent # or handler if a wx instance, also add up chain | |
192 # self.root = getRoot(self) | |
193 # self.root.{instance handle} = self | |
194 # # replace {instance handle} with your designation | |
195 # then, where you need access to the instance, simply add this to the instance | |
196 # that needs to reference | |
197 # self.hparent = getRoot(self) # in the init section, if not already there | |
198 # self.root = getRoot(self) # also in the init | |
199 # then to refer to the instance where you need it: | |
200 # self.root.{instance handle}.{whatever you need} | |
201 # # replace {instance handle} with your designation | |
202 # # replace {whatever you need} with the attribute/method u want. | |
203 | |
204 #d 1.6000 not used. | |
205 #def getCharacterProp(forgetIt): | |
206 # return None | |
207 | |
208 #a 1.6 convinience function added safeGetAttr | |
209 def safeGetAttr(node,lable,defRetV=None): | |
210 cna=node.attributes | |
211 for i2 in range(len(cna)): | |
212 if cna.item(i2).name == lable: | |
213 return cna.item(i2).value | |
214 #retV=node.getAttribute(lable) # getAttribute does not distingish between | |
215 # the attribute not being present vs it having a value of "" | |
216 # This is bad for this routine, thus not used. | |
217 return defRetV | |
218 #a 1.6... safeGetAttr end. | |
219 | |
220 ########End of My global Stuff######## | |
221 ########Start of Main Node Handlers####### | |
222 class dnd3echar_handler(container_handler): | |
223 """ Node handler for a dnd3e charactor | |
224 <nodehandler name='?' module='dnd3e' class='dnd3echar_handler2' /> | |
225 """ | |
226 def __init__(self,xml_dom,tree_node): | |
227 node_handler.__init__(self,xml_dom,tree_node) | |
228 self.Version = "v1.901" #a 1.6000 general documentation, usage. | |
229 | |
230 print "dnd3echar_handler - version:",self.Version #m 1.6000 | |
231 | |
232 self.hparent = None #a 1.5002 allow ability to run up tree, this is the | |
233 #a 1.5002 top of the handler tree, this is used to flag where to stop | |
234 #a 1.5002 on the way up. Changing this will break getRoot(self) | |
235 | |
236 self.frame = open_rpg.get_component('frame') | |
237 self.child_handlers = {} | |
238 self.new_child_handler('howtouse','HowTo use this tool',dnd3ehowto,'note') | |
239 self.new_child_handler('general','GeneralInformation',dnd3egeneral,'gear') | |
240 self.new_child_handler('inventory','MoneyAndInventory',dnd3einventory,'money') | |
241 self.new_child_handler('character','ClassesAndStats',dnd3eclassnstats,'knight') | |
242 self.new_child_handler('snf','SkillsAndFeats',dnd3eskillsnfeats,'book') | |
243 self.new_child_handler('combat','Combat',dnd3ecombat,'spears') | |
244 self.new_child_handler('snp','SpellsAndPowers',dnd3esnp,'flask') | |
245 #wxMenuItem(self.tree.std_menu, dnd3e_EXPORT, "Export...", "Export") | |
246 #print "dnd3echar_handler init - "+\ | |
247 # "self.child_handlers:",self.child_handlers # a (debug) 1.5002 | |
248 self.myeditor = None | |
249 | |
250 | |
251 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
252 node_list = self.master_dom.getElementsByTagName(tag) | |
253 tree = self.tree | |
254 i = self.tree.icons[icon] | |
255 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
256 handler = handler_class(node_list[0],new_tree_node,self) | |
257 tree.SetPyData(new_tree_node,handler) | |
258 self.child_handlers[tag] = handler | |
259 | |
260 def get_design_panel(self,parent): | |
261 return tabbed_panel(parent,self,1) | |
262 | |
263 | |
264 def get_use_panel(self,parent): | |
265 return tabbed_panel(parent,self,2) | |
266 | |
267 def tohtml(self): | |
268 html_str = "<table><tr><td colspan=2 >" | |
269 #d block for 1.6009 start | |
270 #html_str += self.child_handlers['general'].tohtml()+"</td></tr>" | |
271 #html_str += "<tr><td width='50%' valign=top > | |
272 # "+self.child_handlers['abilities'].tohtml() | |
273 #html_str += "<P>" + self.child_handlers['saves'].tohtml() | |
274 #html_str += "<P>" + self.child_handlers['attacks'].tohtml() | |
275 #html_str += "<P>" + self.child_handlers['ac'].tohtml() | |
276 #html_str += "<P>" + self.child_handlers['feats'].tohtml() | |
277 #html_str += "<P>" + self.child_handlers['spells'].tohtml() | |
278 #html_str += "<P>" + self.child_handlers['divine'].tohtml() | |
279 #html_str += "<P>" + self.child_handlers['powers'].tohtml() | |
280 #html_str += "<P>" + self.child_handlers['inventory'].tohtml() +"</td>" | |
281 #html_str += "<td width='50%' valign=top > | |
282 # "+self.child_handlers['classes'].tohtml() | |
283 #html_str += "<P>" + self.child_handlers['hp'].tohtml() | |
284 #html_str += "<P>" + self.child_handlers['pp'].tohtml() | |
285 #html_str += "<P>" + self.child_handlers['skills'].tohtml() +"</td>" | |
286 #d block for 1.6009 end | |
287 #a block for 1.6009 start | |
288 html_str += self.general.tohtml()+"</td></tr>" | |
289 html_str += "<tr><td width='50%' valign=top >"+self.abilities.tohtml() | |
290 html_str += "<P>" + self.saves.tohtml() | |
291 html_str += "<P>" + self.attacks.tohtml() | |
292 html_str += "<P>" + self.ac.tohtml() | |
293 html_str += "<P>" + self.feats.tohtml() | |
294 html_str += "<P>" + self.spells.tohtml() | |
295 html_str += "<P>" + self.divine.tohtml() | |
296 html_str += "<P>" + self.powers.tohtml() | |
297 html_str += "<P>" + self.inventory.tohtml() +"</td>" | |
298 html_str += "<td width='50%' valign=top >"+self.classes.tohtml() | |
299 html_str += "<P>" + self.hp.tohtml() | |
300 html_str += "<P>" + self.pp.tohtml() | |
301 html_str += "<P>" + self.skills.tohtml() +"</td>" | |
302 #a block for 1.6009 end | |
303 | |
304 html_str += "</tr></table>" | |
305 return html_str | |
306 | |
307 def about(self): | |
308 html_str = "<img src='" + orpg.dirpath.dir_struct["icon"] | |
309 html_str += "dnd3e_logo.gif' ><br><b>dnd3e Character Tool " | |
310 html_str += self.Version+"</b>" #m 1.6000 was hard coded. | |
311 html_str += "<br>by Dj Gilcrease<br>digitalxero@gmail.com" | |
312 return html_str | |
313 | |
314 ########Core Handlers are done now############ | |
315 ########Onto the Sub Nodes######## | |
316 ##Primary Sub Node## | |
317 | |
318 class outline_panel(wx.Panel): | |
319 def __init__(self, parent, handler, wnd, txt,): | |
320 self.parent = parent #a 1.9001 | |
321 wx.Panel.__init__(self, parent, -1) | |
322 self.panel = wnd(self,handler) | |
323 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self,-1,txt), wx.VERTICAL) | |
324 | |
325 self.sizer.Add(self.panel, 1, wx.EXPAND) | |
326 self.SetSizer(self.sizer) | |
327 self.SetAutoLayout(True) | |
328 self.Fit() | |
329 | |
330 class dnd3e_char_child(node_handler): | |
331 """ Node Handler for skill. This handler will be | |
332 created by dnd3echar_handler. | |
333 """ | |
334 def __init__(self,xml_dom,tree_node,parent): | |
335 node_handler.__init__(self,xml_dom,tree_node) | |
336 self.char_hander = parent | |
337 self.drag = False | |
338 self.frame = open_rpg.get_component('frame') | |
339 self.myeditor = None | |
340 | |
341 | |
342 def on_drop(self,evt): | |
343 pass | |
344 | |
345 def on_rclick(self,evt): | |
346 pass | |
347 | |
348 def on_ldclick(self,evt): | |
349 return | |
350 | |
351 def on_html(self,evt): | |
352 html_str = self.tohtml() | |
353 wnd = http_html_window(self.frame.note,-1) | |
354 wnd.title = self.master_dom.getAttribute('name') | |
355 self.frame.add_panel(wnd) | |
356 wnd.SetPage(html_str) | |
357 | |
358 def get_design_panel(self,parent): | |
359 pass | |
360 | |
361 def get_use_panel(self,parent): | |
362 return self.get_design_panel(parent) | |
363 | |
364 def delete(self): | |
365 pass | |
366 | |
367 ###Child Nodes Organized the way they are in the XML for easier viewing#### #m 1.5002 corrected typo. | |
368 class dnd3ehowto(dnd3e_char_child): #m 1.5002 corrected string below to reflect "how to" | |
369 """ Node Handler for how to instructions. This handler will be | |
370 created by dnd3echar_handler. | |
371 """ | |
372 def __init__(self,xml_dom,tree_node,parent): | |
373 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
374 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
375 | |
376 def get_design_panel(self,parent): | |
377 wnd = howto_panel(parent, self) | |
378 wnd.title = "How To" | |
379 return wnd | |
380 | |
381 class howto_panel(wx.Panel): | |
382 def __init__(self, parent, handler): | |
383 wx.Panel.__init__(self, parent, -1) | |
384 | |
385 pname = handler.master_dom.setAttribute("name", 'How To') | |
386 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, 'How To'), wx.VERTICAL) | |
387 self.master_dom = handler.master_dom | |
388 n_list = self.master_dom._get_childNodes() | |
389 for n in n_list: | |
390 t_node = safe_get_text_node(n) | |
391 self.sizer.Add(wx.StaticText(self, -1, t_node._get_nodeValue()), 1, wx.EXPAND) | |
392 self.SetSizer(self.sizer) | |
393 self.SetAutoLayout(True) | |
394 self.Fit() | |
395 | |
396 class dnd3egeneral(dnd3e_char_child): | |
397 """ Node Handler for general information. This handler will be | |
398 created by dnd3echar_handler. | |
399 """ | |
400 def __init__(self,xml_dom,tree_node,parent): | |
401 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
402 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
403 self.root = getRoot(self) #a 1.5002 | |
404 self.root.general = self #a 1.5002 | |
405 self.charName = self.get_char_name() # a 1.5002 make getting name easier. | |
406 | |
407 def get_design_panel(self,parent): | |
408 wnd = outline_panel(parent,self,gen_grid,"General Information") | |
409 wnd.title = "General Info" | |
410 return wnd | |
411 | |
412 def tohtml(self): | |
413 n_list = self.master_dom._get_childNodes() | |
414 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>" | |
415 for n in n_list: | |
416 t_node = safe_get_text_node(n) | |
417 html_str += "<B>"+n._get_tagName().capitalize() +":</B> " | |
418 html_str += t_node._get_nodeValue() + ", " | |
419 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
420 return html_str | |
421 | |
422 def on_name_change(self,name): | |
423 self.char_hander.rename(name) | |
424 #o 1.5002 self.char_hander = parent in this case. | |
425 self.charName = name #a 1.5002 make getting name easier. | |
426 | |
427 | |
428 def get_char_name( self ): | |
429 node = self.master_dom.getElementsByTagName( 'name' )[0] | |
430 t_node = safe_get_text_node( node ) | |
431 return t_node._get_nodeValue() | |
432 | |
433 class gen_grid(wx.grid.Grid): | |
434 """grid for gen info""" | |
435 def __init__(self, parent, handler): | |
436 pname = handler.master_dom.setAttribute("name", 'General') | |
437 self.hparent = handler #a 1.5002 allow ability to run up tree, needed | |
438 # a 1.5002 parent is functional parent, not invoking parent. | |
439 | |
440 | |
441 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
442 #self.Bind(wx.EVT_SIZE, self.on_size) | |
443 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
444 self.handler = handler | |
445 n_list = handler.master_dom._get_childNodes() | |
446 self.CreateGrid(len(n_list),2) | |
447 self.SetRowLabelSize(0) | |
448 self.SetColLabelSize(0) | |
449 self.n_list = n_list | |
450 i = 0 | |
451 for i in range(len(n_list)): | |
452 self.refresh_row(i) | |
453 | |
454 def on_cell_change(self,evt): | |
455 row = evt.GetRow() | |
456 col = evt.GetCol() | |
457 value = self.GetCellValue(row,col) | |
458 t_node = self.n_list[row]._get_firstChild() | |
459 t_node._set_nodeValue(value) | |
460 if row==0: | |
461 self.handler.on_name_change(value) | |
462 self.AutoSizeColumn(1) | |
463 | |
464 def refresh_row(self,rowi): | |
465 t_node = safe_get_text_node(self.n_list[rowi]) | |
466 | |
467 self.SetCellValue(rowi,0,self.n_list[rowi]._get_tagName()) | |
468 self.SetReadOnly(rowi,0) | |
469 self.SetCellValue(rowi,1,t_node._get_nodeValue()) | |
470 self.AutoSizeColumn(1) | |
471 | |
472 class dnd3einventory(dnd3e_char_child): | |
473 """ Node Handler for general information. This handler will be | |
474 created by dnd3echar_handler. | |
475 """ | |
476 def __init__(self,xml_dom,tree_node,parent): | |
477 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
478 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
479 self.root = getRoot(self) #a 1.6009 | |
480 self.root.inventory = self #a 1.6009 | |
481 | |
482 def get_design_panel(self,parent): | |
483 wnd = inventory_pane(parent, self) #outline_panel(parent,self,inventory_grid,"Inventory") | |
484 wnd.title = "General Info" | |
485 return wnd | |
486 | |
487 def tohtml(self): | |
488 n_list = self.master_dom._get_childNodes() | |
489 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>" | |
490 for n in n_list: | |
491 t_node = safe_get_text_node(n) | |
492 html_str += "<B>"+n._get_tagName().capitalize() +":</B> " | |
493 html_str += t_node._get_nodeValue() + "<br>" | |
494 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
495 return html_str | |
496 | |
497 class inventory_pane(wx.Panel): | |
498 def __init__(self, parent, handler): | |
499 wx.Panel.__init__(self, parent, wx.ID_ANY) | |
500 | |
501 self.n_list = handler.master_dom._get_childNodes() | |
502 self.autosize = False | |
503 | |
504 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Inventroy"), wx.VERTICAL) | |
505 | |
506 self.lang = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Languages") | |
507 self.gear = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Gear") | |
508 self.magic = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Magic") | |
509 self.grid = wx.grid.Grid(self, wx.ID_ANY, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
510 | |
511 self.grid.CreateGrid(len(self.n_list)-3,2) | |
512 self.grid.SetRowLabelSize(0) | |
513 self.grid.SetColLabelSize(0) | |
514 | |
515 for i in xrange(len(self.n_list)): | |
516 self.refresh_row(i) | |
517 | |
518 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
519 sizer1.Add(self.grid, 1, wx.EXPAND) | |
520 sizer1.Add(self.lang, 1, wx.EXPAND) | |
521 | |
522 self.sizer.Add(sizer1, 0, wx.EXPAND) | |
523 | |
524 sizer2 = wx.BoxSizer(wx.HORIZONTAL) | |
525 sizer2.Add(self.gear, 1, wx.EXPAND) | |
526 sizer2.Add(self.magic, 1, wx.EXPAND) | |
527 | |
528 self.sizer.Add(sizer2, 1, wx.EXPAND) | |
529 | |
530 self.SetSizer(self.sizer) | |
531 self.SetAutoLayout(True) | |
532 self.Fit() | |
533 | |
534 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.lang) | |
535 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.gear) | |
536 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.magic) | |
537 self.Bind(wx.grid.EVT_GRID_EDITOR_HIDDEN, self.on_cell_change, self.grid) | |
538 | |
539 | |
540 def fillTextNode(self, name, value): | |
541 if name == 'Languages': | |
542 self.lang.SetValue(value) | |
543 elif name == 'Gear': | |
544 self.gear.SetValue(value) | |
545 elif name == 'Magic': | |
546 self.magic.SetValue(value) | |
547 | |
548 def onTextNodeChange(self, event): | |
549 id = event.GetId() | |
550 | |
551 if id == self.gear.GetId(): | |
552 nodeName = 'Gear' | |
553 value = self.gear.GetValue() | |
554 elif id == self.magic.GetId(): | |
555 nodeName = 'Magic' | |
556 value = self.magic.GetValue() | |
557 elif id == self.lang.GetId(): | |
558 nodeName = 'Languages' | |
559 value = self.lang.GetValue() | |
560 | |
561 for node in self.n_list: | |
562 if node._get_tagName() == nodeName: | |
563 t_node = safe_get_text_node(node) | |
564 t_node._set_nodeValue(value) | |
565 | |
566 def saveMoney(self, row, col): | |
567 value = self.grid.GetCellValue(row, col) | |
568 t_node = safe_get_text_node(self.n_list[row]) | |
569 t_node._set_nodeValue(value) | |
570 | |
571 def on_cell_change(self, evt): | |
572 row = evt.GetRow() | |
573 col = evt.GetCol() | |
574 self.grid.AutoSizeColumn(col) | |
575 wx.CallAfter(self.saveMoney, row, col) | |
576 | |
577 | |
578 | |
579 def refresh_row(self, row): | |
580 t_node = safe_get_text_node(self.n_list[row]) | |
581 tagname = self.n_list[row]._get_tagName() | |
582 value = t_node._get_nodeValue() | |
583 if tagname == 'Gear': | |
584 self.fillTextNode(tagname, value) | |
585 elif tagname == 'Magic': | |
586 self.fillTextNode(tagname, value) | |
587 elif tagname == 'Languages': | |
588 self.fillTextNode(tagname, value) | |
589 else: | |
590 self.grid.SetCellValue(row, 0, tagname) | |
591 self.grid.SetReadOnly(row, 0) | |
592 self.grid.SetCellValue(row, 1, value) | |
593 self.grid.AutoSize() | |
594 | |
595 | |
596 class dnd3eclassnstats(dnd3e_char_child): | |
597 """ Node handler for a dnd3e charactor | |
598 <nodehandler name='?' module='dnd3e' class='dnd3echar_handler2' /> | |
599 """ | |
600 def __init__(self,xml_dom,tree_node,parent): | |
601 node_handler.__init__(self,xml_dom,tree_node) | |
602 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
603 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
604 self.frame = open_rpg.get_component('frame') | |
605 self.child_handlers = {} | |
606 self.new_child_handler('abilities','Abilities Scores',dnd3eability,'gear') | |
607 self.new_child_handler('classes','Classes',dnd3eclasses,'knight') | |
608 self.new_child_handler('saves','Saves',dnd3esaves,'skull') | |
609 self.myeditor = None | |
610 | |
611 | |
612 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
613 node_list = self.master_dom.getElementsByTagName(tag) | |
614 tree = self.tree | |
615 i = self.tree.icons[icon] | |
616 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
617 handler = handler_class(node_list[0],new_tree_node,self) | |
618 tree.SetPyData(new_tree_node,handler) | |
619 self.child_handlers[tag] = handler | |
620 | |
621 def get_design_panel(self,parent): | |
622 return tabbed_panel(parent,self,1) | |
623 | |
624 | |
625 def get_use_panel(self,parent): | |
626 return tabbed_panel(parent,self,2) | |
627 | |
628 class class_char_child(node_handler): | |
629 """ Node Handler for skill. This handler will be | |
630 created by dnd3echar_handler. | |
631 """ | |
632 def __init__(self,xml_dom,tree_node,parent): | |
633 node_handler.__init__(self,xml_dom,tree_node) | |
634 self.char_hander = parent | |
635 self.drag = False | |
636 self.frame = open_rpg.get_component('frame') | |
637 self.myeditor = None | |
638 | |
639 def on_drop(self,evt): | |
640 pass | |
641 | |
642 def on_rclick(self,evt): | |
643 pass | |
644 | |
645 def on_ldclick(self,evt): | |
646 return | |
647 | |
648 def on_html(self,evt): | |
649 html_str = self.tohtml() | |
650 wnd = http_html_window(self.frame.note,-1) | |
651 wnd.title = self.master_dom.getAttribute('name') | |
652 self.frame.add_panel(wnd) | |
653 wnd.SetPage(html_str) | |
654 | |
655 def get_design_panel(self,parent): | |
656 pass | |
657 | |
658 def get_use_panel(self,parent): | |
659 return self.get_design_panel(parent) | |
660 | |
661 def delete(self): | |
662 pass | |
663 | |
664 class dnd3eability(class_char_child): | |
665 """ Node Handler for ability. This handler will be | |
666 created by dnd3echar_handler. | |
667 """ | |
668 def __init__(self,xml_dom,tree_node,parent): | |
669 class_char_child.__init__(self,xml_dom,tree_node,parent) | |
670 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
671 self.root = getRoot(self) #a 1.5002 get top of our local function tree. | |
672 self.root.abilities = self #a 1.5002 let other classes find me. | |
673 | |
674 self.abilities = {} | |
675 node_list = self.master_dom.getElementsByTagName('stat') | |
676 tree = self.tree | |
677 icons = tree.icons | |
678 | |
679 for n in node_list: | |
680 name = n.getAttribute('abbr') | |
681 self.abilities[name] = n | |
682 new_tree_node = tree.AppendItem( self.mytree_node, name, icons['gear'], icons['gear'] ) | |
683 tree.SetPyData( new_tree_node, self ) | |
684 #print "dnd3eability - init self.abilities",self.abilities #a (debug) 1.5002 | |
685 | |
686 def on_rclick( self, evt ): | |
687 item = self.tree.GetSelection() | |
688 name = self.tree.GetItemText( item ) | |
689 #if item == self.mytree_node: #d 1.6016 | |
690 # dnd3e_char_child.on_ldclick( self, evt ) #d 1.6016 | |
691 if not item == self.mytree_node: #a 1.6016 | |
692 #else: #d 1.6016 | |
693 mod = self.get_mod( name ) | |
694 if mod >= 0: | |
695 mod1 = "+" | |
696 else: | |
697 mod1 = "" | |
698 chat = self.chat | |
699 txt = '%s check: [1d20%s%s]' % ( name, mod1, mod ) | |
700 chat.ParsePost( txt, True, True ) | |
701 | |
702 def get_mod(self,abbr): | |
703 score = int(self.abilities[abbr].getAttribute('base')) | |
704 mod = (score - 10) / 2 | |
705 mod = int(mod) | |
706 return mod | |
707 | |
708 def set_score(self,abbr,score): | |
709 if score >= 0: | |
710 self.abilities[abbr].setAttribute("base",str(score)) | |
711 | |
712 def get_design_panel(self,parent): | |
713 wnd = outline_panel(parent,self,abil_grid,"Abilities") | |
714 wnd.title = "Abilities (edit)" | |
715 return wnd | |
716 | |
717 def tohtml(self): | |
718 html_str = """<table border='1' width=100%><tr BGCOLOR=#E9E9E9 ><th width='50%'>Ability</th> | |
719 <th>Base</th><th>Modifier</th></tr>""" | |
720 node_list = self.master_dom.getElementsByTagName('stat') | |
721 for n in node_list: | |
722 name = n.getAttribute('name') | |
723 abbr = n.getAttribute('abbr') | |
724 base = n.getAttribute('base') | |
725 mod = str(self.get_mod(abbr)) | |
726 if int(mod) >= 0: #m 1.6013 added "int(" and ")" | |
727 mod1 = "+" | |
728 else: | |
729 mod1 = "" | |
730 html_str = (html_str + "<tr ALIGN='center'><td>"+ | |
731 name+"</td><td>"+base+'</td><td>%s%s</td></tr>' % (mod1, mod)) | |
732 html_str = html_str + "</table>" | |
733 return html_str | |
734 | |
735 class abil_grid(wx.grid.Grid): | |
736 """grid for abilities""" | |
737 def __init__(self, parent, handler): | |
738 pname = handler.master_dom.setAttribute("name", 'Stats') | |
739 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
740 self.root = getRoot(self) | |
741 #a 1.5002 in this case, we need the functional parent, not the invoking parent. | |
742 | |
743 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
744 self.Bind(wx.EVT_SIZE, self.on_size) | |
745 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
746 self.handler = handler | |
747 stats = handler.master_dom.getElementsByTagName('stat') | |
748 self.CreateGrid(len(stats),3) | |
749 self.SetRowLabelSize(0) | |
750 col_names = ['Ability','Score','Modifier'] | |
751 for i in range(len(col_names)): | |
752 self.SetColLabelValue(i,col_names[i]) | |
753 self.stats = stats | |
754 i = 0 | |
755 for i in range(len(stats)): | |
756 self.refresh_row(i) | |
757 self.char_wnd = None | |
758 | |
759 def on_cell_change(self,evt): | |
760 row = evt.GetRow() | |
761 col = evt.GetCol() | |
762 value = self.GetCellValue(row,col) | |
763 #print value | |
764 try: | |
765 int(value) | |
766 self.stats[row].setAttribute('base',value) | |
767 self.refresh_row(row) | |
768 except: | |
769 self.SetCellValue(row,col,"0") | |
770 if self.char_wnd: | |
771 self.char_wnd.refresh_data() | |
772 | |
773 #mark5 | |
774 | |
775 def refresh_row(self,rowi): | |
776 s = self.stats[rowi] | |
777 | |
778 name = s.getAttribute('name') | |
779 abbr = s.getAttribute('abbr') | |
780 self.SetCellValue(rowi,0,name) | |
781 self.SetReadOnly(rowi,0) | |
782 self.SetCellValue(rowi,1,s.getAttribute('base')) | |
783 self.SetCellValue(rowi,2,str(self.handler.get_mod(abbr))) | |
784 self.SetReadOnly(rowi,2) | |
785 #if self.root.saves.saveGrid: #a 1.6018 d 1.9002 whole if clause | |
786 #print getmembers(self.root.saves.saveGrid) | |
787 #self.root.saves.saveGrid.refresh_data() #a 1.6018 | |
788 #print "skipping saving throw update, put back in later" | |
789 self.root.saves.refresh_data() #a 1.9002 | |
790 self.root.attacks.refreshMRdata() #a 1.9001 ` | |
791 | |
792 def on_size(self,evt): | |
793 (w,h) = self.GetClientSizeTuple() | |
794 cols = self.GetNumberCols() | |
795 col_w = w/(cols+2) | |
796 self.SetColSize(0,col_w*3) | |
797 for i in range(1,cols): | |
798 self.SetColSize(i,col_w) | |
799 evt.Skip() | |
800 self.Refresh() | |
801 | |
802 def refresh_data(self): | |
803 for r in range(self.GetNumberRows()-1): | |
804 self.refresh_row(r) | |
805 | |
806 class dnd3eclasses(class_char_child): | |
807 """ Node Handler for classes. This handler will be | |
808 created by dnd3echar_handler. | |
809 """ | |
810 def __init__(self,xml_dom,tree_node,parent): | |
811 class_char_child.__init__(self,xml_dom,tree_node,parent) | |
812 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
813 self.root = getRoot(self) | |
814 self.root.classes = self | |
815 #a 1.5002 in this case, we need the functional parent, not the invoking parent. | |
816 | |
817 def get_design_panel(self,parent): | |
818 wnd = outline_panel(parent,self,class_panel,"Classes") | |
819 wnd.title = "Classes" | |
820 return wnd | |
821 | |
822 def tohtml(self): | |
823 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Classes</th></tr><tr><td>" | |
824 n_list = self.master_dom._get_childNodes() | |
825 for n in n_list: | |
826 html_str += n.getAttribute('name') + " ("+n.getAttribute('level')+"), " | |
827 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
828 return html_str | |
829 | |
830 def get_char_lvl( self, attr ): | |
831 node_list = self.master_dom.getElementsByTagName('class') | |
832 # print "eclasses - get_char_lvl node_list",node_list | |
833 tot = 0 #a 1.5009 actually, slipping in a quick enhancement ;-) | |
834 for n in node_list: | |
835 lvl = n.getAttribute('level') #o 1.5009 not sure of the value of this | |
836 tot += int(lvl) #a 1.5009 | |
837 type = n.getAttribute('name') #o 1.5009 not sure of the value of this | |
838 #print type,lvl #a (debug) 1.5009 | |
839 if attr == "level": | |
840 return lvl #o 1.5009 this returns the level of someone's first class. ??? | |
841 elif attr == "class": | |
842 return type #o 1.5009 this returns one of the char's classes. ??? | |
843 if attr == "lvl": #a 1.5009 this has value, adding this. | |
844 return tot #a 1.5009 return character's "overall" level. | |
845 | |
846 def get_class_lvl( self, classN ): #a 1.5009 need to be able to get monk lvl | |
847 #a 1.5009 this function is new. | |
848 node_list = self.master_dom.getElementsByTagName('class') | |
849 #print "eclasses - get_class_lvl node_list",node_list | |
850 for n in node_list: | |
851 lvl = n.getAttribute('level') | |
852 type = n.getAttribute('name') | |
853 if classN == type: | |
854 return lvl | |
855 | |
856 class class_panel(wx.Panel): | |
857 def __init__(self, parent, handler): | |
858 pname = handler.master_dom.setAttribute("name", 'Class') | |
859 | |
860 wx.Panel.__init__(self, parent, -1) | |
861 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
862 sizer = wx.BoxSizer(wx.VERTICAL) | |
863 sizer.Add(self.grid, 1, wx.EXPAND) | |
864 | |
865 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
866 sizer1.Add(wx.Button(self, 10, "Remove Class"), 0, wx.EXPAND) | |
867 sizer1.Add(wx.Size(10,10)) | |
868 sizer1.Add(wx.Button(self, 20, "Add Class"), 0, wx.EXPAND) | |
869 | |
870 sizer.Add(sizer1, 0, wx.EXPAND) | |
871 self.sizer = sizer | |
872 self.SetSizer(self.sizer) | |
873 self.SetAutoLayout(True) | |
874 self.Fit() | |
875 | |
876 #self.Bind(wx.EVT_SIZE, self.on_size) | |
877 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
878 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
879 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
880 | |
881 n_list = handler.master_dom._get_childNodes() | |
882 self.n_list = n_list | |
883 self.master_dom = handler.master_dom | |
884 self.grid.CreateGrid(len(n_list),2,1) | |
885 self.grid.SetRowLabelSize(0) | |
886 self.grid.SetColLabelValue(0,"Class") | |
887 self.grid.SetColLabelValue(1,"Level") | |
888 for i in range(len(n_list)): | |
889 self.refresh_row(i) | |
890 self.temp_dom = None | |
891 | |
892 def on_cell_change(self,evt): | |
893 row = evt.GetRow() | |
894 col = evt.GetCol() | |
895 value = self.grid.GetCellValue(row,col) | |
896 try: | |
897 int(value) | |
898 self.n_list[row].setAttribute('level',value) | |
899 except: | |
900 self.grid.SetCellValue(row,col,"1") | |
901 | |
902 | |
903 def refresh_row(self,i): | |
904 n = self.n_list[i] | |
905 | |
906 name = n.getAttribute('name') | |
907 level = n.getAttribute('level') | |
908 self.grid.SetCellValue(i,0,name) | |
909 self.grid.SetReadOnly(i,0) | |
910 self.grid.SetCellValue(i,1,level) | |
911 #self.grid.SetReadOnly(i,1) | |
912 | |
913 def on_remove(self,evt): | |
914 rows = self.grid.GetNumberRows() | |
915 for i in range(rows): | |
916 if self.grid.IsInSelection(i,0): | |
917 self.grid.DeleteRows(i) | |
918 self.master_dom.removeChild(self.n_list[i]) | |
919 | |
920 def on_add(self,evt): | |
921 if not self.temp_dom: | |
922 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+"dnd3eclasses.xml","r") | |
923 xml_dom = parseXml_with_dlg(self,tmp.read()) | |
924 xml_dom = xml_dom._get_firstChild() | |
925 tmp.close() | |
926 self.temp_dom = xml_dom | |
927 f_list = self.temp_dom.getElementsByTagName('class') | |
928 opts = [] | |
929 for f in f_list: | |
930 opts.append(f.getAttribute('name')) | |
931 dlg = wx.SingleChoiceDialog(self,'Choose Class','Classes',opts) | |
932 if dlg.ShowModal() == wx.ID_OK: | |
933 i = dlg.GetSelection() | |
934 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False)) | |
935 self.grid.AppendRows(1) | |
936 self.refresh_row(self.grid.GetNumberRows()-1) | |
937 dlg.Destroy() | |
938 | |
939 | |
940 def on_size(self,event): | |
941 s = self.GetClientSizeTuple() | |
942 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
943 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
944 (w,h) = self.grid.GetClientSizeTuple() | |
945 cols = self.grid.GetNumberCols() | |
946 col_w = w/(cols) | |
947 for i in range(0,cols): | |
948 self.grid.SetColSize(i,col_w) | |
949 | |
950 | |
951 class dnd3esaves(class_char_child): | |
952 """ Node Handler for saves. This handler will be | |
953 created by dnd3echar_handler. | |
954 """ | |
955 def __init__(self,xml_dom,tree_node,parent): | |
956 class_char_child.__init__(self,xml_dom,tree_node,parent) | |
957 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
958 #self.saveGrid = None #a 1.6018 d 1.9002 | |
959 self.saveGridFrame = [] #a 1.9002 handle list, check frame for close. | |
960 | |
961 tree = self.tree | |
962 icons = self.tree.icons | |
963 | |
964 self.root = getRoot(self) #a 1.5002 | |
965 self.root.saves = self #a 1.6009 | |
966 node_list = self.master_dom.getElementsByTagName('save') | |
967 self.saves={} | |
968 for n in node_list: | |
969 name = n.getAttribute('name') | |
970 self.saves[name] = n | |
971 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear']) | |
972 tree.SetPyData(new_tree_node,self) | |
973 | |
974 #a 1.9002 this whole method | |
975 def refresh_data(self): # refresh the data in the melee/ranged section | |
976 # of the attack chart. | |
977 # count backwards, maintains context despite "removes" | |
978 for i in range(len(self.saveGridFrame)-1,-1,-1): | |
979 x = self.saveGridFrame[i] | |
980 if x == None: | |
981 x.refresh_data() | |
982 else: | |
983 self.saveGridFrame.remove(x) | |
984 | |
985 def get_mod(self,name): | |
986 save = self.saves[name] | |
987 stat = save.getAttribute('stat') | |
988 #print "dnd3esaves, get_mod: self,root",self,self.root #a (debug) 1.5002 | |
989 #print "and abilities",self.root.abilities #a (debug) 1.5002 | |
990 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002 | |
991 base = int(save.getAttribute('base')) | |
992 miscmod = int(save.getAttribute('miscmod')) | |
993 magmod = int(save.getAttribute('magmod')) | |
994 total = stat_mod + base + miscmod + magmod | |
995 return total | |
996 | |
997 def on_rclick(self,evt): | |
998 | |
999 item = self.tree.GetSelection() | |
1000 name = self.tree.GetItemText(item) | |
1001 if item == self.mytree_node: | |
1002 pass #a 1.5003 syntatic place holder | |
1003 return #a 1.5003 | |
1004 #print "failure mode!" | |
1005 #dnd3e_char_child.on_ldclick(self,evt) #d 1.5003 this busted | |
1006 #wnd = save_grid(self.frame.note,self) | |
1007 #wnd.title = "Saves" | |
1008 #self.frame.add_panel(wnd) | |
1009 else: | |
1010 mod = self.get_mod(name) | |
1011 if mod >= 0: | |
1012 mod1 = "+" | |
1013 else: | |
1014 mod1 = "" | |
1015 chat = self.chat | |
1016 txt = '%s save: [1d20%s%s]' % (name, mod1, mod) | |
1017 chat.ParsePost( txt, True, True ) | |
1018 | |
1019 def get_design_panel(self,parent): | |
1020 wnd = outline_panel(parent,self,save_grid,"Saves") | |
1021 wnd.title = "Saves" | |
1022 return wnd | |
1023 | |
1024 def tohtml(self): | |
1025 html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 > | |
1026 <th width='30%'>Save</th> | |
1027 <th>Key</th><th>Base</th><th>Abil</th><th>Magic</th> | |
1028 <th>Misc</th><th>Total</th></tr>""" | |
1029 node_list = self.master_dom.getElementsByTagName('save') | |
1030 for n in node_list: | |
1031 name = n.getAttribute('name') | |
1032 stat = n.getAttribute('stat') | |
1033 base = n.getAttribute('base') | |
1034 html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+stat+"</td><td>"+base+"</td>" | |
1035 #stat_mod = str(dnd_globals["stats"][stat]) #d 1.5002 | |
1036 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002 | |
1037 | |
1038 mag = n.getAttribute('magmod') | |
1039 misc = n.getAttribute('miscmod') | |
1040 mod = str(self.get_mod(name)) | |
1041 if mod >= 0: | |
1042 mod1 = "+" | |
1043 else: | |
1044 mod1 = "" | |
1045 #m 1.5009 next line. added str() around stat_mod | |
1046 html_str = html_str + "<td>"+str(stat_mod)+"</td><td>"+mag+"</td>" | |
1047 html_str = html_str + '<td>'+misc+'</td><td>%s%s</td></tr>' % (mod1, mod) | |
1048 html_str = html_str + "</table>" | |
1049 return html_str | |
1050 | |
1051 #mark6 | |
1052 class save_grid(wx.grid.Grid): | |
1053 """grid for saves""" | |
1054 def __init__(self, parent, handler): | |
1055 pname = handler.master_dom.setAttribute("name", 'Saves') | |
1056 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
1057 #a 1.5002 in this case, we need the functional parent, not the invoking parent. | |
1058 self.root = getRoot(self) | |
1059 | |
1060 #self.hparent.saveGrid = self #a 1.6018 d 1.9001 | |
1061 | |
1062 | |
1063 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
1064 self.Bind(wx.EVT_SIZE, self.on_size) | |
1065 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
1066 self.handler = handler | |
1067 saves = handler.master_dom.getElementsByTagName('save') | |
1068 self.CreateGrid(len(saves),7) | |
1069 self.SetRowLabelSize(0) | |
1070 col_names = ['Save','Key','base','Abil','Magic','Misc','Total'] | |
1071 for i in range(len(col_names)): | |
1072 self.SetColLabelValue(i,col_names[i]) | |
1073 self.saves = saves | |
1074 i = 0 | |
1075 for i in range(len(saves)): | |
1076 self.refresh_row(i) | |
1077 | |
1078 | |
1079 #a 1.9002 remainder of code in this method. | |
1080 climber = parent | |
1081 nameNode = climber.GetClassName() | |
1082 while nameNode != 'wxFrame': | |
1083 climber = climber.parent | |
1084 nameNode = climber.GetClassName() | |
1085 masterFrame=climber | |
1086 masterFrame.refresh_data=self.refresh_data | |
1087 #print getmembers(masterFrame) | |
1088 | |
1089 handler.saveGridFrame.append(masterFrame) | |
1090 | |
1091 def on_cell_change(self,evt): | |
1092 row = evt.GetRow() | |
1093 col = evt.GetCol() | |
1094 value = self.GetCellValue(row,col) | |
1095 try: | |
1096 int(value) | |
1097 if col == 2: | |
1098 self.saves[row].setAttribute('base',value) | |
1099 elif col ==4: | |
1100 self.saves[row].setAttribute('magmod',value) | |
1101 elif col ==5: # 1.5001 | |
1102 self.saves[row].setAttribute('miscmod',value) | |
1103 self.refresh_row(row) | |
1104 except: | |
1105 self.SetCellValue(row,col,"0") | |
1106 | |
1107 def refresh_row(self,rowi): | |
1108 s = self.saves[rowi] | |
1109 | |
1110 name = s.getAttribute('name') | |
1111 self.SetCellValue(rowi,0,name) | |
1112 self.SetReadOnly(rowi,0) | |
1113 stat = s.getAttribute('stat') | |
1114 self.SetCellValue(rowi,1,stat) | |
1115 self.SetReadOnly(rowi,1) | |
1116 self.SetCellValue(rowi,2,s.getAttribute('base')) | |
1117 self.SetCellValue(rowi,3,str(self.root.abilities.get_mod(stat))) | |
1118 self.SetReadOnly(rowi,3) | |
1119 self.SetCellValue(rowi,4,s.getAttribute('magmod')) | |
1120 self.SetCellValue(rowi,5,s.getAttribute('miscmod')) | |
1121 mod = str(self.handler.get_mod(name)) | |
1122 self.SetCellValue(rowi,6,mod) | |
1123 self.SetReadOnly(rowi,6) | |
1124 | |
1125 def on_size(self,evt): | |
1126 (w,h) = self.GetClientSizeTuple() | |
1127 cols = self.GetNumberCols() | |
1128 col_w = w/(cols+2) | |
1129 self.SetColSize(0,col_w*3) | |
1130 for i in range(1,cols): | |
1131 self.SetColSize(i,col_w) | |
1132 evt.Skip() | |
1133 self.Refresh() | |
1134 | |
1135 def refresh_data(self): | |
1136 for r in range(self.GetNumberRows()): | |
1137 self.refresh_row(r) | |
1138 | |
1139 class dnd3eskillsnfeats(dnd3e_char_child): | |
1140 """ Node handler for a dnd3e charactor | |
1141 <nodehandler name='?' module='dnd3e' class='dnd3echar_handler2' /> | |
1142 """ | |
1143 def __init__(self,xml_dom,tree_node,parent): | |
1144 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
1145 self.root = getRoot(self) #a 1.6009 | |
1146 | |
1147 #print "dnd3eskillsnfeats - init, self ",self #a (debug) 1.5002 | |
1148 #print "dnd3eskillsnfeats - init, parent ",self.hparent #a (debug) 1.5002 | |
1149 #print "dnd3eskillsnfeats - init, parent ",parent.dnd3eclassnstats #a (debug) 1.5002 | |
1150 | |
1151 node_handler.__init__(self,xml_dom,tree_node) | |
1152 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
1153 self.frame = open_rpg.get_component('frame') | |
1154 self.child_handlers = {} | |
1155 self.new_child_handler('skills','Skills',dnd3eskill,'book') | |
1156 self.new_child_handler('feats','Feats',dnd3efeats,'book') | |
1157 #wxMenuItem(self.tree.std_menu, dnd3e_EXPORT, "Export...", "Export") | |
1158 self.myeditor = None | |
1159 | |
1160 | |
1161 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
1162 node_list = self.master_dom.getElementsByTagName(tag) | |
1163 tree = self.tree | |
1164 i = self.tree.icons[icon] | |
1165 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
1166 handler = handler_class(node_list[0],new_tree_node,self) | |
1167 tree.SetPyData(new_tree_node,handler) | |
1168 self.child_handlers[tag] = handler | |
1169 | |
1170 def get_design_panel(self,parent): | |
1171 return tabbed_panel(parent,self,1) | |
1172 | |
1173 | |
1174 def get_use_panel(self,parent): | |
1175 return tabbed_panel(parent,self,2) | |
1176 | |
1177 class skills_char_child(node_handler): | |
1178 """ Node Handler for skill. This handler will be | |
1179 created by dnd3echar_handler. | |
1180 """ | |
1181 def __init__(self,xml_dom,tree_node,parent): | |
1182 node_handler.__init__(self,xml_dom,tree_node) | |
1183 self.char_hander = parent | |
1184 self.drag = False | |
1185 self.frame = open_rpg.get_component('frame') | |
1186 self.myeditor = None | |
1187 | |
1188 | |
1189 | |
1190 def on_drop(self,evt): | |
1191 pass | |
1192 | |
1193 def on_rclick(self,evt): | |
1194 pass | |
1195 | |
1196 def on_ldclick(self,evt): | |
1197 return | |
1198 | |
1199 def on_html(self,evt): | |
1200 html_str = self.tohtml() | |
1201 wnd = http_html_window(self.frame.note,-1) | |
1202 wnd.title = self.master_dom.getAttribute('name') | |
1203 self.frame.add_panel(wnd) | |
1204 wnd.SetPage(html_str) | |
1205 | |
1206 def get_design_panel(self,parent): | |
1207 pass | |
1208 | |
1209 def get_use_panel(self,parent): | |
1210 return self.get_design_panel(parent) | |
1211 | |
1212 def delete(self): | |
1213 pass | |
1214 | |
1215 class dnd3eskill(skills_char_child): | |
1216 """ Node Handler for skill. This handler will be | |
1217 created by dnd3echar_handler. | |
1218 """ | |
1219 def __init__(self,xml_dom,tree_node,parent): | |
1220 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
1221 #a 1.5002 Need the functional parent, not the invoking parent. | |
1222 self.root = getRoot(self) #a 1.5002 | |
1223 self.root.skills = self #a 1.6009 | |
1224 | |
1225 skills_char_child.__init__(self,xml_dom,tree_node,parent) | |
1226 tree = self.tree | |
1227 icons = self.tree.icons | |
1228 node_list = self.master_dom.getElementsByTagName('skill') | |
1229 | |
1230 self.skills={} | |
1231 #Adding code to not display skills you can not use -mgt | |
1232 for n in node_list: | |
1233 name = n.getAttribute('name') | |
1234 self.skills[name] = n | |
1235 skill_check = self.skills[name] | |
1236 ranks = int(skill_check.getAttribute('rank')) | |
1237 trained = int(skill_check.getAttribute('untrained')) | |
1238 | |
1239 if ranks > 0 or trained == 1: | |
1240 new_tree_node = tree.AppendItem(self.mytree_node,name, | |
1241 icons['gear'],icons['gear']) | |
1242 else: | |
1243 continue | |
1244 | |
1245 tree.SetPyData(new_tree_node,self) | |
1246 | |
1247 | |
1248 | |
1249 def refresh_skills(self): | |
1250 #Adding this so when you update the grid the tree will reflect | |
1251 #The change. -mgt | |
1252 tree = self.tree | |
1253 icons = self.tree.icons | |
1254 tree.CollapseAndReset(self.mytree_node) | |
1255 node_list = self.master_dom.getElementsByTagName('skill') | |
1256 | |
1257 self.skills={} | |
1258 for n in node_list: | |
1259 name = n.getAttribute('name') | |
1260 self.skills[name] = n | |
1261 skill_check = self.skills[name] | |
1262 ranks = int(skill_check.getAttribute('rank')) | |
1263 trained = int(skill_check.getAttribute('untrained')) | |
1264 | |
1265 if ranks > 0 or trained == 1: | |
1266 new_tree_node = tree.AppendItem(self.mytree_node,name, | |
1267 icons['gear'],icons['gear']) | |
1268 else: | |
1269 continue | |
1270 | |
1271 tree.SetPyData(new_tree_node,self) | |
1272 | |
1273 def get_mod(self,name): | |
1274 skill = self.skills[name] | |
1275 stat = skill.getAttribute('stat') | |
1276 #stat_mod = int(dnd_globals["stats"][stat]) #d 1.5002 | |
1277 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002 | |
1278 rank = int(skill.getAttribute('rank')) | |
1279 misc = int(skill.getAttribute('misc')) | |
1280 total = stat_mod + rank + misc | |
1281 return total | |
1282 | |
1283 def on_rclick(self,evt): | |
1284 item = self.tree.GetSelection() | |
1285 name = self.tree.GetItemText(item) | |
1286 #print "skill rc self",self #a 1.6004 | |
1287 #print "skill rc tree",self.mytree_node #a 1.6004 | |
1288 #print "skill rc item",item #a 1.6004 | |
1289 if item == self.mytree_node: | |
1290 return | |
1291 # following line fails, | |
1292 #dnd3e_char_child.on_ldclick(self,evt) #d 1.6014 | |
1293 # it's what it used to try to do. | |
1294 ac = self.root.ac.get_check_pen() #a 1.5002 for 1.5004 verify fix. | |
1295 | |
1296 skill = self.skills[name] | |
1297 | |
1298 untr = skill.getAttribute('untrained') #a 1.6004 | |
1299 rank = skill.getAttribute('rank') #a 1.6004 | |
1300 if eval('%s == 0' % (untr)): #a 1.6004 | |
1301 if eval('%s == 0' % (rank)): #a 1.6004 | |
1302 res = 'You fumble around, accomplishing nothing' #a 1.6004 | |
1303 txt = '%s Skill Check: %s' % (name, res) #a 1.6004 | |
1304 chat = self.chat #a 1.6004 | |
1305 chat.Post(txt,True,True) #a 1.6004 | |
1306 return #a 1.6004 | |
1307 | |
1308 armor = '' | |
1309 acCp = '' | |
1310 if ac < 0: #acCp >= 1 #m 1.5004 this is stored as negatives. | |
1311 armorCheck = int(skill.getAttribute('armorcheck')) | |
1312 #print "ac,armorCheck",ac,armorCheck | |
1313 if armorCheck == 1: | |
1314 acCp=ac | |
1315 armor = '(includes Armor Penalty of %s)' % (acCp) | |
1316 if item == self.mytree_node: | |
1317 dnd3e_char_child.on_ldclick(self,evt) | |
1318 #wnd = skill_grid(self.frame.note,self) | |
1319 #wnd.title = "Skills" | |
1320 #self.frame.add_panel(wnd) | |
1321 else: | |
1322 mod = self.get_mod(name) | |
1323 if mod >= 0: | |
1324 mod1 = "+" | |
1325 else: | |
1326 mod1 = "" | |
1327 chat = self.chat | |
1328 txt = '%s Skill Check: [1d20%s%s%s] %s' % ( | |
1329 name, mod1, mod, acCp, armor) | |
1330 chat.ParsePost(txt,True,True) | |
1331 | |
1332 def get_design_panel(self,parent): | |
1333 wnd = outline_panel(parent,self,skill_grid,"Skills") | |
1334 wnd.title = "Skills (edit)" | |
1335 return wnd | |
1336 | |
1337 def tohtml(self): | |
1338 html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 > | |
1339 <th width='30%'>Skill</th><th>Key</th> | |
1340 <th>Rank</th><th>Abil</th><th>Misc</th><th>Total</th></tr>""" | |
1341 node_list = self.master_dom.getElementsByTagName('skill') | |
1342 | |
1343 for n in node_list: | |
1344 name = n.getAttribute('name') | |
1345 stat = n.getAttribute('stat') | |
1346 rank = n.getAttribute('rank') | |
1347 untr = n.getAttribute('untrained') #a 1.6004 | |
1348 #Filter unsuable skills out of pretty print -mgt | |
1349 if eval('%s > 0' % (rank)) or eval('%s == 1' % (untr)): | |
1350 if eval('%s >=1' % (rank)): | |
1351 html_str += "<tr ALIGN='center' bgcolor='#CCCCFF'><td>" #a 1.6004 | |
1352 #html_str += "<tr ALIGN='center' bgcolor='green'><td>" #d 1.6004 | |
1353 html_str += name+"</td><td>"+stat+"</td><td>"+rank+"</td>" | |
1354 elif eval('%s == 1' % (untr)): #a 1.6004 | |
1355 html_str += "<tr ALIGN='center' bgcolor='#C0FF40'><td>" #a 1.6004 | |
1356 html_str += name+"</td><td>"+stat+"</td><td>"+rank+"</td>" #a 1.6004 | |
1357 else: | |
1358 html_str += "<tr ALIGN='center'><td>"+name+"</td><td>" | |
1359 html_str += stat+"</td><td>"+rank+"</td>" | |
1360 else: | |
1361 continue | |
1362 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002 | |
1363 #stat_mod = str(dnd_globals["stats"][stat]) #d 1.5002 | |
1364 misc = n.getAttribute('misc') | |
1365 mod = str(self.get_mod(name)) | |
1366 if mod >= 0: | |
1367 mod1 = "+" | |
1368 else: | |
1369 mod1 = "" | |
1370 html_str += "<td>"+str(stat_mod)+"</td><td>"+misc #m 1.6009 str() | |
1371 html_str += '</td><td>%s%s</td></tr>' % (mod1, mod) | |
1372 html_str = html_str + "</table>" | |
1373 return html_str | |
1374 | |
1375 | |
1376 class skill_grid(wx.grid.Grid): | |
1377 """ panel for skills """ | |
1378 def __init__(self, parent, handler): | |
1379 self.hparent = handler #a 1.5002 need function parent, not invoker | |
1380 self.root = getRoot(self) #a 1.5002 | |
1381 pname = handler.master_dom.setAttribute("name", 'Skills') | |
1382 | |
1383 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
1384 self.Bind(wx.EVT_SIZE, self.on_size) | |
1385 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
1386 self.handler = handler | |
1387 skills = handler.master_dom.getElementsByTagName('skill') | |
1388 #xelf.stats = dnd_globals["stats"] #d 1.5002 | |
1389 | |
1390 self.CreateGrid(len(skills),6) | |
1391 self.SetRowLabelSize(0) | |
1392 col_names = ['Skill','Key','Rank','Abil','Misc','Total'] | |
1393 for i in range(len(col_names)): | |
1394 self.SetColLabelValue(i,col_names[i]) | |
1395 rowi = 0 | |
1396 self.skills = skills | |
1397 for i in range(len(skills)): | |
1398 self.refresh_row(i) | |
1399 | |
1400 def on_cell_change(self,evt): | |
1401 row = evt.GetRow() | |
1402 col = evt.GetCol() | |
1403 value = self.GetCellValue(row,col) | |
1404 #print value | |
1405 try: | |
1406 int(value) | |
1407 if col == 2: | |
1408 self.skills[row].setAttribute('rank',value) | |
1409 elif col ==4: | |
1410 self.skills[row].setAttribute('misc',value) | |
1411 self.refresh_row(row) | |
1412 except: | |
1413 self.SetCellValue(row,col,"0") | |
1414 | |
1415 #call refresh_skills | |
1416 self.handler.refresh_skills() | |
1417 | |
1418 def refresh_row(self,rowi): | |
1419 s = self.skills[rowi] | |
1420 name = s.getAttribute('name') | |
1421 self.SetCellValue(rowi,0,name) | |
1422 self.SetReadOnly(rowi,0) | |
1423 stat = s.getAttribute('stat') | |
1424 self.SetCellValue(rowi,1,stat) | |
1425 self.SetReadOnly(rowi,1) | |
1426 self.SetCellValue(rowi,2,s.getAttribute('rank')) | |
1427 #self.SetCellValue(rowi,3,str(dnd_globals["stats"][stat])) #d 1.5002 | |
1428 if self.root.abilities: #a 1.5002 sanity check. | |
1429 stat_mod=self.root.abilities.get_mod(stat) #a 1.5002 | |
1430 else: #a 1.5002 | |
1431 stat_mod = -6 #a 1.5002 this can happen if code is changed so | |
1432 #a 1.5002 that abilities are not defined prior invokation of init. | |
1433 print "Please advise dnd3e maintainer alert 1.5002 raised" | |
1434 | |
1435 self.SetCellValue(rowi,3,str(stat_mod)) #a 1.5002 | |
1436 self.SetReadOnly(rowi,3) | |
1437 self.SetCellValue(rowi,4,s.getAttribute('misc')) | |
1438 mod = str(self.handler.get_mod(name)) | |
1439 self.SetCellValue(rowi,5,mod) | |
1440 self.SetReadOnly(rowi,5) | |
1441 | |
1442 def on_size(self,evt): | |
1443 (w,h) = self.GetClientSizeTuple() | |
1444 cols = self.GetNumberCols() | |
1445 col_w = w/(cols+2) | |
1446 self.SetColSize(0,col_w*3) | |
1447 for i in range(1,cols): | |
1448 self.SetColSize(i,col_w) | |
1449 evt.Skip() | |
1450 self.Refresh() | |
1451 | |
1452 def refresh_data(self): | |
1453 | |
1454 for r in range(self.GetNumberRows()): | |
1455 self.refresh_row(r) | |
1456 | |
1457 | |
1458 | |
1459 | |
1460 class dnd3efeats(skills_char_child): | |
1461 """ Node Handler for classes. This handler will be | |
1462 created by dnd3echar_handler. | |
1463 """ | |
1464 def __init__(self,xml_dom,tree_node,parent): | |
1465 skills_char_child.__init__(self,xml_dom,tree_node,parent) | |
1466 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
1467 self.root = getRoot(self) #a 1.5002 | |
1468 self.root.feats = self #a 1.6009 | |
1469 | |
1470 | |
1471 def get_design_panel(self,parent): | |
1472 setTitle="Feats - " + self.root.general.charName #a 1.5010 | |
1473 wnd = outline_panel(parent,self,feat_panel,setTitle) #a 1.5010 | |
1474 #wnd = outline_panel(parent,self,feat_panel,"Feats") #d 1.5010 | |
1475 wnd.title = "Feats" #d 1.5010 | |
1476 #wnd.title = "Feats - " + self.charName | |
1477 return wnd | |
1478 | |
1479 def tohtml(self): | |
1480 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Feats</th></tr><tr><td>" | |
1481 n_list = self.master_dom._get_childNodes() | |
1482 for n in n_list: | |
1483 html_str += n.getAttribute('name')+ ", " | |
1484 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
1485 return html_str | |
1486 | |
1487 class feat_panel(wx.Panel): | |
1488 def __init__(self, parent, handler): | |
1489 | |
1490 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
1491 #a 1.5002 in this case, we need the functional parent, not the invoking parent. | |
1492 self.root = getRoot(self) #a 1.5002 | |
1493 #tempTitle= 'Feats - ' + self.root.general.charName #a 1.5010 | |
1494 #pname = handler.master_dom.setAttribute("name", tempTitle) #a 1.5010 | |
1495 pname = handler.master_dom.setAttribute("name", 'Feats') #d 1.5010 | |
1496 | |
1497 wx.Panel.__init__(self, parent, -1) | |
1498 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
1499 sizer = wx.BoxSizer(wx.VERTICAL) | |
1500 sizer.Add(self.grid, 1, wx.EXPAND) | |
1501 | |
1502 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
1503 sizer1.Add(wx.Button(self, 10, "Remove Feat"), 0, wx.EXPAND) | |
1504 sizer1.Add(wx.Size(10,10)) | |
1505 sizer1.Add(wx.Button(self, 20, "Add Feat"), 0, wx.EXPAND) | |
1506 | |
1507 sizer.Add(sizer1, 0, wx.EXPAND) | |
1508 self.sizer = sizer | |
1509 | |
1510 self.SetSizer(self.sizer) | |
1511 self.SetAutoLayout(True) | |
1512 self.Fit() | |
1513 | |
1514 #self.Bind(wx.EVT_SIZE, self.on_size) | |
1515 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
1516 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
1517 | |
1518 n_list = handler.master_dom._get_childNodes() | |
1519 self.n_list = n_list | |
1520 self.master_dom = handler.master_dom | |
1521 self.grid.CreateGrid(len(n_list),3,1) | |
1522 self.grid.SetRowLabelSize(0) | |
1523 self.grid.SetColLabelValue(0,"Feat") | |
1524 self.grid.SetColLabelValue(1,"Type") | |
1525 self.grid.SetColLabelValue(2,"Reference") #m 1.6 typo correction. | |
1526 for i in range(len(n_list)): | |
1527 self.refresh_row(i) | |
1528 self.temp_dom = None | |
1529 | |
1530 def refresh_row(self,i): | |
1531 feat = self.n_list[i] | |
1532 | |
1533 name = feat.getAttribute('name') | |
1534 type = feat.getAttribute('type') | |
1535 desc = feat.getAttribute('desc') #m 1.6 correct typo | |
1536 self.grid.SetCellValue(i,0,name) | |
1537 self.grid.SetReadOnly(i,0) | |
1538 self.grid.SetCellValue(i,1,type) | |
1539 self.grid.SetReadOnly(i,1) | |
1540 self.grid.SetCellValue(i,2,desc) #m 1.6 correct typo | |
1541 self.grid.SetReadOnly(i,2) | |
1542 | |
1543 def on_remove(self,evt): | |
1544 rows = self.grid.GetNumberRows() | |
1545 for i in range(rows): | |
1546 if self.grid.IsInSelection(i,0): | |
1547 self.grid.DeleteRows(i) | |
1548 self.master_dom.removeChild(self.n_list[i]) | |
1549 | |
1550 def on_add(self,evt): | |
1551 | |
1552 if not self.temp_dom: | |
1553 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+"dnd3efeats.xml","r") | |
1554 xml_dom = parseXml_with_dlg(self,tmp.read()) | |
1555 xml_dom = xml_dom._get_firstChild() | |
1556 tmp.close() | |
1557 self.temp_dom = xml_dom | |
1558 f_list = self.temp_dom.getElementsByTagName('feat') | |
1559 opts = [] | |
1560 for f in f_list: | |
1561 opts.append(f.getAttribute('name') + " - [" + | |
1562 f.getAttribute('type') + "] - " + f.getAttribute('desc')) | |
1563 dlg = wx.SingleChoiceDialog(self,'Choose Feat','Feats',opts) | |
1564 if dlg.ShowModal() == wx.ID_OK: | |
1565 i = dlg.GetSelection() | |
1566 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False)) | |
1567 self.grid.AppendRows(1) | |
1568 self.refresh_row(self.grid.GetNumberRows()-1) | |
1569 dlg.Destroy() | |
1570 | |
1571 | |
1572 def on_size(self,event): | |
1573 s = self.GetClientSizeTuple() | |
1574 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
1575 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
1576 (w,h) = self.grid.GetClientSizeTuple() | |
1577 cols = self.grid.GetNumberCols() | |
1578 col_w = w/(cols) | |
1579 for i in range(0,cols): | |
1580 self.grid.SetColSize(i,col_w) | |
1581 | |
1582 class dnd3ecombat(dnd3e_char_child): | |
1583 """ Node handler for a dnd3e charactor | |
1584 <nodehandler name='?' module='dnd3e' class='dnd3echar_handler2' /> | |
1585 """ | |
1586 def __init__(self,xml_dom,tree_node,parent): | |
1587 | |
1588 node_handler.__init__(self,xml_dom,tree_node) | |
1589 | |
1590 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
1591 self.root = getRoot(self) #a 1.5012 | |
1592 | |
1593 | |
1594 | |
1595 #mark3 | |
1596 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
1597 self.frame = open_rpg.get_component('frame') | |
1598 self.child_handlers = {} | |
1599 self.new_child_handler('hp','Hit Points',dnd3ehp,'gear') | |
1600 self.new_child_handler('attacks','Attacks',dnd3eattacks,'spears') | |
1601 self.new_child_handler('ac','Armor',dnd3earmor,'spears') | |
1602 #print "combat",self.child_handlers #a (debug) 1.5002 | |
1603 #wxMenuItem(self.tree.std_menu, dnd3e_EXPORT, "Export...", "Export") | |
1604 self.myeditor = None | |
1605 | |
1606 | |
1607 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
1608 node_list = self.master_dom.getElementsByTagName(tag) | |
1609 tree = self.tree | |
1610 i = self.tree.icons[icon] | |
1611 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
1612 handler = handler_class(node_list[0],new_tree_node,self) | |
1613 tree.SetPyData(new_tree_node,handler) | |
1614 self.child_handlers[tag] = handler | |
1615 | |
1616 def get_design_panel(self,parent): | |
1617 return tabbed_panel(parent,self,1) | |
1618 | |
1619 def get_use_panel(self,parent): | |
1620 return tabbed_panel(parent,self,2) | |
1621 | |
1622 | |
1623 class combat_char_child(node_handler): | |
1624 """ Node Handler for combat. This handler will be | |
1625 created by dnd3echar_handler. | |
1626 """ | |
1627 def __init__(self,xml_dom,tree_node,parent): | |
1628 node_handler.__init__(self,xml_dom,tree_node) | |
1629 self.char_hander = parent | |
1630 self.drag = False | |
1631 self.frame = open_rpg.get_component('frame') | |
1632 self.myeditor = None | |
1633 | |
1634 | |
1635 def on_drop(self,evt): | |
1636 pass | |
1637 | |
1638 def on_rclick(self,evt): | |
1639 pass | |
1640 | |
1641 def on_ldclick(self,evt): | |
1642 return | |
1643 | |
1644 def on_html(self,evt): | |
1645 html_str = self.tohtml() | |
1646 wnd = http_html_window(self.frame.note,-1) | |
1647 wnd.title = self.master_dom.getAttribute('name') | |
1648 self.frame.add_panel(wnd) | |
1649 wnd.SetPage(html_str) | |
1650 | |
1651 def get_design_panel(self,parent): | |
1652 pass | |
1653 | |
1654 def get_use_panel(self,parent): | |
1655 return self.get_design_panel(parent) | |
1656 | |
1657 def delete(self): | |
1658 pass | |
1659 | |
1660 class dnd3ehp(combat_char_child): | |
1661 """ Node Handler for hit points. This handler will be | |
1662 created by dnd3echar_handler. | |
1663 """ | |
1664 def __init__(self,xml_dom,tree_node,parent): | |
1665 combat_char_child.__init__(self,xml_dom,tree_node,parent) | |
1666 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
1667 self.root = getRoot(self) #a 1.6009 | |
1668 self.root.hp = self #a 1.6009 | |
1669 | |
1670 def get_design_panel(self,parent): | |
1671 wnd = outline_panel(parent,self,hp_panel,"Hit Points") | |
1672 wnd.title = "Hit Points" | |
1673 return wnd | |
1674 | |
1675 def on_rclick( self, evt ): | |
1676 chp = self.master_dom.getAttribute('current') | |
1677 mhp = self.master_dom.getAttribute('max') | |
1678 txt = '((HP: %s / %s))' % ( chp, mhp ) | |
1679 self.chat.ParsePost( txt, True, True ) | |
1680 | |
1681 def tohtml(self): | |
1682 html_str = "<table width=100% border=1 >" | |
1683 html_str += "<tr BGCOLOR=#E9E9E9 ><th colspan=4>Hit Points</th></tr>" | |
1684 html_str += "<tr><th>Max:</th>" | |
1685 html_str += "<td>"+self.master_dom.getAttribute('max')+"</td>" | |
1686 html_str += "<th>Current:</th>" | |
1687 html_str += "<td>"+self.master_dom.getAttribute('current')+"</td>" | |
1688 html_str += "</tr></table>" | |
1689 return html_str | |
1690 | |
1691 class hp_panel(wx.Panel): | |
1692 def __init__(self, parent, handler): | |
1693 wx.Panel.__init__(self, parent, -1) | |
1694 self.hparent = handler #a 1.5002 allow ability to run up tree. In this | |
1695 #a 1.5002 case, we need the functional parent, not the invoking parent. | |
1696 | |
1697 pname = handler.master_dom.setAttribute("name", 'HitPoints') | |
1698 self.sizer = wx.FlexGridSizer(2, 4, 2, 2) # rows, cols, hgap, vgap | |
1699 self.master_dom = handler.master_dom | |
1700 self.sizer.AddMany([ (wx.StaticText(self, -1, "HP Current:"), 0, | |
1701 wx.ALIGN_CENTER_VERTICAL), | |
1702 (wx.TextCtrl(self, HP_CUR, | |
1703 self.master_dom.getAttribute('current')), 0, wx.EXPAND), | |
1704 (wx.StaticText(self, -1, "HP Max:"), 0, wx.ALIGN_CENTER_VERTICAL), | |
1705 (wx.TextCtrl(self, HP_MAX, self.master_dom.getAttribute('max')), | |
1706 0, wx.EXPAND), | |
1707 ]) | |
1708 self.sizer.AddGrowableCol(1) | |
1709 self.SetSizer(self.sizer) | |
1710 self.SetAutoLayout(True) | |
1711 self.Fit() | |
1712 | |
1713 #self.Bind(wx.EVT_SIZE, self.on_size) | |
1714 self.Bind(wx.EVT_TEXT, self.on_text, id=HP_MAX) | |
1715 self.Bind(wx.EVT_TEXT, self.on_text, id=HP_CUR) | |
1716 | |
1717 def on_text(self,evt): | |
1718 id = evt.GetId() | |
1719 if id == HP_CUR: | |
1720 self.master_dom.setAttribute('current',evt.GetString()) | |
1721 elif id == HP_MAX: | |
1722 self.master_dom.setAttribute('max',evt.GetString()) | |
1723 | |
1724 def on_size(self,evt): | |
1725 s = self.GetClientSizeTuple() | |
1726 self.sizer.SetDimension(0,0,s[0],s[1]) | |
1727 | |
1728 class dnd3eattacks(combat_char_child): | |
1729 """ Node Handler for attacks. This handler will be | |
1730 created by dnd3echar_handler. | |
1731 """ | |
1732 def __init__(self,xml_dom,tree_node,parent): | |
1733 combat_char_child.__init__(self,xml_dom,tree_node,parent) | |
1734 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
1735 self.root = getRoot(self) #a 1.5002 | |
1736 self.root.attacks = self #a 1.6009 so others can find me. | |
1737 self.mrFrame = [] #a 1.9001 | |
1738 | |
1739 #a 1.5012 start a1b | |
1740 | |
1741 self.updateFootNotes = False | |
1742 self.updateFootNotes = False | |
1743 self.html_str = "<html><body>" | |
1744 self.html_str += ("<br> This character has weapons with no "+ | |
1745 "footnotes. This program will "+ | |
1746 "add footnotes to the weapons which have names that still match "+ | |
1747 "the orginal names. If you have changed the weapon name, you "+ | |
1748 "will see some weapons with a footnote of 'X', you will have "+ | |
1749 "to either delete and re-add the weapon, or research "+ | |
1750 "and add the correct footnotes for the weapon.\n"+ | |
1751 "<br> Please be aware, that only the bow/sling footnote is "+ | |
1752 "being used to affect changes to rolls; implemenation of other "+ | |
1753 "footnotes to automaticly adjust rolls will be completed as "+ | |
1754 "soon as time allows." + | |
1755 "<br><br>Update to character:"+self.root.general.charName+ | |
1756 "<br><br>"+ | |
1757 """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 > | |
1758 <th width='80%'>Weapon Name</th><th>Added Footnote</th></tr>\n""") | |
1759 self.temp_dom={} | |
1760 #a 1.5012 end a1b | |
1761 | |
1762 node_list = self.master_dom.getElementsByTagName('melee') | |
1763 self.melee = node_list[0] | |
1764 node_list = self.master_dom.getElementsByTagName('ranged') | |
1765 self.ranged = node_list[0] | |
1766 self.refresh_weapons() # this causes self.weapons to be loaded. | |
1767 | |
1768 #a 1.5012 this whole if clause. | |
1769 if self.updateFootNotes == True: | |
1770 self.updateFootNotes = False | |
1771 name = self.root.general.charName | |
1772 self.html_str += "</table>" | |
1773 self.html_str += "</body> </html> " | |
1774 masterFrame = self.root.frame | |
1775 | |
1776 title = name+"'s weapons' update to have footnotes" | |
1777 fnFrame = wx.Frame(masterFrame, -1, title) | |
1778 fnFrame.panel = wx.html.HtmlWindow(fnFrame,-1) | |
1779 fnFrame.panel.SetPage(self.html_str) | |
1780 fnFrame.Show() | |
1781 | |
1782 #weaponsH = self.master_dom.getElementsByTagName('attacks') | |
1783 #mark7 | |
1784 | |
1785 #a 1.9001 this whole method | |
1786 def refreshMRdata(self): # refresh the data in the melee/ranged section | |
1787 # of the attack chart. | |
1788 # count backwards, maintains context despite "removes" | |
1789 for i in range(len(self.mrFrame)-1,-1,-1): #a 1.9001 | |
1790 x = self.mrFrame[i] | |
1791 if x == None: | |
1792 x.refreshMRdata() #a 1.9001 | |
1793 else: | |
1794 self.mrFrame.remove(x) | |
1795 | |
1796 def refresh_weapons(self): | |
1797 self.weapons = {} | |
1798 | |
1799 tree = self.tree | |
1800 icons = self.tree.icons | |
1801 tree.CollapseAndReset(self.mytree_node) | |
1802 node_list = self.master_dom.getElementsByTagName('weapon') | |
1803 for n in node_list: | |
1804 name = n.getAttribute('name') | |
1805 fn = safeGetAttr(n,'fn') #a 1.5012 can be removed when | |
1806 #a 1.5012 confident all characters in the world have footnotes. | |
1807 #if self.updateFootNotes: | |
1808 if fn == None:#a 1.5012 | |
1809 self.updateFootNotes=True | |
1810 self.updateFootN(n) #a 1.5012 | |
1811 new_tree_node = tree.AppendItem( | |
1812 self.mytree_node,name,icons['sword'],icons['sword']) | |
1813 tree.SetPyData(new_tree_node,self) | |
1814 self.weapons[name]=n | |
1815 | |
1816 def updateFootN(self,n):#a 1.5012 this whole function | |
1817 if not self.temp_dom: | |
1818 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+"dnd3eweapons.xml","r") | |
1819 #tmp = open("c:\clh\codeSamples\sample1.xml","r") #a (debug) 1.5012 | |
1820 self.temp_dom = xml.dom.minidom.parse(tmp) | |
1821 | |
1822 #self.temp_dom = parseXml_with_dlg(self,tmp.read()) | |
1823 self.temp_dom = self.temp_dom._get_firstChild() | |
1824 tmp.close() | |
1825 nameF = n.getAttribute('name') | |
1826 w_list = self.temp_dom.getElementsByTagName('weapon') | |
1827 found = False | |
1828 for w in w_list: | |
1829 if nameF == w.getAttribute('name'): | |
1830 found = True | |
1831 fnN = safeGetAttr(n,'fn') | |
1832 if fnN == None or fnN == 'None': | |
1833 fnW = w.getAttribute('fn') | |
1834 #print "weapon",nameF,"footnotes are updated to",fnW | |
1835 self.html_str += ("<tr ALIGN='center'><td>"+nameF+"</td>"+ | |
1836 "<td>"+fnW+"</td></tr>\n") | |
1837 n.setAttribute('fn',fnW) | |
1838 break | |
1839 if not found: | |
1840 self.html_str += ("<tr ALIGN='center'><td>"+nameF+" - Custom "+ | |
1841 "Weapon, research "+ | |
1842 "and update manually; setting footnote to indicate custom</td>"+ | |
1843 "<td>"+'X'+"</td></tr>\n") | |
1844 n.setAttribute('fn','X') | |
1845 | |
1846 | |
1847 def get_mod(self,type='m'): | |
1848 (base, base2, base3, base4, base5, base6, stat_mod, misc) \ | |
1849 = self.get_attack_data(type) | |
1850 return int(base + misc + int(stat_mod)) | |
1851 | |
1852 def get_attack_data(self,type='m'): | |
1853 if type=='m' or type=='0': | |
1854 stat = 'Str' #m was dnd_globals["stats"]['Str'] 1.5002 | |
1855 temp = self.melee | |
1856 else: | |
1857 stat = 'Dex' #m was dnd_globals["stats"]['Dex'] 1.5002 | |
1858 temp = self.ranged | |
1859 stat_mod = -7 | |
1860 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002 | |
1861 #print "Big test - stat_mod",stat_mod #a (debug) 1.6000 | |
1862 base = int(temp.getAttribute('base')) | |
1863 base2 = int(temp.getAttribute('second')) | |
1864 base3 = int(temp.getAttribute('third')) | |
1865 base4 = int(temp.getAttribute('forth')) | |
1866 base5 = int(temp.getAttribute('fifth')) | |
1867 base6 = int(temp.getAttribute('sixth')) | |
1868 misc = int(temp.getAttribute('misc')) | |
1869 return (base, base2, base3, base4, base5, base6, stat_mod ,misc) | |
1870 | |
1871 def on_rclick(self,evt): | |
1872 item = self.tree.GetSelection() | |
1873 | |
1874 name = self.tree.GetItemText(item) | |
1875 if item == self.mytree_node: | |
1876 #print "bail due to FUD" | |
1877 return #a 1.6015 | |
1878 #dnd3e_char_child.on_ldclick(self,evt)#d 1.6015 | |
1879 #self.frame.add_panel(self.get_design_panel(self.frame.note)) | |
1880 else: | |
1881 #print "entering attack phase" | |
1882 mod = int(self.weapons[name].getAttribute('mod')) | |
1883 wepMod = mod #a 1.5008 | |
1884 footNotes = safeGetAttr(self.weapons[name],'fn','') | |
1885 cat = self.weapons[name].getAttribute('category') #a1.6001 | |
1886 result = split(cat,"-",2) #a 1.6001 | |
1887 if len(result) < 2: #a 1.6021 this if & else | |
1888 print "warning: 1.6002 unable to interpret weapon category" | |
1889 print "format 'type weapon-[Range|Melee]', probably missing" | |
1890 print "the hyphen. Assuming Melee" | |
1891 print "weapon name: ",name | |
1892 tres="Melee" | |
1893 else: | |
1894 tres=result[1] | |
1895 #print "print FootNotes,tres",footNotes,tres | |
1896 if tres == 'Melee': #a 1.6001 #m 1.6022 use of tres here and... | |
1897 #if self.weapons[name].getAttribute('range') == '0':#d 1.6001 | |
1898 rangeOrMelee = 'm' #a 1.5008 code demote for next comment block | |
1899 elif tres == 'Ranged': #m 1.6001 (was just else) #m 1.6022 here | |
1900 rangeOrMelee = 'r' #a 1.5008 | |
1901 else:#a 1.6001 add this whole else clause. | |
1902 print "warning: 1.6001 unable to interpret weapon category" | |
1903 print "treating weapon as Melee, please correct xml" | |
1904 print "weapon name:",name | |
1905 rangeOrMelee ='m' | |
1906 mod = mod + self.get_mod(rangeOrMelee) #a 1.5008 | |
1907 chat = self.chat | |
1908 dmg = self.weapons[name].getAttribute('damage') | |
1909 | |
1910 #a 1.6003 start code fix instance a | |
1911 result = split(dmg,"/",2) | |
1912 dmg = result[0] | |
1913 #print "1.6003 check:dmg",dmg,";result",result | |
1914 #o currently, only picking out dmg; rest are simply ignored. | |
1915 #o May be usefull | |
1916 #o later for two weapon attack correction. | |
1917 #a 1.6003 end code fix instance a | |
1918 | |
1919 monkLvl = self.root.classes.get_class_lvl('Monk') # a 1.5002 | |
1920 #print "monkLvl",monkLvl #a (debug) 1.5002 | |
1921 # monkLvl = dnd_globals["class"]["lvl"] #d 1.5002 | |
1922 if dmg == "Monk Med": | |
1923 if monkLvl == None: #a 1.5009 | |
1924 txt = 'Attempting to use monk attack, but has no monk ' | |
1925 txt += 'levels, please choose a different attack.' | |
1926 chat.ParsePost( txt, True, True ) #a 1.5009 | |
1927 return #a 1.5009 | |
1928 else: #a 1.5009 | |
1929 lvl=int(monkLvl) | |
1930 if lvl <= 3: #m 1.6022 reversed the order of checks. | |
1931 dmg = "1d6" | |
1932 elif lvl <= 7: | |
1933 dmg = "1d8" | |
1934 elif lvl <= 11: | |
1935 dmg = "1d10" | |
1936 elif lvl <= 15: | |
1937 dmg = "2d6" | |
1938 elif lvl <= 19: | |
1939 dmg = "2d8" | |
1940 elif lvl <= 20: | |
1941 dmg = "2d10" | |
1942 if dmg == "Monk Small": | |
1943 if monkLvl == None: #a 1.5009 | |
1944 txt = 'Attempting to use monk attack, but has no monk ' | |
1945 txt += 'levels, please choose a different attack.' | |
1946 chat.ParsePost( txt, True, True ) #a 1.5009 | |
1947 return #a 1.5009 | |
1948 else: #a 1.5009 | |
1949 lvl=int(monkLvl) | |
1950 if lvl <= 3: #m 1.6022 reversed the order of the checks | |
1951 dmg = "1d4" | |
1952 elif lvl <= 7: | |
1953 dmg = "1d6" | |
1954 elif lvl <= 11: | |
1955 dmg = "1d8" | |
1956 elif lvl <= 15: | |
1957 dmg = "1d10" | |
1958 elif lvl <= 20: | |
1959 dmg = "2d6" | |
1960 flu = '' | |
1961 #print "adjusted weapon damage is:",dmg | |
1962 #o 1.5007 str bow | |
1963 #o 1.5011 start looking about here str dam bonus missed for thrown? | |
1964 #o 1.5012 start looking about here str penalty missed for bow/sling? | |
1965 #o 1.5013 off-hand attacks.? dam and all affects? | |
1966 str_mod = self.root.abilities.get_mod('Str') #a 1.5007,11,12,13 | |
1967 if rangeOrMelee == 'r': #a 1.5008 | |
1968 #if off_hand == True then stat_mod = stat_mod/2 #o 1.5013 | |
1969 #c 1.5007 ranged weapons normally get no str mod | |
1970 if find(footNotes,'b') > -1:#a 1.5012 if it's a bow | |
1971 if str_mod >= 0: #a 1.5012 never a str bonus | |
1972 str_mod = 0 #a 1.5012 penalty, | |
1973 else: #a 1.5012 if appropriate | |
1974 str_mod = 0 | |
1975 # c 1.5007 (must adjust for str bows later and thown weapons) | |
1976 #o 1.5007 include + for str bows | |
1977 #o 1.5012 include any str penalty for bows/slings. | |
1978 mod2 = "" #a 1.5007,11-13 | |
1979 if str_mod >= 0: #1.6 tidy up code. | |
1980 mod2 = "+" #1.6 tidy up code. | |
1981 aStrengthMod = mod2 + str(str_mod) #a 1.5008 applicable strength mod | |
1982 | |
1983 #if name == "Flurry of Blows(Monk Med)": #d 1.6012 | |
1984 if find(name ,"Flurry of Blows") > -1: #a 1.6012 | |
1985 flu = '-2' | |
1986 | |
1987 (base, base2, base3, base4, base5, base6, stat_mod, misc)\ | |
1988 = self.get_attack_data(rangeOrMelee) #a 1.5008 | |
1989 self.sendRoll(base ,stat_mod,misc,wepMod,name,flu,dmg, | |
1990 aStrengthMod,'',True,rollAnyWay=True) | |
1991 if flu != '': | |
1992 self.sendRoll(base ,stat_mod,misc,wepMod,name,flu,dmg, | |
1993 aStrengthMod) #a 1.6021 | |
1994 | |
1995 self.sendRoll(base2,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1996 self.sendRoll(base3,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1997 self.sendRoll(base4,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1998 self.sendRoll(base5,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1999 self.sendRoll(base6,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
2000 | |
2001 | |
2002 def sendRoll(self,base,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod, | |
2003 spacer="",pname=False,rollAnyWay=False): | |
2004 if base != 0 or rollAnyWay: | |
2005 base = base + int(stat_mod) + misc + wepMod #m 1.5008 | |
2006 if base >= 0: | |
2007 mod1 = "+" | |
2008 else: | |
2009 mod1 = "" | |
2010 txt = '%s ' % (spacer) | |
2011 txt += '%s Attack Roll: <b>[1d20%s%s%s]</b>' % (name, mod1, base, flu) | |
2012 txt += ' ===> Damage: <b>[%s%s]</b>' % (dmg, aStrengthMod) | |
2013 self.chat.ParsePost( txt, True, True ) | |
2014 | |
2015 def get_design_panel(self,parent): | |
2016 wnd = outline_panel(parent,self,attack_panel,"Attacks") | |
2017 wnd.title = "Attacks" | |
2018 return wnd | |
2019 | |
2020 def tohtml(self): | |
2021 melee = self.get_attack_data('m') | |
2022 ranged = self.get_attack_data('r') | |
2023 html_str = ("""<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 >"""+ | |
2024 "<th>Attack</th><th>Total</th><th >Base</th>"+ | |
2025 "<th>Abil</th><th>Misc</th></tr>") | |
2026 html_str += "<tr ALIGN='center' ><th >Melee:</th>" | |
2027 html_str += "<td>"+str(melee[0]+melee[1]+melee[2])+"</td>" | |
2028 html_str += "<td>"+str(melee[0])+"</td>" | |
2029 html_str += "<td>"+str(melee[1])+"</td>" | |
2030 html_str += "<td>"+str(melee[2])+"</td></tr>" | |
2031 | |
2032 html_str += "<tr ALIGN='center' ><th >Ranged:</th>" | |
2033 html_str += "<td>"+str(ranged[0]+ranged[1]+ranged[2])+"</td>" | |
2034 html_str += "<td>"+str(ranged[0])+"</td>" | |
2035 html_str += "<td>"+str(ranged[1])+"</td>" | |
2036 html_str += "<td>"+str(ranged[2])+"</td></tr></table>" | |
2037 | |
2038 n_list = self.master_dom.getElementsByTagName('weapon') | |
2039 for n in n_list: | |
2040 mod = n.getAttribute('mod') | |
2041 if mod >= 0: | |
2042 mod1 = "+" | |
2043 else: | |
2044 mod1 = "" | |
2045 ran = n.getAttribute('range') | |
2046 total = str(int(mod) + self.get_mod(ran)) | |
2047 html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 > | |
2048 <th colspan=2>Weapon</th> | |
2049 <th>Attack</th><th >Damage</th><th>Critical</th></tr>""" | |
2050 html_str += "<tr ALIGN='center' ><td colspan=2>" | |
2051 html_str += n.getAttribute('name')+"</td><td>"+total+"</td>" | |
2052 html_str += "<td>"+n.getAttribute('damage')+"</td><td>" | |
2053 html_str += n.getAttribute('critical')+"</td></tr>" | |
2054 html_str += """<tr BGCOLOR=#E9E9E9 ><th>Range</th><th>Weight</th> | |
2055 <th>Type</th><th>Size</th><th>Misc Mod</th></tr>""" | |
2056 html_str += "<tr ALIGN='center'><td>"+ran+"</td><td>" | |
2057 html_str += n.getAttribute('weight')+"</td>" | |
2058 html_str += "<td>"+n.getAttribute('type')+"</td><td>" | |
2059 html_str += n.getAttribute('size')+"</td>" | |
2060 html_str += '<td>%s%s</td></tr>' % (mod1, mod) | |
2061 #a 1.5012 add next two lines to pretty print footnotes. | |
2062 html_str += """<tr><th BGCOLOR=#E9E9E9 colspan=2>Footnotes:</th>""" | |
2063 html_str += "<th colspan=3>"+safeGetAttr(n,'fn','')+"</th></tr>" | |
2064 html_str += '</table>' | |
2065 return html_str | |
2066 | |
2067 class attack_grid(wx.grid.Grid): | |
2068 """grid for attacks""" | |
2069 def __init__(self, parent, handler): | |
2070 pname = handler.master_dom.setAttribute("name", 'Melee') | |
2071 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
2072 #a 1.5002 we need the functional parent, not the invoking parent. | |
2073 | |
2074 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
2075 | |
2076 self.root = getRoot(self) #a 1.9001 | |
2077 self.parent = parent | |
2078 self.handler = handler | |
2079 self.rows = (self.handler.melee,self.handler.ranged) | |
2080 self.CreateGrid(2,10) | |
2081 self.SetRowLabelSize(0) | |
2082 col_names = ['Type','base','base 2','base 3','base 4','base 5', | |
2083 'base 6','abil','misc','Total'] | |
2084 for i in range(len(col_names)): | |
2085 self.SetColLabelValue(i,col_names[i]) | |
2086 self.SetCellValue(0,0,"Melee") | |
2087 self.SetCellValue(1,0,"Ranged") | |
2088 self.refresh_data() | |
2089 self.Bind(wx.EVT_SIZE, self.on_size) | |
2090 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
2091 #print "looking for containing frame" | |
2092 | |
2093 #a 1.9001 remainder of code in this method. | |
2094 climber = parent | |
2095 nameNode = climber.GetClassName() | |
2096 while nameNode != 'wxFrame': | |
2097 climber = climber.parent | |
2098 nameNode = climber.GetClassName() | |
2099 masterFrame=climber | |
2100 masterFrame.refreshMRdata=self.refresh_data | |
2101 #print getmembers(masterFrame) | |
2102 | |
2103 handler.mrFrame.append(masterFrame) | |
2104 | |
2105 #print "masterFrame=",masterFrame | |
2106 #print "mr.Show=",masterFrame.Show() | |
2107 #print "mf.GetName",masterFrame.GetName() | |
2108 #print "mf.GetClassName",masterFrame.GetClassName() | |
2109 #print "mf.GetId",masterFrame.GetId() | |
2110 #print "mf.GetLabel",masterFrame.GetLabel() | |
2111 #print "mf.GetHandle",masterFrame.GetHandle() | |
2112 #print "mf.GetParent",masterFrame.GetParent() | |
2113 # here, GetParent consistent returns the master frame of the app. | |
2114 #print "mf.GetGParent",masterFrame.GetGrandParent() #here, always None | |
2115 #print "mf.GetTitle",masterFrame.GetTitle() | |
2116 #print "mf.IsEnabled",masterFrame.IsEnabled() | |
2117 #print "mf.IsShown",masterFrame.IsShown() | |
2118 #print "mf.IsTopLevel",masterFrame.IsTopLevel() | |
2119 #print "self.frame=",self.frame | |
2120 | |
2121 | |
2122 def on_cell_change(self,evt): | |
2123 row = evt.GetRow() | |
2124 col = evt.GetCol() | |
2125 value = self.GetCellValue(row,col) | |
2126 try: | |
2127 int(value) | |
2128 if col==1: | |
2129 self.rows[row].setAttribute('base',value) | |
2130 elif col==2: | |
2131 self.rows[row].setAttribute('second',value) | |
2132 elif col==3: | |
2133 self.rows[row].setAttribute('third',value) | |
2134 elif col==4: | |
2135 self.rows[row].setAttribute('forth',value) | |
2136 elif col==5: | |
2137 self.rows[row].setAttribute('fifth',value) | |
2138 elif col==6: | |
2139 self.rows[row].setAttribute('sixth',value) | |
2140 elif col==8: | |
2141 self.rows[row].setAttribute('misc',value) | |
2142 #print "row:",row,"value",value,self.rows[row] | |
2143 self.parent.refresh_data() | |
2144 except: | |
2145 self.SetCellValue(row,col,"0") | |
2146 | |
2147 def refresh_data(self): | |
2148 | |
2149 melee = self.handler.get_attack_data('m') | |
2150 ranged = self.handler.get_attack_data('r') | |
2151 tmelee = int(melee[0]) + int(melee[6]) + int(melee[7]) | |
2152 tranged = int(ranged[0]) + int(ranged[6]) + int(ranged[7]) | |
2153 # for i in range(0,7): #d 1.5005 | |
2154 for i in range(0,8): #a 1.5005 | |
2155 self.SetCellValue(0,i+1,str(melee[i])) | |
2156 self.SetCellValue(1,i+1,str(ranged[i])) | |
2157 self.SetCellValue(0,9,str(tmelee)) | |
2158 self.SetCellValue(1,9,str(tranged)) | |
2159 self.SetReadOnly(0,0) | |
2160 self.SetReadOnly(1,0) | |
2161 self.SetReadOnly(0,7) | |
2162 self.SetReadOnly(1,7) | |
2163 self.SetReadOnly(0,9) | |
2164 self.SetReadOnly(1,9) | |
2165 | |
2166 | |
2167 def on_size(self,evt): | |
2168 (w,h) = self.GetClientSizeTuple() | |
2169 cols = self.GetNumberCols() | |
2170 col_w = w/(cols+1) | |
2171 self.SetColSize(0,col_w*2) | |
2172 for i in range(1,cols): | |
2173 self.SetColSize(i,col_w) | |
2174 evt.Skip() | |
2175 self.Refresh() | |
2176 | |
2177 class weapon_panel(wx.Panel): | |
2178 def __init__(self, parent, handler): | |
2179 self.hparent = handler #a 1.5012 | |
2180 self.root = getRoot(self) | |
2181 | |
2182 pname = handler.master_dom.setAttribute("name", 'Weapons') | |
2183 | |
2184 wx.Panel.__init__(self, parent, -1) | |
2185 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
2186 sizer = wx.BoxSizer(wx.VERTICAL) | |
2187 sizer.Add(self.grid, 1, wx.EXPAND) | |
2188 | |
2189 sizer2 = wx.BoxSizer(wx.HORIZONTAL) | |
2190 sizer2.Add(wx.Button(self, 10, "Remove Weapon"), 0, wx.EXPAND) | |
2191 sizer2.Add(wx.Size(10,10)) | |
2192 sizer2.Add(wx.Button(self, 20, "Add Weapon"), 0, wx.EXPAND) | |
2193 | |
2194 sizer.Add(sizer2, 0, wx.EXPAND) | |
2195 sizer.Add(wx.StaticText(self, -1, "Right click a weapon's footnote to see what the footnotes mean."),0, wx.EXPAND)#a 1.5012 | |
2196 self.sizer = sizer | |
2197 self.SetSizer(self.sizer) | |
2198 self.SetAutoLayout(True) | |
2199 self.Fit() | |
2200 | |
2201 self.sizer2 = sizer2 | |
2202 #self.Bind(wx.EVT_SIZE, self.on_size) | |
2203 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
2204 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
2205 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
2206 self.grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.on_gridRclick)#a 1.5012 | |
2207 | |
2208 n_list = handler.master_dom.getElementsByTagName('weapon') | |
2209 self.n_list = n_list | |
2210 self.master_dom = handler.master_dom | |
2211 self.handler = handler | |
2212 #trash=input("weapon panel init colnames") | |
2213 self.colAttr = ['name','damage','mod','critical','type','weight', | |
2214 'range','size','Total','fn', 'comment'] #a 1.5012 | |
2215 col_names = ['Name','Damage','To hit\nmod','Critical','Type','Weight', | |
2216 'Range','Size','Total','Foot\nnotes','Comment'] #a 1.5012 | |
2217 gridColCount=len(col_names)#a 1.5012 | |
2218 self.grid.CreateGrid(len(n_list),gridColCount,1) #a 1.5012 | |
2219 #self.grid.CreateGrid(len(n_list),9,1) #d 1.5012 | |
2220 self.grid.SetRowLabelSize(0) | |
2221 #col_names = ['Name','damage','mod','critical','type','weight','range', 'size','Total'] #d 1.5012 | |
2222 #for i in range(len(col_names)): #d 1.5012 | |
2223 for i in range(gridColCount): #a 1.5012 | |
2224 self.grid.SetColLabelValue(i,col_names[i]) | |
2225 self.refresh_data() | |
2226 self.temp_dom = None | |
2227 | |
2228 | |
2229 #mark4 | |
2230 #a 1.5012 add entire method. | |
2231 def on_gridRclick(self,evt): | |
2232 #print "weapon_panel, on_rclick: self,evt",self,evt | |
2233 row = evt.GetRow() | |
2234 col = evt.GetCol() | |
2235 value = self.grid.GetCellValue(row,col) | |
2236 #print "wp, on rclick,grid row,col,value",row,col,value | |
2237 if col == 9 and value != 'None': | |
2238 n = self.n_list[row] | |
2239 name = n.getAttribute('name') | |
2240 #print "we want a panel!" | |
2241 handler = self.hparent | |
2242 #print "handler:",handler | |
2243 # A handler is a node, and nodes have a reference to | |
2244 # the master frame | |
2245 masterFrame = handler.frame | |
2246 #print "masterFrame:",masterFrame | |
2247 title = name+"'s Special Weapon Characteristics" | |
2248 fnFrame = wx.Frame(masterFrame, -1, title) | |
2249 fnFrame.panel = wx.html.HtmlWindow(fnFrame,-1) | |
2250 if not self.temp_dom: | |
2251 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+ | |
2252 "dnd3eweapons.xml","r") | |
2253 #tmp = open("c:\clh\codeSamples\sample1.xml","r") | |
2254 xml_dom = parseXml_with_dlg(self,tmp.read()) | |
2255 xml_dom = xml_dom._get_firstChild() | |
2256 tmp.close() | |
2257 self.temp_dom = xml_dom | |
2258 f_list = self.temp_dom.getElementsByTagName('f') # the footnotes | |
2259 #print "weapon_panel - on_rclick f_list",f_list#a 1.6 | |
2260 n = self.n_list[row] | |
2261 name = n.getAttribute('name') | |
2262 footnotes = n.getAttribute('fn') | |
2263 html_str = "<html><body>" | |
2264 html_str += """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 > | |
2265 <th width='10%'>Note</th><th>Description</th></tr>\n""" | |
2266 #print "rclick,name,fn",name,footnotes | |
2267 if footnotes == "": | |
2268 html_str += "<tr ALIGN='center'><td></td>" | |
2269 html_str += " <td>This weapon has no footnotes</td></tr>" | |
2270 for i in range(len(footnotes)): | |
2271 aNote=footnotes[i] | |
2272 found=False | |
2273 for f in f_list: | |
2274 if f.getAttribute('mark') == aNote: | |
2275 found=True | |
2276 text=f.getAttribute('txt') | |
2277 html_str += ("<tr ALIGN='center'><td>"+aNote+"</td>"+ | |
2278 "<td>"+text+"</td></tr>\n") | |
2279 if not found: | |
2280 html_str += ("<tr ALIGN='center'><td>"+aNote+"</td>"+ | |
2281 "<td>is not a recognized footnote</td></tr>\n") | |
2282 | |
2283 html_str += "</table>" | |
2284 html_str += "</body> </html> " | |
2285 | |
2286 #print html_str | |
2287 fnFrame.panel.SetPage(html_str) | |
2288 fnFrame.Show() | |
2289 return | |
2290 pass | |
2291 | |
2292 | |
2293 | |
2294 def on_cell_change(self,evt): | |
2295 row = evt.GetRow() | |
2296 col = evt.GetCol() | |
2297 value = self.grid.GetCellValue(row,col) | |
2298 if col == 2 and not int(value): # special case for mod, demoted | |
2299 value = "0" #a 5.012 demoted | |
2300 self.n_list[row].setAttribute('mod',value) # a 5.012 demoted | |
2301 if not (col == 9 and value == "None" and | |
2302 self.n_list[row].getAttribute('fn') == "None" | |
2303 ): #a 5.012 special case for footnotes | |
2304 self.n_list[row].setAttribute(self.colAttr[col],value)#a 5.012 | |
2305 #print "cell change",row,col,value | |
2306 #if col == 0:#d 5.012 use of colAttr removed need for this. | |
2307 # self.n_list[row].setAttribute('name',value) #d 5.012 | |
2308 #elif col == 2: #d 5.012 | |
2309 # try:#d 5.012 simplifying... remove this block. | |
2310 # int(value) | |
2311 # self.n_list[row].setAttribute('mod',value) | |
2312 # #self.refresh_row(row) #d 5.012 did nothing. | |
2313 # except: | |
2314 # value = "0" | |
2315 # self.n_list[row].setAttribute('mod',value) | |
2316 #else: #d 5.012 demoted self.n set. | |
2317 # self.n_list[row].setAttribute(self.grid.GetColLabelValue(col),value) | |
2318 | |
2319 | |
2320 def refresh_row(self,i): | |
2321 n = self.n_list[i] | |
2322 fn = n.getAttribute('fn') | |
2323 #print "fn=",fn | |
2324 name = n.getAttribute('name') | |
2325 mod = n.getAttribute('mod') | |
2326 ran = n.getAttribute('range') | |
2327 total = str(int(mod) + self.handler.get_mod(ran)) | |
2328 self.grid.SetCellValue(i,0,name) | |
2329 self.grid.SetCellValue(i,1,n.getAttribute('damage')) | |
2330 self.grid.SetCellValue(i,2,mod) | |
2331 self.grid.SetCellValue(i,3,n.getAttribute('critical')) | |
2332 self.grid.SetCellValue(i,4,n.getAttribute('type')) | |
2333 self.grid.SetCellValue(i,5,n.getAttribute('weight')) | |
2334 self.grid.SetCellValue(i,6,ran) | |
2335 self.grid.SetCellValue(i,7,n.getAttribute('size') ) | |
2336 self.grid.SetCellValue(i,8,total) | |
2337 self.grid.SetCellValue(i,9,safeGetAttr(n,'fn','None')) #a 1.5012 | |
2338 self.grid.SetCellValue(i,10,safeGetAttr(n,'comment','')) #a 1.5012 | |
2339 #fn=safeGetAttr(n,'fn','None') #a (debug) 1.5012 | |
2340 #print "fn ",fn,"<" #a (debug) 1.5012 | |
2341 #o 1.5012 original damage vs what someone has changed it to. | |
2342 | |
2343 self.grid.SetReadOnly(i,8) | |
2344 | |
2345 def on_remove(self,evt): #o 1.6011 correcting wrongful deletion | |
2346 rows = self.grid.GetNumberRows() | |
2347 #for i in range(rows): #d 1.6011 do it backwards, | |
2348 for i in range(rows-1,-1,-1): #a 1.6011 or you lose context | |
2349 if self.grid.IsInSelection(i,0): | |
2350 self.grid.DeleteRows(i) | |
2351 self.master_dom.removeChild(self.n_list[i]) | |
2352 self.n_list = self.master_dom.getElementsByTagName('weapon') | |
2353 self.handler.refresh_weapons() | |
2354 | |
2355 def on_add(self,evt): | |
2356 if not self.temp_dom: | |
2357 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+"dnd3eweapons.xml","r") | |
2358 #tmp = open("c:\clh\codeSamples\sample1.xml","r") #a (debug) 1.5012 | |
2359 xml_dom = parseXml_with_dlg(self,tmp.read()) | |
2360 xml_dom = xml_dom._get_firstChild() | |
2361 tmp.close() | |
2362 self.temp_dom = xml_dom | |
2363 f_list = self.temp_dom.getElementsByTagName('weapon') | |
2364 opts = [] | |
2365 #print "weapon_panel - on_add f_list",f_list#a 1.6 | |
2366 for f in f_list: | |
2367 opts.append(f.getAttribute('name')) | |
2368 dlg = wx.SingleChoiceDialog(self,'Choose Weapon','Weapon List',opts) | |
2369 if dlg.ShowModal() == wx.ID_OK: | |
2370 i = dlg.GetSelection() | |
2371 #print f_list[i] # DOM Element: weapon. | |
2372 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False)) | |
2373 #print self.grid.AppendRows # a bound method of wxGrid | |
2374 self.grid.AppendRows(1) | |
2375 self.n_list = self.master_dom.getElementsByTagName('weapon') | |
2376 #print "self.n_list",self.n_list # list of DOM weapons | |
2377 self.refresh_row(self.grid.GetNumberRows()-1) | |
2378 self.handler.refresh_weapons() | |
2379 dlg.Destroy() | |
2380 | |
2381 def on_size(self,event): | |
2382 s = self.GetClientSizeTuple() | |
2383 self.grid.SetDimensions(0,0,s[0],s[1]-40) | |
2384 self.sizer.SetDimension(0,s[1]-40,s[0],25) | |
2385 self.sizer2.SetDimension(0,s[1]-15,s[0],15) | |
2386 (w,h) = self.grid.GetClientSizeTuple() | |
2387 cols = self.grid.GetNumberCols() | |
2388 col_w = w/(cols+1) | |
2389 self.grid.SetColSize(0,col_w*2) | |
2390 for i in range(1,cols): | |
2391 self.grid.SetColSize(i,col_w) | |
2392 | |
2393 def refresh_data(self): | |
2394 | |
2395 for i in range(len(self.n_list)): | |
2396 self.refresh_row(i) | |
2397 | |
2398 | |
2399 class attack_panel(wx.Panel): | |
2400 def __init__(self, parent, handler): | |
2401 pname = handler.master_dom.setAttribute("name", 'Melee') | |
2402 self.parent = parent #a 1.9001 | |
2403 | |
2404 wx.Panel.__init__(self, parent, -1) | |
2405 | |
2406 self.a_grid = attack_grid(self, handler) | |
2407 self.w_panel = weapon_panel(self, handler) | |
2408 self.sizer = wx.BoxSizer(wx.VERTICAL) | |
2409 self.sizer.Add(self.a_grid, 1, wx.EXPAND) | |
2410 self.sizer.Add(self.w_panel, 2, wx.EXPAND) | |
2411 self.Bind(wx.EVT_SIZE, self.on_size) | |
2412 | |
2413 | |
2414 def on_size(self,event): | |
2415 s = self.GetClientSizeTuple() | |
2416 self.sizer.SetDimension(0,0,s[0],s[1]) | |
2417 | |
2418 def refresh_data(self): | |
2419 | |
2420 self.w_panel.refresh_data() | |
2421 self.a_grid.refresh_data() | |
2422 | |
2423 | |
2424 class dnd3earmor(combat_char_child): | |
2425 """ Node Handler for ac. This handler will be | |
2426 created by dnd3echar_handler. | |
2427 """ | |
2428 def __init__(self,xml_dom,tree_node,parent): | |
2429 combat_char_child.__init__(self,xml_dom,tree_node,parent) | |
2430 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
2431 self.root = getRoot(self) #a 1.5002 | |
2432 self.root.ac = self #a 1.6009 | |
2433 | |
2434 def get_spell_failure(self): | |
2435 return self.get_total('spellfailure') | |
2436 | |
2437 def get_total_weight(self): | |
2438 return self.get_total('weight') | |
2439 | |
2440 def get_check_pen(self): | |
2441 return self.get_total('checkpenalty') | |
2442 | |
2443 def get_armor_class(self): | |
2444 ac_total = 10 | |
2445 | |
2446 ac_total += self.get_total('bonus') | |
2447 #m 1.5009 change to hardcode dex, was incorrect gv "stat" | |
2448 dex_mod = self.root.abilities.get_mod('Dex')#m 1.5009 hardcode dex | |
2449 max_dex = self.get_max_dex() | |
2450 if dex_mod < max_dex: | |
2451 ac_total += dex_mod | |
2452 else: | |
2453 ac_total += max_dex | |
2454 return ac_total | |
2455 | |
2456 def get_max_dex(self): | |
2457 armor_list = self.master_dom.getElementsByTagName('armor') | |
2458 dex = 10 | |
2459 for a in armor_list: | |
2460 temp = int(a.getAttribute("maxdex")) | |
2461 if temp < dex: | |
2462 dex = temp | |
2463 return dex | |
2464 | |
2465 def get_total(self,attr): | |
2466 armor_list = self.master_dom.getElementsByTagName('armor') | |
2467 total = 0 | |
2468 for a in armor_list: | |
2469 total += int(a.getAttribute(attr)) | |
2470 return total | |
2471 | |
2472 def get_design_panel(self,parent): | |
2473 wnd = outline_panel(parent,self,ac_panel,"Armor") | |
2474 wnd.title = "Armor" | |
2475 return wnd | |
2476 | |
2477 def on_rclick( self, evt ): | |
2478 ac = self.get_armor_class() | |
2479 fac = (int(ac)-(self.root.abilities.get_mod('Dex'))) | |
2480 | |
2481 txt = '((AC: %s Normal, %s Flatfoot))' % ( ac, fac ) #a 1.5002 | |
2482 self.chat.ParsePost( txt, True, True ) | |
2483 | |
2484 def tohtml(self): | |
2485 html_str = """<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 > | |
2486 <th>AC</th><th>Check Penalty</th><th >Spell Failure</th> | |
2487 <th>Max Dex</th><th>Total Weight</th></tr>""" | |
2488 html_str += "<tr ALIGN='center' >" | |
2489 html_str += "<td>"+str(self.get_armor_class())+"</td>" | |
2490 html_str += "<td>"+str(self.get_check_pen())+"</td>" | |
2491 html_str += "<td>"+str(self.get_spell_failure())+"</td>" | |
2492 html_str += "<td>"+str(self.get_max_dex())+"</td>" | |
2493 html_str += "<td>"+str(self.get_total_weight())+"</td></tr></table>" | |
2494 n_list = self.master_dom._get_childNodes() | |
2495 for n in n_list: | |
2496 html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 > | |
2497 <th colspan=3>Armor</th><th>Type</th><th >Bonus</th></tr>""" | |
2498 html_str += "<tr ALIGN='center' >" | |
2499 html_str += "<td colspan=3>"+n.getAttribute('name')+"</td>" | |
2500 html_str += "<td>"+n.getAttribute('type')+"</td>" | |
2501 html_str += "<td>"+n.getAttribute('bonus')+"</td></tr>" | |
2502 html_str += """<tr BGCOLOR=#E9E9E9 >""" | |
2503 html_str += "<th>Check Penalty</th><th>Spell Failure</th>" | |
2504 html_str += "<th>Max Dex</th><th>Speed</th><th>Weight</th></tr>" | |
2505 html_str += "<tr ALIGN='center'>" | |
2506 html_str += "<td>"+n.getAttribute('checkpenalty')+"</td>" | |
2507 html_str += "<td>"+n.getAttribute('spellfailure')+"</td>" | |
2508 html_str += "<td>"+n.getAttribute('maxdex')+"</td>" | |
2509 html_str += "<td>"+n.getAttribute('speed')+"</td>" | |
2510 html_str += "<td>"+n.getAttribute('weight')+"</td></tr></table>" | |
2511 return html_str | |
2512 | |
2513 | |
2514 class ac_panel(wx.Panel): | |
2515 def __init__(self, parent, handler): | |
2516 pname = handler.master_dom.setAttribute("name", 'Armor') | |
2517 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
2518 #a 1.5002 we need the functional parent, not the invoking parent. | |
2519 | |
2520 wx.Panel.__init__(self, parent, -1) | |
2521 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
2522 sizer = wx.BoxSizer(wx.VERTICAL) | |
2523 sizer.Add(self.grid, 1, wx.EXPAND) | |
2524 | |
2525 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
2526 sizer1.Add(wx.Button(self, 10, "Remove Armor"), 1, wx.EXPAND) | |
2527 sizer1.Add(wx.Size(10,10)) | |
2528 sizer1.Add(wx.Button(self, 20, "Add Armor"), 1, wx.EXPAND) | |
2529 | |
2530 sizer.Add(sizer1, 0, wx.EXPAND) | |
2531 | |
2532 self.sizer = sizer | |
2533 self.SetSizer(self.sizer) | |
2534 self.SetAutoLayout(True) | |
2535 self.Fit() | |
2536 | |
2537 #self.Bind(wx.EVT_SIZE, self.on_size) | |
2538 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
2539 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
2540 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
2541 self.master_dom = handler.master_dom | |
2542 n_list = handler.master_dom._get_childNodes() | |
2543 self.n_list = n_list | |
2544 col_names = ['Armor','bonus','maxdex','cp','sf','weight','speed','type'] | |
2545 self.grid.CreateGrid(len(n_list),len(col_names),1) | |
2546 self.grid.SetRowLabelSize(0) | |
2547 for i in range(len(col_names)): | |
2548 self.grid.SetColLabelValue(i,col_names[i]) | |
2549 self.atts =['name','bonus','maxdex','checkpenalty', | |
2550 'spellfailure','weight','speed','type'] | |
2551 for i in range(len(n_list)): | |
2552 self.refresh_row(i) | |
2553 self.temp_dom = None | |
2554 | |
2555 | |
2556 def on_cell_change(self,evt): | |
2557 row = evt.GetRow() | |
2558 col = evt.GetCol() | |
2559 value = self.grid.GetCellValue(row,col) | |
2560 if col >= 1 and col <= 5: | |
2561 try: | |
2562 int(value) | |
2563 self.n_list[row].setAttribute(self.atts[col],value) | |
2564 except: | |
2565 self.grid.SetCellValue(row,col,"0") | |
2566 else: | |
2567 self.n_list[row].setAttribute(self.atts[col],value) | |
2568 | |
2569 def refresh_row(self,i): | |
2570 n = self.n_list[i] | |
2571 | |
2572 for y in range(len(self.atts)): | |
2573 self.grid.SetCellValue(i,y,n.getAttribute(self.atts[y])) | |
2574 | |
2575 def on_remove(self,evt): | |
2576 rows = self.grid.GetNumberRows() | |
2577 for i in range(rows): | |
2578 if self.grid.IsInSelection(i,0): | |
2579 self.grid.DeleteRows(i) | |
2580 self.master_dom.removeChild(self.n_list[i]) | |
2581 | |
2582 def on_add(self,evt): | |
2583 if not self.temp_dom: | |
2584 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+"dnd3earmor.xml","r") | |
2585 xml_dom = parseXml_with_dlg(self,tmp.read()) | |
2586 xml_dom = xml_dom._get_firstChild() | |
2587 tmp.close() | |
2588 self.temp_dom = xml_dom | |
2589 f_list = self.temp_dom.getElementsByTagName('armor') | |
2590 opts = [] | |
2591 for f in f_list: | |
2592 opts.append(f.getAttribute('name')) | |
2593 dlg = wx.SingleChoiceDialog(self,'Choose Armor:','Armor List',opts) | |
2594 if dlg.ShowModal() == wx.ID_OK: | |
2595 i = dlg.GetSelection() | |
2596 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False)) | |
2597 self.grid.AppendRows(1) | |
2598 self.refresh_row(self.grid.GetNumberRows()-1) | |
2599 dlg.Destroy() | |
2600 | |
2601 def on_size(self,event): | |
2602 s = self.GetClientSizeTuple() | |
2603 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
2604 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
2605 (w,h) = self.grid.GetClientSizeTuple() | |
2606 cols = self.grid.GetNumberCols() | |
2607 col_w = w/(cols+2) | |
2608 self.grid.SetColSize(0,col_w*3) | |
2609 for i in range(1,cols): | |
2610 self.grid.SetColSize(i,col_w) | |
2611 | |
2612 | |
2613 class dnd3esnp(dnd3e_char_child): | |
2614 """ Node Handler for power points. This handler will be | |
2615 created by dnd3echar_handler. | |
2616 """ | |
2617 def __init__(self,xml_dom,tree_node,parent): | |
2618 node_handler.__init__(self,xml_dom,tree_node) | |
2619 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
2620 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
2621 | |
2622 | |
2623 self.frame = open_rpg.get_component('frame') | |
2624 self.child_handlers = {} | |
2625 self.new_child_handler('spells','Spells',dnd3espells,'book') | |
2626 self.new_child_handler('divine','Divine Spells',dnd3edivine,'book') | |
2627 self.new_child_handler('powers','Powers',dnd3epowers,'book') | |
2628 self.new_child_handler('pp','Power Points',dnd3epp,'gear') | |
2629 self.myeditor = None | |
2630 | |
2631 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
2632 node_list = self.master_dom.getElementsByTagName(tag) | |
2633 tree = self.tree | |
2634 i = self.tree.icons[icon] | |
2635 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
2636 handler = handler_class(node_list[0],new_tree_node,self) | |
2637 tree.SetPyData(new_tree_node,handler) | |
2638 self.child_handlers[tag] = handler | |
2639 | |
2640 def get_design_panel(self,parent): | |
2641 return tabbed_panel(parent,self,1) | |
2642 | |
2643 def get_use_panel(self,parent): | |
2644 return tabbed_panel(parent,self,2) | |
2645 | |
2646 # def set_char_pp(self,attr,evl): #d 1.5002 doesn't seem to be used, but | |
2647 # dnd_globals["pp"][attr] = evl #d 1.5002 uses dnd_globals, so tossing. | |
2648 | |
2649 | |
2650 # def get_char_pp( self, attr ): #d 1.5002 doesn't seem to be used, but | |
2651 # return dnd_globals["pp"][attr] #d 1.5002 doesn't seem to be used, but | |
2652 | |
2653 class snp_char_child(node_handler): | |
2654 """ Node Handler for skill. This handler will be | |
2655 created by dnd3echar_handler. | |
2656 """ | |
2657 def __init__(self,xml_dom,tree_node,parent): | |
2658 node_handler.__init__(self,xml_dom,tree_node) | |
2659 self.char_hander = parent | |
2660 self.drag = False | |
2661 self.frame = open_rpg.get_component('frame') | |
2662 self.myeditor = None | |
2663 | |
2664 | |
2665 | |
2666 def on_drop(self,evt): | |
2667 pass | |
2668 | |
2669 def on_rclick(self,evt): | |
2670 pass | |
2671 | |
2672 def on_ldclick(self,evt): | |
2673 return | |
2674 | |
2675 def on_html(self,evt): | |
2676 html_str = self.tohtml() | |
2677 wnd = http_html_window(self.frame.note,-1) | |
2678 wnd.title = self.master_dom.getAttribute('name') | |
2679 self.frame.add_panel(wnd) | |
2680 wnd.SetPage(html_str) | |
2681 | |
2682 def get_design_panel(self,parent): | |
2683 pass | |
2684 | |
2685 def get_use_panel(self,parent): | |
2686 return self.get_design_panel(parent) | |
2687 | |
2688 def delete(self): | |
2689 pass | |
2690 | |
2691 | |
2692 class dnd3espells(snp_char_child): | |
2693 """ Node Handler for classes. This handler will be | |
2694 created by dnd3echar_handler. | |
2695 """ | |
2696 def __init__(self,xml_dom,tree_node,parent): | |
2697 snp_char_child.__init__(self,xml_dom,tree_node,parent) | |
2698 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
2699 self.root = getRoot(self) #a 1.5002 | |
2700 self.root.spells = self #a 1.6009 | |
2701 | |
2702 | |
2703 node_list = self.master_dom.getElementsByTagName( 'spell' ) | |
2704 self.spells = {} | |
2705 tree = self.tree | |
2706 icons = self.tree.icons | |
2707 for n in node_list: | |
2708 name = n.getAttribute('name') | |
2709 self.spells[ name ] = n | |
2710 new_tree_node = tree.AppendItem( self.mytree_node, name, icons['gear'], icons['gear'] ) | |
2711 tree.SetPyData( new_tree_node, self ) | |
2712 | |
2713 def on_rclick( self, evt ): | |
2714 item = self.tree.GetSelection() | |
2715 name = self.tree.GetItemText( item ) | |
2716 if item == self.mytree_node: | |
2717 dnd3e_char_child.on_ldclick( self, evt ) | |
2718 else: | |
2719 level = self.spells[ name ].getAttribute( 'level' ) | |
2720 descr = self.spells[ name ].getAttribute( 'desc' ) | |
2721 use = self.spells[ name ].getAttribute( 'used' ) | |
2722 memrz = self.spells[ name ].getAttribute( 'memrz' ) | |
2723 use += '+1' | |
2724 charNameL=self.root.general.charName #a 1.5002 | |
2725 left = eval( '%s - ( %s )' % ( memrz, use ) ) | |
2726 if left < 0: | |
2727 txt = '%s Tried to cast %s but has used all of them for today,' | |
2728 #txt +='"Please rest so I can cast more."' % ( dnd_globals["gen"]["Name"], name )##d 1.5002 | |
2729 txt +='"Please rest so I can cast more."' % ( charNameL, name ) #a 1.5002 | |
2730 self.chat.ParsePost( txt, True, False ) | |
2731 else: | |
2732 #txt = '%s casts %s ( level %s, "%s" )' % ( dnd_globals["gen"]["Name"], name, level, descr )#d 1.5002 | |
2733 txt = '%s casts %s ( level %s, "%s" )' % ( charNameL, name, level, descr )#a f 1.5002 | |
2734 self.chat.ParsePost( txt, True, False ) | |
2735 s = '' | |
2736 if left != 1: | |
2737 s = 's' | |
2738 #txt = '%s can cast %s %d more time%s' % ( dnd_globals["gen"]["Name"], name, left, s )#d 1.5002 | |
2739 txt = '%s can cast %s %d more time%s' % ( charNameL, name, left, s ) #a 1.5002 | |
2740 self.chat.ParsePost( txt, False, False ) | |
2741 self.spells[ name ].setAttribute( 'used', `eval( use )` ) | |
2742 | |
2743 def refresh_spells(self): | |
2744 self.spells = {} | |
2745 tree = self.tree | |
2746 icons = self.tree.icons | |
2747 tree.CollapseAndReset(self.mytree_node) | |
2748 node_list = self.master_dom.getElementsByTagName('spell') | |
2749 for n in node_list: | |
2750 name = n.getAttribute('name') | |
2751 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear']) | |
2752 tree.SetPyData(new_tree_node,self) | |
2753 self.spells[name]=n | |
2754 | |
2755 def get_design_panel(self,parent): | |
2756 wnd = outline_panel(parent,self,spells_panel,"Spells") | |
2757 wnd.title = "Spells" | |
2758 return wnd | |
2759 | |
2760 def tohtml(self): | |
2761 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Arcane Spells</th></tr><tr><td><br>" | |
2762 n_list = self.master_dom._get_childNodes() | |
2763 for n in n_list: | |
2764 html_str += "(" + n.getAttribute('level') + ") " + n.getAttribute('name')+ ", " | |
2765 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
2766 return html_str | |
2767 | |
2768 def get_char_lvl( self, attr ): | |
2769 return self.char_hander.get_char_lvl(attr) | |
2770 | |
2771 class spells_panel(wx.Panel): | |
2772 def __init__(self, parent, handler): | |
2773 pname = handler.master_dom.setAttribute("name", 'Arcane Spells') | |
2774 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
2775 #a 1.5002 in this case, we need the functional parent, not the invoking parent. | |
2776 | |
2777 wx.Panel.__init__(self, parent, -1) | |
2778 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
2779 self.handler = handler | |
2780 sizer = wx.BoxSizer(wx.VERTICAL) | |
2781 sizer.Add(self.grid, 1, wx.EXPAND) | |
2782 | |
2783 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
2784 sizer1.Add(wx.Button(self, 10, "Remove Spell"), 1, wx.EXPAND) | |
2785 sizer1.Add(wx.Size(10,10)) | |
2786 sizer1.Add(wx.Button(self, 20, "Add Spell"), 1, wx.EXPAND) | |
2787 sizer1.Add(wx.Size(10,10)) | |
2788 sizer1.Add(wx.Button(self, 30, "Refresh Spells"), 1, wx.EXPAND) | |
2789 | |
2790 sizer.Add(sizer1, 0, wx.EXPAND) | |
2791 self.sizer = sizer | |
2792 self.SetSizer(self.sizer) | |
2793 self.SetAutoLayout(True) | |
2794 self.Fit() | |
2795 | |
2796 #self.Bind(wx.EVT_SIZE, self.on_size) | |
2797 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
2798 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
2799 self.Bind(wx.EVT_BUTTON, self.on_refresh_spells, id=30) | |
2800 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
2801 n_list = handler.master_dom._get_childNodes() | |
2802 self.n_list = n_list | |
2803 self.master_dom = handler.master_dom | |
2804 self.grid.CreateGrid(len(n_list),4,1) | |
2805 self.grid.SetRowLabelSize(0) | |
2806 self.grid.SetColLabelValue(0,"No.") | |
2807 self.grid.SetColLabelValue(1,"Lvl") | |
2808 self.grid.SetColLabelValue(2,"Spell") | |
2809 self.grid.SetColLabelValue(3,"Desc") | |
2810 for i in range(len(n_list)): | |
2811 self.refresh_row(i) | |
2812 self.temp_dom = None | |
2813 | |
2814 def on_cell_change(self,evt): | |
2815 row = evt.GetRow() | |
2816 col = evt.GetCol() | |
2817 value = self.grid.GetCellValue(row,col) | |
2818 if col == 0: | |
2819 self.n_list[row].setAttribute('memrz',value) | |
2820 | |
2821 | |
2822 def refresh_row(self,i): | |
2823 spell = self.n_list[i] | |
2824 | |
2825 memrz = spell.getAttribute('memrz') | |
2826 name = spell.getAttribute('name') | |
2827 type = spell.getAttribute('desc') | |
2828 level = spell.getAttribute('level') | |
2829 self.grid.SetCellValue(i,0,memrz) | |
2830 self.grid.SetCellValue(i,2,name) | |
2831 self.grid.SetReadOnly(i,2) | |
2832 self.grid.SetCellValue(i,3,type) | |
2833 self.grid.SetReadOnly(i,3) | |
2834 self.grid.SetCellValue(i,1,level) | |
2835 self.grid.SetReadOnly(i,1) | |
2836 | |
2837 def on_remove(self,evt): | |
2838 rows = self.grid.GetNumberRows() | |
2839 for i in range(rows): | |
2840 if self.grid.IsInSelection(i,0): | |
2841 self.grid.DeleteRows(i) | |
2842 self.master_dom.removeChild(self.n_list[i]) | |
2843 | |
2844 def on_add(self,evt): | |
2845 | |
2846 if not self.temp_dom: | |
2847 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+"dnd3espells.xml","r") | |
2848 xml_dom = parseXml_with_dlg(self,tmp.read()) | |
2849 xml_dom = xml_dom._get_firstChild() | |
2850 tmp.close() | |
2851 self.temp_dom = xml_dom | |
2852 f_list = self.temp_dom.getElementsByTagName('spell') | |
2853 opts = [] | |
2854 #lvl = int(dnd3e_char_child.get_char_lvl('level')) | |
2855 #castlvl = eval('%s/2' % (lvl)) | |
2856 for f in f_list: | |
2857 spelllvl = f.getAttribute('level') | |
2858 #if spelllvl <= "1": | |
2859 # opts.append("(" + f.getAttribute('level') + ")" + f.getAttribute('name')) | |
2860 #else: | |
2861 # if eval('%d >= %s' %(castlvl, spelllvl)): | |
2862 opts.append("(" + f.getAttribute('level') + ")" + f.getAttribute('name')) | |
2863 dlg = wx.SingleChoiceDialog(self,'Choose Spell','Spells',opts) | |
2864 if dlg.ShowModal() == wx.ID_OK: | |
2865 i = dlg.GetSelection() | |
2866 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False)) | |
2867 self.grid.AppendRows(1) | |
2868 self.n_list = self.master_dom.getElementsByTagName('spell') | |
2869 self.refresh_row(self.grid.GetNumberRows()-1) | |
2870 self.handler.refresh_spells() | |
2871 dlg.Destroy() | |
2872 | |
2873 def on_refresh_spells( self, evt ): | |
2874 f_list = self.master_dom.getElementsByTagName('spell') | |
2875 | |
2876 for spell in f_list: | |
2877 spell.setAttribute( 'used', '0' ) | |
2878 | |
2879 def on_size(self,event): | |
2880 s = self.GetClientSizeTuple() | |
2881 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
2882 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
2883 (w,h) = self.grid.GetClientSizeTuple() | |
2884 cols = self.grid.GetNumberCols() | |
2885 col_w = w/(cols) | |
2886 for i in range(0,cols): | |
2887 self.grid.SetColSize(i,col_w) | |
2888 self.grid.SetColSize(0,w * 0.10) | |
2889 self.grid.SetColSize(1,w * 0.10) | |
2890 self.grid.SetColSize(2,w * 0.30) | |
2891 self.grid.SetColSize(3,w * 0.50) | |
2892 | |
2893 def refresh_data(self): | |
2894 for i in range(len(self.n_list)): | |
2895 self.refresh_row(i) | |
2896 | |
2897 class dnd3edivine(snp_char_child): | |
2898 """ Node Handler for classes. This handler will be | |
2899 created by dnd3echar_handler. | |
2900 """ | |
2901 def __init__(self,xml_dom,tree_node,parent): | |
2902 snp_char_child.__init__(self,xml_dom,tree_node,parent) | |
2903 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
2904 self.root = getRoot(self) #a 1.5002 | |
2905 self.root.divine = self #a 1.6009 | |
2906 | |
2907 | |
2908 node_list = self.master_dom.getElementsByTagName( 'gift' ) | |
2909 self.spells = {} | |
2910 tree = self.tree | |
2911 icons = self.tree.icons | |
2912 for n in node_list: | |
2913 name = n.getAttribute('name') | |
2914 self.spells[ name ] = n | |
2915 new_tree_node = tree.AppendItem( self.mytree_node, name, icons['flask'], icons['flask'] ) | |
2916 tree.SetPyData( new_tree_node, self ) | |
2917 | |
2918 def on_rclick( self, evt ): | |
2919 charNameL=self.root.general.charName #a f 1.5002 | |
2920 item = self.tree.GetSelection() | |
2921 name = self.tree.GetItemText( item ) | |
2922 if item == self.mytree_node: | |
2923 dnd3e_char_child.on_ldclick( self, evt ) | |
2924 else: | |
2925 level = self.spells[ name ].getAttribute( 'level' ) | |
2926 descr = self.spells[ name ].getAttribute( 'desc' ) | |
2927 use = self.spells[ name ].getAttribute( 'used' ) | |
2928 memrz = self.spells[ name ].getAttribute( 'memrz' ) | |
2929 use += '+1' | |
2930 left = eval( '%s - ( %s )' % ( memrz, use ) ) | |
2931 if left < 0: | |
2932 txt = '%s Tried to cast %s but has used all of them for today,' #m 1.5002 break in 2. | |
2933 txt += "Please rest so I can cast more."' % ( charNameL, name )' #a 1.5002 | |
2934 #txt += "Please rest so I can cast more."' % ( dnd_globals["gen"]["Name"], name ) #d 1.5002 | |
2935 self.chat.ParsePost( txt, True, False ) | |
2936 else: | |
2937 #txt = '%s casts %s ( level %s, "%s" )' % ( dnd_globals["gen"]["Name"], name, level, descr ) #d 1.5002 | |
2938 txt = '%s casts %s ( level %s, "%s" )' % ( charNameL, name, level, descr ) #a 5002 | |
2939 self.chat.ParsePost( txt, True, False ) | |
2940 s = '' | |
2941 if left != 1: | |
2942 s = 's' | |
2943 #txt = '%s can cast %s %d more time%s' % ( dnd_globals["gen"]["Name"], name, left, s ) #d 1.5002 | |
2944 txt = '%s can cast %s %d more time%s' % ( charNameL, name, left, s ) #a 1.5002 | |
2945 self.chat.ParsePost( txt, False, False ) | |
2946 self.spells[ name ].setAttribute( 'used', `eval( use )` ) | |
2947 | |
2948 def refresh_spells(self): | |
2949 self.spells = {} | |
2950 tree = self.tree | |
2951 icons = self.tree.icons | |
2952 tree.CollapseAndReset(self.mytree_node) | |
2953 | |
2954 node_list = self.master_dom.getElementsByTagName('gift') | |
2955 for n in node_list: | |
2956 name = n.getAttribute('name') | |
2957 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['flask'],icons['flask']) | |
2958 tree.SetPyData(new_tree_node,self) | |
2959 self.spells[name]=n | |
2960 | |
2961 def get_design_panel(self,parent): | |
2962 wnd = outline_panel(parent,self,divine_panel,"Spells") | |
2963 wnd.title = "Spells" | |
2964 return wnd | |
2965 | |
2966 def tohtml(self): | |
2967 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Divine Spells</th></tr><tr><td><br>" | |
2968 n_list = self.master_dom._get_childNodes() | |
2969 for n in n_list: | |
2970 html_str += "(" + n.getAttribute('level') + ") " + n.getAttribute('name')+ ", " | |
2971 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
2972 return html_str | |
2973 | |
2974 def get_char_lvl( self, attr ): | |
2975 return self.char_hander.get_char_lvl(attr) | |
2976 | |
2977 class divine_panel(wx.Panel): | |
2978 def __init__(self, parent, handler): | |
2979 pname = handler.master_dom.setAttribute("name", 'Divine Spells') | |
2980 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
2981 #a 1.5002 in this case, we need the functional parent, not the invoking parent. | |
2982 | |
2983 wx.Panel.__init__(self, parent, -1) | |
2984 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
2985 self.handler = handler | |
2986 sizer = wx.BoxSizer(wx.VERTICAL) | |
2987 sizer.Add(self.grid, 1, wx.EXPAND) | |
2988 | |
2989 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
2990 sizer1.Add(wx.Button(self, 10, "Remove Spell"), 1, wx.EXPAND) | |
2991 sizer1.Add(wx.Size(10,10)) | |
2992 sizer1.Add(wx.Button(self, 20, "Add Spell"), 1, wx.EXPAND) | |
2993 sizer1.Add(wx.Size(10,10)) | |
2994 sizer1.Add(wx.Button(self, 30, "Refresh Spells"), 1, wx.EXPAND) | |
2995 | |
2996 sizer.Add(sizer1, 0, wx.EXPAND) | |
2997 self.sizer = sizer | |
2998 self.SetSizer(self.sizer) | |
2999 self.SetAutoLayout(True) | |
3000 self.Fit() | |
3001 | |
3002 #self.Bind(wx.EVT_SIZE, self.on_size) | |
3003 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
3004 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
3005 self.Bind(wx.EVT_BUTTON, self.on_refresh_spells, id=30) | |
3006 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
3007 | |
3008 n_list = handler.master_dom._get_childNodes() | |
3009 self.n_list = n_list | |
3010 self.master_dom = handler.master_dom | |
3011 self.grid.CreateGrid(len(n_list),4,1) | |
3012 self.grid.SetRowLabelSize(0) | |
3013 self.grid.SetColLabelValue(0,"No.") | |
3014 self.grid.SetColLabelValue(1,"Lvl") | |
3015 self.grid.SetColLabelValue(2,"Spell") | |
3016 self.grid.SetColLabelValue(3,"Desc") | |
3017 for i in range(len(n_list)): | |
3018 self.refresh_row(i) | |
3019 self.temp_dom = None | |
3020 | |
3021 def on_cell_change(self,evt): | |
3022 row = evt.GetRow() | |
3023 | |
3024 col = evt.GetCol() | |
3025 value = self.grid.GetCellValue(row,col) | |
3026 if col == 0: | |
3027 self.n_list[row].setAttribute('memrz',value) | |
3028 | |
3029 | |
3030 def refresh_row(self,i): | |
3031 spell = self.n_list[i] | |
3032 | |
3033 memrz = spell.getAttribute('memrz') | |
3034 name = spell.getAttribute('name') | |
3035 type = spell.getAttribute('desc') | |
3036 level = spell.getAttribute('level') | |
3037 self.grid.SetCellValue(i,0,memrz) | |
3038 self.grid.SetCellValue(i,2,name) | |
3039 self.grid.SetReadOnly(i,2) | |
3040 self.grid.SetCellValue(i,3,type) | |
3041 self.grid.SetReadOnly(i,3) | |
3042 self.grid.SetCellValue(i,1,level) | |
3043 self.grid.SetReadOnly(i,1) | |
3044 | |
3045 def on_remove(self,evt): | |
3046 rows = self.grid.GetNumberRows() | |
3047 for i in range(rows): | |
3048 if self.grid.IsInSelection(i,0): | |
3049 self.grid.DeleteRows(i) | |
3050 self.master_dom.removeChild(self.n_list[i]) | |
3051 | |
3052 def on_add(self,evt): | |
3053 if not self.temp_dom: | |
3054 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+"dnd3edivine.xml","r") | |
3055 | |
3056 xml_dom = parseXml_with_dlg(self,tmp.read()) | |
3057 xml_dom = xml_dom._get_firstChild() | |
3058 tmp.close() | |
3059 self.temp_dom = xml_dom | |
3060 f_list = self.temp_dom.getElementsByTagName('gift') | |
3061 opts = [] | |
3062 #lvl = int(dnd3e_char_child.get_char_lvl('level')) | |
3063 #castlvl = lvl / 2 | |
3064 for f in f_list: | |
3065 spelllvl = f.getAttribute('level') | |
3066 #if spelllvl <= "1": | |
3067 # opts.append("(" + f.getAttribute('level') + ")" + f.getAttribute('name')) | |
3068 #else: | |
3069 # if eval('%d >= %s' %(castlvl, spelllvl)): | |
3070 opts.append("(" + f.getAttribute('level') + ")" + f.getAttribute('name')) | |
3071 dlg = wx.SingleChoiceDialog(self,'Choose Spell','Spells',opts) | |
3072 if dlg.ShowModal() == wx.ID_OK: | |
3073 i = dlg.GetSelection() | |
3074 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False)) | |
3075 self.grid.AppendRows(1) | |
3076 self.n_list = self.master_dom.getElementsByTagName('gift') | |
3077 self.refresh_row(self.grid.GetNumberRows()-1) | |
3078 self.handler.refresh_spells() | |
3079 dlg.Destroy() | |
3080 | |
3081 def on_refresh_spells( self, evt ): | |
3082 f_list = self.master_dom.getElementsByTagName('gift') | |
3083 for spell in f_list: | |
3084 spell.setAttribute( 'used', '0' ) | |
3085 | |
3086 def on_size(self,event): | |
3087 s = self.GetClientSizeTuple() | |
3088 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
3089 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
3090 (w,h) = self.grid.GetClientSizeTuple() | |
3091 cols = self.grid.GetNumberCols() | |
3092 col_w = w/(cols) | |
3093 for i in range(0,cols): | |
3094 self.grid.SetColSize(i,col_w) | |
3095 self.grid.SetColSize(0,w * 0.10) | |
3096 self.grid.SetColSize(1,w * 0.10) | |
3097 self.grid.SetColSize(2,w * 0.30) | |
3098 self.grid.SetColSize(3,w * 0.50) | |
3099 | |
3100 def refresh_data(self): | |
3101 | |
3102 for i in range(len(self.n_list)): | |
3103 self.refresh_row(i) | |
3104 | |
3105 | |
3106 class dnd3epowers(snp_char_child): | |
3107 """ Node Handler for classes. This handler will be | |
3108 created by dnd3echar_handler. | |
3109 """ | |
3110 def __init__(self,xml_dom,tree_node,parent): | |
3111 snp_char_child.__init__(self,xml_dom,tree_node,parent) | |
3112 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
3113 self.root = getRoot(self) #a 1.5002 | |
3114 self.root.powers = self #a 1.6009 | |
3115 | |
3116 node_list = self.master_dom.getElementsByTagName( 'power' ) | |
3117 self.powers = {} | |
3118 tree = self.tree | |
3119 icons = self.tree.icons | |
3120 for n in node_list: | |
3121 name = n.getAttribute('name') | |
3122 self.powers[ name ] = n | |
3123 new_tree_node = tree.AppendItem( self.mytree_node, name, | |
3124 icons['gear'], icons['gear'] ) | |
3125 tree.SetPyData( new_tree_node, self ) | |
3126 | |
3127 def on_rclick( self, evt ): | |
3128 charNameL = self.root.general.charName #a f 1.5002 | |
3129 | |
3130 item = self.tree.GetSelection() | |
3131 name = self.tree.GetItemText( item ) | |
3132 charNameL = self.root.general.charName #a 1.5002 | |
3133 if item == self.mytree_node: | |
3134 dnd3e_char_child.on_ldclick( self, evt ) | |
3135 else: | |
3136 level = int(self.powers[ name ].getAttribute( 'level' )) | |
3137 descr = self.powers[ name ].getAttribute( 'desc' ) | |
3138 #use can be removed -mgt | |
3139 #use = self.powers[ name ].getAttribute( 'used' ) | |
3140 points = self.powers[ name ].getAttribute( 'point' ) | |
3141 #cpp and fre are strings without the eval -mgt | |
3142 cpp = eval(self.root.pp.get_char_pp('current1')) #a 1.5002 | |
3143 fre = eval(self.root.pp.get_char_pp('free')) #a 1.5002 | |
3144 if level == 0 and fre > 0: | |
3145 left = eval('%s - ( %s )' % ( fre, points )) | |
3146 numcast = eval('%s / %s' % (left, points)) | |
3147 if left < 0: | |
3148 #In theory you should never see this -mgt | |
3149 txt = ('%s doesnt have enough PowerPoints to use %s' | |
3150 % ( charNameL, name )) #a 1.5002 | |
3151 self.chat.ParsePost( txt, True, False ) | |
3152 else: | |
3153 txt = ('%s uses %s as a Free Talent ( level %s, "%s" )' | |
3154 % ( charNameL, name, level, descr )) #a 1.5002 | |
3155 self.chat.ParsePost( txt, True, False ) | |
3156 s = '' | |
3157 if left != 1: | |
3158 s = 's' | |
3159 txt = '%s has %d Free Talent%s left' % ( charNameL, numcast, s ) #a 1.5002 | |
3160 self.chat.ParsePost( txt, False, False ) | |
3161 self.root.pp.set_char_pp('free',left) #a 1.5002 | |
3162 else: | |
3163 left = eval('%s - ( %s )' % ( cpp, points )) | |
3164 #numcast = eval('%s / %s' % (left, points)) | |
3165 if left < 0: | |
3166 txt = '%s doesnt have enough PowerPoints to use %s' % ( charNameL, name ) #m 1.5002 | |
3167 self.chat.ParsePost( txt, True, False ) | |
3168 else: | |
3169 txt = '%s uses %s ( level %s, "%s" )' % ( charNameL, name, level, descr ) #m 1.5002 | |
3170 self.chat.ParsePost( txt, True, False ) | |
3171 s = '' | |
3172 if left != 1: | |
3173 s = 's' | |
3174 #numcast is meaningless here -mgt | |
3175 #txt = '%s can use %s %d more time%s' % ( charNameL, name, numcast, s ) #m 1.5002 | |
3176 #txt += ' - And has %d more PowerpointsP left' % (left) | |
3177 txt = '%s has %d more Powerpoint%s' % ( charNameL, left, s ) #m 1.5002 | |
3178 self.chat.ParsePost( txt, False, False ) | |
3179 self.root.pp.set_char_pp('current1',left) #a 1.5002 | |
3180 | |
3181 def refresh_powers(self): | |
3182 self.powers = {} | |
3183 | |
3184 tree = self.tree | |
3185 icons = self.tree.icons | |
3186 tree.CollapseAndReset(self.mytree_node) | |
3187 node_list = self.master_dom.getElementsByTagName('power') | |
3188 for n in node_list: | |
3189 name = n.getAttribute('name') | |
3190 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear']) | |
3191 tree.SetPyData(new_tree_node,self) | |
3192 self.powers[name]=n | |
3193 | |
3194 def get_design_panel(self,parent): | |
3195 wnd = outline_panel(parent,self,power_panel,"Powers") | |
3196 wnd.title = "Powers" | |
3197 return wnd | |
3198 | |
3199 def tohtml(self): | |
3200 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Powers</th></tr><tr><td><br>" | |
3201 n_list = self.master_dom._get_childNodes() | |
3202 for n in n_list: | |
3203 html_str += "(" + n.getAttribute('level') + ") " + n.getAttribute('name')+ ", " | |
3204 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
3205 return html_str | |
3206 | |
3207 | |
3208 class power_panel(wx.Panel): | |
3209 def __init__(self, parent, handler): | |
3210 #m 1.5015 corrected typo, was Pionic. | |
3211 pname = handler.master_dom.setAttribute("name", 'Psionic Powers') | |
3212 self.hparent = handler #a 1.5002 allow ability to run up tree. In this | |
3213 #a 1.5002 case, we need the functional parent, not the invoking parent. | |
3214 self.root = getRoot(self) #a (debug) 1.5002,1.5014 | |
3215 | |
3216 wx.Panel.__init__(self, parent, -1) | |
3217 self.grid = wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
3218 self.handler = handler | |
3219 sizer = wx.BoxSizer(wx.VERTICAL) | |
3220 sizer.Add(self.grid, 1, wx.EXPAND) | |
3221 | |
3222 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
3223 sizer1.Add(wx.Button(self, 10, "Remove Power"), 1, wx.EXPAND) | |
3224 sizer1.Add(wx.Size(10,10)) | |
3225 sizer1.Add(wx.Button(self, 20, "Add Power"), 1, wx.EXPAND) | |
3226 sizer1.Add(wx.Size(10,10)) | |
3227 sizer1.Add(wx.Button(self, 30, "Refresh Power"), 1, wx.EXPAND) | |
3228 | |
3229 sizer.Add(sizer1, 0, wx.EXPAND) | |
3230 self.sizer = sizer | |
3231 self.SetSizer(self.sizer) | |
3232 self.SetAutoLayout(True) | |
3233 self.Fit() | |
3234 #self.Bind(wx.EVT_SIZE, self.on_size) | |
3235 | |
3236 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
3237 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
3238 self.Bind(wx.EVT_BUTTON, self.on_refresh_powers, id=30) | |
3239 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
3240 n_list = handler.master_dom._get_childNodes() | |
3241 self.n_list = n_list | |
3242 self.master_dom = handler.master_dom | |
3243 self.grid.CreateGrid(len(n_list),5,1) | |
3244 self.grid.SetRowLabelSize(0) | |
3245 self.grid.SetColLabelValue(0,"PP") | |
3246 self.grid.SetColLabelValue(1,"Lvl") | |
3247 self.grid.SetColLabelValue(2,"Power") | |
3248 self.grid.SetColLabelValue(3,"Desc") | |
3249 self.grid.SetColLabelValue(4,"Type") | |
3250 for i in range(len(n_list)): | |
3251 self.refresh_row(i) | |
3252 self.refresh_data() | |
3253 self.temp_dom = None | |
3254 | |
3255 def on_cell_change(self,evt): | |
3256 row = evt.GetRow() | |
3257 col = evt.GetCol() | |
3258 value = self.grid.GetCellValue(row,col) | |
3259 """if col == 0: | |
3260 self.n_list[row].setAttribute('memrz',value)""" | |
3261 | |
3262 | |
3263 def refresh_row(self,i): | |
3264 power = self.n_list[i] | |
3265 | |
3266 point = power.getAttribute('point') | |
3267 name = power.getAttribute('name') | |
3268 type = power.getAttribute('desc') | |
3269 test = power.getAttribute('test') | |
3270 level = power.getAttribute('level') | |
3271 self.grid.SetCellValue(i,0,point) | |
3272 self.grid.SetReadOnly(i,0) | |
3273 self.grid.SetCellValue(i,1,level) | |
3274 self.grid.SetReadOnly(i,1) | |
3275 self.grid.SetCellValue(i,2,name) | |
3276 self.grid.SetReadOnly(i,2) | |
3277 self.grid.SetCellValue(i,3,type) | |
3278 self.grid.SetReadOnly(i,3) | |
3279 self.grid.SetCellValue(i,4,test) | |
3280 self.grid.SetReadOnly(i,4) | |
3281 | |
3282 def on_remove(self,evt): | |
3283 rows = self.grid.GetNumberRows() | |
3284 for i in range(rows): | |
3285 if self.grid.IsInSelection(i,0): | |
3286 self.grid.DeleteRows(i) | |
3287 self.master_dom.removeChild(self.n_list[i]) | |
3288 | |
3289 def on_add(self,evt): | |
3290 if not self.temp_dom: | |
3291 tmp = open(orpg.dirpath.dir_struct["dnd3e"]+"dnd3epowers.xml","r") | |
3292 | |
3293 xml_dom = parseXml_with_dlg(self,tmp.read()) | |
3294 xml_dom = xml_dom._get_firstChild() | |
3295 tmp.close() | |
3296 self.temp_dom = xml_dom | |
3297 f_list = self.temp_dom.getElementsByTagName('power') | |
3298 opts = [] | |
3299 #lvl = int(dnd3e_char_child.get_char_lvl('level')) | |
3300 #castlvl = lvl / 2 | |
3301 for f in f_list: | |
3302 spelllvl = f.getAttribute('level') | |
3303 #if spelllvl <= "1": | |
3304 # opts.append("(" + f.getAttribute('level') + ") - " + f.getAttribute('name') + " - " + f.getAttribute('test')) | |
3305 #else: | |
3306 # if eval('%d >= %s' %(castlvl, spelllvl)): | |
3307 opts.append("(" + f.getAttribute('level') + ") - " + | |
3308 f.getAttribute('name') + " - " + f.getAttribute('test')) | |
3309 dlg = wx.SingleChoiceDialog(self,'Choose Power','Powers',opts) | |
3310 if dlg.ShowModal() == wx.ID_OK: | |
3311 i = dlg.GetSelection() | |
3312 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False)) | |
3313 self.grid.AppendRows(1) | |
3314 self.n_list = self.master_dom.getElementsByTagName('power') | |
3315 self.refresh_row(self.grid.GetNumberRows()-1) | |
3316 self.handler.refresh_powers() | |
3317 dlg.Destroy() | |
3318 | |
3319 def on_remove(self,evt): | |
3320 rows = self.grid.GetNumberRows() | |
3321 for i in range(rows): | |
3322 if self.grid.IsInSelection(i,0): | |
3323 self.grid.DeleteRows(i) | |
3324 self.master_dom.removeChild(self.n_list[i]) | |
3325 self.n_list = self.master_dom.getElementsByTagName('weapon') | |
3326 self.handler.refresh_powers() | |
3327 | |
3328 def on_refresh_powers( self, evt ): | |
3329 #a 1.5002,1.5014 s | |
3330 self.root.pp.set_char_pp('current1',self.root.pp.get_char_pp('max1')) | |
3331 self.root.pp.set_char_pp('free',self.root.pp.get_char_pp('maxfree')) | |
3332 #a 1.5002,1.5014 e | |
3333 | |
3334 | |
3335 | |
3336 def on_size(self,event): | |
3337 s = self.GetClientSizeTuple() | |
3338 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
3339 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
3340 (w,h) = self.grid.GetClientSizeTuple() | |
3341 cols = self.grid.GetNumberCols() | |
3342 col_w = w/(cols) | |
3343 for i in range(0,cols): | |
3344 self.grid.SetColSize(i,col_w) | |
3345 self.grid.SetColSize(0,w * 0.05) | |
3346 self.grid.SetColSize(1,w * 0.05) | |
3347 self.grid.SetColSize(2,w * 0.30) | |
3348 self.grid.SetColSize(3,w * 0.30) | |
3349 self.grid.SetColSize(4,w * 0.30) | |
3350 | |
3351 def refresh_data(self): | |
3352 | |
3353 for i in range(len(self.n_list)): | |
3354 self.refresh_row(i) | |
3355 | |
3356 class dnd3epp(snp_char_child): | |
3357 """ Node Handler for power points. This handler will be | |
3358 created by dnd3echar_handler. | |
3359 """ | |
3360 def __init__(self,xml_dom,tree_node,parent): | |
3361 snp_char_child.__init__(self,xml_dom,tree_node,parent) | |
3362 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
3363 self.root = getRoot(self) | |
3364 self.root.pp = self | |
3365 self.ppPanel=None | |
3366 | |
3367 | |
3368 def get_design_panel(self,parent): | |
3369 wnd = outline_panel(parent,self,pp_panel,"Power Points") | |
3370 wnd.title = "Power Points" | |
3371 return wnd | |
3372 | |
3373 | |
3374 def tohtml(self): | |
3375 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 >" | |
3376 #html_str += "<th colspan=8>Power Points</th></tr>" #d 1.6010 | |
3377 html_str += "<th colspan=7>Power Points</th>" #a 1.6010 | |
3378 #m 1.6010 rearanged everything below to "return html_str" | |
3379 html_str += "</tr><tr>" | |
3380 html_str += "<th colspan=2>Max:</th>" | |
3381 html_str += "<td>"+self.master_dom.getAttribute('max1')+"</td>" | |
3382 html_str += "<th colspan=3>Max Talents/day:</th>" | |
3383 html_str += "<td>"+self.master_dom.getAttribute('maxfree')+"</td>" | |
3384 html_str += "</tr><tr>" | |
3385 html_str += "<th colspan=2>Current:</th>" | |
3386 html_str += "<td>"+self.master_dom.getAttribute('current1')+"</td>" | |
3387 html_str += "<th colspan=3>Current Talents/day:</th>" | |
3388 html_str += "<td>"+self.master_dom.getAttribute('free')+"</td>" | |
3389 html_str += "</tr></table>" | |
3390 return html_str | |
3391 | |
3392 def get_char_pp( self, attr ): | |
3393 pp = self.master_dom.getAttribute(attr) | |
3394 #print "dnd3epp -get_char_pp: attr,pp",attr,pp | |
3395 return pp | |
3396 | |
3397 def set_char_pp( self, attr, evl ): | |
3398 qSub = str(evl) #a 1.5014 must force it to be a string for next call. | |
3399 self.master_dom.setAttribute(attr, qSub) | |
3400 #This function needs to be looked at the idea is to refresh the power panel | |
3401 #But it causes a seg fault when you refresh from powers -mgt | |
3402 #if self.ppPanel: #a 1.5015 | |
3403 # self.ppPanel.on_refresh(attr,qSub) #a 1.5015 | |
3404 | |
3405 | |
3406 class pp_panel(wx.Panel): | |
3407 def __init__(self, parent, handler): | |
3408 wx.Panel.__init__(self, parent, -1) | |
3409 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
3410 #a 1.5002 we need the functional parent, not the invoking parent. | |
3411 self.hparent.ppPanel=self #a 1.5xx | |
3412 | |
3413 pname = handler.master_dom.setAttribute("name", 'PowerPoints') | |
3414 self.sizer = wx.FlexGridSizer(2, 4, 2, 2) # rows, cols, hgap, vgap | |
3415 self.master_dom = handler.master_dom | |
3416 | |
3417 self.static1= wx.StaticText(self, -1, "PP Current:") #a 1.5015 | |
3418 self.dyn1= wx.TextCtrl(self, PP_CUR, | |
3419 self.master_dom.getAttribute('current1')) #a 1.5015 | |
3420 self.dyn3= wx.TextCtrl(self, PP_FRE, | |
3421 self.master_dom.getAttribute('free')) #a 1.5015 | |
3422 # self.sizer.AddMany([ (wx.StaticText(self, -1, "PP Current:"), #d 1.5015 | |
3423 # 0, wx.ALIGN_CENTER_VERTICAL), | |
3424 # (wx.TextCtrl(self, PP_CUR, #d 1.5015 | |
3425 # self.master_dom.getAttribute('current1')), 0, wx.EXPAND), | |
3426 self.sizer.AddMany([ (self.static1, 0, wx.ALIGN_CENTER_VERTICAL), | |
3427 (self.dyn1, 0, wx.EXPAND), | |
3428 (wx.StaticText(self, -1, "PP Max:"), 0, wx.ALIGN_CENTER_VERTICAL), | |
3429 (wx.TextCtrl(self, PP_MAX, | |
3430 self.master_dom.getAttribute('max1')), 0, wx.EXPAND), | |
3431 (wx.StaticText(self, -1, "Current Free Talants per day:"), | |
3432 0, wx.ALIGN_CENTER_VERTICAL), | |
3433 (self.dyn3, 0, wx.EXPAND), #a 1.5015 | |
3434 # (wx.TextCtrl(self, PP_FRE, | |
3435 # self.master_dom.getAttribute('free')), 0, wx.EXPAND),#d 1.5015 | |
3436 (wx.StaticText(self, -1, "Max Free Talants per day:"), | |
3437 0, wx.ALIGN_CENTER_VERTICAL), | |
3438 (wx.TextCtrl(self, PP_MFRE, | |
3439 self.master_dom.getAttribute('maxfree')), 0, wx.EXPAND), | |
3440 ]) | |
3441 | |
3442 self.sizer.AddGrowableCol(1) | |
3443 self.SetSizer(self.sizer) | |
3444 self.SetAutoLayout(True) | |
3445 self.Fit() | |
3446 | |
3447 #self.Bind(wx.EVT_SIZE, self.on_size) | |
3448 self.Bind(wx.EVT_TEXT, self.on_text, id=PP_MAX) | |
3449 self.Bind(wx.EVT_TEXT, self.on_text, id=PP_CUR) | |
3450 self.Bind(wx.EVT_TEXT, self.on_text, id=PP_FRE) | |
3451 self.Bind(wx.EVT_TEXT, self.on_text, id=PP_MFRE) | |
3452 | |
3453 def on_text(self,evt): | |
3454 id = evt.GetId() | |
3455 if id == PP_CUR: | |
3456 self.master_dom.setAttribute('current1',evt.GetString()) | |
3457 elif id == PP_MAX: | |
3458 self.master_dom.setAttribute('max1',evt.GetString()) | |
3459 elif id == PP_FRE: | |
3460 self.master_dom.setAttribute('free',evt.GetString()) | |
3461 elif id == PP_MFRE: | |
3462 self.master_dom.setAttribute('maxfree',evt.GetString()) | |
3463 | |
3464 def on_size(self,evt): | |
3465 s = self.GetClientSizeTuple() | |
3466 self.sizer.SetDimension(0,0,s[0],s[1]) | |
3467 | |
3468 #a 5.015 this whole function. | |
3469 def on_refresh(self,attr,value): | |
3470 if attr == 'current1': | |
3471 self.dyn1.SetValue(value) | |
3472 else: | |
3473 self.dyn3.SetValue(value) |