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