Mercurial > traipse
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) |