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