Mercurial > traipse_dev
annotate orpg/gametree/nodehandlers/dnd3e.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 | 3bbfd84619c0 |
children |
rev | line source |
---|---|
156 | 1 # Copyright (C) 2000-2001 The OpenRPG Project |
2 # | |
3 # openrpg-dev@lists.sourceforge.net | |
4 # | |
5 # This program is free software; you can redistribute it and/or modify | |
6 # it under the terms of the GNU General Public License as published by | |
7 # the Free Software Foundation; either version 2 of the License, or | |
8 # (at your option) any later version. | |
9 # | |
10 # This program is distributed in the hope that it will be useful, | |
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 # GNU General Public License for more details. | |
14 # | |
15 # You should have received a copy of the GNU General Public License | |
16 # along with this program; if not, write to the Free Software | |
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 # -- | |
19 # | |
20 # File: dnd3e.py | |
21 # Author: Chris Davis & Digitalxero | |
22 # Maintainer: leadb | |
23 # Version: | |
184 | 24 # $Id: dnd3e.py,v Traipse 'Ornery-Orc' prof.ebral Exp $ |
156 | 25 # |
26 # Description: The file contains code for the dnd3e nodehanlers | |
27 # | |
74 | 28 |
156 | 29 from core import * |
30 from containers import * | |
31 from string import * #a 1.6003 | |
74 | 32 from inspect import * #a 1.9001 |
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:
74
diff
changeset
|
33 from orpg.dirpath import dir_struct |
135 | 34 from orpg.tools.orpg_log import debug |
35 from xml.etree.ElementTree import parse | |
243 | 36 from orpg.tools.InterParse import Parse |
156 | 37 |
38 dnd3e_EXPORT = wx.NewId() | |
39 ############Global Stuff############## | |
40 | |
41 HP_CUR = wx.NewId() | |
42 HP_MAX = wx.NewId() | |
43 PP_CUR = wx.NewId() | |
44 PP_MAX = wx.NewId() | |
45 PP_FRE = wx.NewId() | |
46 PP_MFRE = wx.NewId() | |
47 HOWTO_MAX = wx.NewId() | |
48 | |
49 def getRoot (node): # a 1.5002 this whole function is new. | |
50 root = None | |
51 target = node | |
52 while target != None: | |
53 root = target | |
54 target = target.hparent | |
55 return root | |
152 | 56 |
156 | 57 # if a method runs getRoot for its instance and assigns the |
58 # value returned to self.root, you can get to instances X via Y | |
59 # instance handle via invocation | |
60 # --------------- --- ----------- | |
61 # classes via self.root.classes | |
62 # abilities via self.root.abilities | |
63 # pp via self.root.pp | |
64 # general via self.root.general | |
65 # saves via self.root.saves | |
66 # attacks via self.root.attacks | |
67 # ac via self.root.ac | |
68 # feats via self.root.feats | |
69 # spells via self.root.spells | |
70 # divine via self.root.divine | |
71 # powers via self.root.powers | |
72 # inventory via self.root.inventory | |
73 # hp via self.root.hp | |
74 # skills via self.root.skills | |
75 #... if other instances are needed and the instance exists uniquely, | |
76 # add to the instance you need access to in the __init__ section the following: | |
77 # self.hparent = parent # or handler if a wx instance, also add up chain | |
78 # self.root = getRoot(self) | |
79 # self.root.{instance handle} = self | |
80 # # replace {instance handle} with your designation | |
81 # then, where you need access to the instance, simply add this to the instance | |
82 # that needs to reference | |
83 # self.hparent = getRoot(self) # in the init section, if not already there | |
84 # self.root = getRoot(self) # also in the init | |
85 # then to refer to the instance where you need it: | |
86 # self.root.{instance handle}.{whatever you need} | |
87 # # replace {instance handle} with your designation | |
88 # # replace {whatever you need} with the attribute/method u want. | |
89 | |
90 def safeGetAttr(node, label, defRetV=None): | |
91 cna=node.attrib | |
135 | 92 for key in cna: |
156 | 93 if key == label: return cna[key] |
94 return defRetV | |
95 | |
96 | |
97 ########End of My global Stuff######## | |
98 ########Start of Main Node Handlers####### | |
99 class dnd3echar_handler(container_handler): | |
100 """ Node handler for a dnd3e charactor | |
101 <nodehandler name='?' module='dnd3e' class='dnd3echar_handler2' /> | |
102 """ | |
103 def __init__(self,xml_dom,tree_node): | |
104 node_handler.__init__(self,xml_dom,tree_node) | |
105 self.Version = "v1.901" #a 1.6000 general documentation, usage. | |
106 | |
107 print "dnd3echar_handler - version:", self.Version #m 1.6000 | |
108 | |
109 self.hparent = None | |
110 self.frame = component.get('frame') | |
111 self.child_handlers = {} | |
112 self.new_child_handler('howtouse','HowTo use this tool',dnd3ehowto,'note') | |
113 self.new_child_handler('general','GeneralInformation',dnd3egeneral,'gear') | |
114 self.new_child_handler('inventory','MoneyAndInventory',dnd3einventory,'money') | |
115 self.new_child_handler('character','ClassesAndStats',dnd3eclassnstats,'knight') | |
116 self.new_child_handler('snf','SkillsAndFeats',dnd3eskillsnfeats,'book') | |
117 self.new_child_handler('combat','Combat',dnd3ecombat,'spears') | |
118 self.new_child_handler('snp','SpellsAndPowers',dnd3esnp,'flask') | |
119 self.myeditor = None | |
120 | |
121 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
122 node_list = self.xml.findall(tag) | |
123 tree = self.tree | |
124 i = self.tree.icons[icon] | |
125 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
126 handler = handler_class(node_list[0],new_tree_node,self) | |
127 tree.SetPyData(new_tree_node,handler) | |
128 self.child_handlers[tag] = handler | |
129 | |
130 def get_design_panel(self,parent): | |
131 return tabbed_panel(parent,self,1) | |
132 | |
133 def get_use_panel(self,parent): | |
134 return tabbed_panel(parent,self,2) | |
135 | |
136 def tohtml(self): | |
137 html_str = "<table><tr><td colspan=2 >" | |
138 html_str += self.general.tohtml()+"</td></tr>" | |
139 html_str += "<tr><td width='50%' valign=top >"+self.abilities.tohtml() | |
140 html_str += "<P>" + self.saves.tohtml() | |
141 html_str += "<P>" + self.attacks.tohtml() | |
142 html_str += "<P>" + self.ac.tohtml() | |
143 html_str += "<P>" + self.feats.tohtml() | |
144 html_str += "<P>" + self.spells.tohtml() | |
145 html_str += "<P>" + self.divine.tohtml() | |
146 html_str += "<P>" + self.powers.tohtml() | |
147 html_str += "<P>" + self.inventory.tohtml() +"</td>" | |
148 html_str += "<td width='50%' valign=top >"+self.classes.tohtml() | |
149 html_str += "<P>" + self.hp.tohtml() | |
150 html_str += "<P>" + self.pp.tohtml() | |
151 html_str += "<P>" + self.skills.tohtml() +"</td>" | |
152 html_str += "</tr></table>" | |
153 return html_str | |
154 | |
155 def about(self): | |
156 """html_str = "<img src='" + dir_struct["icon"] | |
157 html_str += "dnd3e_logo.gif' ><br><b>dnd3e Character Tool " | |
158 html_str += self.Version+"</b>" | |
159 html_str += "<br>by Dj Gilcrease<br>digitalxero@gmail.com" | |
152 | 160 return html_str""" |
161 text = 'dnd3e Character Tool' + self.Version +'\n' | |
162 text += 'by Dj Gilcrease digitalxero@gmail.com' | |
156 | 163 return text |
164 | |
165 ########Core Handlers are done now############ | |
166 ########Onto the Sub Nodes######## | |
167 ##Primary Sub Node## | |
168 | |
169 class outline_panel(wx.Panel): | |
170 def __init__(self, parent, handler, wnd, txt,): | |
171 self.parent = parent #a 1.9001 | |
172 wx.Panel.__init__(self, parent, -1) | |
173 self.panel = wnd(self,handler) | |
174 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self,-1,txt), wx.VERTICAL) | |
175 | |
176 self.sizer.Add(self.panel, 1, wx.EXPAND) | |
177 self.SetSizer(self.sizer) | |
178 self.SetAutoLayout(True) | |
179 self.Fit() | |
180 | |
181 class dnd3e_char_child(node_handler): | |
182 """ Node Handler for skill. This handler will be | |
183 created by dnd3echar_handler. | |
184 """ | |
185 def __init__(self,xml_dom,tree_node,parent): | |
186 node_handler.__init__(self,xml_dom,tree_node) | |
187 self.char_hander = parent | |
188 self.drag = False | |
189 self.frame = component.get('frame') | |
190 self.myeditor = None | |
191 | |
192 def on_drop(self,evt): | |
193 pass | |
194 | |
195 def on_rclick(self,evt): | |
196 pass | |
197 | |
198 def on_ldclick(self,evt): | |
199 return | |
200 | |
201 def on_html(self,evt): | |
202 html_str = self.tohtml() | |
203 wnd = http_html_window(self.frame.note,-1) | |
204 wnd.title = self.xml.get('name') | |
205 self.frame.add_panel(wnd) | |
206 wnd.SetPage(html_str) | |
207 | |
208 def get_design_panel(self,parent): | |
209 pass | |
210 | |
211 def get_use_panel(self,parent): | |
212 return self.get_design_panel(parent) | |
213 | |
214 def delete(self): | |
215 pass | |
216 | |
217 ###Child Nodes Organized the way they are in the XML for easier viewing#### #m 1.5002 corrected typo. | |
218 class dnd3ehowto(dnd3e_char_child): #m 1.5002 corrected string below to reflect "how to" | |
219 """ Node Handler for how to instructions. This handler will be | |
220 created by dnd3echar_handler. | |
221 """ | |
222 def __init__(self,xml_dom,tree_node,parent): | |
223 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
224 self.hparent = parent | |
225 | |
226 def get_design_panel(self,parent): | |
227 wnd = howto_panel(parent, self) | |
228 wnd.title = "How To" | |
229 return wnd | |
230 | |
231 class howto_panel(wx.Panel): | |
232 def __init__(self, parent, handler): | |
233 wx.Panel.__init__(self, parent, -1) | |
234 | |
235 pname = handler.xml.set("name", 'How To') | |
236 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, 'How To'), wx.VERTICAL) | |
237 self.xml = handler.xml | |
238 n_list = self.xml.getchildren() | |
239 for n in n_list: | |
240 self.sizer.Add(wx.StaticText(self, -1, n.text), 1, wx.EXPAND) | |
241 self.SetSizer(self.sizer) | |
242 self.SetAutoLayout(True) | |
243 self.Fit() | |
244 | |
245 class dnd3egeneral(dnd3e_char_child): | |
246 """ Node Handler for general information. This handler will be | |
247 created by dnd3echar_handler. | |
248 """ | |
249 def __init__(self,xml_dom,tree_node,parent): | |
250 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
251 self.hparent = parent | |
252 self.root = getRoot(self) | |
253 self.root.general = self | |
254 self.charName = self.get_char_name() | |
255 | |
256 def get_design_panel(self,parent): | |
257 wnd = outline_panel(parent,self,gen_grid,"General Information") | |
258 wnd.title = "General Info" | |
259 return wnd | |
260 | |
261 def tohtml(self): | |
262 n_list = self.xml.getchildren() | |
263 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>" | |
264 for n in n_list: | |
265 html_str += "<B>"+n.tag.capitalize() +":</B> " | |
266 html_str += n.text + ", " | |
267 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
268 return html_str | |
269 | |
270 def on_name_change(self,name): | |
271 self.char_hander.rename(name) | |
272 self.charName = name | |
273 | |
274 def get_char_name( self ): | |
275 node = self.xml.findall( 'name' )[0] | |
276 return node.text | |
277 | |
278 class gen_grid(wx.grid.Grid): | |
279 """grid for gen info""" | |
280 def __init__(self, parent, handler): | |
281 pname = handler.xml.set("name", 'General') | |
282 self.hparent = handler | |
283 | |
284 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
285 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
286 self.handler = handler | |
287 n_list = handler.xml.getchildren() | |
288 self.CreateGrid(len(n_list),2) | |
289 self.SetRowLabelSize(0) | |
290 self.SetColLabelSize(0) | |
291 self.n_list = n_list | |
292 i = 0 | |
293 for i in range(len(n_list)): self.refresh_row(i) | |
294 | |
295 def on_cell_change(self,evt): | |
296 row = evt.GetRow() | |
297 col = evt.GetCol() | |
298 value = self.GetCellValue(row,col) | |
299 self.n_list[row].text = value | |
300 if row==0: self.handler.on_name_change(value) | |
301 | |
302 def refresh_row(self,rowi): | |
303 self.SetCellValue(rowi,0,self.n_list[rowi].tag) | |
304 self.SetReadOnly(rowi,0) | |
305 self.SetCellValue(rowi,1,self.n_list[rowi].text) | |
306 self.AutoSizeColumn(1) | |
307 | |
308 class dnd3einventory(dnd3e_char_child): | |
309 """ Node Handler for general information. This handler will be | |
310 created by dnd3echar_handler. | |
311 """ | |
312 def __init__(self,xml_dom,tree_node,parent): | |
313 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
314 self.hparent = parent | |
315 self.root = getRoot(self) | |
316 self.root.inventory = self | |
317 | |
318 def get_design_panel(self,parent): | |
319 wnd = inventory_pane(parent, self) #outline_panel(parent,self,inventory_grid,"Inventory") | |
320 wnd.title = "Inventory" | |
321 return wnd | |
322 | |
323 def tohtml(self): | |
324 n_list = self.xml.getchildren() | |
325 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>" | |
135 | 326 for n in n_list: |
156 | 327 html_str += "<B>"+n.tag.capitalize()+":</B> " |
328 html_str += n.text + "<br>" | |
329 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
330 return html_str | |
331 | |
332 class inventory_pane(wx.Panel): | |
333 def __init__(self, parent, handler): | |
334 wx.Panel.__init__(self, parent, wx.ID_ANY) | |
335 self.n_list = handler.xml.getchildren() | |
336 self.autosize = False | |
337 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Inventory"), wx.VERTICAL) | |
338 self.lang = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Languages") | |
339 self.gear = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Gear") | |
340 self.magic = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_BESTWRAP, name="Magic") | |
341 self.grid = wx.grid.Grid(self, wx.ID_ANY, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
342 self.grid.CreateGrid(len(self.n_list)-3,2) | |
343 self.grid.SetRowLabelSize(0) | |
344 self.grid.SetColLabelSize(0) | |
345 for i in xrange(len(self.n_list)): self.refresh_row(i) | |
346 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
347 sizer1.Add(self.grid, 1, wx.EXPAND) | |
348 sizer1.Add(self.lang, 1, wx.EXPAND) | |
349 self.sizer.Add(sizer1, 0, wx.EXPAND) | |
350 sizer2 = wx.BoxSizer(wx.HORIZONTAL) | |
351 sizer2.Add(self.gear, 1, wx.EXPAND) | |
352 sizer2.Add(self.magic, 1, wx.EXPAND) | |
353 self.sizer.Add(sizer2, 1, wx.EXPAND) | |
354 self.SetSizer(self.sizer) | |
355 self.SetAutoLayout(True) | |
356 self.Fit() | |
357 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.lang) | |
358 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.gear) | |
359 self.Bind(wx.EVT_TEXT, self.onTextNodeChange, self.magic) | |
360 self.Bind(wx.grid.EVT_GRID_EDITOR_HIDDEN, self.on_cell_change, self.grid) | |
361 | |
362 def fillTextNode(self, name, value): | |
363 if name == 'Languages': self.lang.SetValue(value) | |
364 elif name == 'Gear': self.gear.SetValue(value) | |
365 elif name == 'Magic': self.magic.SetValue(value) | |
366 | |
367 def onTextNodeChange(self, event): | |
368 id = event.GetId() | |
369 if id == self.gear.GetId(): | |
370 nodeName = 'Gear' | |
371 value = self.gear.GetValue() | |
372 elif id == self.magic.GetId(): | |
373 nodeName = 'Magic' | |
374 value = self.magic.GetValue() | |
375 elif id == self.lang.GetId(): | |
376 nodeName = 'Languages' | |
377 value = self.lang.GetValue() | |
378 for node in self.n_list: | |
379 if node.tag == nodeName: | |
380 node.text = value | |
381 | |
382 def saveMoney(self, row, col): | |
383 value = self.grid.GetCellValue(row, col) | |
384 self.n_list[row].text = value | |
385 | |
386 def on_cell_change(self, evt): | |
387 row = evt.GetRow() | |
388 col = evt.GetCol() | |
389 self.grid.AutoSizeColumn(col) | |
390 wx.CallAfter(self.saveMoney, row, col) | |
391 | |
392 def refresh_row(self, row): | |
393 tagname = self.n_list[row].tag | |
394 value = self.n_list[row].text | |
395 if tagname == 'Gear': self.fillTextNode(tagname, value) | |
396 elif tagname == 'Magic': self.fillTextNode(tagname, value) | |
397 elif tagname == 'Languages': self.fillTextNode(tagname, value) | |
398 else: | |
399 self.grid.SetCellValue(row, 0, tagname) | |
400 self.grid.SetReadOnly(row, 0) | |
401 self.grid.SetCellValue(row, 1, value) | |
402 self.grid.AutoSize() | |
403 | |
404 | |
405 class dnd3eclassnstats(dnd3e_char_child): | |
406 """ Node handler for a dnd3e charactor | |
407 <nodehandler name='?' module='dnd3e' class='dnd3echar_handler2' /> | |
408 """ | |
409 def __init__(self,xml_dom,tree_node,parent): | |
410 node_handler.__init__(self,xml_dom,tree_node) | |
411 self.hparent = parent | |
412 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
413 self.frame = component.get('frame') | |
414 self.child_handlers = {} | |
415 self.new_child_handler('abilities','Abilities Scores',dnd3eability,'gear') | |
416 self.new_child_handler('classes','Classes',dnd3eclasses,'knight') | |
417 self.new_child_handler('saves','Saves',dnd3esaves,'skull') | |
418 self.myeditor = None | |
419 | |
420 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
421 node_list = self.xml.findall(tag) | |
422 tree = self.tree | |
423 i = self.tree.icons[icon] | |
424 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
425 handler = handler_class(node_list[0],new_tree_node,self) | |
426 tree.SetPyData(new_tree_node,handler) | |
427 self.child_handlers[tag] = handler | |
428 | |
429 def get_design_panel(self,parent): | |
430 return tabbed_panel(parent,self,1) | |
431 | |
432 def get_use_panel(self,parent): | |
433 print 'here' | |
434 return tabbed_panel(parent,self,2) | |
435 | |
436 class class_char_child(node_handler): | |
437 """ Node Handler for skill. This handler will be | |
438 created by dnd3echar_handler. | |
439 """ | |
440 def __init__(self,xml_dom,tree_node,parent): | |
441 node_handler.__init__(self,xml_dom,tree_node) | |
442 self.char_hander = parent | |
443 self.drag = False | |
444 self.frame = component.get('frame') | |
445 self.myeditor = None | |
446 | |
447 def on_drop(self,evt): | |
448 pass | |
449 | |
450 def on_rclick(self,evt): | |
451 pass | |
452 | |
453 def on_ldclick(self,evt): | |
454 return | |
455 | |
456 def on_html(self,evt): | |
457 html_str = self.tohtml() | |
458 wnd = http_html_window(self.frame.note,-1) | |
459 wnd.title = self.xml.get('name') | |
460 self.frame.add_panel(wnd) | |
461 wnd.SetPage(html_str) | |
462 | |
463 def get_design_panel(self,parent): | |
464 pass | |
465 | |
466 def get_use_panel(self,parent): | |
467 return self.get_design_panel(parent) | |
468 | |
469 def delete(self): | |
470 pass | |
471 | |
472 class dnd3eability(class_char_child): | |
473 """ Node Handler for ability. This handler will be | |
474 created by dnd3echar_handler. | |
475 """ | |
476 def __init__(self,xml_dom,tree_node,parent): | |
477 class_char_child.__init__(self,xml_dom,tree_node,parent) | |
478 self.hparent = parent | |
479 self.root = getRoot(self) | |
480 self.root.abilities = self | |
481 self.abilities = {} | |
482 node_list = self.xml.findall('stat') | |
483 tree = self.tree | |
484 icons = tree.icons | |
485 for n in node_list: | |
486 name = n.get('abbr') | |
487 self.abilities[name] = n | |
488 new_tree_node = tree.AppendItem( self.mytree_node, name, icons['gear'], icons['gear'] ) | |
489 tree.SetPyData( new_tree_node, self ) | |
490 | |
491 def on_rclick( self, evt ): | |
492 item = self.tree.GetSelection() | |
493 name = self.tree.GetItemText( item ) | |
494 if not item == self.mytree_node: | |
495 mod = self.get_mod( name ) | |
496 if mod >= 0: mod1 = "+" | |
497 else: mod1 = "" | |
498 chat = self.chat | |
499 txt = '%s check: [1d20%s%s]' % ( name, mod1, mod ) | |
500 chat.ParsePost( txt, True, True ) | |
501 | |
502 def get_mod(self,abbr): | |
503 score = int(self.abilities[abbr].get('base')) | |
504 mod = (score - 10) / 2 | |
505 mod = int(mod) | |
506 return mod | |
507 | |
508 def set_score(self,abbr,score): | |
509 if score >= 0: | |
510 self.abilities[abbr].set("base",str(score)) | |
511 | |
512 def get_design_panel(self,parent): | |
513 wnd = outline_panel(parent,self,abil_grid,"Abilities") | |
514 wnd.title = "Abilities (edit)" | |
515 return wnd | |
516 | |
517 def tohtml(self): | |
518 html_str = """<table border='1' width=100%><tr BGCOLOR=#E9E9E9 ><th width='50%'>Ability</th> | |
519 <th>Base</th><th>Modifier</th></tr>""" | |
520 node_list = self.xml.findall('stat') | |
521 for n in node_list: | |
522 name = n.get('name') | |
523 abbr = n.get('abbr') | |
524 base = n.get('base') | |
525 mod = str(self.get_mod(abbr)) | |
526 if int(mod) >= 0: mod1 = "+" | |
527 else: mod1 = "" | |
528 html_str = (html_str + "<tr ALIGN='center'><td>"+ | |
529 name+"</td><td>"+base+'</td><td>%s%s</td></tr>' % (mod1, mod)) | |
530 html_str = html_str + "</table>" | |
531 return html_str | |
532 | |
533 class abil_grid(wx.grid.Grid): | |
534 """grid for abilities""" | |
535 def __init__(self, parent, handler): | |
536 pname = handler.xml.set("name", 'Stats') | |
537 self.hparent = handler | |
538 self.root = getRoot(self) | |
539 | |
540 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
541 self.Bind(wx.EVT_SIZE, self.on_size) | |
542 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
543 self.handler = handler | |
544 stats = handler.xml.findall('stat') | |
545 self.CreateGrid(len(stats),3) | |
546 self.SetRowLabelSize(0) | |
547 col_names = ['Ability','Score','Modifier'] | |
548 for i in range(len(col_names)): self.SetColLabelValue(i,col_names[i]) | |
549 self.stats = stats | |
550 i = 0 | |
551 for i in range(len(stats)): self.refresh_row(i) | |
552 self.char_wnd = None | |
553 | |
554 def on_cell_change(self,evt): | |
555 row = evt.GetRow() | |
556 col = evt.GetCol() | |
557 value = self.GetCellValue(row,col) | |
558 try: | |
559 int(value) | |
560 self.stats[row].set('base',value) | |
561 self.refresh_row(row) | |
562 except: | |
563 self.SetCellValue(row,col,"0") | |
564 if self.char_wnd: self.char_wnd.refresh_data() | |
565 | |
135 | 566 def refresh_row(self,rowi): |
156 | 567 s = self.stats[rowi] |
568 name = s.get('name') | |
569 abbr = s.get('abbr') | |
570 self.SetCellValue(rowi,0,name) | |
571 self.SetReadOnly(rowi,0) | |
572 self.SetCellValue(rowi,1,s.get('base')) | |
573 self.SetCellValue(rowi,2,str(self.handler.get_mod(abbr))) | |
574 self.SetReadOnly(rowi,2) | |
575 self.root.saves.refresh_data() | |
576 self.root.attacks.refreshMRdata() | |
577 | |
578 def on_size(self,evt): | |
579 (w,h) = self.GetClientSizeTuple() | |
580 cols = self.GetNumberCols() | |
581 col_w = w/(cols+2) | |
582 self.SetColSize(0,col_w*3) | |
583 for i in range(1,cols): self.SetColSize(i,col_w) | |
584 evt.Skip() | |
585 self.Refresh() | |
586 | |
587 def refresh_data(self): | |
588 for r in range(self.GetNumberRows()-1): self.refresh_row(r) | |
589 | |
590 class dnd3eclasses(class_char_child): | |
591 """ Node Handler for classes. This handler will be | |
592 created by dnd3echar_handler. | |
593 """ | |
594 def __init__(self,xml_dom,tree_node,parent): | |
595 class_char_child.__init__(self,xml_dom,tree_node,parent) | |
596 self.hparent = parent | |
597 self.root = getRoot(self) | |
598 self.root.classes = self | |
599 | |
600 def get_design_panel(self,parent): | |
601 wnd = outline_panel(parent,self,class_panel,"Classes") | |
602 wnd.title = "Classes" | |
603 return wnd | |
604 | |
605 def tohtml(self): | |
606 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Classes</th></tr><tr><td>" | |
607 n_list = self.xml.getchildren() | |
608 for n in n_list: html_str += n.get('name') + " ("+n.get('level')+"), " | |
609 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
610 return html_str | |
611 | |
612 def get_char_lvl( self, attr ): | |
613 node_list = self.xml.findall('class') | |
614 tot = 0 | |
615 for n in node_list: | |
616 lvl = n.get('level') | |
617 tot += int(lvl) | |
618 type = n.get('name') | |
619 if attr == "level": return lvl | |
620 elif attr == "class": return type | |
621 if attr == "lvl": return tot | |
622 | |
623 def get_class_lvl( self, classN ): | |
624 node_list = self.xml.findall('class') | |
625 for n in node_list: | |
626 lvl = n.get('level') | |
627 type = n.get('name') | |
628 if classN == type: return lvl | |
629 | |
630 class class_panel(wx.Panel): | |
631 def __init__(self, parent, handler): | |
632 pname = handler.xml.set("name", 'Class') | |
633 | |
634 wx.Panel.__init__(self, parent, -1) | |
635 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
636 sizer = wx.BoxSizer(wx.VERTICAL) | |
637 sizer.Add(self.grid, 1, wx.EXPAND) | |
638 | |
639 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
640 sizer1.Add(wx.Button(self, 10, "Remove Class"), 0, wx.EXPAND) | |
641 sizer1.Add(wx.Size(10,10)) | |
642 sizer1.Add(wx.Button(self, 20, "Add Class"), 0, wx.EXPAND) | |
643 | |
644 sizer.Add(sizer1, 0, wx.EXPAND) | |
645 self.sizer = sizer | |
646 self.SetSizer(self.sizer) | |
647 self.SetAutoLayout(True) | |
648 self.Fit() | |
649 | |
650 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
651 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
652 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
653 | |
654 n_list = handler.xml.getchildren() | |
655 self.n_list = n_list | |
656 self.xml = handler.xml | |
657 self.grid.CreateGrid(len(n_list),2,1) | |
658 self.grid.SetRowLabelSize(0) | |
659 self.grid.SetColLabelValue(0,"Class") | |
660 self.grid.SetColLabelValue(1,"Level") | |
661 for i in range(len(n_list)): self.refresh_row(i) | |
662 self.temp_dom = None | |
663 | |
664 def on_cell_change(self,evt): | |
665 row = evt.GetRow() | |
666 col = evt.GetCol() | |
667 value = self.grid.GetCellValue(row,col) | |
668 try: | |
669 int(value) | |
670 self.n_list[row].set('level',value) | |
671 except: self.grid.SetCellValue(row,col,"1") | |
672 | |
673 def refresh_row(self,i): | |
674 n = self.n_list[i] | |
675 name = n.get('name') | |
676 level = n.get('level') | |
677 self.grid.SetCellValue(i,0,name) | |
678 self.grid.SetReadOnly(i,0) | |
679 self.grid.SetCellValue(i,1,level) | |
680 | |
681 def on_remove(self,evt): | |
682 rows = self.grid.GetNumberRows() | |
683 for i in range(rows): | |
684 if self.grid.IsInSelection(i,0): | |
685 self.grid.DeleteRows(i) | |
686 self.xml.remove(self.n_list[i]) | |
687 | |
688 def on_add(self,evt): | |
689 if not self.temp_dom: | |
690 tree = parse(dir_struct["dnd3e"]+"dnd3eclasses.xml") | |
691 xml_dom = tree.getroot() | |
692 self.temp_dom = xml_dom | |
693 f_list = self.temp_dom.findall('class') | |
694 opts = [] | |
695 for f in f_list: opts.append(f.get('name')) | |
696 dlg = wx.SingleChoiceDialog(self,'Choose Class','Classes',opts) | |
697 if dlg.ShowModal() == wx.ID_OK: | |
698 i = dlg.GetSelection() | |
699 new_node = self.xml.append(f_list[i]) | |
700 self.grid.AppendRows(1) | |
701 self.refresh_row(self.grid.GetNumberRows()-1) | |
702 dlg.Destroy() | |
703 | |
704 def on_size(self,event): | |
705 s = self.GetClientSizeTuple() | |
706 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
707 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
708 (w,h) = self.grid.GetClientSizeTuple() | |
709 cols = self.grid.GetNumberCols() | |
710 col_w = w/(cols) | |
711 for i in range(0,cols): self.grid.SetColSize(i,col_w) | |
712 | |
713 | |
714 class dnd3esaves(class_char_child): | |
715 """ Node Handler for saves. This handler will be | |
716 created by dnd3echar_handler. | |
717 """ | |
718 def __init__(self,xml_dom,tree_node,parent): | |
719 class_char_child.__init__(self,xml_dom,tree_node,parent) | |
720 self.hparent = parent | |
721 self.saveGridFrame = [] | |
722 | |
723 tree = self.tree | |
724 icons = self.tree.icons | |
725 | |
726 self.root = getRoot(self) | |
727 self.root.saves = self | |
728 node_list = self.xml.findall('save') | |
729 self.saves={} | |
730 for n in node_list: | |
731 name = n.get('name') | |
732 self.saves[name] = n | |
733 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear']) | |
734 tree.SetPyData(new_tree_node,self) | |
735 | |
736 | |
737 def refresh_data(self): | |
738 # of the attack chart. | |
739 # count backwards, maintains context despite "removes" | |
740 for i in range(len(self.saveGridFrame)-1,-1,-1): | |
741 x = self.saveGridFrame[i] | |
742 if x == None: x.refresh_data() | |
743 else: self.saveGridFrame.remove(x) | |
744 | |
745 def get_mod(self,name): | |
746 save = self.saves[name] | |
747 stat = save.get('stat') | |
748 stat_mod = self.root.abilities.get_mod(stat) | |
749 base = int(save.get('base')) | |
750 miscmod = int(save.get('miscmod')) | |
751 magmod = int(save.get('magmod')) | |
752 total = stat_mod + base + miscmod + magmod | |
753 return total | |
754 | |
755 def on_rclick(self,evt): | |
756 item = self.tree.GetSelection() | |
757 name = self.tree.GetItemText(item) | |
758 if item == self.mytree_node: | |
759 pass | |
760 return | |
761 else: | |
762 mod = self.get_mod(name) | |
763 if mod >= 0: mod1 = "+" | |
764 else: mod1 = "" | |
765 chat = self.chat | |
766 txt = '%s save: [1d20%s%s]' % (name, mod1, mod) | |
243 | 767 Parse.Post( txt, self.chat, True, True ) |
156 | 768 |
769 def get_design_panel(self,parent): | |
770 wnd = outline_panel(parent,self,save_grid,"Saves") | |
771 wnd.title = "Saves" | |
772 return wnd | |
773 | |
774 def tohtml(self): | |
775 html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 > | |
776 <th width='30%'>Save</th> | |
777 <th>Key</th><th>Base</th><th>Abil</th><th>Magic</th> | |
778 <th>Misc</th><th>Total</th></tr>""" | |
779 node_list = self.xml.findall('save') | |
780 for n in node_list: | |
781 name = n.get('name') | |
782 stat = n.get('stat') | |
783 base = n.get('base') | |
784 html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+stat+"</td><td>"+base+"</td>" | |
785 stat_mod = self.root.abilities.get_mod(stat) | |
786 | |
787 mag = n.get('magmod') | |
788 misc = n.get('miscmod') | |
789 mod = str(self.get_mod(name)) | |
790 if mod >= 0: mod1 = "+" | |
791 else: mod1 = "" | |
792 html_str = html_str + "<td>"+str(stat_mod)+"</td><td>"+mag+"</td>" | |
793 html_str = html_str + '<td>'+misc+'</td><td>%s%s</td></tr>' % (mod1, mod) | |
794 html_str = html_str + "</table>" | |
795 return html_str | |
796 | |
797 #mark6 | |
798 class save_grid(wx.grid.Grid): | |
799 """grid for saves""" | |
800 def __init__(self, parent, handler): | |
801 pname = handler.xml.set("name", 'Saves') | |
802 self.hparent = handler | |
803 self.root = getRoot(self) | |
804 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
805 self.Bind(wx.EVT_SIZE, self.on_size) | |
806 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
807 self.handler = handler | |
808 saves = handler.xml.findall('save') | |
809 self.CreateGrid(len(saves),7) | |
810 self.SetRowLabelSize(0) | |
811 col_names = ['Save','Key','base','Abil','Magic','Misc','Total'] | |
812 for i in range(len(col_names)): self.SetColLabelValue(i,col_names[i]) | |
813 self.saves = saves | |
814 i = 0 | |
815 for i in range(len(saves)): self.refresh_row(i) | |
816 climber = parent | |
817 nameNode = climber.GetClassName() | |
818 while nameNode != 'wxFrame': | |
819 climber = climber.parent | |
820 nameNode = climber.GetClassName() | |
821 masterFrame=climber | |
822 masterFrame.refresh_data=self.refresh_data | |
823 handler.saveGridFrame.append(masterFrame) | |
824 | |
825 def on_cell_change(self,evt): | |
826 row = evt.GetRow() | |
827 col = evt.GetCol() | |
828 value = self.GetCellValue(row,col) | |
829 try: | |
830 int(value) | |
831 if col == 2: self.saves[row].set('base',value) | |
832 elif col == 4: self.saves[row].set('magmod',value) | |
833 elif col == 5: self.saves[row].set('miscmod',value) | |
834 self.refresh_row(row) | |
835 except: self.SetCellValue(row,col,"0") | |
836 | |
837 def refresh_row(self,rowi): | |
838 s = self.saves[rowi] | |
839 name = s.get('name') | |
840 self.SetCellValue(rowi,0,name) | |
841 self.SetReadOnly(rowi,0) | |
842 stat = s.get('stat') | |
843 self.SetCellValue(rowi,1,stat) | |
844 self.SetReadOnly(rowi,1) | |
845 self.SetCellValue(rowi,2,s.get('base')) | |
846 self.SetCellValue(rowi,3,str(self.root.abilities.get_mod(stat))) | |
847 self.SetReadOnly(rowi,3) | |
848 self.SetCellValue(rowi,4,s.get('magmod')) | |
849 self.SetCellValue(rowi,5,s.get('miscmod')) | |
850 mod = str(self.handler.get_mod(name)) | |
851 self.SetCellValue(rowi,6,mod) | |
852 self.SetReadOnly(rowi,6) | |
853 | |
854 def on_size(self,evt): | |
855 (w,h) = self.GetClientSizeTuple() | |
856 cols = self.GetNumberCols() | |
857 col_w = w/(cols+2) | |
858 self.SetColSize(0,col_w*3) | |
859 for i in range(1,cols): self.SetColSize(i,col_w) | |
860 evt.Skip() | |
861 self.Refresh() | |
862 | |
863 def refresh_data(self): | |
864 for r in range(self.GetNumberRows()): self.refresh_row(r) | |
865 | |
866 class dnd3eskillsnfeats(dnd3e_char_child): | |
867 """ Node handler for a dnd3e charactor | |
868 <nodehandler name='?' module='dnd3e' class='dnd3echar_handler2' /> | |
869 """ | |
870 def __init__(self,xml_dom,tree_node,parent): | |
871 self.hparent = parent | |
872 self.root = getRoot(self) | |
873 node_handler.__init__(self,xml_dom,tree_node) | |
874 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
875 self.frame = component.get('frame') | |
876 self.child_handlers = {} | |
877 self.new_child_handler('skills','Skills',dnd3eskill,'book') | |
878 self.new_child_handler('feats','Feats',dnd3efeats,'book') | |
879 self.myeditor = None | |
880 | |
881 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
882 node_list = self.xml.findall(tag) | |
883 tree = self.tree | |
884 i = self.tree.icons[icon] | |
885 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
886 handler = handler_class(node_list[0],new_tree_node,self) | |
887 tree.SetPyData(new_tree_node,handler) | |
888 self.child_handlers[tag] = handler | |
889 | |
890 def get_design_panel(self,parent): | |
891 return tabbed_panel(parent,self,1) | |
892 | |
893 def get_use_panel(self,parent): | |
894 return tabbed_panel(parent,self,2) | |
895 | |
896 class skills_char_child(node_handler): | |
897 """ Node Handler for skill. This handler will be | |
898 created by dnd3echar_handler. | |
899 """ | |
900 def __init__(self,xml_dom,tree_node,parent): | |
901 node_handler.__init__(self,xml_dom,tree_node) | |
902 self.char_hander = parent | |
903 self.drag = False | |
904 self.frame = component.get('frame') | |
905 self.myeditor = None | |
906 | |
907 def on_drop(self,evt): | |
908 pass | |
909 | |
910 def on_rclick(self,evt): | |
911 pass | |
912 | |
913 def on_ldclick(self,evt): | |
914 return | |
915 | |
916 def on_html(self,evt): | |
917 html_str = self.tohtml() | |
918 wnd = http_html_window(self.frame.note,-1) | |
919 wnd.title = self.xml.get('name') | |
920 self.frame.add_panel(wnd) | |
921 wnd.SetPage(html_str) | |
922 | |
923 def get_design_panel(self,parent): | |
924 pass | |
925 | |
926 def get_use_panel(self,parent): | |
927 return self.get_design_panel(parent) | |
928 | |
929 def delete(self): | |
930 pass | |
931 | |
932 class dnd3eskill(skills_char_child): | |
933 """ Node Handler for skill. This handler will be | |
934 created by dnd3echar_handler. | |
935 """ | |
936 def __init__(self,xml_dom,tree_node,parent): | |
937 self.hparent = parent | |
938 self.root = getRoot(self) | |
939 self.root.skills = self | |
940 | |
941 skills_char_child.__init__(self,xml_dom,tree_node,parent) | |
942 tree = self.tree | |
943 icons = self.tree.icons | |
944 node_list = self.xml.findall('skill') | |
945 | |
946 self.skills={} | |
947 for n in node_list: | |
948 name = n.get('name') | |
949 self.skills[name] = n | |
950 skill_check = self.skills[name] | |
951 ranks = int(skill_check.get('rank')) | |
952 trained = int(skill_check.get('untrained')) | |
953 if ranks > 0 or trained == 1: | |
954 new_tree_node = tree.AppendItem(self.mytree_node,name, | |
955 icons['gear'],icons['gear']) | |
956 else: continue | |
957 tree.SetPyData(new_tree_node,self) | |
958 | |
959 | |
960 def refresh_skills(self): | |
961 #Adding this so when you update the grid the tree will reflect | |
962 #The change. -mgt | |
963 tree = self.tree | |
964 icons = self.tree.icons | |
965 tree.CollapseAndReset(self.mytree_node) | |
966 node_list = self.xml.findall('skill') | |
967 self.skills={} | |
968 for n in node_list: | |
969 name = n.get('name') | |
970 self.skills[name] = n | |
971 skill_check = self.skills[name] | |
972 ranks = int(skill_check.get('rank')) | |
973 trained = int(skill_check.get('untrained')) | |
974 if ranks > 0 or trained == 1: | |
975 new_tree_node = tree.AppendItem(self.mytree_node,name, | |
976 icons['gear'],icons['gear']) | |
977 else: continue | |
978 tree.SetPyData(new_tree_node,self) | |
979 | |
980 def get_mod(self,name): | |
981 skill = self.skills[name] | |
982 stat = skill.get('stat') | |
983 stat_mod = self.root.abilities.get_mod(stat) | |
984 rank = int(skill.get('rank')) | |
985 misc = int(skill.get('misc')) | |
986 total = stat_mod + rank + misc | |
987 return total | |
988 | |
989 def on_rclick(self,evt): | |
990 item = self.tree.GetSelection() | |
991 name = self.tree.GetItemText(item) | |
992 if item == self.mytree_node: return | |
993 ac = self.root.ac.get_check_pen() | |
994 skill = self.skills[name] | |
995 untr = skill.get('untrained') | |
996 rank = skill.get('rank') | |
997 if eval('%s == 0' % (untr)): | |
998 if eval('%s == 0' % (rank)): | |
999 res = 'You fumble around, accomplishing nothing' | |
1000 txt = '%s Skill Check: %s' % (name, res) | |
1001 chat = self.chat | |
1002 chat.Post(txt,True,True) | |
1003 return | |
1004 armor = '' | |
1005 acCp = '' | |
1006 if ac < 0: | |
1007 armorCheck = int(skill.get('armorcheck')) | |
1008 if armorCheck == 1: | |
1009 acCp=ac | |
1010 armor = '(includes Armor Penalty of %s)' % (acCp) | |
1011 if item == self.mytree_node: | |
1012 dnd3e_char_child.on_ldclick(self,evt) | |
1013 else: | |
1014 mod = self.get_mod(name) | |
1015 if mod >= 0: mod1 = "+" | |
1016 else: mod1 = "" | |
1017 chat = self.chat | |
1018 txt = '%s Skill Check: [1d20%s%s%s] %s' % ( | |
1019 name, mod1, mod, acCp, armor) | |
243 | 1020 Parse.Post( txt, self.chat, True, True ) |
156 | 1021 |
1022 def get_design_panel(self,parent): | |
1023 wnd = outline_panel(parent,self,skill_grid,"Skills") | |
1024 wnd.title = "Skills (edit)" | |
1025 return wnd | |
1026 | |
1027 def tohtml(self): | |
1028 html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 > | |
1029 <th width='30%'>Skill</th><th>Key</th> | |
1030 <th>Rank</th><th>Abil</th><th>Misc</th><th>Total</th></tr>""" | |
1031 node_list = self.xml.findall('skill') | |
1032 | |
1033 for n in node_list: | |
1034 name = n.get('name') | |
1035 stat = n.get('stat') | |
1036 rank = n.get('rank') | |
1037 untr = n.get('untrained') | |
1038 #Filter unsuable skills out of pretty print -mgt | |
1039 if eval('%s > 0' % (rank)) or eval('%s == 1' % (untr)): | |
1040 if eval('%s >=1' % (rank)): | |
1041 html_str += "<tr ALIGN='center' bgcolor='#CCCCFF'><td>" | |
1042 html_str += name+"</td><td>"+stat+"</td><td>"+rank+"</td>" | |
1043 elif eval('%s == 1' % (untr)): | |
1044 html_str += "<tr ALIGN='center' bgcolor='#C0FF40'><td>" | |
1045 html_str += name+"</td><td>"+stat+"</td><td>"+rank+"</td>" | |
1046 else: | |
1047 html_str += "<tr ALIGN='center'><td>"+name+"</td><td>" | |
1048 html_str += stat+"</td><td>"+rank+"</td>" | |
1049 else: continue | |
1050 stat_mod = self.root.abilities.get_mod(stat) | |
1051 misc = n.get('misc') | |
1052 mod = str(self.get_mod(name)) | |
1053 if mod >= 0: mod1 = "+" | |
1054 else: mod1 = "" | |
1055 html_str += "<td>"+str(stat_mod)+"</td><td>"+misc #m 1.6009 str() | |
1056 html_str += '</td><td>%s%s</td></tr>' % (mod1, mod) | |
1057 html_str = html_str + "</table>" | |
1058 return html_str | |
1059 | |
1060 | |
1061 class skill_grid(wx.grid.Grid): | |
1062 """ panel for skills """ | |
1063 def __init__(self, parent, handler): | |
1064 self.hparent = handler | |
1065 self.root = getRoot(self) | |
1066 pname = handler.xml.set("name", 'Skills') | |
1067 | |
1068 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
1069 self.Bind(wx.EVT_SIZE, self.on_size) | |
1070 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
1071 self.handler = handler | |
1072 skills = handler.xml.findall('skill') | |
1073 | |
1074 self.CreateGrid(len(skills),6) | |
1075 self.SetRowLabelSize(0) | |
1076 col_names = ['Skill','Key','Rank','Abil','Misc','Total'] | |
1077 for i in range(len(col_names)): | |
1078 self.SetColLabelValue(i,col_names[i]) | |
1079 rowi = 0 | |
1080 self.skills = skills | |
1081 for i in range(len(skills)): self.refresh_row(i) | |
1082 | |
1083 def on_cell_change(self,evt): | |
1084 row = evt.GetRow() | |
1085 col = evt.GetCol() | |
1086 value = self.GetCellValue(row,col) | |
1087 try: | |
1088 int(value) | |
1089 if col == 2: self.skills[row].set('rank',value) | |
1090 elif col ==4: self.skills[row].set('misc',value) | |
1091 self.refresh_row(row) | |
1092 except: self.SetCellValue(row,col,"0") | |
1093 self.handler.refresh_skills() | |
1094 | |
1095 def refresh_row(self,rowi): | |
1096 s = self.skills[rowi] | |
1097 name = s.get('name') | |
1098 self.SetCellValue(rowi,0,name) | |
1099 self.SetReadOnly(rowi,0) | |
1100 stat = s.get('stat') | |
1101 self.SetCellValue(rowi,1,stat) | |
1102 self.SetReadOnly(rowi,1) | |
1103 self.SetCellValue(rowi,2,s.get('rank')) | |
1104 if self.root.abilities: stat_mod=self.root.abilities.get_mod(stat) | |
1105 else: | |
1106 stat_mod = -6 | |
1107 print "Please advise dnd3e maintainer alert 1.5002 raised" | |
1108 | |
1109 self.SetCellValue(rowi,3,str(stat_mod)) | |
1110 self.SetReadOnly(rowi,3) | |
1111 self.SetCellValue(rowi,4,s.get('misc')) | |
1112 mod = str(self.handler.get_mod(name)) | |
1113 self.SetCellValue(rowi,5,mod) | |
1114 self.SetReadOnly(rowi,5) | |
1115 | |
1116 def on_size(self,evt): | |
1117 (w,h) = self.GetClientSizeTuple() | |
1118 cols = self.GetNumberCols() | |
1119 col_w = w/(cols+2) | |
1120 self.SetColSize(0,col_w*3) | |
1121 for i in range(1,cols): self.SetColSize(i,col_w) | |
1122 evt.Skip() | |
1123 self.Refresh() | |
1124 | |
1125 def refresh_data(self): | |
1126 for r in range(self.GetNumberRows()): self.refresh_row(r) | |
1127 | |
1128 | |
1129 class dnd3efeats(skills_char_child): | |
1130 """ Node Handler for classes. This handler will be | |
1131 created by dnd3echar_handler. | |
1132 """ | |
1133 def __init__(self,xml_dom,tree_node,parent): | |
1134 skills_char_child.__init__(self,xml_dom,tree_node,parent) | |
1135 self.hparent = parent | |
1136 self.root = getRoot(self) | |
1137 self.root.feats = self | |
1138 | |
1139 def get_design_panel(self,parent): | |
1140 setTitle="Feats - " + self.root.general.charName | |
1141 wnd = outline_panel(parent,self,feat_panel,setTitle) | |
1142 wnd.title = "Feats" | |
1143 return wnd | |
1144 | |
1145 def tohtml(self): | |
1146 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Feats</th></tr><tr><td>" | |
1147 n_list = self.xml.getchildren() | |
135 | 1148 for n in n_list: |
156 | 1149 html_str += n.get('name')+ ", " |
1150 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
1151 return html_str | |
1152 | |
1153 class feat_panel(wx.Panel): | |
1154 def __init__(self, parent, handler): | |
1155 | |
1156 self.hparent = handler | |
1157 self.root = getRoot(self) | |
1158 pname = handler.xml.set("name", 'Feats') | |
1159 wx.Panel.__init__(self, parent, -1) | |
1160 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
1161 sizer = wx.BoxSizer(wx.VERTICAL) | |
1162 sizer.Add(self.grid, 1, wx.EXPAND) | |
1163 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
1164 sizer1.Add(wx.Button(self, 10, "Remove Feat"), 0, wx.EXPAND) | |
1165 sizer1.Add(wx.Size(10,10)) | |
1166 sizer1.Add(wx.Button(self, 20, "Add Feat"), 0, wx.EXPAND) | |
1167 sizer.Add(sizer1, 0, wx.EXPAND) | |
1168 self.sizer = sizer | |
1169 self.SetSizer(self.sizer) | |
1170 self.SetAutoLayout(True) | |
1171 self.Fit() | |
1172 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
1173 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
1174 n_list = handler.xml.getchildren() | |
1175 self.n_list = n_list | |
1176 self.xml = handler.xml | |
1177 self.grid.CreateGrid(len(n_list),3,1) | |
1178 self.grid.SetRowLabelSize(0) | |
1179 self.grid.SetColLabelValue(0,"Feat") | |
1180 self.grid.SetColLabelValue(1,"Type") | |
1181 self.grid.SetColLabelValue(2,"Reference") | |
1182 for i in range(len(n_list)): self.refresh_row(i) | |
1183 self.temp_dom = None | |
1184 | |
1185 def refresh_row(self,i): | |
1186 feat = self.n_list[i] | |
1187 name = feat.get('name') | |
1188 type = feat.get('type') | |
1189 desc = feat.get('desc') | |
1190 self.grid.SetCellValue(i,0,name) | |
1191 self.grid.SetReadOnly(i,0) | |
1192 self.grid.SetCellValue(i,1,type) | |
1193 self.grid.SetReadOnly(i,1) | |
1194 self.grid.SetCellValue(i,2,desc) | |
1195 self.grid.SetReadOnly(i,2) | |
1196 | |
1197 def on_remove(self,evt): | |
1198 rows = self.grid.GetNumberRows() | |
1199 for i in range(rows): | |
1200 if self.grid.IsInSelection(i,0): | |
1201 self.grid.DeleteRows(i) | |
1202 self.xml.remove(self.n_list[i]) | |
1203 | |
1204 def on_add(self,evt): | |
1205 | |
1206 if not self.temp_dom: | |
1207 tree = parse(dir_struct["dnd3e"]+"dnd3efeats.xml") | |
1208 temp_dom = tree.getroot() | |
1209 f_list = temp_dom.findall('feat') | |
1210 opts = [] | |
1211 for f in f_list: | |
1212 opts.append(f.get('name') + " - [" + | |
1213 f.get('type') + "] - " + f.get('desc')) | |
1214 dlg = wx.SingleChoiceDialog(self,'Choose Feat','Feats',opts) | |
1215 if dlg.ShowModal() == wx.ID_OK: | |
1216 i = dlg.GetSelection() | |
1217 new_node = self.xml.append(f_list[i]) | |
1218 self.grid.AppendRows(1) | |
1219 self.refresh_row(self.grid.GetNumberRows()-1) | |
1220 dlg.Destroy() | |
1221 | |
1222 | |
1223 def on_size(self,event): | |
1224 s = self.GetClientSizeTuple() | |
1225 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
1226 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
1227 (w,h) = self.grid.GetClientSizeTuple() | |
1228 cols = self.grid.GetNumberCols() | |
1229 col_w = w/(cols) | |
1230 for i in range(0,cols): | |
1231 self.grid.SetColSize(i,col_w) | |
1232 | |
1233 class dnd3ecombat(dnd3e_char_child): | |
1234 """ Node handler for a dnd3e charactor | |
1235 <nodehandler name='?' module='dnd3e' class='dnd3echar_handler2' /> | |
1236 """ | |
1237 def __init__(self,xml_dom,tree_node,parent): | |
1238 | |
1239 node_handler.__init__(self,xml_dom,tree_node) | |
1240 | |
1241 self.hparent = parent | |
1242 self.root = getRoot(self) | |
1243 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
1244 self.frame = component.get('frame') | |
1245 self.child_handlers = {} | |
1246 self.new_child_handler('hp','Hit Points',dnd3ehp,'gear') | |
1247 self.new_child_handler('attacks','Attacks',dnd3eattacks,'spears') | |
1248 self.new_child_handler('ac','Armor',dnd3earmor,'spears') | |
1249 self.myeditor = None | |
1250 | |
1251 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
1252 node_list = self.xml.findall(tag) | |
1253 tree = self.tree | |
1254 i = self.tree.icons[icon] | |
1255 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
1256 handler = handler_class(node_list[0],new_tree_node,self) | |
1257 tree.SetPyData(new_tree_node,handler) | |
1258 self.child_handlers[tag] = handler | |
1259 | |
1260 def get_design_panel(self,parent): | |
1261 return tabbed_panel(parent,self,1) | |
1262 | |
1263 def get_use_panel(self,parent): | |
1264 return tabbed_panel(parent,self,2) | |
1265 | |
1266 | |
1267 class combat_char_child(node_handler): | |
1268 """ Node Handler for combat. This handler will be | |
1269 created by dnd3echar_handler. | |
1270 """ | |
1271 def __init__(self,xml_dom,tree_node,parent): | |
1272 node_handler.__init__(self,xml_dom,tree_node) | |
1273 self.char_hander = parent | |
1274 self.drag = False | |
1275 self.frame = component.get('frame') | |
1276 self.myeditor = None | |
1277 | |
1278 def on_drop(self,evt): | |
1279 pass | |
1280 | |
1281 def on_rclick(self,evt): | |
1282 pass | |
1283 | |
1284 def on_ldclick(self,evt): | |
1285 return | |
1286 | |
1287 def on_html(self,evt): | |
1288 html_str = self.tohtml() | |
1289 wnd = http_html_window(self.frame.note,-1) | |
1290 wnd.title = self.xml.get('name') | |
1291 self.frame.add_panel(wnd) | |
1292 wnd.SetPage(html_str) | |
1293 | |
1294 def get_design_panel(self,parent): | |
1295 pass | |
1296 | |
152 | 1297 def get_use_panel(self,parent): |
156 | 1298 return self.get_design_panel(parent) |
1299 | |
1300 def delete(self): | |
1301 pass | |
1302 | |
1303 class dnd3ehp(combat_char_child): | |
1304 """ Node Handler for hit points. This handler will be | |
1305 created by dnd3echar_handler. | |
1306 """ | |
1307 def __init__(self,xml_dom,tree_node,parent): | |
1308 combat_char_child.__init__(self,xml_dom,tree_node,parent) | |
1309 self.hparent = parent | |
1310 self.root = getRoot(self) | |
1311 self.root.hp = self | |
1312 | |
1313 def get_design_panel(self,parent): | |
1314 wnd = outline_panel(parent,self,hp_panel,"Hit Points") | |
1315 wnd.title = "Hit Points" | |
1316 return wnd | |
1317 | |
1318 def on_rclick( self, evt ): | |
1319 chp = self.xml.get('current') | |
1320 mhp = self.xml.get('max') | |
1321 txt = '((HP: %s / %s))' % ( chp, mhp ) | |
243 | 1322 Parse.Post( txt, self.chat, True, True ) |
156 | 1323 |
1324 def tohtml(self): | |
1325 html_str = "<table width=100% border=1 >" | |
1326 html_str += "<tr BGCOLOR=#E9E9E9 ><th colspan=4>Hit Points</th></tr>" | |
1327 html_str += "<tr><th>Max:</th>" | |
1328 html_str += "<td>"+self.xml.get('max')+"</td>" | |
1329 html_str += "<th>Current:</th>" | |
1330 html_str += "<td>"+self.xml.get('current')+"</td>" | |
1331 html_str += "</tr></table>" | |
1332 return html_str | |
1333 | |
1334 class hp_panel(wx.Panel): | |
1335 def __init__(self, parent, handler): | |
1336 wx.Panel.__init__(self, parent, -1) | |
1337 self.hparent = handler | |
1338 pname = handler.xml.set("name", 'HitPoints') | |
1339 self.sizer = wx.FlexGridSizer(2, 4, 2, 2) # rows, cols, hgap, vgap | |
1340 self.xml = handler.xml | |
1341 self.sizer.AddMany([ (wx.StaticText(self, -1, "HP Current:"), 0, | |
1342 wx.ALIGN_CENTER_VERTICAL), | |
1343 (wx.TextCtrl(self, HP_CUR, | |
1344 self.xml.get('current')), 0, wx.EXPAND), | |
1345 (wx.StaticText(self, -1, "HP Max:"), 0, wx.ALIGN_CENTER_VERTICAL), | |
1346 (wx.TextCtrl(self, HP_MAX, self.xml.get('max')), | |
1347 0, wx.EXPAND), | |
1348 ]) | |
1349 self.sizer.AddGrowableCol(1) | |
1350 self.SetSizer(self.sizer) | |
1351 self.SetAutoLayout(True) | |
1352 self.Fit() | |
1353 self.Bind(wx.EVT_TEXT, self.on_text, id=HP_MAX) | |
1354 self.Bind(wx.EVT_TEXT, self.on_text, id=HP_CUR) | |
1355 | |
1356 def on_text(self,evt): | |
1357 id = evt.GetId() | |
1358 if id == HP_CUR: self.xml.set('current',evt.GetString()) | |
1359 elif id == HP_MAX: self.xml.set('max',evt.GetString()) | |
1360 | |
1361 def on_size(self,evt): | |
1362 s = self.GetClientSizeTuple() | |
1363 self.sizer.SetDimension(0,0,s[0],s[1]) | |
1364 | |
1365 class dnd3eattacks(combat_char_child): | |
1366 """ Node Handler for attacks. This handler will be | |
1367 created by dnd3echar_handler. | |
1368 """ | |
1369 def __init__(self,xml_dom,tree_node,parent): | |
1370 combat_char_child.__init__(self,xml_dom,tree_node,parent) | |
1371 self.hparent = parent | |
1372 self.root = getRoot(self) | |
1373 self.root.attacks = self | |
1374 self.mrFrame = [] | |
1375 self.updateFootNotes = False | |
1376 self.updateFootNotes = False | |
1377 self.html_str = "<html><body>" | |
1378 self.html_str += ("<br> This character has weapons with no "+ | |
1379 "footnotes. This program will "+ | |
1380 "add footnotes to the weapons which have names that still match "+ | |
1381 "the orginal names. If you have changed the weapon name, you "+ | |
1382 "will see some weapons with a footnote of 'X', you will have "+ | |
1383 "to either delete and re-add the weapon, or research "+ | |
1384 "and add the correct footnotes for the weapon.\n"+ | |
1385 "<br> Please be aware, that only the bow/sling footnote is "+ | |
1386 "being used to affect changes to rolls; implemenation of other "+ | |
1387 "footnotes to automaticly adjust rolls will be completed as "+ | |
1388 "soon as time allows." + | |
1389 "<br><br>Update to character:"+self.root.general.charName+ | |
1390 "<br><br>"+ | |
1391 """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 > | |
1392 <th width='80%'>Weapon Name</th><th>Added Footnote</th></tr>\n""") | |
1393 self.temp_dom={} | |
1394 node_list = self.xml.findall('melee') | |
1395 self.melee = node_list[0] | |
1396 node_list = self.xml.findall('ranged') | |
1397 self.ranged = node_list[0] | |
1398 self.refresh_weapons() | |
1399 if self.updateFootNotes == True: | |
1400 self.updateFootNotes = False | |
1401 name = self.root.general.charName | |
1402 self.html_str += "</table>" | |
1403 self.html_str += "</body> </html> " | |
1404 masterFrame = self.root.frame | |
1405 title = name+"'s weapons' update to have footnotes" | |
1406 fnFrame = wx.Frame(masterFrame, -1, title) | |
1407 fnFrame.panel = wx.html.HtmlWindow(fnFrame,-1) | |
1408 fnFrame.panel.SetPage(self.html_str) | |
1409 fnFrame.Show() | |
1410 | |
1411 | |
1412 | |
1413 def refreshMRdata(self): | |
1414 # of the attack chart. | |
1415 # count backwards, maintains context despite "removes" | |
1416 for i in range(len(self.mrFrame)-1,-1,-1): | |
1417 x = self.mrFrame[i] | |
1418 if x == None: x.refreshMRdata() #a 1.9001 | |
1419 else: self.mrFrame.remove(x) | |
1420 | |
1421 def refresh_weapons(self): | |
1422 self.weapons = {} | |
1423 | |
1424 tree = self.tree | |
1425 icons = self.tree.icons | |
1426 tree.CollapseAndReset(self.mytree_node) | |
1427 node_list = self.xml.findall('weapon') | |
1428 for n in node_list: | |
1429 name = n.get('name') | |
1430 fn = safeGetAttr(n,'fn') | |
1431 if fn == None: | |
1432 self.updateFootNotes=True | |
1433 self.updateFootN(n) | |
1434 new_tree_node = tree.AppendItem( | |
1435 self.mytree_node,name,icons['sword'],icons['sword']) | |
1436 tree.SetPyData(new_tree_node,self) | |
1437 self.weapons[name]=n | |
1438 | |
1439 def updateFootN(self,n): | |
1440 if not self.temp_dom: | |
1441 tree = parse(dir_struct["dnd3e"]+"dnd3eweapons.xml") | |
1442 self.temp_dom = tree.getroot() | |
1443 nameF = n.get('name') | |
1444 w_list = self.temp_dom.findall('weapon') | |
1445 found = False | |
1446 for w in w_list: | |
1447 if nameF == w.get('name'): | |
1448 found = True | |
1449 fnN = safeGetAttr(n,'fn') | |
1450 if fnN == None or fnN == 'None': | |
1451 fnW = w.get('fn') | |
1452 self.html_str += ("<tr ALIGN='center'><td>"+nameF+"</td>"+ | |
1453 "<td>"+fnW+"</td></tr>\n") | |
1454 n.set('fn',fnW) | |
1455 break | |
1456 if not found: | |
1457 self.html_str += ("<tr ALIGN='center'><td>"+nameF+" - Custom "+ | |
1458 "Weapon, research "+ | |
1459 "and update manually; setting footnote to indicate custom</td>"+ | |
1460 "<td>"+'X'+"</td></tr>\n") | |
1461 n.set('fn','X') | |
1462 | |
1463 def get_mod(self,type='m'): | |
1464 (base, base2, base3, base4, base5, base6, stat_mod, misc) \ | |
1465 = self.get_attack_data(type) | |
1466 return int(base + misc + int(stat_mod)) | |
1467 | |
1468 def get_attack_data(self,type='m'): | |
1469 if type=='m' or type=='0': | |
1470 stat = 'Str' | |
1471 temp = self.melee | |
1472 else: | |
1473 stat = 'Dex' | |
1474 temp = self.ranged | |
1475 stat_mod = -7 | |
1476 stat_mod = self.root.abilities.get_mod(stat) | |
1477 base = int(temp.get('base')) | |
1478 base2 = int(temp.get('second')) | |
1479 base3 = int(temp.get('third')) | |
1480 base4 = int(temp.get('forth')) | |
1481 base5 = int(temp.get('fifth')) | |
1482 base6 = int(temp.get('sixth')) | |
1483 misc = int(temp.get('misc')) | |
1484 return (base, base2, base3, base4, base5, base6, stat_mod ,misc) | |
1485 | |
1486 def on_rclick(self,evt): | |
1487 item = self.tree.GetSelection() | |
1488 | |
1489 name = self.tree.GetItemText(item) | |
1490 if item == self.mytree_node: | |
1491 return | |
1492 else: | |
1493 | |
1494 mod = int(self.weapons[name].get('mod')) | |
1495 wepMod = mod #a 1.5008 | |
1496 footNotes = safeGetAttr(self.weapons[name],'fn','') | |
1497 cat = self.weapons[name].get('category') #a1.6001 | |
1498 result = split(cat,"-",2) #a 1.6001 | |
1499 if len(result) < 2: #a 1.6021 this if & else | |
1500 print "warning: 1.6002 unable to interpret weapon category" | |
1501 print "format 'type weapon-[Range|Melee]', probably missing" | |
1502 print "the hyphen. Assuming Melee" | |
1503 print "weapon name: ",name | |
1504 tres="Melee" | |
1505 else: | |
1506 tres=result[1] | |
1507 if tres == 'Melee': #a 1.6001 #m 1.6022 use of tres here and... | |
1508 rangeOrMelee = 'm' #a 1.5008 code demote for next comment block | |
1509 elif tres == 'Ranged': #m 1.6001 (was just else) #m 1.6022 here | |
1510 rangeOrMelee = 'r' #a 1.5008 | |
1511 else:#a 1.6001 add this whole else clause. | |
1512 print "warning: 1.6001 unable to interpret weapon category" | |
1513 print "treating weapon as Melee, please correct xml" | |
1514 print "weapon name:",name | |
1515 rangeOrMelee ='m' | |
1516 mod = mod + self.get_mod(rangeOrMelee) #a 1.5008 | |
1517 chat = self.chat | |
1518 dmg = self.weapons[name].get('damage') | |
1519 | |
1520 #a 1.6003 start code fix instance a | |
1521 result = split(dmg,"/",2) | |
1522 dmg = result[0] | |
1523 monkLvl = self.root.classes.get_class_lvl('Monk') # a 1.5002 | |
1524 if dmg == "Monk Med": | |
1525 if monkLvl == None: #a 1.5009 | |
1526 txt = 'Attempting to use monk attack, but has no monk ' | |
1527 txt += 'levels, please choose a different attack.' | |
243 | 1528 Parse.Post( txt, self.chat, True, True ) |
156 | 1529 return #a 1.5009 |
1530 else: #a 1.5009 | |
1531 lvl=int(monkLvl) | |
1532 if lvl <= 3: dmg = "1d6" | |
1533 elif lvl <= 7: dmg = "1d8" | |
1534 elif lvl <= 11: dmg = "1d10" | |
1535 elif lvl <= 15: dmg = "2d6" | |
1536 elif lvl <= 19: dmg = "2d8" | |
1537 elif lvl <= 20: dmg = "2d10" | |
1538 if dmg == "Monk Small": | |
1539 if monkLvl == None: | |
1540 txt = 'Attempting to use monk attack, but has no monk ' | |
1541 txt += 'levels, please choose a different attack.' | |
243 | 1542 Parse.Post( txt, self.chat, True, True ) |
156 | 1543 return |
1544 else: | |
1545 lvl=int(monkLvl) | |
1546 if lvl <= 3: dmg = "1d4" | |
1547 elif lvl <= 7: dmg = "1d6" | |
1548 elif lvl <= 11: dmg = "1d8" | |
1549 elif lvl <= 15: dmg = "1d10" | |
1550 elif lvl <= 20: dmg = "2d6" | |
1551 flu = '' | |
1552 str_mod = self.root.abilities.get_mod('Str') #a 1.5007,11,12,13 | |
1553 if rangeOrMelee == 'r': #a 1.5008 | |
1554 | |
1555 if find(footNotes,'b') > -1: | |
1556 if str_mod >= 0: str_mod = 0 | |
1557 else: str_mod = 0 | |
1558 mod2 = "" | |
1559 if str_mod >= 0: mod2 = "+" | |
1560 aStrengthMod = mod2 + str(str_mod) #a 1.5008 applicable strength mod | |
1561 if find(name ,"Flurry of Blows") > -1: #a 1.6012 | |
1562 flu = '-2' | |
1563 (base, base2, base3, base4, base5, base6, stat_mod, misc)\ | |
1564 = self.get_attack_data(rangeOrMelee) #a 1.5008 | |
1565 self.sendRoll(base ,stat_mod,misc,wepMod,name,flu,dmg, | |
1566 aStrengthMod,'',True,rollAnyWay=True) | |
1567 if flu != '': | |
1568 self.sendRoll(base ,stat_mod,misc,wepMod,name,flu,dmg, | |
1569 aStrengthMod) #a 1.6021 | |
1570 | |
1571 self.sendRoll(base2,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1572 self.sendRoll(base3,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1573 self.sendRoll(base4,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1574 self.sendRoll(base5,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1575 self.sendRoll(base6,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod) | |
1576 | |
1577 | |
1578 def sendRoll(self,base,stat_mod,misc,wepMod,name,flu,dmg,aStrengthMod, | |
1579 spacer="",pname=False,rollAnyWay=False): | |
1580 if base != 0 or rollAnyWay: | |
1581 base = base + int(stat_mod) + misc + wepMod #m 1.5008 | |
1582 if base >= 0: mod1 = "+" | |
1583 else: mod1 = "" | |
1584 txt = '%s ' % (spacer) | |
1585 txt += '%s Attack Roll: <b>[1d20%s%s%s]</b>' % (name, mod1, base, flu) | |
1586 txt += ' ===> Damage: <b>[%s%s]</b>' % (dmg, aStrengthMod) | |
243 | 1587 Parse.Post( txt, self.chat, True, True ) |
156 | 1588 |
1589 def get_design_panel(self,parent): | |
1590 wnd = outline_panel(parent,self,attack_panel,"Attacks") | |
1591 wnd.title = "Attacks" | |
1592 return wnd | |
1593 | |
1594 def tohtml(self): | |
1595 melee = self.get_attack_data('m') | |
1596 ranged = self.get_attack_data('r') | |
1597 html_str = ("""<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 >"""+ | |
1598 "<th>Attack</th><th>Total</th><th >Base</th>"+ | |
1599 "<th>Abil</th><th>Misc</th></tr>") | |
1600 html_str += "<tr ALIGN='center' ><th >Melee:</th>" | |
1601 html_str += "<td>"+str(melee[0]+melee[1]+melee[2])+"</td>" | |
1602 html_str += "<td>"+str(melee[0])+"</td>" | |
1603 html_str += "<td>"+str(melee[1])+"</td>" | |
1604 html_str += "<td>"+str(melee[2])+"</td></tr>" | |
1605 | |
1606 html_str += "<tr ALIGN='center' ><th >Ranged:</th>" | |
1607 html_str += "<td>"+str(ranged[0]+ranged[1]+ranged[2])+"</td>" | |
1608 html_str += "<td>"+str(ranged[0])+"</td>" | |
1609 html_str += "<td>"+str(ranged[1])+"</td>" | |
1610 html_str += "<td>"+str(ranged[2])+"</td></tr></table>" | |
1611 | |
1612 n_list = self.xml.findall('weapon') | |
1613 for n in n_list: | |
1614 mod = n.get('mod') | |
1615 if mod >= 0: mod1 = "+" | |
1616 else: mod1 = "" | |
1617 ran = n.get('range') | |
1618 total = str(int(mod) + self.get_mod(ran)) | |
1619 html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 > | |
1620 <th colspan=2>Weapon</th> | |
1621 <th>Attack</th><th >Damage</th><th>Critical</th></tr>""" | |
1622 html_str += "<tr ALIGN='center' ><td colspan=2>" | |
1623 html_str += n.get('name')+"</td><td>"+total+"</td>" | |
1624 html_str += "<td>"+n.get('damage')+"</td><td>" | |
1625 html_str += n.get('critical')+"</td></tr>" | |
1626 html_str += """<tr BGCOLOR=#E9E9E9 ><th>Range</th><th>Weight</th> | |
1627 <th>Type</th><th>Size</th><th>Misc Mod</th></tr>""" | |
1628 html_str += "<tr ALIGN='center'><td>"+ran+"</td><td>" | |
1629 html_str += n.get('weight')+"</td>" | |
1630 html_str += "<td>"+n.get('type')+"</td><td>" | |
1631 html_str += n.get('size')+"</td>" | |
1632 html_str += '<td>%s%s</td></tr>' % (mod1, mod) | |
1633 html_str += """<tr><th BGCOLOR=#E9E9E9 colspan=2>Footnotes:</th>""" | |
1634 html_str += "<th colspan=3>"+safeGetAttr(n,'fn','')+"</th></tr>" | |
1635 html_str += '</table>' | |
1636 return html_str | |
1637 | |
1638 class attack_grid(wx.grid.Grid): | |
1639 """grid for attacks""" | |
1640 def __init__(self, parent, handler): | |
1641 pname = handler.xml.set("name", 'Melee') | |
1642 self.hparent = handler | |
1643 wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
1644 | |
1645 self.root = getRoot(self) #a 1.9001 | |
1646 self.parent = parent | |
1647 self.handler = handler | |
1648 self.rows = (self.handler.melee,self.handler.ranged) | |
1649 self.CreateGrid(2,10) | |
1650 self.SetRowLabelSize(0) | |
1651 col_names = ['Type','base','base 2','base 3','base 4','base 5', | |
1652 'base 6','abil','misc','Total'] | |
1653 for i in range(len(col_names)): self.SetColLabelValue(i,col_names[i]) | |
1654 self.SetCellValue(0,0,"Melee") | |
1655 self.SetCellValue(1,0,"Ranged") | |
1656 self.refresh_data() | |
1657 self.Bind(wx.EVT_SIZE, self.on_size) | |
1658 self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
1659 climber = parent | |
1660 nameNode = climber.GetClassName() | |
1661 while nameNode != 'wxFrame': | |
1662 climber = climber.parent | |
1663 nameNode = climber.GetClassName() | |
1664 masterFrame=climber | |
1665 masterFrame.refreshMRdata=self.refresh_data | |
1666 handler.mrFrame.append(masterFrame) | |
1667 | |
1668 | |
1669 def on_cell_change(self,evt): | |
1670 row = evt.GetRow() | |
1671 col = evt.GetCol() | |
1672 value = self.GetCellValue(row,col) | |
1673 try: | |
1674 int(value) | |
1675 if col==1: self.rows[row].set('base',value) | |
1676 elif col==2: self.rows[row].set('second',value) | |
1677 elif col==3: self.rows[row].set('third',value) | |
1678 elif col==4: self.rows[row].set('forth',value) | |
1679 elif col==5: self.rows[row].set('fifth',value) | |
1680 elif col==6: self.rows[row].set('sixth',value) | |
1681 elif col==8: self.rows[row].set('misc',value) | |
1682 self.parent.refresh_data() | |
1683 except: self.SetCellValue(row,col,"0") | |
1684 | |
1685 def refresh_data(self): | |
1686 melee = self.handler.get_attack_data('m') | |
1687 ranged = self.handler.get_attack_data('r') | |
1688 tmelee = int(melee[0]) + int(melee[6]) + int(melee[7]) | |
1689 tranged = int(ranged[0]) + int(ranged[6]) + int(ranged[7]) | |
1690 for i in range(0,8): #a 1.5005 | |
1691 self.SetCellValue(0,i+1,str(melee[i])) | |
1692 self.SetCellValue(1,i+1,str(ranged[i])) | |
1693 self.SetCellValue(0,9,str(tmelee)) | |
1694 self.SetCellValue(1,9,str(tranged)) | |
1695 self.SetReadOnly(0,0) | |
1696 self.SetReadOnly(1,0) | |
1697 self.SetReadOnly(0,7) | |
1698 self.SetReadOnly(1,7) | |
1699 self.SetReadOnly(0,9) | |
1700 self.SetReadOnly(1,9) | |
1701 | |
1702 def on_size(self,evt): | |
1703 (w,h) = self.GetClientSizeTuple() | |
1704 cols = self.GetNumberCols() | |
1705 col_w = w/(cols+1) | |
1706 self.SetColSize(0,col_w*2) | |
1707 for i in range(1,cols): self.SetColSize(i,col_w) | |
1708 evt.Skip() | |
1709 self.Refresh() | |
1710 | |
1711 class weapon_panel(wx.Panel): | |
1712 def __init__(self, parent, handler): | |
1713 self.hparent = handler | |
1714 self.root = getRoot(self) | |
1715 pname = handler.xml.set("name", 'Weapons') | |
1716 wx.Panel.__init__(self, parent, -1) | |
1717 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
1718 sizer = wx.BoxSizer(wx.VERTICAL) | |
1719 sizer.Add(self.grid, 1, wx.EXPAND) | |
1720 sizer2 = wx.BoxSizer(wx.HORIZONTAL) | |
1721 sizer2.Add(wx.Button(self, 10, "Remove Weapon"), 0, wx.EXPAND) | |
1722 sizer2.Add(wx.Size(10,10)) | |
1723 sizer2.Add(wx.Button(self, 20, "Add Weapon"), 0, wx.EXPAND) | |
1724 sizer.Add(sizer2, 0, wx.EXPAND) | |
1725 sizer.Add(wx.StaticText(self, -1, "Right click a weapon's footnote to see what the footnotes mean."),0, wx.EXPAND)#a 1.5012 | |
1726 self.sizer = sizer | |
1727 self.SetSizer(self.sizer) | |
1728 self.SetAutoLayout(True) | |
1729 self.Fit() | |
1730 self.sizer2 = sizer2 | |
1731 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
1732 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
1733 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
1734 self.grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.on_gridRclick)#a 1.5012 | |
1735 | |
1736 n_list = handler.xml.findall('weapon') | |
1737 self.n_list = n_list | |
1738 self.xml = handler.xml | |
1739 self.handler = handler | |
1740 self.colAttr = ['name','damage','mod','critical','type','weight', | |
1741 'range','size','Total','fn', 'comment'] | |
1742 col_names = ['Name','Damage','To hit\nmod','Critical','Type','Weight', | |
1743 'Range','Size','Total','Foot\nnotes','Comment'] | |
1744 gridColCount=len(col_names) | |
1745 self.grid.CreateGrid(len(n_list),gridColCount,1) | |
1746 self.grid.SetRowLabelSize(0) | |
1747 for i in range(gridColCount): self.grid.SetColLabelValue(i,col_names[i]) | |
1748 self.refresh_data() | |
1749 self.temp_dom = None | |
1750 | |
1751 | |
1752 #mark4 | |
1753 #a 1.5012 add entire method. | |
1754 def on_gridRclick(self,evt): | |
1755 row = evt.GetRow() | |
1756 col = evt.GetCol() | |
1757 value = self.grid.GetCellValue(row,col) | |
1758 if col == 9 and value != 'None': | |
1759 n = self.n_list[row] | |
1760 name = n.get('name') | |
1761 handler = self.hparent | |
1762 # A handler is a node, and nodes have a reference to | |
1763 # the master frame | |
1764 masterFrame = handler.frame | |
1765 title = name+"'s Special Weapon Characteristics" | |
1766 fnFrame = wx.Frame(masterFrame, -1, title) | |
1767 fnFrame.panel = wx.html.HtmlWindow(fnFrame,-1) | |
1768 if not self.temp_dom: | |
1769 tree = parse(dir_struct["dnd3e"]+"dnd3eweapons.xml") | |
1770 xml_dom = tree.getroot() | |
1771 self.temp_dom = xml_dom | |
1772 f_list = self.temp_dom.findall('f') # the footnotes | |
1773 n = self.n_list[row] | |
1774 name = n.get('name') | |
1775 footnotes = n.get('fn') | |
1776 html_str = "<html><body>" | |
1777 html_str += """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 > | |
1778 <th width='10%'>Note</th><th>Description</th></tr>\n""" | |
1779 if footnotes == "": | |
1780 html_str += "<tr ALIGN='center'><td></td>" | |
1781 html_str += " <td>This weapon has no footnotes</td></tr>" | |
1782 for i in range(len(footnotes)): | |
1783 aNote=footnotes[i] | |
1784 found=False | |
1785 for f in f_list: | |
1786 if f.get('mark') == aNote: | |
1787 found=True | |
1788 text=f.get('txt') | |
1789 html_str += ("<tr ALIGN='center'><td>"+aNote+"</td>"+ | |
1790 "<td>"+text+"</td></tr>\n") | |
1791 if not found: | |
1792 html_str += ("<tr ALIGN='center'><td>"+aNote+"</td>"+ | |
1793 "<td>is not a recognized footnote</td></tr>\n") | |
1794 | |
1795 html_str += "</table>" | |
1796 html_str += "</body> </html> " | |
1797 fnFrame.panel.SetPage(html_str) | |
1798 fnFrame.Show() | |
1799 return | |
1800 pass | |
1801 | |
1802 | |
1803 def on_cell_change(self,evt): | |
1804 row = evt.GetRow() | |
1805 col = evt.GetCol() | |
1806 value = self.grid.GetCellValue(row,col) | |
1807 if col == 2 and not int(value): # special case for mod, demoted | |
1808 value = "0" #a 5.012 demoted | |
1809 self.n_list[row].set('mod',value) # a 5.012 demoted | |
1810 if not (col == 9 and value == "None" and | |
1811 self.n_list[row].get('fn') == "None" | |
1812 ): #a 5.012 special case for footnotes | |
1813 self.n_list[row].set(self.colAttr[col],value)#a 5.012 | |
1814 | |
1815 | |
1816 def refresh_row(self,i): | |
1817 n = self.n_list[i] | |
1818 fn = n.get('fn') | |
1819 name = n.get('name') | |
1820 mod = n.get('mod') | |
1821 ran = n.get('range') | |
1822 total = str(int(mod) + self.handler.get_mod(ran)) | |
1823 self.grid.SetCellValue(i,0,name) | |
1824 self.grid.SetCellValue(i,1,n.get('damage')) | |
1825 self.grid.SetCellValue(i,2,mod) | |
1826 self.grid.SetCellValue(i,3,n.get('critical')) | |
1827 self.grid.SetCellValue(i,4,n.get('type')) | |
1828 self.grid.SetCellValue(i,5,n.get('weight')) | |
1829 self.grid.SetCellValue(i,6,ran) | |
1830 self.grid.SetCellValue(i,7,n.get('size') ) | |
1831 self.grid.SetCellValue(i,8,total) | |
1832 self.grid.SetCellValue(i,9,safeGetAttr(n,'fn','None')) #a 1.5012 | |
1833 self.grid.SetCellValue(i,10,safeGetAttr(n,'comment','')) #a 1.5012 | |
1834 self.grid.SetReadOnly(i,8) | |
1835 | |
1836 def on_remove(self,evt): #o 1.6011 correcting wrongful deletion | |
1837 rows = self.grid.GetNumberRows() | |
1838 for i in range(rows-1,-1,-1): #a 1.6011 or you lose context | |
1839 if self.grid.IsInSelection(i,0): | |
1840 self.grid.DeleteRows(i) | |
1841 self.xml.remove(self.n_list[i]) | |
1842 self.n_list = self.xml.findall('weapon') | |
1843 self.handler.refresh_weapons() | |
1844 | |
1845 def on_add(self,evt): | |
1846 if not self.temp_dom: | |
1847 tree = parse(dir_struct["dnd3e"]+"dnd3eweapons.xml") | |
1848 xml_dom = tree.getroot() | |
1849 self.temp_dom = xml_dom | |
1850 f_list = self.temp_dom.findall('weapon') | |
1851 opts = [] | |
1852 for f in f_list: | |
1853 opts.append(f.get('name')) | |
1854 dlg = wx.SingleChoiceDialog(self,'Choose Weapon','Weapon List',opts) | |
1855 if dlg.ShowModal() == wx.ID_OK: | |
1856 i = dlg.GetSelection() | |
1857 new_node = self.xml.append(f_list[i]) | |
1858 self.grid.AppendRows(1) | |
1859 self.n_list = self.xml.findall('weapon') | |
1860 self.refresh_row(self.grid.GetNumberRows()-1) | |
1861 self.handler.refresh_weapons() | |
1862 dlg.Destroy() | |
1863 | |
1864 def on_size(self,event): | |
1865 s = self.GetClientSizeTuple() | |
1866 self.grid.SetDimensions(0,0,s[0],s[1]-40) | |
1867 self.sizer.SetDimension(0,s[1]-40,s[0],25) | |
1868 self.sizer2.SetDimension(0,s[1]-15,s[0],15) | |
1869 (w,h) = self.grid.GetClientSizeTuple() | |
1870 cols = self.grid.GetNumberCols() | |
1871 col_w = w/(cols+1) | |
1872 self.grid.SetColSize(0,col_w*2) | |
1873 for i in range(1,cols): self.grid.SetColSize(i,col_w) | |
1874 | |
1875 def refresh_data(self): | |
1876 for i in range(len(self.n_list)): self.refresh_row(i) | |
1877 | |
1878 | |
1879 class attack_panel(wx.Panel): | |
1880 def __init__(self, parent, handler): | |
1881 pname = handler.xml.set("name", 'Melee') | |
1882 self.parent = parent #a 1.9001 | |
1883 wx.Panel.__init__(self, parent, -1) | |
1884 self.a_grid = attack_grid(self, handler) | |
1885 self.w_panel = weapon_panel(self, handler) | |
1886 self.sizer = wx.BoxSizer(wx.VERTICAL) | |
1887 self.sizer.Add(self.a_grid, 1, wx.EXPAND) | |
1888 self.sizer.Add(self.w_panel, 2, wx.EXPAND) | |
1889 self.Bind(wx.EVT_SIZE, self.on_size) | |
1890 | |
1891 def on_size(self,event): | |
1892 s = self.GetClientSizeTuple() | |
1893 self.sizer.SetDimension(0,0,s[0],s[1]) | |
1894 | |
1895 def refresh_data(self): | |
1896 self.w_panel.refresh_data() | |
1897 self.a_grid.refresh_data() | |
1898 | |
1899 | |
1900 class dnd3earmor(combat_char_child): | |
1901 """ Node Handler for ac. This handler will be | |
1902 created by dnd3echar_handler. | |
1903 """ | |
1904 def __init__(self,xml_dom,tree_node,parent): | |
1905 combat_char_child.__init__(self,xml_dom,tree_node,parent) | |
1906 self.hparent = parent | |
1907 self.root = getRoot(self) | |
1908 self.root.ac = self | |
1909 | |
1910 def get_spell_failure(self): | |
1911 return self.get_total('spellfailure') | |
1912 | |
1913 def get_total_weight(self): | |
1914 return self.get_total('weight') | |
1915 | |
1916 def get_check_pen(self): | |
1917 return self.get_total('checkpenalty') | |
1918 | |
1919 def get_armor_class(self): | |
1920 ac_total = 10 | |
1921 | |
1922 ac_total += self.get_total('bonus') | |
1923 dex_mod = self.root.abilities.get_mod('Dex') | |
1924 max_dex = self.get_max_dex() | |
1925 if dex_mod < max_dex: ac_total += dex_mod | |
1926 else: ac_total += max_dex | |
1927 return ac_total | |
1928 | |
1929 def get_max_dex(self): | |
1930 armor_list = self.xml.findall('armor') | |
1931 dex = 10 | |
1932 for a in armor_list: | |
1933 temp = int(a.get("maxdex")) | |
1934 if temp < dex: dex = temp | |
1935 return dex | |
1936 | |
1937 def get_total(self,attr): | |
1938 armor_list = self.xml.findall('armor') | |
1939 total = 0 | |
1940 for a in armor_list: total += int(a.get(attr)) | |
1941 return total | |
1942 | |
1943 def get_design_panel(self,parent): | |
1944 wnd = outline_panel(parent,self,ac_panel,"Armor") | |
1945 wnd.title = "Armor" | |
1946 return wnd | |
1947 | |
1948 def on_rclick( self, evt ): | |
1949 ac = self.get_armor_class() | |
1950 fac = (int(ac)-(self.root.abilities.get_mod('Dex'))) | |
1951 txt = '((AC: %s Normal, %s Flatfoot))' % ( ac, fac ) #a 1.5002 | |
243 | 1952 Parse.Post( txt, self.chat, True, True ) |
156 | 1953 |
1954 def tohtml(self): | |
1955 html_str = """<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 > | |
1956 <th>AC</th><th>Check Penalty</th><th >Spell Failure</th> | |
1957 <th>Max Dex</th><th>Total Weight</th></tr>""" | |
1958 html_str += "<tr ALIGN='center' >" | |
1959 html_str += "<td>"+str(self.get_armor_class())+"</td>" | |
1960 html_str += "<td>"+str(self.get_check_pen())+"</td>" | |
1961 html_str += "<td>"+str(self.get_spell_failure())+"</td>" | |
1962 html_str += "<td>"+str(self.get_max_dex())+"</td>" | |
1963 html_str += "<td>"+str(self.get_total_weight())+"</td></tr></table>" | |
1964 n_list = self.xml.getchildren() | |
1965 for n in n_list: | |
1966 html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 > | |
1967 <th colspan=3>Armor</th><th>Type</th><th >Bonus</th></tr>""" | |
1968 html_str += "<tr ALIGN='center' >" | |
1969 html_str += "<td colspan=3>"+n.get('name')+"</td>" | |
1970 html_str += "<td>"+n.get('type')+"</td>" | |
1971 html_str += "<td>"+n.get('bonus')+"</td></tr>" | |
1972 html_str += """<tr BGCOLOR=#E9E9E9 >""" | |
1973 html_str += "<th>Check Penalty</th><th>Spell Failure</th>" | |
1974 html_str += "<th>Max Dex</th><th>Speed</th><th>Weight</th></tr>" | |
1975 html_str += "<tr ALIGN='center'>" | |
1976 html_str += "<td>"+n.get('checkpenalty')+"</td>" | |
1977 html_str += "<td>"+n.get('spellfailure')+"</td>" | |
1978 html_str += "<td>"+n.get('maxdex')+"</td>" | |
1979 html_str += "<td>"+n.get('speed')+"</td>" | |
1980 html_str += "<td>"+n.get('weight')+"</td></tr></table>" | |
1981 return html_str | |
1982 | |
1983 | |
1984 class ac_panel(wx.Panel): | |
1985 def __init__(self, parent, handler): | |
1986 pname = handler.xml.set("name", 'Armor') | |
1987 self.hparent = handler | |
1988 wx.Panel.__init__(self, parent, -1) | |
1989 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
1990 sizer = wx.BoxSizer(wx.VERTICAL) | |
1991 sizer.Add(self.grid, 1, wx.EXPAND) | |
1992 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
1993 sizer1.Add(wx.Button(self, 10, "Remove Armor"), 1, wx.EXPAND) | |
1994 sizer1.Add(wx.Size(10,10)) | |
1995 sizer1.Add(wx.Button(self, 20, "Add Armor"), 1, wx.EXPAND) | |
1996 sizer.Add(sizer1, 0, wx.EXPAND) | |
1997 self.sizer = sizer | |
1998 self.SetSizer(self.sizer) | |
1999 self.SetAutoLayout(True) | |
2000 self.Fit() | |
2001 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
2002 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
2003 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
2004 self.xml = handler.xml | |
2005 n_list = handler.xml.getchildren() | |
2006 self.n_list = n_list | |
2007 col_names = ['Armor','bonus','maxdex','cp','sf','weight','speed','type'] | |
2008 self.grid.CreateGrid(len(n_list),len(col_names),1) | |
2009 self.grid.SetRowLabelSize(0) | |
2010 for i in range(len(col_names)): self.grid.SetColLabelValue(i,col_names[i]) | |
2011 self.atts =['name','bonus','maxdex','checkpenalty', | |
2012 'spellfailure','weight','speed','type'] | |
2013 for i in range(len(n_list)): self.refresh_row(i) | |
2014 self.temp_dom = None | |
2015 | |
2016 | |
2017 def on_cell_change(self,evt): | |
2018 row = evt.GetRow() | |
2019 col = evt.GetCol() | |
2020 value = self.grid.GetCellValue(row,col) | |
2021 if col >= 1 and col <= 5: | |
2022 try: | |
2023 int(value) | |
2024 self.n_list[row].set(self.atts[col],value) | |
2025 except: self.grid.SetCellValue(row,col,"0") | |
2026 else: self.n_list[row].set(self.atts[col],value) | |
2027 | |
2028 def refresh_row(self,i): | |
2029 n = self.n_list[i] | |
2030 for y in range(len(self.atts)): self.grid.SetCellValue(i,y,n.get(self.atts[y])) | |
2031 | |
2032 def on_remove(self,evt): | |
2033 rows = self.grid.GetNumberRows() | |
2034 for i in range(rows): | |
2035 if self.grid.IsInSelection(i,0): | |
2036 self.grid.DeleteRows(i) | |
2037 self.xml.remove(self.n_list[i]) | |
2038 | |
2039 def on_add(self,evt): | |
2040 if not self.temp_dom: | |
2041 tree = parse(dir_struct["dnd3e"]+"dnd3earmor.xml") | |
2042 xml_dom = tree.getroot() | |
2043 self.temp_dom = xml_dom | |
2044 f_list = self.temp_dom.findall('armor') | |
2045 opts = [] | |
2046 for f in f_list: opts.append(f.get('name')) | |
2047 dlg = wx.SingleChoiceDialog(self,'Choose Armor:','Armor List',opts) | |
2048 if dlg.ShowModal() == wx.ID_OK: | |
2049 i = dlg.GetSelection() | |
2050 new_node = self.xml.append(f_list[i]) | |
2051 self.grid.AppendRows(1) | |
2052 self.refresh_row(self.grid.GetNumberRows()-1) | |
2053 dlg.Destroy() | |
152 | 2054 |
156 | 2055 def on_size(self,event): |
2056 s = self.GetClientSizeTuple() | |
2057 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
2058 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
2059 (w,h) = self.grid.GetClientSizeTuple() | |
2060 cols = self.grid.GetNumberCols() | |
2061 col_w = w/(cols+2) | |
2062 self.grid.SetColSize(0,col_w*3) | |
2063 for i in range(1,cols): self.grid.SetColSize(i,col_w) | |
2064 | |
2065 | |
2066 class dnd3esnp(dnd3e_char_child): | |
2067 """ Node Handler for power points. This handler will be | |
2068 created by dnd3echar_handler. | |
2069 """ | |
2070 def __init__(self,xml_dom,tree_node,parent): | |
2071 node_handler.__init__(self,xml_dom,tree_node) | |
2072 dnd3e_char_child.__init__(self,xml_dom,tree_node,parent) | |
2073 self.hparent = parent | |
2074 self.frame = component.get('frame') | |
2075 self.child_handlers = {} | |
2076 self.new_child_handler('spells','Spells',dnd3espells,'book') | |
2077 self.new_child_handler('divine','Divine Spells',dnd3edivine,'book') | |
2078 self.new_child_handler('powers','Powers',dnd3epowers,'book') | |
2079 self.new_child_handler('pp','Power Points',dnd3epp,'gear') | |
2080 self.myeditor = None | |
2081 | |
2082 def new_child_handler(self,tag,text,handler_class,icon='gear'): | |
2083 node_list = self.xml.findall(tag) | |
2084 tree = self.tree | |
2085 i = self.tree.icons[icon] | |
2086 new_tree_node = tree.AppendItem(self.mytree_node,text,i,i) | |
2087 handler = handler_class(node_list[0],new_tree_node,self) | |
2088 tree.SetPyData(new_tree_node,handler) | |
2089 self.child_handlers[tag] = handler | |
2090 | |
2091 def get_design_panel(self,parent): | |
2092 return tabbed_panel(parent,self,1) | |
2093 | |
2094 def get_use_panel(self,parent): | |
2095 return tabbed_panel(parent,self,2) | |
2096 | |
2097 | |
2098 class snp_char_child(node_handler): | |
2099 """ Node Handler for skill. This handler will be | |
2100 created by dnd3echar_handler. | |
2101 """ | |
2102 def __init__(self,xml_dom,tree_node,parent): | |
2103 node_handler.__init__(self,xml_dom,tree_node) | |
2104 self.char_hander = parent | |
2105 self.drag = False | |
2106 self.frame = component.get('frame') | |
2107 self.myeditor = None | |
2108 | |
2109 def on_drop(self,evt): | |
2110 pass | |
2111 | |
2112 def on_rclick(self,evt): | |
2113 pass | |
2114 | |
2115 def on_ldclick(self,evt): | |
2116 return | |
2117 | |
2118 def on_html(self,evt): | |
2119 html_str = self.tohtml() | |
2120 wnd = http_html_window(self.frame.note,-1) | |
2121 wnd.title = self.xml.get('name') | |
2122 self.frame.add_panel(wnd) | |
2123 wnd.SetPage(html_str) | |
2124 | |
2125 def get_design_panel(self,parent): | |
2126 pass | |
2127 | |
2128 def get_use_panel(self,parent): | |
2129 return self.get_design_panel(parent) | |
2130 | |
2131 def delete(self): | |
2132 pass | |
2133 | |
2134 | |
2135 class dnd3espells(snp_char_child): | |
2136 """ Node Handler for classes. This handler will be | |
2137 created by dnd3echar_handler. | |
2138 """ | |
2139 def __init__(self,xml_dom,tree_node,parent): | |
2140 snp_char_child.__init__(self,xml_dom,tree_node,parent) | |
2141 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
2142 self.root = getRoot(self) #a 1.5002 | |
2143 self.root.spells = self #a 1.6009 | |
2144 | |
2145 | |
2146 node_list = self.xml.findall( 'spell' ) | |
2147 self.spells = {} | |
2148 tree = self.tree | |
2149 icons = self.tree.icons | |
2150 for n in node_list: | |
2151 name = n.get('name') | |
2152 self.spells[ name ] = n | |
2153 new_tree_node = tree.AppendItem( self.mytree_node, name, icons['gear'], icons['gear'] ) | |
2154 tree.SetPyData( new_tree_node, self ) | |
2155 | |
2156 def on_rclick( self, evt ): | |
2157 item = self.tree.GetSelection() | |
2158 name = self.tree.GetItemText( item ) | |
2159 if item == self.mytree_node: | |
2160 dnd3e_char_child.on_ldclick( self, evt ) | |
2161 else: | |
2162 level = self.spells[ name ].get( 'level' ) | |
2163 descr = self.spells[ name ].get( 'desc' ) | |
2164 use = self.spells[ name ].get( 'used' ) | |
2165 memrz = self.spells[ name ].get( 'memrz' ) | |
2166 use += '+1' | |
2167 charNameL=self.root.general.charName #a 1.5002 | |
2168 left = eval( '%s - ( %s )' % ( memrz, use ) ) | |
2169 if left < 0: | |
2170 txt = '%s Tried to cast %s but has used all of them for today,' | |
2171 txt +='"Please rest so I can cast more."' % ( charNameL, name ) #a 1.5002 | |
243 | 2172 Parse.Post( txt, self.chat, True, False ) |
156 | 2173 else: |
2174 txt = '%s casts %s ( level %s, "%s" )' % ( charNameL, name, level, descr )#a f 1.5002 | |
243 | 2175 Parse.Post( txt, self.chat, True, False ) |
156 | 2176 s = '' |
2177 if left != 1: s = 's' | |
2178 txt = '%s can cast %s %d more time%s' % ( charNameL, name, left, s ) #a 1.5002 | |
243 | 2179 Parse.Post( txt, self.chat, False, False ) |
156 | 2180 self.spells[ name ].set( 'used', `eval( use )` ) |
2181 | |
2182 def refresh_spells(self): | |
2183 self.spells = {} | |
2184 tree = self.tree | |
2185 icons = self.tree.icons | |
2186 tree.CollapseAndReset(self.mytree_node) | |
2187 node_list = self.xml.findall('spell') | |
2188 for n in node_list: | |
2189 name = n.get('name') | |
2190 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear']) | |
2191 tree.SetPyData(new_tree_node,self) | |
2192 self.spells[name]=n | |
2193 | |
2194 def get_design_panel(self,parent): | |
2195 wnd = outline_panel(parent,self,spells_panel,"Spells") | |
2196 wnd.title = "Spells" | |
2197 return wnd | |
2198 | |
2199 def tohtml(self): | |
2200 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Arcane Spells</th></tr><tr><td><br>" | |
2201 n_list = self.xml.getchildren() | |
2202 for n in n_list: html_str += "(" + n.get('level') + ") " + n.get('name')+ ", " | |
2203 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
2204 return html_str | |
2205 | |
2206 def get_char_lvl( self, attr ): | |
2207 return self.char_hander.get_char_lvl(attr) | |
2208 | |
2209 class spells_panel(wx.Panel): | |
2210 def __init__(self, parent, handler): | |
2211 pname = handler.xml.set("name", 'Arcane Spells') | |
2212 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
2213 wx.Panel.__init__(self, parent, -1) | |
2214 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
2215 self.handler = handler | |
2216 sizer = wx.BoxSizer(wx.VERTICAL) | |
2217 sizer.Add(self.grid, 1, wx.EXPAND) | |
2218 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
2219 sizer1.Add(wx.Button(self, 10, "Remove Spell"), 1, wx.EXPAND) | |
2220 sizer1.Add(wx.Size(10,10)) | |
2221 sizer1.Add(wx.Button(self, 20, "Add Spell"), 1, wx.EXPAND) | |
2222 sizer1.Add(wx.Size(10,10)) | |
2223 sizer1.Add(wx.Button(self, 30, "Refresh Spells"), 1, wx.EXPAND) | |
2224 sizer.Add(sizer1, 0, wx.EXPAND) | |
2225 self.sizer = sizer | |
2226 self.SetSizer(self.sizer) | |
2227 self.SetAutoLayout(True) | |
2228 self.Fit() | |
2229 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
2230 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
2231 self.Bind(wx.EVT_BUTTON, self.on_refresh_spells, id=30) | |
2232 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
2233 n_list = handler.xml.getchildren() | |
2234 self.n_list = n_list | |
2235 self.xml = handler.xml | |
2236 self.grid.CreateGrid(len(n_list),4,1) | |
2237 self.grid.SetRowLabelSize(0) | |
2238 self.grid.SetColLabelValue(0,"No.") | |
2239 self.grid.SetColLabelValue(1,"Lvl") | |
2240 self.grid.SetColLabelValue(2,"Spell") | |
2241 self.grid.SetColLabelValue(3,"Desc") | |
2242 for i in range(len(n_list)): self.refresh_row(i) | |
2243 self.temp_dom = None | |
2244 | |
2245 def on_cell_change(self,evt): | |
2246 row = evt.GetRow() | |
2247 col = evt.GetCol() | |
2248 value = self.grid.GetCellValue(row,col) | |
2249 if col == 0: self.n_list[row].set('memrz',value) | |
2250 | |
2251 def refresh_row(self,i): | |
2252 spell = self.n_list[i] | |
2253 memrz = spell.get('memrz') | |
2254 name = spell.get('name') | |
2255 type = spell.get('desc') | |
2256 level = spell.get('level') | |
2257 self.grid.SetCellValue(i,0,memrz) | |
2258 self.grid.SetCellValue(i,2,name) | |
2259 self.grid.SetReadOnly(i,2) | |
2260 self.grid.SetCellValue(i,3,type) | |
243 | 2261 self.grid.SetReadOnly(i,3) |
2262 self.grid.SetCellValue(i,1,level) | |
156 | 2263 self.grid.SetReadOnly(i,1) |
2264 | |
2265 def on_remove(self,evt): | |
2266 rows = self.grid.GetNumberRows() | |
2267 for i in range(rows): | |
2268 if self.grid.IsInSelection(i,0): | |
2269 self.grid.DeleteRows(i) | |
2270 self.xml.remove(self.n_list[i]) | |
2271 | |
2272 def on_add(self,evt): | |
2273 if not self.temp_dom: | |
2274 tree = parse(dir_struct["dnd3e"]+"dnd3espells.xml") | |
2275 xml_dom = tree.getroot() | |
135 | 2276 self.temp_dom = xml_dom |
156 | 2277 f_list = self.temp_dom.findall('spell') |
2278 opts = [] | |
2279 #lvl = int(dnd3e_char_child.get_char_lvl('level')) | |
2280 #castlvl = eval('%s/2' % (lvl)) | |
2281 for f in f_list: | |
2282 spelllvl = f.get('level') | |
2283 opts.append("(" + f.get('level') + ")" + f.get('name')) | |
2284 dlg = wx.SingleChoiceDialog(self,'Choose Spell','Spells',opts) | |
2285 if dlg.ShowModal() == wx.ID_OK: | |
2286 i = dlg.GetSelection() | |
2287 new_node = self.xml.append(f_list[i]) | |
2288 self.grid.AppendRows(1) | |
2289 self.n_list = self.xml.findall('spell') | |
2290 self.refresh_row(self.grid.GetNumberRows()-1) | |
2291 self.handler.refresh_spells() | |
2292 dlg.Destroy() | |
2293 | |
2294 def on_refresh_spells( self, evt ): | |
2295 f_list = self.xml.findall('spell') | |
2296 for spell in f_list: spell.set( 'used', '0' ) | |
2297 | |
2298 def on_size(self,event): | |
2299 s = self.GetClientSizeTuple() | |
2300 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
2301 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
2302 (w,h) = self.grid.GetClientSizeTuple() | |
2303 cols = self.grid.GetNumberCols() | |
2304 col_w = w/(cols) | |
2305 for i in range(0,cols): self.grid.SetColSize(i,col_w) | |
2306 self.grid.SetColSize(0,w * 0.10) | |
2307 self.grid.SetColSize(1,w * 0.10) | |
2308 self.grid.SetColSize(2,w * 0.30) | |
2309 self.grid.SetColSize(3,w * 0.50) | |
2310 | |
2311 def refresh_data(self): | |
2312 for i in range(len(self.n_list)): self.refresh_row(i) | |
2313 | |
2314 class dnd3edivine(snp_char_child): | |
2315 """ Node Handler for classes. This handler will be | |
2316 created by dnd3echar_handler. | |
2317 """ | |
2318 def __init__(self,xml_dom,tree_node,parent): | |
2319 snp_char_child.__init__(self,xml_dom,tree_node,parent) | |
2320 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
2321 self.root = getRoot(self) #a 1.5002 | |
2322 self.root.divine = self #a 1.6009 | |
2323 node_list = self.xml.findall( 'gift' ) | |
2324 self.spells = {} | |
2325 tree = self.tree | |
2326 icons = self.tree.icons | |
2327 for n in node_list: | |
2328 name = n.get('name') | |
2329 self.spells[ name ] = n | |
2330 new_tree_node = tree.AppendItem( self.mytree_node, name, icons['flask'], icons['flask'] ) | |
2331 tree.SetPyData( new_tree_node, self ) | |
2332 | |
2333 def on_rclick( self, evt ): | |
2334 charNameL=self.root.general.charName #a f 1.5002 | |
2335 item = self.tree.GetSelection() | |
2336 name = self.tree.GetItemText( item ) | |
2337 if item == self.mytree_node: | |
2338 dnd3e_char_child.on_ldclick( self, evt ) | |
2339 else: | |
2340 level = self.spells[ name ].get( 'level' ) | |
2341 descr = self.spells[ name ].get( 'desc' ) | |
2342 use = self.spells[ name ].get( 'used' ) | |
2343 memrz = self.spells[ name ].get( 'memrz' ) | |
2344 use += '+1' | |
2345 left = eval( '%s - ( %s )' % ( memrz, use ) ) | |
2346 if left < 0: | |
2347 txt = '%s Tried to cast %s but has used all of them for today,' #m 1.5002 break in 2. | |
2348 txt += "Please rest so I can cast more."' % ( charNameL, name )' #a 1.5002 | |
243 | 2349 Parse.Post( txt, self.chat, True, False ) |
156 | 2350 else: |
2351 txt = '%s casts %s ( level %s, "%s" )' % ( charNameL, name, level, descr ) #a 5002 | |
243 | 2352 Parse.Post( txt, self.chat, True, False ) |
156 | 2353 s = '' |
2354 if left != 1: s = 's' | |
2355 txt = '%s can cast %s %d more time%s' % ( charNameL, name, left, s ) #a 1.5002 | |
243 | 2356 Parse.Post( txt, self.chat, False, False ) |
156 | 2357 self.spells[ name ].set( 'used', `eval( use )` ) |
2358 | |
2359 def refresh_spells(self): | |
2360 self.spells = {} | |
2361 tree = self.tree | |
2362 icons = self.tree.icons | |
2363 tree.CollapseAndReset(self.mytree_node) | |
2364 node_list = self.xml.findall('gift') | |
2365 for n in node_list: | |
2366 name = n.get('name') | |
2367 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['flask'],icons['flask']) | |
2368 tree.SetPyData(new_tree_node,self) | |
2369 self.spells[name]=n | |
2370 | |
2371 def get_design_panel(self,parent): | |
2372 wnd = outline_panel(parent,self,divine_panel,"Spells") | |
2373 wnd.title = "Spells" | |
2374 return wnd | |
2375 | |
2376 def tohtml(self): | |
2377 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Divine Spells</th></tr><tr><td><br>" | |
2378 n_list = self.xml.getchildren() | |
2379 for n in n_list: html_str += "(" + n.get('level') + ") " + n.get('name')+ ", " | |
2380 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
2381 return html_str | |
2382 | |
2383 def get_char_lvl( self, attr ): | |
2384 return self.char_hander.get_char_lvl(attr) | |
2385 | |
2386 class divine_panel(wx.Panel): | |
2387 def __init__(self, parent, handler): | |
2388 pname = handler.xml.set("name", 'Divine Spells') | |
2389 self.hparent = handler | |
2390 wx.Panel.__init__(self, parent, -1) | |
2391 self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
2392 self.handler = handler | |
2393 sizer = wx.BoxSizer(wx.VERTICAL) | |
2394 sizer.Add(self.grid, 1, wx.EXPAND) | |
2395 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
2396 sizer1.Add(wx.Button(self, 10, "Remove Spell"), 1, wx.EXPAND) | |
2397 sizer1.Add(wx.Size(10,10)) | |
2398 sizer1.Add(wx.Button(self, 20, "Add Spell"), 1, wx.EXPAND) | |
2399 sizer1.Add(wx.Size(10,10)) | |
2400 sizer1.Add(wx.Button(self, 30, "Refresh Spells"), 1, wx.EXPAND) | |
2401 sizer.Add(sizer1, 0, wx.EXPAND) | |
2402 self.sizer = sizer | |
2403 self.SetSizer(self.sizer) | |
2404 self.SetAutoLayout(True) | |
2405 self.Fit() | |
243 | 2406 |
2407 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
156 | 2408 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) |
2409 self.Bind(wx.EVT_BUTTON, self.on_refresh_spells, id=30) | |
2410 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
2411 | |
2412 n_list = handler.xml.getchildren() | |
2413 self.n_list = n_list | |
2414 self.xml = handler.xml | |
2415 self.grid.CreateGrid(len(n_list),4,1) | |
2416 self.grid.SetRowLabelSize(0) | |
2417 self.grid.SetColLabelValue(0,"No.") | |
2418 self.grid.SetColLabelValue(1,"Lvl") | |
2419 self.grid.SetColLabelValue(2,"Spell") | |
2420 self.grid.SetColLabelValue(3,"Desc") | |
2421 for i in range(len(n_list)): self.refresh_row(i) | |
2422 self.temp_dom = None | |
2423 | |
2424 def on_cell_change(self,evt): | |
2425 row = evt.GetRow() | |
2426 col = evt.GetCol() | |
2427 value = self.grid.GetCellValue(row,col) | |
2428 if col == 0: self.n_list[row].set('memrz',value) | |
2429 | |
2430 def refresh_row(self,i): | |
2431 spell = self.n_list[i] | |
2432 memrz = spell.get('memrz') | |
2433 name = spell.get('name') | |
2434 type = spell.get('desc') | |
2435 level = spell.get('level') | |
2436 self.grid.SetCellValue(i,0,memrz) | |
2437 self.grid.SetCellValue(i,2,name) | |
2438 self.grid.SetReadOnly(i,2) | |
2439 self.grid.SetCellValue(i,3,type) | |
2440 self.grid.SetReadOnly(i,3) | |
2441 self.grid.SetCellValue(i,1,level) | |
2442 self.grid.SetReadOnly(i,1) | |
2443 | |
2444 def on_remove(self,evt): | |
2445 rows = self.grid.GetNumberRows() | |
2446 for i in range(rows): | |
2447 if self.grid.IsInSelection(i,0): | |
2448 self.grid.DeleteRows(i) | |
2449 self.xml.remove(self.n_list[i]) | |
2450 | |
135 | 2451 def on_add(self,evt): |
156 | 2452 if not self.temp_dom: |
2453 tree = parse(dir_struct["dnd3e"]+"dnd3edivine.xml") | |
2454 xml_dom = tree.getroot() | |
135 | 2455 self.temp_dom = xml_dom |
156 | 2456 f_list = self.temp_dom.findall('gift') |
2457 opts = [] | |
2458 for f in f_list: | |
2459 spelllvl = f.get('level') | |
2460 opts.append("(" + f.get('level') + ")" + f.get('name')) | |
2461 dlg = wx.SingleChoiceDialog(self,'Choose Spell','Spells',opts) | |
2462 if dlg.ShowModal() == wx.ID_OK: | |
2463 i = dlg.GetSelection() | |
2464 new_node = self.xml.append(f_list[i]) | |
2465 self.grid.AppendRows(1) | |
2466 self.n_list = self.xml.findall('gift') | |
2467 self.refresh_row(self.grid.GetNumberRows()-1) | |
2468 self.handler.refresh_spells() | |
2469 dlg.Destroy() | |
2470 | |
2471 def on_refresh_spells( self, evt ): | |
2472 f_list = self.xml.findall('gift') | |
2473 for spell in f_list: spell.set( 'used', '0' ) | |
2474 | |
2475 def on_size(self,event): | |
2476 s = self.GetClientSizeTuple() | |
2477 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
2478 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
2479 (w,h) = self.grid.GetClientSizeTuple() | |
2480 cols = self.grid.GetNumberCols() | |
2481 col_w = w/(cols) | |
2482 for i in range(0,cols): self.grid.SetColSize(i,col_w) | |
2483 self.grid.SetColSize(0,w * 0.10) | |
2484 self.grid.SetColSize(1,w * 0.10) | |
2485 self.grid.SetColSize(2,w * 0.30) | |
2486 self.grid.SetColSize(3,w * 0.50) | |
2487 | |
2488 def refresh_data(self): | |
2489 for i in range(len(self.n_list)): self.refresh_row(i) | |
2490 | |
2491 | |
2492 class dnd3epowers(snp_char_child): | |
2493 """ Node Handler for classes. This handler will be | |
2494 created by dnd3echar_handler. | |
2495 """ | |
2496 def __init__(self,xml_dom,tree_node,parent): | |
2497 snp_char_child.__init__(self,xml_dom,tree_node,parent) | |
2498 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
2499 self.root = getRoot(self) #a 1.5002 | |
2500 self.root.powers = self #a 1.6009 | |
2501 | |
2502 node_list = self.xml.findall( 'power' ) | |
2503 self.powers = {} | |
2504 tree = self.tree | |
2505 icons = self.tree.icons | |
2506 for n in node_list: | |
2507 name = n.get('name') | |
2508 self.powers[ name ] = n | |
2509 new_tree_node = tree.AppendItem( self.mytree_node, name, | |
2510 icons['gear'], icons['gear'] ) | |
2511 tree.SetPyData( new_tree_node, self ) | |
2512 | |
2513 def on_rclick( self, evt ): | |
2514 charNameL = self.root.general.charName #a f 1.5002 | |
2515 | |
2516 item = self.tree.GetSelection() | |
2517 name = self.tree.GetItemText( item ) | |
2518 charNameL = self.root.general.charName #a 1.5002 | |
2519 if item == self.mytree_node: | |
2520 dnd3e_char_child.on_ldclick( self, evt ) | |
2521 else: | |
2522 level = int(self.powers[ name ].get( 'level' )) | |
2523 descr = self.powers[ name ].get( 'desc' ) | |
2524 #use can be removed -mgt | |
2525 #use = self.powers[ name ].get( 'used' ) | |
2526 points = self.powers[ name ].get( 'point' ) | |
2527 #cpp and fre are strings without the eval -mgt | |
2528 cpp = eval(self.root.pp.get_char_pp('current1')) #a 1.5002 | |
2529 fre = eval(self.root.pp.get_char_pp('free')) #a 1.5002 | |
2530 if level == 0 and fre > 0: | |
2531 left = eval('%s - ( %s )' % ( fre, points )) | |
2532 numcast = eval('%s / %s' % (left, points)) | |
2533 if left < 0: | |
2534 #In theory you should never see this -mgt | |
2535 txt = ('%s doesnt have enough PowerPoints to use %s' | |
2536 % ( charNameL, name )) #a 1.5002 | |
243 | 2537 Parse.Post( txt, self.chat, True, False ) |
156 | 2538 else: |
2539 txt = ('%s uses %s as a Free Talent ( level %s, "%s" )' | |
2540 % ( charNameL, name, level, descr )) #a 1.5002 | |
243 | 2541 Parse.Post( txt, self.chat, True, False ) |
156 | 2542 s = '' |
2543 if left != 1: s = 's' | |
2544 txt = '%s has %d Free Talent%s left' % ( charNameL, numcast, s ) #a 1.5002 | |
243 | 2545 Parse.Post( txt, self.chat, False, False ) |
156 | 2546 self.root.pp.set_char_pp('free',left) #a 1.5002 |
2547 else: | |
2548 left = eval('%s - ( %s )' % ( cpp, points )) | |
2549 #numcast = eval('%s / %s' % (left, points)) | |
2550 if left < 0: | |
2551 txt = '%s doesnt have enough PowerPoints to use %s' % ( charNameL, name ) #m 1.5002 | |
243 | 2552 Parse.Post( txt, self.chat, True, False ) |
156 | 2553 else: |
2554 txt = '%s uses %s ( level %s, "%s" )' % ( charNameL, name, level, descr ) #m 1.5002 | |
243 | 2555 Parse.Post( txt, self.chat, True, False ) |
156 | 2556 s = '' |
2557 if left != 1: | |
2558 s = 's' | |
2559 #numcast is meaningless here -mgt | |
2560 #txt = '%s can use %s %d more time%s' % ( charNameL, name, numcast, s ) #m 1.5002 | |
2561 #txt += ' - And has %d more PowerpointsP left' % (left) | |
2562 txt = '%s has %d more Powerpoint%s' % ( charNameL, left, s ) #m 1.5002 | |
243 | 2563 Parse.Post( txt, self.chat, False, False ) |
156 | 2564 self.root.pp.set_char_pp('current1',left) #a 1.5002 |
2565 | |
2566 def refresh_powers(self): | |
2567 self.powers = {} | |
2568 tree = self.tree | |
2569 icons = self.tree.icons | |
2570 tree.CollapseAndReset(self.mytree_node) | |
2571 node_list = self.xml.findall('power') | |
2572 for n in node_list: | |
2573 name = n.get('name') | |
2574 new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear']) | |
2575 tree.SetPyData(new_tree_node,self) | |
2576 self.powers[name]=n | |
2577 | |
2578 def get_design_panel(self,parent): | |
2579 wnd = outline_panel(parent,self,power_panel,"Powers") | |
2580 wnd.title = "Powers" | |
2581 return wnd | |
2582 | |
2583 def tohtml(self): | |
2584 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Powers</th></tr><tr><td><br>" | |
2585 n_list = self.xml.getchildren() | |
2586 for n in n_list: | |
2587 html_str += "(" + n.get('level') + ") " + n.get('name')+ ", " | |
2588 html_str = html_str[:len(html_str)-2] + "</td></tr></table>" | |
2589 return html_str | |
2590 | |
2591 | |
2592 class power_panel(wx.Panel): | |
2593 def __init__(self, parent, handler): | |
2594 #m 1.5015 corrected typo, was Pionic. | |
2595 pname = handler.xml.set("name", 'Psionic Powers') | |
2596 self.hparent = handler | |
2597 self.root = getRoot(self) #a (debug) 1.5002,1.5014 | |
2598 | |
2599 wx.Panel.__init__(self, parent, -1) | |
2600 self.grid = wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS) | |
2601 self.handler = handler | |
2602 sizer = wx.BoxSizer(wx.VERTICAL) | |
2603 sizer.Add(self.grid, 1, wx.EXPAND) | |
2604 | |
2605 sizer1 = wx.BoxSizer(wx.HORIZONTAL) | |
2606 sizer1.Add(wx.Button(self, 10, "Remove Power"), 1, wx.EXPAND) | |
2607 sizer1.Add(wx.Size(10,10)) | |
2608 sizer1.Add(wx.Button(self, 20, "Add Power"), 1, wx.EXPAND) | |
2609 sizer1.Add(wx.Size(10,10)) | |
2610 sizer1.Add(wx.Button(self, 30, "Refresh Power"), 1, wx.EXPAND) | |
2611 | |
2612 sizer.Add(sizer1, 0, wx.EXPAND) | |
2613 self.sizer = sizer | |
2614 self.SetSizer(self.sizer) | |
2615 self.SetAutoLayout(True) | |
2616 self.Fit() | |
2617 #self.Bind(wx.EVT_SIZE, self.on_size) | |
2618 | |
2619 self.Bind(wx.EVT_BUTTON, self.on_remove, id=10) | |
2620 self.Bind(wx.EVT_BUTTON, self.on_add, id=20) | |
2621 self.Bind(wx.EVT_BUTTON, self.on_refresh_powers, id=30) | |
2622 self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change) | |
2623 n_list = handler.xml.getchildren() | |
2624 self.n_list = n_list | |
2625 self.xml = handler.xml | |
2626 self.grid.CreateGrid(len(n_list),5,1) | |
2627 self.grid.SetRowLabelSize(0) | |
2628 self.grid.SetColLabelValue(0,"PP") | |
2629 self.grid.SetColLabelValue(1,"Lvl") | |
2630 self.grid.SetColLabelValue(2,"Power") | |
2631 self.grid.SetColLabelValue(3,"Desc") | |
2632 self.grid.SetColLabelValue(4,"Type") | |
2633 for i in range(len(n_list)): self.refresh_row(i) | |
2634 self.refresh_data() | |
2635 self.temp_dom = None | |
2636 | |
2637 def on_cell_change(self,evt): | |
2638 row = evt.GetRow() | |
2639 col = evt.GetCol() | |
2640 value = self.grid.GetCellValue(row,col) | |
2641 | |
2642 def refresh_row(self,i): | |
2643 power = self.n_list[i] | |
2644 point = power.get('point') | |
2645 name = power.get('name') | |
2646 type = power.get('desc') | |
2647 test = power.get('test') | |
2648 level = power.get('level') | |
2649 self.grid.SetCellValue(i,0,point) | |
2650 self.grid.SetReadOnly(i,0) | |
2651 self.grid.SetCellValue(i,1,level) | |
2652 self.grid.SetReadOnly(i,1) | |
2653 self.grid.SetCellValue(i,2,name) | |
2654 self.grid.SetReadOnly(i,2) | |
2655 self.grid.SetCellValue(i,3,type) | |
2656 self.grid.SetReadOnly(i,3) | |
2657 self.grid.SetCellValue(i,4,test) | |
2658 self.grid.SetReadOnly(i,4) | |
2659 | |
2660 def on_remove(self,evt): | |
2661 rows = self.grid.GetNumberRows() | |
2662 for i in range(rows): | |
2663 if self.grid.IsInSelection(i,0): | |
2664 self.grid.DeleteRows(i) | |
2665 self.xml.remove(self.n_list[i]) | |
2666 | |
2667 def on_add(self,evt): | |
2668 if not self.temp_dom: | |
2669 tree = parse(dir_struct["dnd3e"]+"dnd3epowers.xml") | |
2670 xml_dom = tree.getroot() | |
2671 self.temp_dom = xml_dom | |
2672 f_list = self.temp_dom.findall('power') | |
2673 opts = [] | |
2674 for f in f_list: | |
2675 spelllvl = f.get('level') | |
2676 opts.append("(" + f.get('level') + ") - " + | |
2677 f.get('name') + " - " + f.get('test')) | |
2678 dlg = wx.SingleChoiceDialog(self,'Choose Power','Powers',opts) | |
2679 if dlg.ShowModal() == wx.ID_OK: | |
2680 i = dlg.GetSelection() | |
2681 new_node = self.xml.append(f_list[i]) | |
2682 self.grid.AppendRows(1) | |
2683 self.n_list = self.xml.findall('power') | |
2684 self.refresh_row(self.grid.GetNumberRows()-1) | |
2685 self.handler.refresh_powers() | |
2686 dlg.Destroy() | |
2687 | |
2688 def on_remove(self,evt): | |
2689 rows = self.grid.GetNumberRows() | |
2690 for i in range(rows): | |
2691 if self.grid.IsInSelection(i,0): | |
2692 self.grid.DeleteRows(i) | |
2693 self.xml.remove(self.n_list[i]) | |
2694 self.n_list = self.xml.findall('weapon') | |
2695 self.handler.refresh_powers() | |
2696 | |
2697 def on_refresh_powers( self, evt ): | |
2698 self.root.pp.set_char_pp('current1',self.root.pp.get_char_pp('max1')) | |
2699 self.root.pp.set_char_pp('free',self.root.pp.get_char_pp('maxfree')) | |
2700 | |
2701 def on_size(self,event): | |
2702 s = self.GetClientSizeTuple() | |
2703 self.grid.SetDimensions(0,0,s[0],s[1]-25) | |
2704 self.sizer.SetDimension(0,s[1]-25,s[0],25) | |
2705 (w,h) = self.grid.GetClientSizeTuple() | |
2706 cols = self.grid.GetNumberCols() | |
2707 col_w = w/(cols) | |
2708 for i in range(0,cols): self.grid.SetColSize(i,col_w) | |
2709 self.grid.SetColSize(0,w * 0.05) | |
2710 self.grid.SetColSize(1,w * 0.05) | |
2711 self.grid.SetColSize(2,w * 0.30) | |
2712 self.grid.SetColSize(3,w * 0.30) | |
2713 self.grid.SetColSize(4,w * 0.30) | |
2714 | |
2715 def refresh_data(self): | |
2716 for i in range(len(self.n_list)): self.refresh_row(i) | |
2717 | |
2718 class dnd3epp(snp_char_child): | |
2719 """ Node Handler for power points. This handler will be | |
2720 created by dnd3echar_handler. | |
2721 """ | |
2722 def __init__(self,xml_dom,tree_node,parent): | |
2723 snp_char_child.__init__(self,xml_dom,tree_node,parent) | |
2724 self.hparent = parent #a 1.5002 allow ability to run up tree. | |
2725 self.root = getRoot(self) | |
2726 self.root.pp = self | |
2727 self.ppPanel=None | |
2728 | |
2729 def get_design_panel(self,parent): | |
2730 wnd = outline_panel(parent,self,pp_panel,"Power Points") | |
2731 wnd.title = "Power Points" | |
2732 return wnd | |
2733 | |
2734 | |
2735 def tohtml(self): | |
2736 html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 >" | |
2737 html_str += "<th colspan=7>Power Points</th>" #a 1.6010 | |
2738 html_str += "</tr><tr>" | |
2739 html_str += "<th colspan=2>Max:</th>" | |
2740 html_str += "<td>"+self.xml.get('max1')+"</td>" | |
2741 html_str += "<th colspan=3>Max Talents/day:</th>" | |
2742 html_str += "<td>"+self.xml.get('maxfree')+"</td>" | |
2743 html_str += "</tr><tr>" | |
2744 html_str += "<th colspan=2>Current:</th>" | |
2745 html_str += "<td>"+self.xml.get('current1')+"</td>" | |
2746 html_str += "<th colspan=3>Current Talents/day:</th>" | |
2747 html_str += "<td>"+self.xml.get('free')+"</td>" | |
2748 html_str += "</tr></table>" | |
2749 return html_str | |
2750 | |
2751 def get_char_pp( self, attr ): | |
2752 pp = self.xml.get(attr) | |
2753 return pp | |
2754 | |
2755 def set_char_pp( self, attr, evl ): | |
2756 qSub = str(evl) #a 1.5014 must force it to be a string for next call. | |
2757 self.xml.set(attr, qSub) | |
2758 | |
2759 class pp_panel(wx.Panel): | |
2760 def __init__(self, parent, handler): | |
2761 wx.Panel.__init__(self, parent, -1) | |
2762 self.hparent = handler #a 1.5002 allow ability to run up tree. | |
2763 self.hparent.ppPanel=self #a 1.5xx | |
2764 | |
2765 pname = handler.xml.set("name", 'PowerPoints') | |
2766 self.sizer = wx.FlexGridSizer(2, 4, 2, 2) # rows, cols, hgap, vgap | |
2767 self.xml = handler.xml | |
2768 | |
2769 self.static1= wx.StaticText(self, -1, "PP Current:") #a 1.5015 | |
2770 self.dyn1= wx.TextCtrl(self, PP_CUR, | |
2771 self.xml.get('current1')) #a 1.5015 | |
2772 self.dyn3= wx.TextCtrl(self, PP_FRE, | |
2773 self.xml.get('free')) #a 1.5015 | |
2774 self.sizer.AddMany([ (self.static1, 0, wx.ALIGN_CENTER_VERTICAL), | |
2775 (self.dyn1, 0, wx.EXPAND), | |
2776 (wx.StaticText(self, -1, "PP Max:"), 0, wx.ALIGN_CENTER_VERTICAL), | |
2777 (wx.TextCtrl(self, PP_MAX, | |
2778 self.xml.get('max1')), 0, wx.EXPAND), | |
2779 (wx.StaticText(self, -1, "Current Free Talants per day:"), | |
2780 0, wx.ALIGN_CENTER_VERTICAL), | |
2781 (self.dyn3, 0, wx.EXPAND), #a 1.5015 | |
2782 (wx.StaticText(self, -1, "Max Free Talants per day:"), | |
2783 0, wx.ALIGN_CENTER_VERTICAL), | |
2784 (wx.TextCtrl(self, PP_MFRE, | |
2785 self.xml.get('maxfree')), 0, wx.EXPAND), | |
2786 ]) | |
2787 | |
2788 self.sizer.AddGrowableCol(1) | |
2789 self.SetSizer(self.sizer) | |
2790 self.SetAutoLayout(True) | |
2791 self.Fit() | |
2792 self.Bind(wx.EVT_TEXT, self.on_text, id=PP_MAX) | |
2793 self.Bind(wx.EVT_TEXT, self.on_text, id=PP_CUR) | |
2794 self.Bind(wx.EVT_TEXT, self.on_text, id=PP_FRE) | |
2795 self.Bind(wx.EVT_TEXT, self.on_text, id=PP_MFRE) | |
2796 | |
2797 def on_text(self,evt): | |
2798 id = evt.GetId() | |
2799 if id == PP_CUR: self.xml.set('current1',evt.GetString()) | |
2800 elif id == PP_MAX: self.xml.set('max1',evt.GetString()) | |
2801 elif id == PP_FRE: self.xml.set('free',evt.GetString()) | |
2802 elif id == PP_MFRE: self.xml.set('maxfree',evt.GetString()) | |
2803 | |
2804 def on_size(self,evt): | |
2805 s = self.GetClientSizeTuple() | |
2806 self.sizer.SetDimension(0,0,s[0],s[1]) | |
2807 | |
2808 #a 5.015 this whole function. | |
2809 def on_refresh(self,attr,value): | |
2810 if attr == 'current1': self.dyn1.SetValue(value) | |
2811 else: self.dyn3.SetValue(value) |