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