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)