comparison orpg/gametree/nodehandlers/dnd35.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 import orpg.tools.orpg_settings
2 import orpg.minidom
3 from core import *
4 from containers import *
5 from string import * #a 1.6003
6 from inspect import * #a 1.9001
7 dnd35_EXPORT = wx.NewId()
8
9 ############Global Stuff##############
10
11 HP_CUR = wx.NewId()
12 HP_MAX = wx.NewId()
13
14 def getRoot (node): # a 1.5002 this whole function is new.
15 root = None
16 target = node
17 while target != None:
18 root = target
19 target = target.hparent
20 return root
21
22 #a 1.6 convinience function added safeGetAttr
23 def safeGetAttr(node,lable,defRetV=None):
24 cna=node.attributes
25 for i2 in range(len(cna)):
26 if cna.item(i2).name == lable:
27 return cna.item(i2).value
28 #retV=node.getAttribute(lable) # getAttribute does not distingish between
29 # the attribute not being present vs it having a value of ""
30 # This is bad for this routine, thus not used.
31 return defRetV
32 #a 1.6... safeGetAttr end.
33
34 ########End of My global Stuff########
35 ########Start of Main Node Handlers#######
36 class dnd35char_handler(container_handler):
37 """ Node handler for a dnd35 charactor
38 <nodehandler name='?' module='dnd35' class='dnd35char_handler2' />
39 """
40 def __init__(self,xml_dom,tree_node):
41 node_handler.__init__(self,xml_dom,tree_node)
42 self.Version = "v1.000" #a 1.6000 general documentation, usage.
43
44 print "dnd35char_handler - version:",self.Version #m 1.6000
45
46 self.hparent = None #a 1.5002 allow ability to run up tree, this is the
47
48 self.frame = open_rpg.get_component('frame')
49 self.child_handlers = {}
50 self.new_child_handler('general','GeneralInformation',dnd35general,'gear')
51 self.new_child_handler('inventory','MoneyAndInventory',dnd35inventory,'money')
52 self.new_child_handler('character','ClassesAndStats',dnd35classnstats,'knight')
53 self.new_child_handler('snf','SkillsAndFeats',dnd35skillsnfeats,'book')
54 self.new_child_handler('combat','Combat',dnd35combat,'spears')
55
56 self.myeditor = None
57
58
59 def new_child_handler(self,tag,text,handler_class,icon='gear'):
60 node_list = self.master_dom.getElementsByTagName(tag)
61 tree = self.tree
62 i = self.tree.icons[icon]
63 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i)
64 handler = handler_class(node_list[0],new_tree_node,self)
65 tree.SetPyData(new_tree_node,handler)
66 self.child_handlers[tag] = handler
67
68 def get_design_panel(self,parent):
69 return tabbed_panel(parent,self,1)
70
71
72 def get_use_panel(self,parent):
73 return tabbed_panel(parent,self,2)
74
75 def tohtml(self):
76 html_str = "<table><tr><td colspan=2 >"
77 html_str += self.general.tohtml()+"</td></tr>"
78 html_str += "<tr><td width='50%' valign=top >"+self.abilities.tohtml()
79 html_str += "<P>" + self.saves.tohtml()
80 html_str += "<P>" + self.attacks.tohtml()
81 html_str += "<P>" + self.ac.tohtml()
82 html_str += "<P>" + self.feats.tohtml()
83 html_str += "<P>" + self.inventory.tohtml() +"</td>"
84 html_str += "<td width='50%' valign=top >"+self.classes.tohtml()
85 html_str += "<P>" + self.hp.tohtml()
86 html_str += "<P>" + self.skills.tohtml() +"</td>"
87 #a block for 1.6009 end
88
89 html_str += "</tr></table>"
90 return html_str
91
92 def about(self):
93 html_str = "<img src='" + orpg.dirpath.dir_struct["icon"]
94 html_str += "dnd3e_logo.gif' ><br /><b>dnd35 Character Tool "
95 html_str += self.Version+"</b>" #m 1.6000 was hard coded.
96 html_str += "<br />by Dj Gilcrease<br />digitalxero@gmail.com"
97 return html_str
98
99 ########Core Handlers are done now############
100 ########Onto the Sub Nodes########
101 ##Primary Sub Node##
102
103 class outline_panel(wx.Panel):
104 def __init__(self, parent, handler, wnd, txt,):
105 self.parent = parent #a 1.9001
106 wx.Panel.__init__(self, parent, -1)
107 self.panel = wnd(self,handler)
108 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self,-1,txt), wx.VERTICAL)
109
110 self.sizer.Add(self.panel, 1, wx.EXPAND)
111 self.SetSizer(self.sizer)
112 self.SetAutoLayout(True)
113 self.Fit()
114
115 class dnd35_char_child(node_handler):
116 """ Node Handler for skill. This handler will be
117 created by dnd35char_handler.
118 """
119 def __init__(self,xml_dom,tree_node,parent):
120 node_handler.__init__(self,xml_dom,tree_node)
121 self.char_hander = parent
122 self.drag = False
123 self.frame = open_rpg.get_component('frame')
124 self.myeditor = None
125
126
127 def on_drop(self,evt):
128 pass
129
130 def on_rclick(self,evt):
131 pass
132
133 def on_ldclick(self,evt):
134 return
135
136 def on_html(self,evt):
137 html_str = self.tohtml()
138 wnd = http_html_window(self.frame.note,-1)
139 wnd.title = self.master_dom.getAttribute('name')
140 self.frame.add_panel(wnd)
141 wnd.SetPage(html_str)
142
143 def get_design_panel(self,parent):
144 pass
145
146 def get_use_panel(self,parent):
147 return self.get_design_panel(parent)
148
149 def delete(self):
150 pass
151
152 class dnd35general(dnd35_char_child):
153 """ Node Handler for general information. This handler will be
154 created by dnd35char_handler.
155 """
156 def __init__(self,xml_dom,tree_node,parent):
157 dnd35_char_child.__init__(self,xml_dom,tree_node,parent)
158 self.hparent = parent #a 1.5002 allow ability to run up tree.
159 self.root = getRoot(self) #a 1.5002
160 self.root.general = self #a 1.5002
161 self.charName = self.get_char_name() # a 1.5002 make getting name easier.
162
163 def get_design_panel(self,parent):
164 wnd = outline_panel(parent,self,gen_grid,"General Information")
165 wnd.title = "General Info"
166 return wnd
167
168 def tohtml(self):
169 n_list = self.master_dom._get_childNodes()
170 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>"
171 for n in n_list:
172 t_node = safe_get_text_node(n)
173 html_str += "<B>"+n._get_tagName().capitalize() +":</B> "
174 html_str += t_node._get_nodeValue() + ", "
175 html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
176 return html_str
177
178 def on_name_change(self,name):
179 self.char_hander.rename(name)
180 #o 1.5002 self.char_hander = parent in this case.
181 self.charName = name #a 1.5002 make getting name easier.
182
183
184 def get_char_name( self ):
185 node = self.master_dom.getElementsByTagName( 'name' )[0]
186 t_node = safe_get_text_node( node )
187 return t_node._get_nodeValue()
188
189 class gen_grid(wx.grid.Grid):
190 """grid for gen info"""
191 def __init__(self, parent, handler):
192 pname = handler.master_dom.setAttribute("name", 'General')
193 self.hparent = handler #a 1.5002 allow ability to run up tree, needed
194 # a 1.5002 parent is functional parent, not invoking parent.
195
196
197 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
198 #self.Bind(wx.EVT_SIZE, self.on_size)
199 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
200 self.handler = handler
201 n_list = handler.master_dom._get_childNodes()
202 self.CreateGrid(len(n_list),2)
203 self.SetRowLabelSize(0)
204 self.SetColLabelSize(0)
205 self.n_list = n_list
206 i = 0
207 for i in range(len(n_list)):
208 self.refresh_row(i)
209
210 def on_cell_change(self,evt):
211 row = evt.GetRow()
212 col = evt.GetCol()
213 value = self.GetCellValue(row,col)
214 t_node = self.n_list[row]._get_firstChild()
215 t_node._set_nodeValue(value)
216 if row==0:
217 self.handler.on_name_change(value)
218 self.AutoSizeColumn(1)
219
220 def refresh_row(self,rowi):
221 t_node = safe_get_text_node(self.n_list[rowi])
222
223 self.SetCellValue(rowi,0,self.n_list[rowi]._get_tagName())
224 self.SetReadOnly(rowi,0)
225 self.SetCellValue(rowi,1,t_node._get_nodeValue())
226 self.AutoSizeColumn(1)
227
228 class dnd35inventory(dnd35_char_child):
229 """ Node Handler for general information. This handler will be
230 created by dnd35char_handler.
231 """
232 def __init__(self,xml_dom,tree_node,parent):
233 dnd35_char_child.__init__(self,xml_dom,tree_node,parent)
234 self.hparent = parent #a 1.5002 allow ability to run up tree.
235 self.root = getRoot(self) #a 1.6009
236 self.root.inventory = self #a 1.6009
237
238 def get_design_panel(self,parent):
239 wnd = inventory_pane(parent, self) #outline_panel(parent,self,inventory_grid,"Inventory")
240 wnd.title = "Inventory"
241 return wnd
242
243 def tohtml(self):
244 n_list = self.master_dom._get_childNodes()
245 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Inventory</th></tr><tr><td>"
246 for n in n_list:
247 t_node = safe_get_text_node(n)
248 html_str += "<B>"+n._get_tagName().capitalize() +":</B> "
249 html_str += t_node._get_nodeValue() + "<br />"
250 html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
251 return html_str
252
253 class inventory_pane(wx.Panel):
254 def __init__(self, parent, handler):
255 wx.Panel.__init__(self, parent, wx.ID_ANY)
256
257 self.n_list = handler.master_dom._get_childNodes()
258 self.autosize = False
259
260 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Inventroy"), wx.VERTICAL)
261
262 self.lang = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Languages")
263 self.gear = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Gear")
264 self.magic = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Magic")
265 self.grid = wx.grid.Grid(self, wx.ID_ANY, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
266
267 self.grid.CreateGrid(len(self.n_list)-3,2)
268 self.grid.SetRowLabelSize(0)
269 self.grid.SetColLabelSize(0)
270
271 for i in xrange(len(self.n_list)):
272 self.refresh_row(i)
273
274 sizer1 = wx.BoxSizer(wx.HORIZONTAL)
275 sizer1.Add(self.grid, 1, wx.EXPAND)
276 sizer1.Add(self.lang, 1, wx.EXPAND)
277
278 self.sizer.Add(sizer1, 0, wx.EXPAND)
279
280 sizer2 = wx.BoxSizer(wx.HORIZONTAL)
281 sizer2.Add(self.gear, 1, wx.EXPAND)
282 sizer2.Add(self.magic, 1, wx.EXPAND)
283
284 self.sizer.Add(sizer2, 1, wx.EXPAND)
285
286 self.SetSizer(self.sizer)
287 self.SetAutoLayout(True)
288 self.Fit()
289
290 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.lang)
291 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.gear)
292 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.magic)
293 self.Bind(wx.grid.EVT_GRID_EDITOR_HIDDEN, self.on_cell_change, self.grid)
294
295
296 def fillTextNode(self, name, value):
297 if name == 'Languages':
298 self.lang.SetValue(value)
299 elif name == 'Gear':
300 self.gear.SetValue(value)
301 elif name == 'Magic':
302 self.magic.SetValue(value)
303
304 def onTextNodeChange(self, event):
305 id = event.GetId()
306
307 if id == self.gear.GetId():
308 nodeName = 'Gear'
309 value = self.gear.GetValue()
310 elif id == self.magic.GetId():
311 nodeName = 'Magic'
312 value = self.magic.GetValue()
313 elif id == self.lang.GetId():
314 nodeName = 'Languages'
315 value = self.lang.GetValue()
316
317 for node in self.n_list:
318 if node._get_tagName() == nodeName:
319 t_node = safe_get_text_node(node)
320 t_node._set_nodeValue(value)
321
322 def saveMoney(self, row, col):
323 value = self.grid.GetCellValue(row, col)
324 t_node = safe_get_text_node(self.n_list[row])
325 t_node._set_nodeValue(value)
326
327 def on_cell_change(self, evt):
328 row = evt.GetRow()
329 col = evt.GetCol()
330 self.grid.AutoSizeColumn(col)
331 wx.CallAfter(self.saveMoney, row, col)
332
333
334
335 def refresh_row(self, row):
336 t_node = safe_get_text_node(self.n_list[row])
337 tagname = self.n_list[row]._get_tagName()
338 value = t_node._get_nodeValue()
339 if tagname == 'Gear':
340 self.fillTextNode(tagname, value)
341 elif tagname == 'Magic':
342 self.fillTextNode(tagname, value)
343 elif tagname == 'Languages':
344 self.fillTextNode(tagname, value)
345 else:
346 self.grid.SetCellValue(row, 0, tagname)
347 self.grid.SetReadOnly(row, 0)
348 self.grid.SetCellValue(row, 1, value)
349 self.grid.AutoSize()
350
351
352 class dnd35classnstats(dnd35_char_child):
353 """ Node handler for a dnd35 charactor
354 <nodehandler name='?' module='dnd35' class='dnd35char_handler2' />
355 """
356 def __init__(self,xml_dom,tree_node,parent):
357 node_handler.__init__(self,xml_dom,tree_node)
358 self.hparent = parent #a 1.5002 allow ability to run up tree.
359 dnd35_char_child.__init__(self,xml_dom,tree_node,parent)
360 self.frame = open_rpg.get_component('frame')
361 self.child_handlers = {}
362 self.new_child_handler('abilities','Abilities Scores',dnd35ability,'gear')
363 self.new_child_handler('classes','Classes',dnd35classes,'knight')
364 self.new_child_handler('saves','Saves',dnd35saves,'skull')
365 self.myeditor = None
366
367
368 def new_child_handler(self,tag,text,handler_class,icon='gear'):
369 node_list = self.master_dom.getElementsByTagName(tag)
370 tree = self.tree
371 i = self.tree.icons[icon]
372 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i)
373 handler = handler_class(node_list[0],new_tree_node,self)
374 tree.SetPyData(new_tree_node,handler)
375 self.child_handlers[tag] = handler
376
377 def get_design_panel(self,parent):
378 return tabbed_panel(parent,self,1)
379
380
381 def get_use_panel(self,parent):
382 return tabbed_panel(parent,self,2)
383
384 class class_char_child(node_handler):
385 """ Node Handler for skill. This handler will be
386 created by dnd35char_handler.
387 """
388 def __init__(self,xml_dom,tree_node,parent):
389 node_handler.__init__(self,xml_dom,tree_node)
390 self.char_hander = parent
391 self.drag = False
392 self.frame = open_rpg.get_component('frame')
393 self.myeditor = None
394
395 def on_drop(self,evt):
396 pass
397
398 def on_rclick(self,evt):
399 pass
400
401 def on_ldclick(self,evt):
402 return
403
404 def on_html(self,evt):
405 html_str = self.tohtml()
406 wnd = http_html_window(self.frame.note,-1)
407 wnd.title = self.master_dom.getAttribute('name')
408 self.frame.add_panel(wnd)
409 wnd.SetPage(html_str)
410
411 def get_design_panel(self,parent):
412 pass
413
414 def get_use_panel(self,parent):
415 return self.get_design_panel(parent)
416
417 def delete(self):
418 pass
419
420 class dnd35ability(class_char_child):
421 """ Node Handler for ability. This handler will be
422 created by dnd35char_handler.
423 """
424 def __init__(self,xml_dom,tree_node,parent):
425 class_char_child.__init__(self,xml_dom,tree_node,parent)
426 self.hparent = parent #a 1.5002 allow ability to run up tree.
427 self.root = getRoot(self) #a 1.5002 get top of our local function tree.
428 self.root.abilities = self #a 1.5002 let other classes find me.
429
430 self.abilities = {}
431 node_list = self.master_dom.getElementsByTagName('stat')
432 tree = self.tree
433 icons = tree.icons
434
435 for n in node_list:
436 name = n.getAttribute('abbr')
437 self.abilities[name] = n
438 new_tree_node = tree.AppendItem( self.mytree_node, name, icons['gear'], icons['gear'] )
439 tree.SetPyData( new_tree_node, self )
440 #print "dnd35ability - init self.abilities",self.abilities #a (debug) 1.5002
441
442 def on_rclick( self, evt ):
443 item = self.tree.GetSelection()
444 name = self.tree.GetItemText( item )
445 #if item == self.mytree_node: #d 1.6016
446 # dnd35_char_child.on_ldclick( self, evt ) #d 1.6016
447 if not item == self.mytree_node: #a 1.6016
448 #else: #d 1.6016
449 mod = self.get_mod( name )
450 if mod >= 0:
451 mod1 = "+"
452 else:
453 mod1 = ""
454 chat = self.chat
455 txt = '%s check: [1d20%s%s]' % ( name, mod1, mod )
456 chat.ParsePost( txt, True, True )
457
458 def get_mod(self,abbr):
459 score = int(self.abilities[abbr].getAttribute('base'))
460 mod = (score - 10) / 2
461 mod = int(mod)
462 return mod
463
464 def set_score(self,abbr,score):
465 if score >= 0:
466 self.abilities[abbr].setAttribute("base",str(score))
467
468 def get_design_panel(self,parent):
469 wnd = outline_panel(parent,self,abil_grid,"Abilities")
470 wnd.title = "Abilities (edit)"
471 return wnd
472
473 def tohtml(self):
474 html_str = """<table border='1' width=100%><tr BGCOLOR=#E9E9E9 ><th width='50%'>Ability</th>
475 <th>Base</th><th>Modifier</th></tr>"""
476 node_list = self.master_dom.getElementsByTagName('stat')
477 for n in node_list:
478 name = n.getAttribute('name')
479 abbr = n.getAttribute('abbr')
480 base = n.getAttribute('base')
481 mod = str(self.get_mod(abbr))
482 if int(mod) >= 0: #m 1.6013 added "int(" and ")"
483 mod1 = "+"
484 else:
485 mod1 = ""
486 html_str = (html_str + "<tr ALIGN='center'><td>"+
487 name+"</td><td>"+base+'</td><td>%s%s</td></tr>' % (mod1, mod))
488 html_str = html_str + "</table>"
489 return html_str
490
491 class abil_grid(wx.grid.Grid):
492 """grid for abilities"""
493 def __init__(self, parent, handler):
494 pname = handler.master_dom.setAttribute("name", 'Stats')
495 self.hparent = handler #a 1.5002 allow ability to run up tree.
496 self.root = getRoot(self)
497 #a 1.5002 in this case, we need the functional parent, not the invoking parent.
498
499 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
500 self.Bind(wx.EVT_SIZE, self.on_size)
501 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
502 self.handler = handler
503 stats = handler.master_dom.getElementsByTagName('stat')
504 self.CreateGrid(len(stats),3)
505 self.SetRowLabelSize(0)
506 col_names = ['Ability','Score','Modifier']
507 for i in range(len(col_names)):
508 self.SetColLabelValue(i,col_names[i])
509 self.stats = stats
510 i = 0
511 for i in range(len(stats)):
512 self.refresh_row(i)
513 self.char_wnd = None
514
515 def on_cell_change(self,evt):
516 row = evt.GetRow()
517 col = evt.GetCol()
518 value = self.GetCellValue(row,col)
519 #print value
520 try:
521 int(value)
522 self.stats[row].setAttribute('base',value)
523 self.refresh_row(row)
524 except:
525 self.SetCellValue(row,col,"0")
526 if self.char_wnd:
527 self.char_wnd.refresh_data()
528
529 #mark5
530
531 def refresh_row(self,rowi):
532 s = self.stats[rowi]
533
534 name = s.getAttribute('name')
535 abbr = s.getAttribute('abbr')
536 self.SetCellValue(rowi,0,name)
537 self.SetReadOnly(rowi,0)
538 self.SetCellValue(rowi,1,s.getAttribute('base'))
539 self.SetCellValue(rowi,2,str(self.handler.get_mod(abbr)))
540 self.SetReadOnly(rowi,2)
541 #if self.root.saves.saveGrid: #a 1.6018 d 1.9002 whole if clause
542 #print getmembers(self.root.saves.saveGrid)
543 #self.root.saves.saveGrid.refresh_data() #a 1.6018
544 #print "skipping saving throw update, put back in later"
545 self.root.saves.refresh_data() #a 1.9002
546 self.root.attacks.refreshMRdata() #a 1.9001 `
547
548 def on_size(self,evt):
549 (w,h) = self.GetClientSizeTuple()
550 cols = self.GetNumberCols()
551 col_w = w/(cols+2)
552 self.SetColSize(0,col_w*3)
553 for i in range(1,cols):
554 self.SetColSize(i,col_w)
555 evt.Skip()
556 self.Refresh()
557
558 def refresh_data(self):
559 for r in range(self.GetNumberRows()-1):
560 self.refresh_row(r)
561
562 class dnd35classes(class_char_child):
563 """ Node Handler for classes. This handler will be
564 created by dnd35char_handler.
565 """
566 def __init__(self,xml_dom,tree_node,parent):
567 class_char_child.__init__(self,xml_dom,tree_node,parent)
568 self.hparent = parent #a 1.5002 allow ability to run up tree.
569 self.root = getRoot(self)
570 self.root.classes = self
571 #a 1.5002 in this case, we need the functional parent, not the invoking parent.
572
573 def get_design_panel(self,parent):
574 wnd = outline_panel(parent,self,class_panel,"Classes")
575 wnd.title = "Classes"
576 return wnd
577
578 def tohtml(self):
579 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Classes</th></tr><tr><td>"
580 n_list = self.master_dom._get_childNodes()
581 for n in n_list:
582 html_str += n.getAttribute('name') + " ("+n.getAttribute('level')+"), "
583 html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
584 return html_str
585
586 def get_char_lvl( self, attr ):
587 node_list = self.master_dom.getElementsByTagName('class')
588 # print "eclasses - get_char_lvl node_list",node_list
589 tot = 0 #a 1.5009 actually, slipping in a quick enhancement ;-)
590 for n in node_list:
591 lvl = n.getAttribute('level') #o 1.5009 not sure of the value of this
592 tot += int(lvl) #a 1.5009
593 type = n.getAttribute('name') #o 1.5009 not sure of the value of this
594 #print type,lvl #a (debug) 1.5009
595 if attr == "level":
596 return lvl #o 1.5009 this returns the level of someone's first class. ???
597 elif attr == "class":
598 return type #o 1.5009 this returns one of the char's classes. ???
599 if attr == "lvl": #a 1.5009 this has value, adding this.
600 return tot #a 1.5009 return character's "overall" level.
601
602 def get_class_lvl( self, classN ): #a 1.5009 need to be able to get monk lvl
603 #a 1.5009 this function is new.
604 node_list = self.master_dom.getElementsByTagName('class')
605 #print "eclasses - get_class_lvl node_list",node_list
606 for n in node_list:
607 lvl = n.getAttribute('level')
608 type = n.getAttribute('name')
609 if classN == type:
610 return lvl
611
612 class class_panel(wx.Panel):
613 def __init__(self, parent, handler):
614 pname = handler.master_dom.setAttribute("name", 'Class')
615
616 wx.Panel.__init__(self, parent, -1)
617 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
618 sizer = wx.BoxSizer(wx.VERTICAL)
619 sizer.Add(self.grid, 1, wx.EXPAND)
620
621 sizer1 = wx.BoxSizer(wx.HORIZONTAL)
622 sizer1.Add(wx.Button(self, 10, "Remove Class"), 0, wx.EXPAND)
623 sizer1.Add(wx.Size(10,10))
624 sizer1.Add(wx.Button(self, 20, "Add Class"), 0, wx.EXPAND)
625
626 sizer.Add(sizer1, 0, wx.EXPAND)
627 self.sizer = sizer
628 self.SetSizer(self.sizer)
629 self.SetAutoLayout(True)
630 self.Fit()
631
632 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10)
633 self.Bind(wx.EVT_BUTTON, self.on_add, id=20)
634 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
635
636 n_list = handler.master_dom._get_childNodes()
637 self.n_list = n_list
638 self.master_dom = handler.master_dom
639 self.grid.CreateGrid(len(n_list),3,1)
640 self.grid.SetRowLabelSize(0)
641 self.grid.SetColLabelValue(0,"Class")
642 self.grid.SetColLabelValue(1,"Level")
643 self.grid.SetColLabelValue(2,"Refrence")
644 for i in range(len(n_list)):
645 self.refresh_row(i)
646 self.temp_dom = None
647
648 def on_cell_change(self,evt):
649 row = evt.GetRow()
650 col = evt.GetCol()
651 value = self.grid.GetCellValue(row,col)
652 try:
653 int(value)
654 self.n_list[row].setAttribute('level',value)
655 except:
656 self.grid.SetCellValue(row,col,"1")
657
658
659 def refresh_row(self,i):
660 n = self.n_list[i]
661
662 name = n.getAttribute('name')
663 level = n.getAttribute('level')
664 book = n.getAttribute('book')
665 self.grid.SetCellValue(i,0,name)
666 self.grid.SetReadOnly(i,0)
667 self.grid.SetCellValue(i,1,level)
668 self.grid.SetCellValue(i,2,book)
669 self.grid.SetReadOnly(i,0)
670 self.grid.AutoSizeColumn(0)
671 self.grid.AutoSizeColumn(1)
672 self.grid.AutoSizeColumn(2)
673
674 def on_remove(self,evt):
675 rows = self.grid.GetNumberRows()
676 for i in range(rows):
677 if self.grid.IsInSelection(i,0):
678 self.grid.DeleteRows(i)
679 self.master_dom.removeChild(self.n_list[i])
680
681 def on_add(self,evt):
682 if not self.temp_dom:
683 tmp = open(orpg.dirpath.dir_struct["dnd35"]+"dnd35classes.xml","r")
684 xml_dom = parseXml_with_dlg(self,tmp.read())
685 xml_dom = xml_dom._get_firstChild()
686 tmp.close()
687 self.temp_dom = xml_dom
688 f_list = self.temp_dom.getElementsByTagName('class')
689 opts = []
690 for f in f_list:
691 opts.append(f.getAttribute('name'))
692 dlg = wx.SingleChoiceDialog(self,'Choose Class','Classes',opts)
693 if dlg.ShowModal() == wx.ID_OK:
694 i = dlg.GetSelection()
695 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
696 self.grid.AppendRows(1)
697 self.refresh_row(self.grid.GetNumberRows()-1)
698 dlg.Destroy()
699
700
701 def on_size(self,event):
702 s = self.GetClientSizeTuple()
703 self.grid.SetDimensions(0,0,s[0],s[1]-25)
704 self.sizer.SetDimension(0,s[1]-25,s[0],25)
705 (w,h) = self.grid.GetClientSizeTuple()
706 cols = self.grid.GetNumberCols()
707 col_w = w/(cols)
708 for i in range(0,cols):
709 self.grid.SetColSize(i,col_w)
710
711
712 class dnd35saves(class_char_child):
713 """ Node Handler for saves. This handler will be
714 created by dnd35char_handler.
715 """
716 def __init__(self,xml_dom,tree_node,parent):
717 class_char_child.__init__(self,xml_dom,tree_node,parent)
718 self.hparent = parent #a 1.5002 allow ability to run up tree.
719 #self.saveGrid = None #a 1.6018 d 1.9002
720 self.saveGridFrame = [] #a 1.9002 handle list, check frame for close.
721
722 tree = self.tree
723 icons = self.tree.icons
724
725 self.root = getRoot(self) #a 1.5002
726 self.root.saves = self #a 1.6009
727 node_list = self.master_dom.getElementsByTagName('save')
728 self.saves={}
729 for n in node_list:
730 name = n.getAttribute('name')
731 self.saves[name] = n
732 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear'])
733 tree.SetPyData(new_tree_node,self)
734
735 #a 1.9002 this whole method
736 def refresh_data(self): # refresh the data in the melee/ranged section
737 # of the attack chart.
738 # count backwards, maintains context despite "removes"
739 for i in range(len(self.saveGridFrame)-1,-1,-1):
740 x = self.saveGridFrame[i]
741 if x == None:
742 x.refresh_data()
743 else:
744 self.saveGridFrame.remove(x)
745
746 def get_mod(self,name):
747 save = self.saves[name]
748 stat = save.getAttribute('stat')
749 #print "dnd35saves, get_mod: self,root",self,self.root #a (debug) 1.5002
750 #print "and abilities",self.root.abilities #a (debug) 1.5002
751 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002
752 base = int(save.getAttribute('base'))
753 miscmod = int(save.getAttribute('miscmod'))
754 magmod = int(save.getAttribute('magmod'))
755 total = stat_mod + base + miscmod + magmod
756 return total
757
758 def on_rclick(self,evt):
759
760 item = self.tree.GetSelection()
761 name = self.tree.GetItemText(item)
762 if item == self.mytree_node:
763 pass #a 1.5003 syntatic place holder
764 return #a 1.5003
765 #print "failure mode!"
766 #dnd35_char_child.on_ldclick(self,evt) #d 1.5003 this busted
767 #wnd = save_grid(self.frame.note,self)
768 #wnd.title = "Saves"
769 #self.frame.add_panel(wnd)
770 else:
771 mod = self.get_mod(name)
772 if mod >= 0:
773 mod1 = "+"
774 else:
775 mod1 = ""
776 chat = self.chat
777 txt = '%s save: [1d20%s%s]' % (name, mod1, mod)
778 chat.ParsePost( txt, True, True )
779
780 def get_design_panel(self,parent):
781 wnd = outline_panel(parent,self,save_grid,"Saves")
782 wnd.title = "Saves"
783 return wnd
784
785 def tohtml(self):
786 html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 >
787 <th width='30%'>Save</th>
788 <th>Key</th><th>Base</th><th>Abil</th><th>Magic</th>
789 <th>Misc</th><th>Total</th></tr>"""
790 node_list = self.master_dom.getElementsByTagName('save')
791 for n in node_list:
792 name = n.getAttribute('name')
793 stat = n.getAttribute('stat')
794 base = n.getAttribute('base')
795 html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+stat+"</td><td>"+base+"</td>"
796 #stat_mod = str(dnd_globals["stats"][stat]) #d 1.5002
797 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002
798
799 mag = n.getAttribute('magmod')
800 misc = n.getAttribute('miscmod')
801 mod = str(self.get_mod(name))
802 if mod >= 0:
803 mod1 = "+"
804 else:
805 mod1 = ""
806 #m 1.5009 next line. added str() around stat_mod
807 html_str = html_str + "<td>"+str(stat_mod)+"</td><td>"+mag+"</td>"
808 html_str = html_str + '<td>'+misc+'</td><td>%s%s</td></tr>' % (mod1, mod)
809 html_str = html_str + "</table>"
810 return html_str
811
812 #mark6
813 class save_grid(wx.grid.Grid):
814 """grid for saves"""
815 def __init__(self, parent, handler):
816 pname = handler.master_dom.setAttribute("name", 'Saves')
817 self.hparent = handler #a 1.5002 allow ability to run up tree.
818 #a 1.5002 in this case, we need the functional parent, not the invoking parent.
819 self.root = getRoot(self)
820
821 #self.hparent.saveGrid = self #a 1.6018 d 1.9001
822
823
824 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
825 self.Bind(wx.EVT_SIZE, self.on_size)
826 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
827 self.handler = handler
828 saves = handler.master_dom.getElementsByTagName('save')
829 self.CreateGrid(len(saves),7)
830 self.SetRowLabelSize(0)
831 col_names = ['Save','Key','base','Abil','Magic','Misc','Total']
832 for i in range(len(col_names)):
833 self.SetColLabelValue(i,col_names[i])
834 self.saves = saves
835 i = 0
836 for i in range(len(saves)):
837 self.refresh_row(i)
838
839
840 #a 1.9002 remainder of code in this method.
841 climber = parent
842 nameNode = climber.GetClassName()
843 while nameNode != 'wxFrame':
844 climber = climber.parent
845 nameNode = climber.GetClassName()
846 masterFrame=climber
847 masterFrame.refresh_data=self.refresh_data
848 #print getmembers(masterFrame)
849
850 handler.saveGridFrame.append(masterFrame)
851
852 def on_cell_change(self,evt):
853 row = evt.GetRow()
854 col = evt.GetCol()
855 value = self.GetCellValue(row,col)
856 try:
857 int(value)
858 if col == 2:
859 self.saves[row].setAttribute('base',value)
860 elif col ==4:
861 self.saves[row].setAttribute('magmod',value)
862 elif col ==5: # 1.5001
863 self.saves[row].setAttribute('miscmod',value)
864 self.refresh_row(row)
865 except:
866 self.SetCellValue(row,col,"0")
867
868 def refresh_row(self,rowi):
869 s = self.saves[rowi]
870
871 name = s.getAttribute('name')
872 self.SetCellValue(rowi,0,name)
873 self.SetReadOnly(rowi,0)
874 stat = s.getAttribute('stat')
875 self.SetCellValue(rowi,1,stat)
876 self.SetReadOnly(rowi,1)
877 self.SetCellValue(rowi,2,s.getAttribute('base'))
878 self.SetCellValue(rowi,3,str(self.root.abilities.get_mod(stat)))
879 self.SetReadOnly(rowi,3)
880 self.SetCellValue(rowi,4,s.getAttribute('magmod'))
881 self.SetCellValue(rowi,5,s.getAttribute('miscmod'))
882 mod = str(self.handler.get_mod(name))
883 self.SetCellValue(rowi,6,mod)
884 self.SetReadOnly(rowi,6)
885
886 def on_size(self,evt):
887 (w,h) = self.GetClientSizeTuple()
888 cols = self.GetNumberCols()
889 col_w = w/(cols+2)
890 self.SetColSize(0,col_w*3)
891 for i in range(1,cols):
892 self.SetColSize(i,col_w)
893 evt.Skip()
894 self.Refresh()
895
896 def refresh_data(self):
897 for r in range(self.GetNumberRows()):
898 self.refresh_row(r)
899
900 class dnd35skillsnfeats(dnd35_char_child):
901 """ Node handler for a dnd35 charactor
902 <nodehandler name='?' module='dnd35' class='dnd35char_handler2' />
903 """
904 def __init__(self,xml_dom,tree_node,parent):
905 self.hparent = parent #a 1.5002 allow ability to run up tree.
906 self.root = getRoot(self) #a 1.6009
907
908 node_handler.__init__(self,xml_dom,tree_node)
909 dnd35_char_child.__init__(self,xml_dom,tree_node,parent)
910 self.frame = open_rpg.get_component('frame')
911 self.child_handlers = {}
912 self.new_child_handler('skills','Skills',dnd35skill,'book')
913 self.new_child_handler('feats','Feats',dnd35feats,'book')
914 self.myeditor = None
915
916
917 def new_child_handler(self,tag,text,handler_class,icon='gear'):
918 node_list = self.master_dom.getElementsByTagName(tag)
919 tree = self.tree
920 i = self.tree.icons[icon]
921 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i)
922 handler = handler_class(node_list[0],new_tree_node,self)
923 tree.SetPyData(new_tree_node,handler)
924 self.child_handlers[tag] = handler
925
926 def get_design_panel(self,parent):
927 return tabbed_panel(parent,self,1)
928
929
930 def get_use_panel(self,parent):
931 return tabbed_panel(parent,self,2)
932
933 class skills_char_child(node_handler):
934 """ Node Handler for skill. This handler will be
935 created by dnd35char_handler.
936 """
937 def __init__(self,xml_dom,tree_node,parent):
938 node_handler.__init__(self,xml_dom,tree_node)
939 self.char_hander = parent
940 self.drag = False
941 self.frame = open_rpg.get_component('frame')
942 self.myeditor = None
943
944
945
946 def on_drop(self,evt):
947 pass
948
949 def on_rclick(self,evt):
950 pass
951
952 def on_ldclick(self,evt):
953 return
954
955 def on_html(self,evt):
956 html_str = self.tohtml()
957 wnd = http_html_window(self.frame.note,-1)
958 wnd.title = self.master_dom.getAttribute('name')
959 self.frame.add_panel(wnd)
960 wnd.SetPage(html_str)
961
962 def get_design_panel(self,parent):
963 pass
964
965 def get_use_panel(self,parent):
966 return self.get_design_panel(parent)
967
968 def delete(self):
969 pass
970
971 class dnd35skill(skills_char_child):
972 """ Node Handler for skill. This handler will be
973 created by dnd35char_handler.
974 """
975 def __init__(self,xml_dom,tree_node,parent):
976 self.hparent = parent #a 1.5002 allow ability to run up tree.
977 #a 1.5002 Need the functional parent, not the invoking parent.
978 self.root = getRoot(self) #a 1.5002
979 self.root.skills = self #a 1.6009
980
981 skills_char_child.__init__(self,xml_dom,tree_node,parent)
982 tree = self.tree
983 icons = self.tree.icons
984 node_list = self.master_dom.getElementsByTagName('skill')
985
986 self.skills={}
987 #Adding code to not display skills you can not use -mgt
988 for n in node_list:
989 name = n.getAttribute('name')
990 self.skills[name] = n
991 skill_check = self.skills[name]
992 ranks = int(skill_check.getAttribute('rank'))
993 trained = int(skill_check.getAttribute('untrained'))
994
995 if ranks > 0 or trained == 1:
996 new_tree_node = tree.AppendItem(self.mytree_node,name,
997 icons['gear'],icons['gear'])
998 else:
999 continue
1000
1001 tree.SetPyData(new_tree_node,self)
1002
1003
1004
1005 def refresh_skills(self):
1006 #Adding this so when you update the grid the tree will reflect
1007 #The change. -mgt
1008 tree = self.tree
1009 icons = self.tree.icons
1010 tree.CollapseAndReset(self.mytree_node)
1011 node_list = self.master_dom.getElementsByTagName('skill')
1012
1013 self.skills={}
1014 for n in node_list:
1015 name = n.getAttribute('name')
1016 self.skills[name] = n
1017 skill_check = self.skills[name]
1018 ranks = int(skill_check.getAttribute('rank'))
1019 trained = int(skill_check.getAttribute('untrained'))
1020
1021 if ranks > 0 or trained == 1:
1022 new_tree_node = tree.AppendItem(self.mytree_node,name,
1023 icons['gear'],icons['gear'])
1024 else:
1025 continue
1026
1027 tree.SetPyData(new_tree_node,self)
1028
1029 def get_mod(self,name):
1030 skill = self.skills[name]
1031 stat = skill.getAttribute('stat')
1032 #stat_mod = int(dnd_globals["stats"][stat]) #d 1.5002
1033 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002
1034 rank = int(skill.getAttribute('rank'))
1035 misc = int(skill.getAttribute('misc'))
1036 total = stat_mod + rank + misc
1037 return total
1038
1039 def on_rclick(self,evt):
1040 item = self.tree.GetSelection()
1041 name = self.tree.GetItemText(item)
1042 #print "skill rc self",self #a 1.6004
1043 #print "skill rc tree",self.mytree_node #a 1.6004
1044 #print "skill rc item",item #a 1.6004
1045 if item == self.mytree_node:
1046 return
1047 # following line fails,
1048 #dnd35_char_child.on_ldclick(self,evt) #d 1.6014
1049 # it's what it used to try to do.
1050 ac = self.root.ac.get_check_pen() #a 1.5002 for 1.5004 verify fix.
1051
1052 skill = self.skills[name]
1053
1054 untr = skill.getAttribute('untrained') #a 1.6004
1055 rank = skill.getAttribute('rank') #a 1.6004
1056 if eval('%s == 0' % (untr)): #a 1.6004
1057 if eval('%s == 0' % (rank)): #a 1.6004
1058 res = 'You fumble around, accomplishing nothing' #a 1.6004
1059 txt = '%s Skill Check: %s' % (name, res) #a 1.6004
1060 chat = self.chat #a 1.6004
1061 chat.Post(txt,True,True) #a 1.6004
1062 return #a 1.6004
1063
1064 armor = ''
1065 acCp = ''
1066 if ac < 0: #acCp >= 1 #m 1.5004 this is stored as negatives.
1067 armorCheck = int(skill.getAttribute('armorcheck'))
1068 #print "ac,armorCheck",ac,armorCheck
1069 if armorCheck == 1:
1070 acCp=ac
1071 armor = '(includes Armor Penalty of %s)' % (acCp)
1072 if item == self.mytree_node:
1073 dnd35_char_child.on_ldclick(self,evt)
1074 #wnd = skill_grid(self.frame.note,self)
1075 #wnd.title = "Skills"
1076 #self.frame.add_panel(wnd)
1077 else:
1078 mod = self.get_mod(name)
1079 if mod >= 0:
1080 mod1 = "+"
1081 else:
1082 mod1 = ""
1083 chat = self.chat
1084 txt = '%s Skill Check: [1d20%s%s%s] %s' % (
1085 name, mod1, mod, acCp, armor)
1086 chat.ParsePost(txt,True,True)
1087
1088 def get_design_panel(self,parent):
1089 wnd = outline_panel(parent,self,skill_grid,"Skills")
1090 wnd.title = "Skills (edit)"
1091 return wnd
1092
1093 def tohtml(self):
1094 html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 >
1095 <th width='30%'>Skill</th><th>Key</th>
1096 <th>Rank</th><th>Abil</th><th>Misc</th><th>Total</th></tr>"""
1097 node_list = self.master_dom.getElementsByTagName('skill')
1098
1099 for n in node_list:
1100 name = n.getAttribute('name')
1101 stat = n.getAttribute('stat')
1102 rank = n.getAttribute('rank')
1103 untr = n.getAttribute('untrained') #a 1.6004
1104 #Filter unsuable skills out of pretty print -mgt
1105 if eval('%s > 0' % (rank)) or eval('%s == 1' % (untr)):
1106 if eval('%s >=1' % (rank)):
1107 html_str += "<tr ALIGN='center' bgcolor='#CCCCFF'><td>" #a 1.6004
1108 #html_str += "<tr ALIGN='center' bgcolor='green'><td>" #d 1.6004
1109 html_str += name+"</td><td>"+stat+"</td><td>"+rank+"</td>"
1110 elif eval('%s == 1' % (untr)): #a 1.6004
1111 html_str += "<tr ALIGN='center' bgcolor='#C0FF40'><td>" #a 1.6004
1112 html_str += name+"</td><td>"+stat+"</td><td>"+rank+"</td>" #a 1.6004
1113 else:
1114 html_str += "<tr ALIGN='center'><td>"+name+"</td><td>"
1115 html_str += stat+"</td><td>"+rank+"</td>"
1116 else:
1117 continue
1118 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002
1119 #stat_mod = str(dnd_globals["stats"][stat]) #d 1.5002
1120 misc = n.getAttribute('misc')
1121 mod = str(self.get_mod(name))
1122 if mod >= 0:
1123 mod1 = "+"
1124 else:
1125 mod1 = ""
1126 html_str += "<td>"+str(stat_mod)+"</td><td>"+misc #m 1.6009 str()
1127 html_str += '</td><td>%s%s</td></tr>' % (mod1, mod)
1128 html_str = html_str + "</table>"
1129 return html_str
1130
1131
1132 class skill_grid(wx.grid.Grid):
1133 """ panel for skills """
1134 def __init__(self, parent, handler):
1135 self.hparent = handler #a 1.5002 need function parent, not invoker
1136 self.root = getRoot(self) #a 1.5002
1137 pname = handler.master_dom.setAttribute("name", 'Skills')
1138
1139 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
1140 self.Bind(wx.EVT_SIZE, self.on_size)
1141 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
1142 self.handler = handler
1143 skills = handler.master_dom.getElementsByTagName('skill')
1144 #xelf.stats = dnd_globals["stats"] #d 1.5002
1145
1146 self.CreateGrid(len(skills),6)
1147 self.SetRowLabelSize(0)
1148 col_names = ['Skill','Key','Rank','Abil','Misc','Total']
1149 for i in range(len(col_names)):
1150 self.SetColLabelValue(i,col_names[i])
1151 rowi = 0
1152 self.skills = skills
1153 for i in range(len(skills)):
1154 self.refresh_row(i)
1155
1156 def on_cell_change(self,evt):
1157 row = evt.GetRow()
1158 col = evt.GetCol()
1159 value = self.GetCellValue(row,col)
1160 #print value
1161 try:
1162 int(value)
1163 if col == 2:
1164 self.skills[row].setAttribute('rank',value)
1165 elif col ==4:
1166 self.skills[row].setAttribute('misc',value)
1167 self.refresh_row(row)
1168 except:
1169 self.SetCellValue(row,col,"0")
1170
1171 #call refresh_skills
1172 self.handler.refresh_skills()
1173
1174 def refresh_row(self,rowi):
1175 s = self.skills[rowi]
1176 name = s.getAttribute('name')
1177 self.SetCellValue(rowi,0,name)
1178 self.SetReadOnly(rowi,0)
1179 stat = s.getAttribute('stat')
1180 self.SetCellValue(rowi,1,stat)
1181 self.SetReadOnly(rowi,1)
1182 self.SetCellValue(rowi,2,s.getAttribute('rank'))
1183 #self.SetCellValue(rowi,3,str(dnd_globals["stats"][stat])) #d 1.5002
1184 if self.root.abilities: #a 1.5002 sanity check.
1185 stat_mod=self.root.abilities.get_mod(stat) #a 1.5002
1186 else: #a 1.5002
1187 stat_mod = -6 #a 1.5002 this can happen if code is changed so
1188 #a 1.5002 that abilities are not defined prior invokation of init.
1189 print "Please advise dnd35 maintainer alert 1.5002 raised"
1190
1191 self.SetCellValue(rowi,3,str(stat_mod)) #a 1.5002
1192 self.SetReadOnly(rowi,3)
1193 self.SetCellValue(rowi,4,s.getAttribute('misc'))
1194 mod = str(self.handler.get_mod(name))
1195 self.SetCellValue(rowi,5,mod)
1196 self.SetReadOnly(rowi,5)
1197
1198 def on_size(self,evt):
1199 (w,h) = self.GetClientSizeTuple()
1200 cols = self.GetNumberCols()
1201 col_w = w/(cols+2)
1202 self.SetColSize(0,col_w*3)
1203 for i in range(1,cols):
1204 self.SetColSize(i,col_w)
1205 evt.Skip()
1206 self.Refresh()
1207
1208 def refresh_data(self):
1209
1210 for r in range(self.GetNumberRows()):
1211 self.refresh_row(r)
1212
1213
1214
1215
1216 class dnd35feats(skills_char_child):
1217 """ Node Handler for classes. This handler will be
1218 created by dnd35char_handler.
1219 """
1220 def __init__(self,xml_dom,tree_node,parent):
1221 skills_char_child.__init__(self,xml_dom,tree_node,parent)
1222 self.hparent = parent #a 1.5002 allow ability to run up tree.
1223 self.root = getRoot(self) #a 1.5002
1224 self.root.feats = self #a 1.6009
1225
1226
1227 def get_design_panel(self,parent):
1228 setTitle="Feats - " + self.root.general.charName #a 1.5010
1229 wnd = outline_panel(parent,self,feat_panel,setTitle) #a 1.5010
1230 #wnd = outline_panel(parent,self,feat_panel,"Feats") #d 1.5010
1231 wnd.title = "Feats" #d 1.5010
1232 #wnd.title = "Feats - " + self.charName
1233 return wnd
1234
1235 def tohtml(self):
1236 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Feats</th></tr><tr><td>"
1237 n_list = self.master_dom._get_childNodes()
1238 for n in n_list:
1239 html_str += n.getAttribute('name')+ ", "
1240 html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
1241 return html_str
1242
1243 class feat_panel(wx.Panel):
1244 def __init__(self, parent, handler):
1245
1246 self.hparent = handler #a 1.5002 allow ability to run up tree.
1247 #a 1.5002 in this case, we need the functional parent, not the invoking parent.
1248 self.root = getRoot(self) #a 1.5002
1249 #tempTitle= 'Feats - ' + self.root.general.charName #a 1.5010
1250 #pname = handler.master_dom.setAttribute("name", tempTitle) #a 1.5010
1251 pname = handler.master_dom.setAttribute("name", 'Feats') #d 1.5010
1252
1253 wx.Panel.__init__(self, parent, -1)
1254 self.grid = wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
1255 sizer = wx.BoxSizer(wx.VERTICAL)
1256 sizer.Add(self.grid, 1, wx.EXPAND)
1257
1258 sizer1 = wx.BoxSizer(wx.HORIZONTAL)
1259 sizer1.Add(wx.Button(self, 10, "Remove Feat"), 0, wx.EXPAND)
1260 sizer1.Add(wx.Size(10,10))
1261 sizer1.Add(wx.Button(self, 20, "Add Feat"), 0, wx.EXPAND)
1262
1263 sizer.Add(sizer1, 0, wx.EXPAND)
1264 self.sizer = sizer
1265
1266 self.SetSizer(self.sizer)
1267 self.SetAutoLayout(True)
1268 self.Fit()
1269
1270 #self.Bind(wx.EVT_SIZE, self.on_size)
1271 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10)
1272 self.Bind(wx.EVT_BUTTON, self.on_add, id=20)
1273
1274 n_list = handler.master_dom._get_childNodes()
1275 self.n_list = n_list
1276 self.master_dom = handler.master_dom
1277 self.grid.CreateGrid(len(n_list),3,1)
1278 self.grid.SetRowLabelSize(0)
1279 self.grid.SetColLabelValue(0,"Feat")
1280 self.grid.SetColLabelValue(1,"Reference")
1281 self.grid.SetColLabelValue(2,"Description") #m 1.6 typo correction.
1282 wrap = wx.grid.GridCellAutoWrapStringRenderer()
1283 attr = wx.grid.GridCellAttr()
1284 attr.SetRenderer(wrap)
1285 self.grid.SetColAttr(2, attr)
1286 for i in range(len(n_list)):
1287 self.refresh_row(i)
1288 self.temp_dom = None
1289
1290 def refresh_row(self,i):
1291 feat = self.n_list[i]
1292
1293 name = feat.getAttribute('name')
1294 type = feat.getAttribute('type')
1295 desc = feat.getAttribute('desc') #m 1.6 correct typo
1296 self.grid.SetCellValue(i,0,name)
1297 self.grid.SetReadOnly(i,0)
1298 self.grid.SetCellValue(i,1,type)
1299 self.grid.SetReadOnly(i,1)
1300 self.grid.SetCellValue(i,2,desc) #m 1.6 correct typo
1301 self.grid.SetReadOnly(i,2)
1302 self.grid.AutoSizeColumn(0)
1303 self.grid.AutoSizeColumn(1)
1304 self.grid.AutoSizeColumn(2, False)
1305 self.grid.AutoSizeRow(i)
1306
1307 def on_remove(self,evt):
1308 rows = self.grid.GetNumberRows()
1309 for i in range(rows):
1310 if self.grid.IsInSelection(i,0):
1311 self.grid.DeleteRows(i)
1312 self.master_dom.removeChild(self.n_list[i])
1313
1314 def on_add(self,evt):
1315
1316 if not self.temp_dom:
1317 tmp = open(orpg.dirpath.dir_struct["dnd35"]+"dnd35feats.xml","r")
1318 xml_dom = parseXml_with_dlg(self,tmp.read())
1319 xml_dom = xml_dom._get_firstChild()
1320 tmp.close()
1321 self.temp_dom = xml_dom
1322 f_list = self.temp_dom.getElementsByTagName('feat')
1323 opts = []
1324 for f in f_list:
1325 opts.append(f.getAttribute('name') + " - [" +
1326 f.getAttribute('type') + "] - " + f.getAttribute('desc'))
1327 dlg = wx.SingleChoiceDialog(self,'Choose Feat','Feats',opts)
1328 if dlg.ShowModal() == wx.ID_OK:
1329 i = dlg.GetSelection()
1330 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
1331 self.grid.AppendRows(1)
1332 self.refresh_row(self.grid.GetNumberRows()-1)
1333 dlg.Destroy()
1334
1335
1336 def on_size(self,event):
1337 s = self.GetClientSizeTuple()
1338 self.grid.SetDimensions(0,0,s[0],s[1]-25)
1339 self.sizer.SetDimension(0,s[1]-25,s[0],25)
1340 (w,h) = self.grid.GetClientSizeTuple()
1341 cols = self.grid.GetNumberCols()
1342 col_w = w/(cols)
1343 for i in range(0,cols):
1344 self.grid.SetColSize(i,col_w)
1345
1346 class dnd35combat(dnd35_char_child):
1347 """ Node handler for a dnd35 charactor
1348 <nodehandler name='?' module='dnd35' class='dnd35char_handler2' />
1349 """
1350 def __init__(self,xml_dom,tree_node,parent):
1351
1352 node_handler.__init__(self,xml_dom,tree_node)
1353
1354 self.hparent = parent #a 1.5002 allow ability to run up tree.
1355 self.root = getRoot(self) #a 1.5012
1356
1357
1358
1359 #mark3
1360 dnd35_char_child.__init__(self,xml_dom,tree_node,parent)
1361 self.frame = open_rpg.get_component('frame')
1362 self.child_handlers = {}
1363 self.new_child_handler('hp','Hit Points',dnd35hp,'gear')
1364 self.new_child_handler('attacks','Attacks',dnd35attacks,'spears')
1365 self.new_child_handler('ac','Armor',dnd35armor,'spears')
1366 #print "combat",self.child_handlers #a (debug) 1.5002
1367 #wxMenuItem(self.tree.std_menu, dnd35_EXPORT, "Export...", "Export")
1368 self.myeditor = None
1369
1370
1371 def new_child_handler(self,tag,text,handler_class,icon='gear'):
1372 node_list = self.master_dom.getElementsByTagName(tag)
1373 tree = self.tree
1374 i = self.tree.icons[icon]
1375 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i)
1376 handler = handler_class(node_list[0],new_tree_node,self)
1377 tree.SetPyData(new_tree_node,handler)
1378 self.child_handlers[tag] = handler
1379
1380 def get_design_panel(self,parent):
1381 return tabbed_panel(parent,self,1)
1382
1383 def get_use_panel(self,parent):
1384 return tabbed_panel(parent,self,2)
1385
1386
1387 class combat_char_child(node_handler):
1388 """ Node Handler for combat. This handler will be
1389 created by dnd35char_handler.
1390 """
1391 def __init__(self,xml_dom,tree_node,parent):
1392 node_handler.__init__(self,xml_dom,tree_node)
1393 self.char_hander = parent
1394 self.drag = False
1395 self.frame = open_rpg.get_component('frame')
1396 self.myeditor = None
1397
1398
1399 def on_drop(self,evt):
1400 pass
1401
1402 def on_rclick(self,evt):
1403 pass
1404
1405 def on_ldclick(self,evt):
1406 return
1407
1408 def on_html(self,evt):
1409 html_str = self.tohtml()
1410 wnd = http_html_window(self.frame.note,-1)
1411 wnd.title = self.master_dom.getAttribute('name')
1412 self.frame.add_panel(wnd)
1413 wnd.SetPage(html_str)
1414
1415 def get_design_panel(self,parent):
1416 pass
1417
1418 def get_use_panel(self,parent):
1419 return self.get_design_panel(parent)
1420
1421 def delete(self):
1422 pass
1423
1424 class dnd35hp(combat_char_child):
1425 """ Node Handler for hit points. This handler will be
1426 created by dnd35char_handler.
1427 """
1428 def __init__(self,xml_dom,tree_node,parent):
1429 combat_char_child.__init__(self,xml_dom,tree_node,parent)
1430 self.hparent = parent #a 1.5002 allow ability to run up tree.
1431 self.root = getRoot(self) #a 1.6009
1432 self.root.hp = self #a 1.6009
1433
1434 def get_design_panel(self,parent):
1435 wnd = outline_panel(parent,self,hp_panel,"Hit Points")
1436 wnd.title = "Hit Points"
1437 return wnd
1438
1439 def on_rclick( self, evt ):
1440 chp = self.master_dom.getAttribute('current')
1441 mhp = self.master_dom.getAttribute('max')
1442 txt = '((HP: %s / %s))' % ( chp, mhp )
1443 self.chat.ParsePost( txt, True, True )
1444
1445 def tohtml(self):
1446 html_str = "<table width=100% border=1 >"
1447 html_str += "<tr BGCOLOR=#E9E9E9 ><th colspan=4>Hit Points</th></tr>"
1448 html_str += "<tr><th>Max:</th>"
1449 html_str += "<td>"+self.master_dom.getAttribute('max')+"</td>"
1450 html_str += "<th>Current:</th>"
1451 html_str += "<td>"+self.master_dom.getAttribute('current')+"</td>"
1452 html_str += "</tr></table>"
1453 return html_str
1454
1455 class hp_panel(wx.Panel):
1456 def __init__(self, parent, handler):
1457 wx.Panel.__init__(self, parent, -1)
1458 self.hparent = handler #a 1.5002 allow ability to run up tree. In this
1459 #a 1.5002 case, we need the functional parent, not the invoking parent.
1460
1461 pname = handler.master_dom.setAttribute("name", 'HitPoints')
1462 self.sizer = wx.FlexGridSizer(2, 4, 2, 2) # rows, cols, hgap, vgap
1463 self.master_dom = handler.master_dom
1464 self.sizer.AddMany([ (wx.StaticText(self, -1, "HP Current:"), 0,
1465 wx.ALIGN_CENTER_VERTICAL),
1466 (wx.TextCtrl(self, HP_CUR,
1467 self.master_dom.getAttribute('current')), 0, wx.EXPAND),
1468 (wx.StaticText(self, -1, "HP Max:"), 0, wx.ALIGN_CENTER_VERTICAL),
1469 (wx.TextCtrl(self, HP_MAX, self.master_dom.getAttribute('max')),
1470 0, wx.EXPAND),
1471 ])
1472 self.sizer.AddGrowableCol(1)
1473 self.SetSizer(self.sizer)
1474 self.SetAutoLayout(True)
1475 self.Fit()
1476
1477 #self.Bind(wx.EVT_SIZE, self.on_size)
1478 self.Bind(wx.EVT_TEXT, self.on_text, id=HP_MAX)
1479 self.Bind(wx.EVT_TEXT, self.on_text, id=HP_CUR)
1480
1481 def on_text(self,evt):
1482 id = evt.GetId()
1483 if id == HP_CUR:
1484 self.master_dom.setAttribute('current',evt.GetString())
1485 elif id == HP_MAX:
1486 self.master_dom.setAttribute('max',evt.GetString())
1487
1488 def on_size(self,evt):
1489 s = self.GetClientSizeTuple()
1490 self.sizer.SetDimension(0,0,s[0],s[1])
1491
1492 class dnd35attacks(combat_char_child):
1493 """ Node Handler for attacks. This handler will be
1494 created by dnd35char_handler.
1495 """
1496 def __init__(self,xml_dom,tree_node,parent):
1497 combat_char_child.__init__(self,xml_dom,tree_node,parent)
1498 self.hparent = parent #a 1.5002 allow ability to run up tree.
1499 self.root = getRoot(self) #a 1.5002
1500 self.root.attacks = self #a 1.6009 so others can find me.
1501 self.mrFrame = [] #a 1.9001
1502
1503 #a 1.5012 start a1b
1504
1505 self.updateFootNotes = False
1506 self.updateFootNotes = False
1507 self.html_str = "<html><body>"
1508 self.html_str += ("<br /> This character has weapons with no "+
1509 "footnotes. This program will "+
1510 "add footnotes to the weapons which have names that still match "+
1511 "the orginal names. If you have changed the weapon name, you "+
1512 "will see some weapons with a footnote of 'X', you will have "+
1513 "to either delete and re-add the weapon, or research "+
1514 "and add the correct footnotes for the weapon.\n"+
1515 "<br /> Please be aware, that only the bow/sling footnote is "+
1516 "being used to affect changes to rolls; implemenation of other "+
1517 "footnotes to automaticly adjust rolls will be completed as "+
1518 "soon as time allows." +
1519 "<br /><br />Update to character:"+self.root.general.charName+
1520 "<br /><br />"+
1521 """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 >
1522 <th width='80%'>Weapon Name</th><th>Added Footnote</th></tr>\n""")
1523 self.temp_dom={}
1524 #a 1.5012 end a1b
1525
1526 node_list = self.master_dom.getElementsByTagName('melee')
1527 self.melee = node_list[0]
1528 node_list = self.master_dom.getElementsByTagName('ranged')
1529 self.ranged = node_list[0]
1530 self.refresh_weapons() # this causes self.weapons to be loaded.
1531
1532 #a 1.5012 this whole if clause.
1533 if self.updateFootNotes == True:
1534 self.updateFootNotes = False
1535 name = self.root.general.charName
1536 self.html_str += "</table>"
1537 self.html_str += "</body> </html> "
1538 masterFrame = self.root.frame
1539
1540 title = name+"'s weapons' update to have footnotes"
1541 fnFrame = wx.Frame(masterFrame, -1, title)
1542 fnFrame.panel = wx.html.HtmlWindow(fnFrame,-1)
1543 fnFrame.panel.SetPage(self.html_str)
1544 fnFrame.Show()
1545
1546 #weaponsH = self.master_dom.getElementsByTagName('attacks')
1547 #mark7
1548
1549 #a 1.9001 this whole method
1550 def refreshMRdata(self): # refresh the data in the melee/ranged section
1551 # of the attack chart.
1552 # count backwards, maintains context despite "removes"
1553 for i in range(len(self.mrFrame)-1,-1,-1): #a 1.9001
1554 x = self.mrFrame[i]
1555 if x == None:
1556 x.refreshMRdata() #a 1.9001
1557 else:
1558 self.mrFrame.remove(x)
1559
1560 def refresh_weapons(self):
1561 self.weapons = {}
1562
1563 tree = self.tree
1564 icons = self.tree.icons
1565 tree.CollapseAndReset(self.mytree_node)
1566 node_list = self.master_dom.getElementsByTagName('weapon')
1567 for n in node_list:
1568 name = n.getAttribute('name')
1569 fn = safeGetAttr(n,'fn') #a 1.5012 can be removed when
1570 #a 1.5012 confident all characters in the world have footnotes.
1571 #if self.updateFootNotes:
1572 if fn == None:#a 1.5012
1573 self.updateFootNotes=True
1574 self.updateFootN(n) #a 1.5012
1575 new_tree_node = tree.AppendItem(
1576 self.mytree_node,name,icons['sword'],icons['sword'])
1577 tree.SetPyData(new_tree_node,self)
1578 self.weapons[name]=n
1579
1580 def updateFootN(self,n):#a 1.5012 this whole function
1581 if not self.temp_dom:
1582 tmp = open(orpg.dirpath.dir_struct["dnd35"]+"dnd35weapons.xml","r")
1583 #tmp = open("c:\clh\codeSamples\sample1.xml","r") #a (debug) 1.5012
1584 self.temp_dom = xml.dom.minidom.parse(tmp)
1585
1586 #self.temp_dom = parseXml_with_dlg(self,tmp.read())
1587 self.temp_dom = self.temp_dom._get_firstChild()
1588 tmp.close()
1589 nameF = n.getAttribute('name')
1590 w_list = self.temp_dom.getElementsByTagName('weapon')
1591 found = False
1592 for w in w_list:
1593 if nameF == w.getAttribute('name'):
1594 found = True
1595 fnN = safeGetAttr(n,'fn')
1596 if fnN == None or fnN == 'None':
1597 fnW = w.getAttribute('fn')
1598 #print "weapon",nameF,"footnotes are updated to",fnW
1599 self.html_str += ("<tr ALIGN='center'><td>"+nameF+"</td>"+
1600 "<td>"+fnW+"</td></tr>\n")
1601 n.setAttribute('fn',fnW)
1602 break
1603 if not found:
1604 self.html_str += ("<tr ALIGN='center'><td>"+nameF+" - Custom "+
1605 "Weapon, research "+
1606 "and update manually; setting footnote to indicate custom</td>"+
1607 "<td>"+'X'+"</td></tr>\n")
1608 n.setAttribute('fn','X')
1609
1610
1611 def get_mod(self,type='m'):
1612 (base, base2, base3, base4, base5, base6, stat_mod, misc) \
1613 = self.get_attack_data(type)
1614 return int(base + misc + int(stat_mod))
1615
1616 def get_attack_data(self,type='m'):
1617 if type=='m' or type=='0':
1618 stat = 'Str' #m was dnd_globals["stats"]['Str'] 1.5002
1619 temp = self.melee
1620 else:
1621 stat = 'Dex' #m was dnd_globals["stats"]['Dex'] 1.5002
1622 temp = self.ranged
1623 stat_mod = -7
1624 stat_mod = self.root.abilities.get_mod(stat) #a 1.5002
1625 #print "Big test - stat_mod",stat_mod #a (debug) 1.6000
1626 base = int(temp.getAttribute('base'))
1627 base2 = int(temp.getAttribute('second'))
1628 base3 = int(temp.getAttribute('third'))
1629 base4 = int(temp.getAttribute('forth'))
1630 base5 = int(temp.getAttribute('fifth'))
1631 base6 = int(temp.getAttribute('sixth'))
1632 misc = int(temp.getAttribute('misc'))
1633 return (base, base2, base3, base4, base5, base6, stat_mod ,misc)
1634
1635 def on_rclick(self,evt):
1636 item = self.tree.GetSelection()
1637
1638 name = self.tree.GetItemText(item)
1639 if item == self.mytree_node:
1640 #print "bail due to FUD"
1641 return #a 1.6015
1642 #dnd35_char_child.on_ldclick(self,evt)#d 1.6015
1643 #self.frame.add_panel(self.get_design_panel(self.frame.note))
1644 else:
1645 #print "entering attack phase"
1646 mod = int(self.weapons[name].getAttribute('mod'))
1647 wepMod = mod #a 1.5008
1648 footNotes = safeGetAttr(self.weapons[name],'fn','')
1649 cat = self.weapons[name].getAttribute('category') #a1.6001
1650 result = split(cat,"-",2) #a 1.6001
1651 if len(result) < 2: #a 1.6021 this if & else
1652 print "warning: 1.6002 unable to interpret weapon category"
1653 print "format 'type weapon-[Range|Melee]', probably missing"
1654 print "the hyphen. Assuming Melee"
1655 print "weapon name: ",name
1656 tres="Melee"
1657 else:
1658 tres=result[1]
1659 #print "print FootNotes,tres",footNotes,tres
1660 if tres == 'Melee': #a 1.6001 #m 1.6022 use of tres here and...
1661 #if self.weapons[name].getAttribute('range') == '0':#d 1.6001
1662 rangeOrMelee = 'm' #a 1.5008 code demote for next comment block
1663 elif tres == 'Ranged': #m 1.6001 (was just else) #m 1.6022 here
1664 rangeOrMelee = 'r' #a 1.5008
1665 else:#a 1.6001 add this whole else clause.
1666 print "warning: 1.6001 unable to interpret weapon category"
1667 print "treating weapon as Melee, please correct xml"
1668 print "weapon name:",name
1669 rangeOrMelee ='m'
1670 mod = mod + self.get_mod(rangeOrMelee) #a 1.5008
1671 chat = self.chat
1672 dmg = self.weapons[name].getAttribute('damage')
1673
1674 #a 1.6003 start code fix instance a
1675 result = split(dmg,"/",2)
1676 dmg = result[0]
1677 #print "1.6003 check:dmg",dmg,";result",result
1678 #o currently, only picking out dmg; rest are simply ignored.
1679 #o May be usefull
1680 #o later for two weapon attack correction.
1681 #a 1.6003 end code fix instance a
1682
1683 monkLvl = self.root.classes.get_class_lvl('Monk') # a 1.5002
1684 #print "monkLvl",monkLvl #a (debug) 1.5002
1685 # monkLvl = dnd_globals["class"]["lvl"] #d 1.5002
1686 if find(dmg, "Monk Med") > -1:
1687 if monkLvl == None: #a 1.5009
1688 txt = 'Attempting to use monk attack, but has no monk '
1689 txt += 'levels, please choose a different attack.'
1690 chat.ParsePost( txt, True, True ) #a 1.5009
1691 return #a 1.5009
1692 else: #a 1.5009
1693 lvl=int(monkLvl)
1694 if lvl <= 3: #m 1.6022 reversed the order of checks.
1695 dmg = dmg.replace("Monk Med", "1d6")
1696 elif lvl <= 7:
1697 dmg = dmg.replace("Monk Med", "1d8")
1698 elif lvl <= 11:
1699 dmg = dmg.replace("Monk Med", "1d10")
1700 elif lvl <= 15:
1701 dmg = dmg.replace("Monk Med", "2d6")
1702 elif lvl <= 19:
1703 dmg = dmg.replace("Monk Med", "2d8")
1704 elif lvl <= 20:
1705 dmg = dmg.replace("Monk Med", "2d10")
1706 if find(dmg, "Monk Small") > -1:
1707 if monkLvl == None: #a 1.5009
1708 txt = 'Attempting to use monk attack, but has no monk '
1709 txt += 'levels, please choose a different attack.'
1710 chat.ParsePost( txt, True, True ) #a 1.5009
1711 return #a 1.5009
1712 else: #a 1.5009
1713 lvl=int(monkLvl)
1714 if lvl <= 3: #m 1.6022 reversed the order of the checks
1715 dmg = dmg.replace("Monk Small", "1d4")
1716 elif lvl <= 7:
1717 dmg = dmg.replace("Monk Small", "1d6")
1718 elif lvl <= 11:
1719 dmg = dmg.replace("Monk Small", "1d8")
1720 elif lvl <= 15:
1721 dmg = dmg.replace("Monk Small", "1d10")
1722 elif lvl <= 19:
1723 dmg = dmg.replace("Monk Small", "2d6")
1724 elif lvl <= 20:
1725 dmg = dmg.replace("Monk Small", "2d8")
1726 if find(dmg, "Monk Large") > -1:
1727 if monkLvl == None: #a 1.5009
1728 txt = 'Attempting to use monk attack, but has no monk '
1729 txt += 'levels, please choose a different attack.'
1730 chat.ParsePost( txt, True, True ) #a 1.5009
1731 return #a 1.5009
1732 else: #a 1.5009
1733 lvl=int(monkLvl)
1734 if lvl <= 3: #m 1.6022 reversed the order of the checks
1735 dmg = dmg.replace("Monk Large", "1d8")
1736 elif lvl <= 7:
1737 dmg = dmg.replace("Monk Large", "2d6")
1738 elif lvl <= 11:
1739 dmg = dmg.replace("Monk Large", "2d8")
1740 elif lvl <= 15:
1741 dmg = dmg.replace("Monk Large", "3d6")
1742 elif lvl <= 19:
1743 dmg = dmg.replace("Monk Large", "3d8")
1744 elif lvl <= 20:
1745 dmg = dmg.replace("Monk Large", "4d8")
1746 flurry = False
1747 #print "adjusted weapon damage is:",dmg
1748 #o 1.5007 str bow
1749 #o 1.5011 start looking about here str dam bonus missed for thrown?
1750 #o 1.5012 start looking about here str penalty missed for bow/sling?
1751 #o 1.5013 off-hand attacks.? dam and all affects?
1752 str_mod = self.root.abilities.get_mod('Str') #a 1.5007,11,12,13
1753 if rangeOrMelee == 'r': #a 1.5008
1754 #if off_hand == True then stat_mod = stat_mod/2 #o 1.5013
1755 #c 1.5007 ranged weapons normally get no str mod
1756 if find(footNotes,'b') > -1:#a 1.5012 if it's a bow
1757 if str_mod >= 0: #a 1.5012 never a str bonus
1758 str_mod = 0 #a 1.5012 penalty,
1759 else: #a 1.5012 if appropriate
1760 str_mod = 0
1761 # c 1.5007 (must adjust for str bows later and thown weapons)
1762 #o 1.5007 include + for str bows
1763 #o 1.5012 include any str penalty for bows/slings.
1764 mod2 = "" #a 1.5007,11-13
1765 if str_mod >= 0: #1.6 tidy up code.
1766 mod2 = "+" #1.6 tidy up code.
1767 aStrengthMod = mod2 + str(str_mod) #a 1.5008 applicable strength mod
1768
1769 #if name == "Flurry of Blows(Monk Med)": #d 1.6012
1770 if find(name ,"Flurry of Blows") > -1: #a 1.6012
1771 flurry = True
1772
1773 (base, base2, base3, base4, base5, base6, stat_mod, misc) = self.get_attack_data(rangeOrMelee) #a 1.5008
1774 name = name.replace('(Monk Med)', '')
1775 name = name.replace('(Monk Small)', '')
1776 if not flurry:
1777 if name == 'Shuriken':
1778 for n in xrange(3):
1779 self.sendRoll(base, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod, rollAnyWay=True)
1780 self.sendRoll(base2, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1781 self.sendRoll(base3, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1782 self.sendRoll(base4, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1783 self.sendRoll(base5, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1784 self.sendRoll(base6, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1785 else:
1786 self.sendRoll(base, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod, rollAnyWay=True)
1787 self.sendRoll(base2, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1788 self.sendRoll(base3, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1789 self.sendRoll(base4, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1790 self.sendRoll(base5, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1791 self.sendRoll(base6, stat_mod, misc, wepMod, name, '', dmg, aStrengthMod)
1792 else:
1793 if monkLvl == None:
1794 txt = 'Attempting to use monk attack, but has no monk '
1795 txt += 'levels, please choose a different attack.'
1796 chat.ParsePost( txt, True, True ) #a 1.5009
1797 return
1798 else:
1799 lvl = int(monkLvl)
1800 if lvl <= 4:
1801 flu = '-2'
1802 atks = False
1803 elif lvl <= 8:
1804 flu = '-1'
1805 atks = False
1806 elif lvl <= 10:
1807 flu = ''
1808 atks = False
1809 elif lvl <= 20:
1810 flu = ''
1811 atks = True
1812
1813 self.sendRoll(base, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod, rollAnyWay=True)
1814 self.sendRoll(base, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod, rollAnyWay=True)
1815 if atks:
1816 self.sendRoll(base, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod, rollAnyWay=True)
1817 self.sendRoll(base2, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod)
1818 self.sendRoll(base3, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod)
1819 self.sendRoll(base4, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod)
1820 self.sendRoll(base5, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod)
1821 self.sendRoll(base6, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod)
1822
1823
1824
1825 def sendRoll(self, base, stat_mod, misc, wepMod, name, flu, dmg, aStrengthMod, rollAnyWay=False):
1826 if base != 0 or rollAnyWay:
1827 base = base + int(stat_mod) + misc + wepMod #m 1.5008
1828 if base >= 0:
1829 mod1 = "+"
1830 else:
1831 mod1 = ""
1832 txt = ' %s Attack Roll: <b>[1d20%s%s%s]</b>' % (name, mod1, base, flu)
1833 txt += ' ===> Damage: <b>[%s%s]</b>' % (dmg, aStrengthMod)
1834 self.chat.ParsePost( txt, True, True )
1835
1836 def get_design_panel(self,parent):
1837 wnd = outline_panel(parent,self,attack_panel,"Attacks")
1838 wnd.title = "Attacks"
1839 return wnd
1840
1841 def tohtml(self):
1842 melee = self.get_attack_data('m')
1843 ranged = self.get_attack_data('r')
1844 html_str = ("""<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 >"""+
1845 "<th>Attack</th><th>Total</th><th >Base</th>"+
1846 "<th>Abil</th><th>Misc</th></tr>")
1847 html_str += "<tr ALIGN='center' ><th >Melee:</th>"
1848 html_str += "<td>"+str(melee[0]+melee[1]+melee[2])+"</td>"
1849 html_str += "<td>"+str(melee[0])+"</td>"
1850 html_str += "<td>"+str(melee[1])+"</td>"
1851 html_str += "<td>"+str(melee[2])+"</td></tr>"
1852
1853 html_str += "<tr ALIGN='center' ><th >Ranged:</th>"
1854 html_str += "<td>"+str(ranged[0]+ranged[1]+ranged[2])+"</td>"
1855 html_str += "<td>"+str(ranged[0])+"</td>"
1856 html_str += "<td>"+str(ranged[1])+"</td>"
1857 html_str += "<td>"+str(ranged[2])+"</td></tr></table>"
1858
1859 n_list = self.master_dom.getElementsByTagName('weapon')
1860 for n in n_list:
1861 mod = n.getAttribute('mod')
1862 if mod >= 0:
1863 mod1 = "+"
1864 else:
1865 mod1 = ""
1866 ran = n.getAttribute('range')
1867 total = str(int(mod) + self.get_mod(ran))
1868 html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 >
1869 <th colspan=2>Weapon</th>
1870 <th>Attack</th><th >Damage</th><th>Critical</th></tr>"""
1871 html_str += "<tr ALIGN='center' ><td colspan=2>"
1872 html_str += n.getAttribute('name')+"</td><td>"+total+"</td>"
1873 html_str += "<td>"+n.getAttribute('damage')+"</td><td>"
1874 html_str += n.getAttribute('critical')+"</td></tr>"
1875 html_str += """<tr BGCOLOR=#E9E9E9 ><th>Range</th><th>Weight</th>
1876 <th>Type</th><th>Size</th><th>Misc Mod</th></tr>"""
1877 html_str += "<tr ALIGN='center'><td>"+ran+"</td><td>"
1878 html_str += n.getAttribute('weight')+"</td>"
1879 html_str += "<td>"+n.getAttribute('type')+"</td><td>"
1880 html_str += n.getAttribute('size')+"</td>"
1881 html_str += '<td>%s%s</td></tr>' % (mod1, mod)
1882 #a 1.5012 add next two lines to pretty print footnotes.
1883 html_str += """<tr><th BGCOLOR=#E9E9E9 colspan=2>Footnotes:</th>"""
1884 html_str += "<th colspan=3>"+safeGetAttr(n,'fn','')+"</th></tr>"
1885 html_str += '</table>'
1886 return html_str
1887
1888 class attack_grid(wx.grid.Grid):
1889 """grid for attacks"""
1890 def __init__(self, parent, handler):
1891 pname = handler.master_dom.setAttribute("name", 'Melee')
1892 self.hparent = handler #a 1.5002 allow ability to run up tree.
1893 #a 1.5002 we need the functional parent, not the invoking parent.
1894
1895 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
1896
1897 self.root = getRoot(self) #a 1.9001
1898 self.parent = parent
1899 self.handler = handler
1900 self.rows = (self.handler.melee,self.handler.ranged)
1901 self.CreateGrid(2,10)
1902 self.SetRowLabelSize(0)
1903 col_names = ['Type','base','base 2','base 3','base 4','base 5',
1904 'base 6','abil','misc','Total']
1905 for i in range(len(col_names)):
1906 self.SetColLabelValue(i,col_names[i])
1907 self.SetCellValue(0,0,"Melee")
1908 self.SetCellValue(1,0,"Ranged")
1909 self.refresh_data()
1910 self.Bind(wx.EVT_SIZE, self.on_size)
1911 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
1912 #print "looking for containing frame"
1913
1914 #a 1.9001 remainder of code in this method.
1915 climber = parent
1916 nameNode = climber.GetClassName()
1917 while nameNode != 'wxFrame':
1918 climber = climber.parent
1919 nameNode = climber.GetClassName()
1920 masterFrame=climber
1921 masterFrame.refreshMRdata=self.refresh_data
1922
1923 handler.mrFrame.append(masterFrame)
1924
1925
1926 def on_cell_change(self,evt):
1927 row = evt.GetRow()
1928 col = evt.GetCol()
1929 value = self.GetCellValue(row,col)
1930 try:
1931 int(value)
1932 if col==1:
1933 self.rows[row].setAttribute('base',value)
1934 elif col==2:
1935 self.rows[row].setAttribute('second',value)
1936 elif col==3:
1937 self.rows[row].setAttribute('third',value)
1938 elif col==4:
1939 self.rows[row].setAttribute('forth',value)
1940 elif col==5:
1941 self.rows[row].setAttribute('fifth',value)
1942 elif col==6:
1943 self.rows[row].setAttribute('sixth',value)
1944 elif col==8:
1945 self.rows[row].setAttribute('misc',value)
1946 self.parent.refresh_data()
1947 except:
1948 self.SetCellValue(row,col,"0")
1949
1950 def refresh_data(self):
1951
1952 melee = self.handler.get_attack_data('m')
1953 ranged = self.handler.get_attack_data('r')
1954 tmelee = int(melee[0]) + int(melee[6]) + int(melee[7])
1955 tranged = int(ranged[0]) + int(ranged[6]) + int(ranged[7])
1956 for i in range(0,8): #a 1.5005
1957 self.SetCellValue(0,i+1,str(melee[i]))
1958 self.SetCellValue(1,i+1,str(ranged[i]))
1959 self.SetCellValue(0,9,str(tmelee))
1960 self.SetCellValue(1,9,str(tranged))
1961 self.SetReadOnly(0,0)
1962 self.SetReadOnly(1,0)
1963 self.SetReadOnly(0,7)
1964 self.SetReadOnly(1,7)
1965 self.SetReadOnly(0,9)
1966 self.SetReadOnly(1,9)
1967
1968
1969 def on_size(self,evt):
1970 (w,h) = self.GetClientSizeTuple()
1971 cols = self.GetNumberCols()
1972 col_w = w/(cols+1)
1973 self.SetColSize(0,col_w*2)
1974 for i in range(1,cols):
1975 self.SetColSize(i,col_w)
1976 evt.Skip()
1977 self.Refresh()
1978
1979 class weapon_panel(wx.Panel):
1980 def __init__(self, parent, handler):
1981 self.hparent = handler #a 1.5012
1982 self.root = getRoot(self)
1983
1984 pname = handler.master_dom.setAttribute("name", 'Weapons')
1985
1986 wx.Panel.__init__(self, parent, -1)
1987 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
1988 sizer = wx.BoxSizer(wx.VERTICAL)
1989 sizer.Add(self.grid, 1, wx.EXPAND)
1990
1991 sizer2 = wx.BoxSizer(wx.HORIZONTAL)
1992 sizer2.Add(wx.Button(self, 10, "Remove Weapon"), 0, wx.EXPAND)
1993 sizer2.Add(wx.Size(10,10))
1994 sizer2.Add(wx.Button(self, 20, "Add Weapon"), 0, wx.EXPAND)
1995
1996 sizer.Add(sizer2, 0, wx.EXPAND)
1997 sizer.Add(wx.StaticText(self, -1, "Right click a weapon's footnote to see what the footnotes mean."),0, wx.EXPAND)#a 1.5012
1998 self.sizer = sizer
1999 self.SetSizer(self.sizer)
2000 self.SetAutoLayout(True)
2001 self.Fit()
2002
2003 self.sizer2 = sizer2
2004 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10)
2005 self.Bind(wx.EVT_BUTTON, self.on_add, id=20)
2006 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
2007 self.grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.on_gridRclick)#a 1.5012
2008
2009 n_list = handler.master_dom.getElementsByTagName('weapon')
2010 self.n_list = n_list
2011 self.master_dom = handler.master_dom
2012 self.handler = handler
2013 #trash=input("weapon panel init colnames")
2014 self.colAttr = ['name','damage','mod','critical','type','weight',
2015 'range','size','Total','fn', 'comment'] #a 1.5012
2016 col_names = ['Name','Damage','To hit\nmod','Critical','Type','Weight',
2017 'Range','Size','Total','Foot\nnotes','Comment'] #a 1.5012
2018 gridColCount=len(col_names)#a 1.5012
2019 self.grid.CreateGrid(len(n_list),gridColCount,1) #a 1.5012
2020 #self.grid.CreateGrid(len(n_list),9,1) #d 1.5012
2021 self.grid.SetRowLabelSize(0)
2022
2023 for i in range(gridColCount): #a 1.5012
2024 self.grid.SetColLabelValue(i,col_names[i])
2025 self.refresh_data()
2026 self.temp_dom = None
2027
2028
2029 #mark4
2030 #a 1.5012 add entire method.
2031 def on_gridRclick(self,evt):
2032 #print "weapon_panel, on_rclick: self,evt",self,evt
2033 row = evt.GetRow()
2034 col = evt.GetCol()
2035 value = self.grid.GetCellValue(row,col)
2036 #print "wp, on rclick,grid row,col,value",row,col,value
2037 if col == 9 and value != 'None':
2038 n = self.n_list[row]
2039 name = n.getAttribute('name')
2040 #print "we want a panel!"
2041 handler = self.hparent
2042 #print "handler:",handler
2043 # A handler is a node, and nodes have a reference to
2044 # the master frame
2045 masterFrame = handler.frame
2046 #print "masterFrame:",masterFrame
2047 title = name+"'s Special Weapon Characteristics"
2048 fnFrame = wx.Frame(masterFrame, -1, title)
2049 fnFrame.panel = wx.html.HtmlWindow(fnFrame,-1)
2050 if not self.temp_dom:
2051 tmp = open(orpg.dirpath.dir_struct["dnd35"]+
2052 "dnd35weapons.xml","r")
2053 #tmp = open("c:\clh\codeSamples\sample1.xml","r")
2054 xml_dom = parseXml_with_dlg(self,tmp.read())
2055 xml_dom = xml_dom._get_firstChild()
2056 tmp.close()
2057 self.temp_dom = xml_dom
2058 f_list = self.temp_dom.getElementsByTagName('f') # the footnotes
2059 #print "weapon_panel - on_rclick f_list",f_list#a 1.6
2060 n = self.n_list[row]
2061 name = n.getAttribute('name')
2062 footnotes = n.getAttribute('fn')
2063 html_str = "<html><body>"
2064 html_str += """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 >
2065 <th width='10%'>Note</th><th>Description</th></tr>\n"""
2066 #print "rclick,name,fn",name,footnotes
2067 if footnotes == "":
2068 html_str += "<tr ALIGN='center'><td></td>"
2069 html_str += " <td>This weapon has no footnotes</td></tr>"
2070 for i in range(len(footnotes)):
2071 aNote=footnotes[i]
2072 found=False
2073 for f in f_list:
2074 if f.getAttribute('mark') == aNote:
2075 found=True
2076 text=f.getAttribute('txt')
2077 html_str += ("<tr ALIGN='center'><td>"+aNote+"</td>"+
2078 "<td>"+text+"</td></tr>\n")
2079 if not found:
2080 html_str += ("<tr ALIGN='center'><td>"+aNote+"</td>"+
2081 "<td>is not a recognized footnote</td></tr>\n")
2082
2083 html_str += "</table>"
2084 html_str += "</body> </html> "
2085
2086 #print html_str
2087 fnFrame.panel.SetPage(html_str)
2088 fnFrame.Show()
2089 return
2090 pass
2091
2092
2093
2094 def on_cell_change(self,evt):
2095 row = evt.GetRow()
2096 col = evt.GetCol()
2097 value = self.grid.GetCellValue(row,col)
2098 if col == 2 and not int(value): # special case for mod, demoted
2099 value = "0" #a 5.012 demoted
2100 self.n_list[row].setAttribute('mod',value) # a 5.012 demoted
2101 if not (col == 9 and value == "None" and
2102 self.n_list[row].getAttribute('fn') == "None"
2103 ): #a 5.012 special case for footnotes
2104 self.n_list[row].setAttribute(self.colAttr[col],value)#a 5.012
2105
2106
2107 def refresh_row(self,i):
2108 n = self.n_list[i]
2109 fn = n.getAttribute('fn')
2110 #print "fn=",fn
2111 name = n.getAttribute('name')
2112 mod = n.getAttribute('mod')
2113 ran = n.getAttribute('range')
2114 total = str(int(mod) + self.handler.get_mod(ran))
2115 self.grid.SetCellValue(i,0,name)
2116 self.grid.SetCellValue(i,1,n.getAttribute('damage'))
2117 self.grid.SetCellValue(i,2,mod)
2118 self.grid.SetCellValue(i,3,n.getAttribute('critical'))
2119 self.grid.SetCellValue(i,4,n.getAttribute('type'))
2120 self.grid.SetCellValue(i,5,n.getAttribute('weight'))
2121 self.grid.SetCellValue(i,6,ran)
2122 self.grid.SetCellValue(i,7,n.getAttribute('size') )
2123 self.grid.SetCellValue(i,8,total)
2124 self.grid.SetCellValue(i,9,safeGetAttr(n,'fn','None')) #a 1.5012
2125 self.grid.SetCellValue(i,10,safeGetAttr(n,'comment','')) #a 1.5012
2126 #fn=safeGetAttr(n,'fn','None') #a (debug) 1.5012
2127 #print "fn ",fn,"<" #a (debug) 1.5012
2128 #o 1.5012 original damage vs what someone has changed it to.
2129
2130 self.grid.SetReadOnly(i,8)
2131
2132 def on_remove(self,evt): #o 1.6011 correcting wrongful deletion
2133 rows = self.grid.GetNumberRows()
2134 #for i in range(rows): #d 1.6011 do it backwards,
2135 for i in range(rows-1,-1,-1): #a 1.6011 or you lose context
2136 if self.grid.IsInSelection(i,0):
2137 self.grid.DeleteRows(i)
2138 self.master_dom.removeChild(self.n_list[i])
2139 self.n_list = self.master_dom.getElementsByTagName('weapon')
2140 self.handler.refresh_weapons()
2141
2142 def on_add(self,evt):
2143 if not self.temp_dom:
2144 tmp = open(orpg.dirpath.dir_struct["dnd35"]+"dnd35weapons.xml","r")
2145 #tmp = open("c:\clh\codeSamples\sample1.xml","r") #a (debug) 1.5012
2146 xml_dom = parseXml_with_dlg(self,tmp.read())
2147 xml_dom = xml_dom._get_firstChild()
2148 tmp.close()
2149 self.temp_dom = xml_dom
2150 f_list = self.temp_dom.getElementsByTagName('weapon')
2151 opts = []
2152 #print "weapon_panel - on_add f_list",f_list#a 1.6
2153 for f in f_list:
2154 opts.append(f.getAttribute('name'))
2155 dlg = wx.SingleChoiceDialog(self,'Choose Weapon','Weapon List',opts)
2156 if dlg.ShowModal() == wx.ID_OK:
2157 i = dlg.GetSelection()
2158 #print f_list[i] # DOM Element: weapon.
2159 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
2160 #print self.grid.AppendRows # a bound method of wxGrid
2161 self.grid.AppendRows(1)
2162 self.n_list = self.master_dom.getElementsByTagName('weapon')
2163 #print "self.n_list",self.n_list # list of DOM weapons
2164 self.refresh_row(self.grid.GetNumberRows()-1)
2165 self.handler.refresh_weapons()
2166 dlg.Destroy()
2167
2168 def on_size(self,event):
2169 s = self.GetClientSizeTuple()
2170 self.grid.SetDimensions(0,0,s[0],s[1]-40)
2171 self.sizer.SetDimension(0,s[1]-40,s[0],25)
2172 self.sizer2.SetDimension(0,s[1]-15,s[0],15)
2173 (w,h) = self.grid.GetClientSizeTuple()
2174 cols = self.grid.GetNumberCols()
2175 col_w = w/(cols+1)
2176 self.grid.SetColSize(0,col_w*2)
2177 for i in range(1,cols):
2178 self.grid.SetColSize(i,col_w)
2179
2180 def refresh_data(self):
2181
2182 for i in range(len(self.n_list)):
2183 self.refresh_row(i)
2184
2185
2186 class attack_panel(wx.Panel):
2187 def __init__(self, parent, handler):
2188 pname = handler.master_dom.setAttribute("name", 'Melee')
2189 self.parent = parent #a 1.9001
2190
2191 wx.Panel.__init__(self, parent, -1)
2192
2193 self.a_grid = attack_grid(self, handler)
2194 self.w_panel = weapon_panel(self, handler)
2195 self.sizer = wx.BoxSizer(wx.VERTICAL)
2196 self.sizer.Add(self.a_grid, 1, wx.EXPAND)
2197 self.sizer.Add(self.w_panel, 2, wx.EXPAND)
2198 self.Bind(wx.EVT_SIZE, self.on_size)
2199
2200
2201 def on_size(self,event):
2202 s = self.GetClientSizeTuple()
2203 self.sizer.SetDimension(0,0,s[0],s[1])
2204
2205 def refresh_data(self):
2206
2207 self.w_panel.refresh_data()
2208 self.a_grid.refresh_data()
2209
2210
2211 class dnd35armor(combat_char_child):
2212 """ Node Handler for ac. This handler will be
2213 created by dnd35char_handler.
2214 """
2215 def __init__(self,xml_dom,tree_node,parent):
2216 combat_char_child.__init__(self,xml_dom,tree_node,parent)
2217 self.hparent = parent #a 1.5002 allow ability to run up tree.
2218 self.root = getRoot(self) #a 1.5002
2219 self.root.ac = self #a 1.6009
2220
2221 def get_spell_failure(self):
2222 return self.get_total('spellfailure')
2223
2224 def get_total_weight(self):
2225 return self.get_total('weight')
2226
2227 def get_check_pen(self):
2228 return self.get_total('checkpenalty')
2229
2230 def get_armor_class(self):
2231 ac_total = 10
2232
2233 ac_total += self.get_total('bonus')
2234 #m 1.5009 change to hardcode dex, was incorrect gv "stat"
2235 dex_mod = self.root.abilities.get_mod('Dex')#m 1.5009 hardcode dex
2236 max_dex = self.get_max_dex()
2237 if dex_mod < max_dex:
2238 ac_total += dex_mod
2239 else:
2240 ac_total += max_dex
2241 return ac_total
2242
2243 def get_max_dex(self):
2244 armor_list = self.master_dom.getElementsByTagName('armor')
2245 dex = 10
2246 for a in armor_list:
2247 temp = int(a.getAttribute("maxdex"))
2248 if temp < dex:
2249 dex = temp
2250 return dex
2251
2252 def get_total(self,attr):
2253 armor_list = self.master_dom.getElementsByTagName('armor')
2254 total = 0
2255 for a in armor_list:
2256 total += int(a.getAttribute(attr))
2257 return total
2258
2259 def get_design_panel(self,parent):
2260 wnd = outline_panel(parent,self,ac_panel,"Armor")
2261 wnd.title = "Armor"
2262 return wnd
2263
2264 def on_rclick( self, evt ):
2265 ac = self.get_armor_class()
2266 fac = (int(ac)-(self.root.abilities.get_mod('Dex')))
2267
2268 txt = '((AC: %s Normal, %s Flatfoot))' % ( ac, fac ) #a 1.5002
2269 self.chat.ParsePost( txt, True, True )
2270
2271 def tohtml(self):
2272 html_str = """<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 >
2273 <th>AC</th><th>Check Penalty</th><th >Spell Failure</th>
2274 <th>Max Dex</th><th>Total Weight</th></tr>"""
2275 html_str += "<tr ALIGN='center' >"
2276 html_str += "<td>"+str(self.get_armor_class())+"</td>"
2277 html_str += "<td>"+str(self.get_check_pen())+"</td>"
2278 html_str += "<td>"+str(self.get_spell_failure())+"</td>"
2279 html_str += "<td>"+str(self.get_max_dex())+"</td>"
2280 html_str += "<td>"+str(self.get_total_weight())+"</td></tr></table>"
2281 n_list = self.master_dom._get_childNodes()
2282 for n in n_list:
2283 html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 >
2284 <th colspan=3>Armor</th><th>Type</th><th >Bonus</th></tr>"""
2285 html_str += "<tr ALIGN='center' >"
2286 html_str += "<td colspan=3>"+n.getAttribute('name')+"</td>"
2287 html_str += "<td>"+n.getAttribute('type')+"</td>"
2288 html_str += "<td>"+n.getAttribute('bonus')+"</td></tr>"
2289 html_str += """<tr BGCOLOR=#E9E9E9 >"""
2290 html_str += "<th>Check Penalty</th><th>Spell Failure</th>"
2291 html_str += "<th>Max Dex</th><th>Speed</th><th>Weight</th></tr>"
2292 html_str += "<tr ALIGN='center'>"
2293 html_str += "<td>"+n.getAttribute('checkpenalty')+"</td>"
2294 html_str += "<td>"+n.getAttribute('spellfailure')+"</td>"
2295 html_str += "<td>"+n.getAttribute('maxdex')+"</td>"
2296 html_str += "<td>"+n.getAttribute('speed')+"</td>"
2297 html_str += "<td>"+n.getAttribute('weight')+"</td></tr></table>"
2298 return html_str
2299
2300
2301 class ac_panel(wx.Panel):
2302 def __init__(self, parent, handler):
2303 pname = handler.master_dom.setAttribute("name", 'Armor')
2304 self.hparent = handler #a 1.5002 allow ability to run up tree.
2305 #a 1.5002 we need the functional parent, not the invoking parent.
2306
2307 wx.Panel.__init__(self, parent, -1)
2308 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
2309 sizer = wx.BoxSizer(wx.VERTICAL)
2310 sizer.Add(self.grid, 1, wx.EXPAND)
2311
2312 sizer1 = wx.BoxSizer(wx.HORIZONTAL)
2313 sizer1.Add(wx.Button(self, 10, "Remove Armor"), 1, wx.EXPAND)
2314 sizer1.Add(wx.Size(10,10))
2315 sizer1.Add(wx.Button(self, 20, "Add Armor"), 1, wx.EXPAND)
2316
2317 sizer.Add(sizer1, 0, wx.EXPAND)
2318
2319 self.sizer = sizer
2320 self.SetSizer(self.sizer)
2321 self.SetAutoLayout(True)
2322 self.Fit()
2323
2324 #self.Bind(wx.EVT_SIZE, self.on_size)
2325 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10)
2326 self.Bind(wx.EVT_BUTTON, self.on_add, id=20)
2327 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
2328 self.master_dom = handler.master_dom
2329 n_list = handler.master_dom._get_childNodes()
2330 self.n_list = n_list
2331 col_names = ['Armor','bonus','maxdex','cp','sf','weight','speed','type']
2332 self.grid.CreateGrid(len(n_list),len(col_names),1)
2333 self.grid.SetRowLabelSize(0)
2334 for i in range(len(col_names)):
2335 self.grid.SetColLabelValue(i,col_names[i])
2336 self.atts =['name','bonus','maxdex','checkpenalty',
2337 'spellfailure','weight','speed','type']
2338 for i in range(len(n_list)):
2339 self.refresh_row(i)
2340 self.temp_dom = None
2341
2342
2343 def on_cell_change(self,evt):
2344 row = evt.GetRow()
2345 col = evt.GetCol()
2346 value = self.grid.GetCellValue(row,col)
2347 if col >= 1 and col <= 5:
2348 try:
2349 int(value)
2350 self.n_list[row].setAttribute(self.atts[col],value)
2351 except:
2352 self.grid.SetCellValue(row,col,"0")
2353 else:
2354 self.n_list[row].setAttribute(self.atts[col],value)
2355
2356 def refresh_row(self,i):
2357 n = self.n_list[i]
2358
2359 for y in range(len(self.atts)):
2360 self.grid.SetCellValue(i,y,n.getAttribute(self.atts[y]))
2361
2362 def on_remove(self,evt):
2363 rows = self.grid.GetNumberRows()
2364 for i in range(rows):
2365 if self.grid.IsInSelection(i,0):
2366 self.grid.DeleteRows(i)
2367 self.master_dom.removeChild(self.n_list[i])
2368
2369 def on_add(self,evt):
2370 if not self.temp_dom:
2371 tmp = open(orpg.dirpath.dir_struct["dnd35"]+"dnd35armor.xml","r")
2372 xml_dom = parseXml_with_dlg(self,tmp.read())
2373 xml_dom = xml_dom._get_firstChild()
2374 tmp.close()
2375 self.temp_dom = xml_dom
2376 f_list = self.temp_dom.getElementsByTagName('armor')
2377 opts = []
2378 for f in f_list:
2379 opts.append(f.getAttribute('name'))
2380 dlg = wx.SingleChoiceDialog(self,'Choose Armor:','Armor List',opts)
2381 if dlg.ShowModal() == wx.ID_OK:
2382 i = dlg.GetSelection()
2383 new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
2384 self.grid.AppendRows(1)
2385 self.refresh_row(self.grid.GetNumberRows()-1)
2386 dlg.Destroy()
2387
2388 def on_size(self,event):
2389 s = self.GetClientSizeTuple()
2390 self.grid.SetDimensions(0,0,s[0],s[1]-25)
2391 self.sizer.SetDimension(0,s[1]-25,s[0],25)
2392 (w,h) = self.grid.GetClientSizeTuple()
2393 cols = self.grid.GetNumberCols()
2394 col_w = w/(cols+2)
2395 self.grid.SetColSize(0,col_w*3)
2396 for i in range(1,cols):
2397 self.grid.SetColSize(i,col_w)