28
|
1 from orpg.orpgCore import component
|
|
2 import re
|
|
3 from orpg.tools.orpg_log import logger
|
|
4 from wx import TextEntryDialog, ID_OK
|
|
5
|
|
6 class InterParse():
|
|
7
|
|
8 def __init__(self):
|
|
9 pass
|
|
10
|
|
11 def Post(self, s, send=False, myself=False):
|
|
12 s = self.Normalize(s)
|
|
13 component.get('chat').set_colors()
|
|
14 component.get('chat').Post(s, send, myself)
|
|
15
|
|
16 def Normalize(self, s):
|
|
17 for plugin_fname in component.get('chat').activeplugins.keys():
|
|
18 plugin = component.get('chat').activeplugins[plugin_fname]
|
|
19 try: s = plugin.pre_parse(s)
|
|
20 except Exception, e:
|
|
21 if str(e) != "'module' object has no attribute 'post_msg'":
|
|
22 logger.general(traceback.format_exc())
|
|
23 logger.general("EXCEPTION: " + str(e))
|
|
24 if component.get('chat').parsed == 0:
|
|
25 s = self.Node(s)
|
|
26 s = self.Dice(s)
|
|
27 s = self.Filter(s)
|
|
28 component.get('chat').parsed = 1
|
|
29 return s
|
|
30
|
|
31 def Filter(self, s):
|
|
32 s = component.get('chat').GetFilteredText(s)
|
|
33 return s
|
|
34
|
|
35 def Node(self, s):
|
|
36 """Parses player input for embedded nodes rolls"""
|
|
37 cur_loc = 0
|
|
38 #[a-zA-Z0-9 _\-\.]
|
|
39 reg = re.compile("(!@(.*?)@!)")
|
|
40 matches = reg.findall(s)
|
|
41 for i in xrange(0,len(matches)):
|
|
42 newstr = self.Node(self.resolve_nodes(matches[i][1]))
|
|
43 s = s.replace(matches[i][0], newstr, 1)
|
|
44 return s
|
|
45
|
|
46 def Dice(self, s):
|
|
47 """Parses player input for embedded dice rolls"""
|
|
48 reg = re.compile("\[([^]]*?)\]")
|
|
49 matches = reg.findall(s)
|
|
50 for i in xrange(0,len(matches)):
|
|
51 newstr = self.Unknown(matches[i])
|
|
52 qmode = 0
|
|
53 newstr1 = newstr
|
|
54 if newstr[0].lower() == 'q':
|
|
55 newstr = newstr[1:]
|
|
56 qmode = 1
|
|
57 if newstr[0].lower() == '#':
|
|
58 newstr = newstr[1:]
|
|
59 qmode = 2
|
|
60 try: newstr = component.get('DiceManager').proccessRoll(newstr)
|
|
61 except: pass
|
|
62 if qmode == 1:
|
|
63 s = s.replace("[" + matches[i] + "]",
|
|
64 "<!-- Official Roll [" + newstr1 + "] => " + newstr + "-->" + newstr, 1)
|
|
65 elif qmode == 2:
|
|
66 s = s.replace("[" + matches[i] + "]", newstr[len(newstr)-2:-1], 1)
|
|
67 else: s = s.replace("[" + matches[i] + "]",
|
|
68 "[" + newstr1 + "<!-- Official Roll -->] => " + newstr, 1)
|
|
69 return s
|
|
70
|
|
71 def Unknown(self, s):
|
|
72 # Uses a tuple. Usage: ?Label}dY. If no Label is assigned then use ?}DY
|
|
73 newstr = "0"
|
|
74 reg = re.compile("(\?\{*)([a-zA-Z ]*)(\}*)")
|
|
75 matches = reg.findall(s)
|
|
76 for i in xrange(0,len(matches)):
|
|
77 lb = "Replace '?' with: "
|
|
78 if len(matches[i][0]):
|
|
79 lb = matches[i][1] + "?: "
|
|
80 dlg = TextEntryDialog(self, lb, "Missing Value?")
|
|
81 dlg.SetValue('')
|
|
82 if matches[i][0] != '':
|
|
83 dlg.SetTitle("Enter Value for " + matches[i][1])
|
|
84 if dlg.ShowModal() == ID_OK: newstr = dlg.GetValue()
|
|
85 if newstr == '': newstr = '0'
|
|
86 s = s.replace(matches[i][0], newstr, 1).replace(matches[i][1], '', 1).replace(matches[i][2], '', 1)
|
|
87 dlg.Destroy()
|
|
88 return s
|
|
89
|
|
90 def NodeMap(self, s, node):
|
|
91 """Parses player input for embedded nodes rolls"""
|
|
92 cur_loc = 0
|
|
93 reg = re.compile("(!!(.*?)!!)")
|
|
94 matches = reg.findall(s)
|
|
95 for i in xrange(0,len(matches)):
|
|
96 tree_map = node.get('map')
|
|
97 tree_map = tree_map + '::' + matches[i][1]
|
|
98 newstr = '!@'+ tree_map +'@!'
|
|
99 s = s.replace(matches[i][0], newstr, 1)
|
|
100 s = self.Node(s)
|
|
101 s = self.NodeParent(s, tree_map)
|
|
102 return s
|
|
103
|
|
104 def NodeParent(self, s, tree_map):
|
|
105 """Parses player input for embedded nodes rolls"""
|
|
106 cur_loc = 0
|
|
107 reg = re.compile("(!#(.*?)#!)")
|
|
108 matches = reg.findall(s)
|
|
109 for i in xrange(0,len(matches)):
|
|
110 ## Build the new tree_map
|
|
111 new_map = tree_map.split('::')
|
|
112 del new_map[len(new_map)-1]
|
|
113 parent_map = matches[i][1].split('::')
|
|
114 ## Backwards Reference the Parent Children
|
|
115 child_node = self.get_node('::'.join(new_map))
|
|
116 newstr = self.get_root(child_node, tree_map, new_map, parent_map)
|
|
117 s = s.replace(matches[i][0], newstr, 1)
|
|
118 s = self.Node(s)
|
|
119 return s
|
|
120
|
|
121 def get_root(self, child_node, tree_map, new_map, parent_map):
|
|
122 if child_node == 'Invalid Reference!': return child_node
|
|
123 roots = child_node.getchildren(); tr = tree_map.split('::')
|
|
124 newstr = ''
|
|
125 for root in roots:
|
|
126 try: t = new_map.index(root.get('name'))
|
|
127 except: t = 1
|
|
128 if parent_map[0] == root.get('name'):
|
|
129 newstr = '!@' + '::'.join(new_map[:len(tr)-t]) + '::' + '::'.join(parent_map) + '@!'
|
|
130 if newstr != '': return newstr
|
|
131 else:
|
|
132 del new_map[len(new_map)-1]
|
|
133 child_node = self.get_node('::'.join(new_map))
|
|
134 newstr = self.get_root(child_node, tree_map, new_map, parent_map)
|
|
135 return newstr
|
|
136
|
|
137 def get_node(self, s):
|
|
138 return_node = 'Invalid Reference!'
|
|
139 value = ""
|
|
140 path = s.split('::')
|
|
141 depth = len(path)
|
|
142 try: node = component.get('tree').tree_map[path[0]]['node']
|
|
143 except Exception, e: return return_node
|
|
144 return_node = self.resolve_get_loop(node, path, 1, depth)
|
|
145 return return_node
|
|
146
|
|
147 def resolve_get_loop(self, node, path, step, depth):
|
|
148 if step == depth: return node
|
|
149 else:
|
|
150 child_list = node.findall('nodehandler')
|
|
151 for child in child_list:
|
|
152 if step == depth: break
|
|
153 if child.get('name') == path[step]:
|
|
154 node = self.resolve_get_loop(child, path, step+1, depth)
|
|
155 return node
|
|
156
|
|
157 def resolve_nodes(self, s):
|
|
158 self.passed = False
|
|
159 string = 'Invalid Reference!'
|
|
160 value = ""
|
|
161 path = s.split('::')
|
|
162 depth = len(path)
|
|
163 try: node = component.get('tree').tree_map[path[0]]['node']
|
|
164 except Exception, e: return string
|
|
165 if node.get('class') in ('dnd35char_handler',
|
|
166 "SWd20char_handler",
|
|
167 "d20char_handler",
|
|
168 "dnd3echar_handler"): string = self.resolve_cust_loop(node, path, 1, depth)
|
|
169 elif node.get('class') == 'rpg_grid_handler': self.resolve_grid(node, path, 1, depth)
|
|
170 else: string = self.resolve_loop(node, path, 1, depth)
|
|
171 return string
|
|
172
|
|
173 def resolve_loop(self, node, path, step, depth):
|
|
174 if step == depth: return self.resolution(node)
|
|
175 else:
|
|
176 child_list = node.findall('nodehandler')
|
|
177 for child in child_list:
|
|
178 if step == depth: break
|
|
179 if child.get('name') == path[step]:
|
|
180 node = child
|
|
181 step += 1
|
|
182 if node.get('class') in ('dnd35char_handler',
|
|
183 "SWd20char_handler",
|
|
184 "d20char_handler",
|
|
185 "dnd3echar_handler"):
|
|
186 string = self.resolve_cust_loop(node, path, step, depth)
|
|
187 elif node.get('class') == 'rpg_grid_handler':
|
|
188 string = self.resolve_grid(node, path, step, depth)
|
|
189 else: string = self.resolve_loop(node, path, step, depth)
|
|
190 return string
|
|
191
|
|
192 def resolution(self, node):
|
|
193 if self.passed == False:
|
|
194 self.passed = True
|
|
195 if node.get('class') == 'textctrl_handler':
|
|
196 s = str(node.find('text').text)
|
|
197 else: s = 'Nodehandler for '+ node.get('class') + ' not done!' or 'Invalid Reference!'
|
|
198 else:
|
|
199 s = ''
|
|
200 s = self.NodeMap(s, node)
|
|
201 s = self.NodeParent(s, node.get('map'))
|
|
202 return s
|
|
203
|
|
204 def resolve_grid(self, node, path, step, depth):
|
|
205 if step == depth:
|
|
206 return 'Invalid Grid Reference!'
|
|
207 cell = tuple(path[step].strip('(').strip(')').split(','))
|
|
208 grid = node.find('grid')
|
|
209 rows = grid.findall('row')
|
|
210 col = rows[int(self.Dice(cell[0]))-1].findall('cell')
|
|
211 try: s = self.NodeMap(col[int(self.Dice(cell[1]))-1].text, node) or 'No Cell Data'
|
|
212 except: s = 'Invalid Grid Reference!'
|
|
213 return s
|
|
214
|
|
215 def resolve_cust_loop(self, node, path, step, depth):
|
|
216 s = 'Invalid Reference!'
|
|
217 node_class = node.get('class')
|
|
218 ## Code needs clean up. Either choose .lower() or .title(), then reset the path list's content ##
|
|
219 if step == depth: self.resolution(node)
|
|
220 ##Build Abilities dictionary##
|
|
221 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('abilities')
|
|
222 else: ab = node.find('abilities')
|
|
223 ab_list = ab.findall('stat'); pc_stats = {}
|
|
224
|
|
225 for ability in ab_list:
|
|
226 pc_stats[ability.get('name')] = (
|
|
227 str(ability.get('base')),
|
|
228 str((int(ability.get('base'))-10)/2) )
|
|
229 pc_stats[ability.get('abbr')] = (
|
|
230 str(ability.get('base')),
|
|
231 str((int(ability.get('base'))-10)/2) )
|
|
232
|
|
233 if node_class not in ('d20char_handler', "SWd20char_handler"): ab = node.find('character').find('saves')
|
|
234 else: ab = node.find('saves')
|
|
235 ab_list = ab.findall('save')
|
|
236 for save in ab_list:
|
|
237 pc_stats[save.get('name')] = (str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) )
|
|
238 if save.get('name') == 'Fortitude': abbr = 'Fort'
|
|
239 if save.get('name') == 'Reflex': abbr = 'Ref'
|
|
240 if save.get('name') == 'Will': abbr = 'Will'
|
|
241 pc_stats[abbr] = ( str(save.get('base')), str(int(save.get('magmod')) + int(save.get('miscmod')) + int(pc_stats[save.get('stat')][1]) ) )
|
|
242
|
|
243 if path[step].lower() == 'skill':
|
|
244 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf')
|
|
245 node = node.find('skills')
|
|
246 child_list = node.findall('skill')
|
|
247 for child in child_list:
|
|
248 if path[step+1].lower() == child.get('name').lower():
|
|
249 if step+2 == depth: s = child.get('rank')
|
|
250 elif path[step+2].lower() == 'check':
|
|
251 s = '<b>Skill Check:</b> ' + child.get('name') + ' [1d20+'+str( int(child.get('rank')) + int(pc_stats[child.get('stat')][1]) )+']'
|
|
252 return s
|
|
253
|
|
254 if path[step].lower() == 'feat':
|
|
255 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snf')
|
|
256 node = node.find('feats')
|
|
257 child_list = node.findall('feat')
|
|
258 for child in child_list:
|
|
259 if path[step+1].lower() == child.get('name').lower():
|
|
260 if step+2 == depth: s = '<b>'+child.get('name')+'</b>'+': '+child.get('desc')
|
|
261 return s
|
|
262 if path[step].lower() == 'cast':
|
|
263 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('snp')
|
|
264 node = node.find('spells')
|
|
265 child_list = node.findall('spell')
|
|
266 for child in child_list:
|
|
267 if path[step+1].lower() == child.get('name').lower():
|
|
268 if step+2 == depth: s = '<b>'+child.get('name')+'</b>'+': '+child.get('desc')
|
|
269 return s
|
|
270 if path[step].lower() == 'attack':
|
|
271 if node_class not in ('d20char_handler', "SWd20char_handler"): node = node.find('combat')
|
|
272 if path[step+1].lower() == 'melee' or path[step+1].lower() == 'm':
|
|
273 bonus_text = '(Melee)'
|
|
274 bonus = node.find('attacks')
|
|
275 bonus = bonus.find('melee')
|
|
276 bonus = bonus.attrib; d = int(pc_stats['Str'][1])
|
|
277 elif path[step+1].lower() == 'ranged' or path[step+1].lower() == 'r':
|
|
278 bonus_text = '(Ranged)'
|
|
279 bonus = node.find('attacks')
|
|
280 bonus = bonus.find('ranged')
|
|
281 bonus = bonus.attrib; d = int(pc_stats['Dex'][1])
|
|
282 for b in bonus:
|
|
283 d += int(bonus[b])
|
|
284 bonus = str(d)
|
|
285 if path[step+2] == None: s= bonus
|
|
286 else:
|
|
287 weapons = node.find('attacks')
|
|
288 weapons = weapons.findall('weapon')
|
|
289 for child in weapons:
|
|
290 if path[step+2].lower() == child.get('name').lower():
|
|
291 s = '<b>Attack: '+bonus_text+'</b> '+child.get('name')+' [1d20+'+bonus+'] ' + 'Damage: ['+child.get('damage')+']'
|
|
292 return s
|
|
293 elif pc_stats.has_key(path[step].title()):
|
|
294 if step+1 == depth: s = pc_stats[path[step].title()][0] + ' +('+pc_stats[path[step].title()][1]+')'
|
|
295 elif path[step+1].title() == 'Mod': s = pc_stats[path[step].title()][1]
|
|
296 elif path[step+1].title() == 'Check': s = '<b>'+path[step].title()+' Check:</b> [1d20+'+str(pc_stats[path[step].title()][1])+']'
|
|
297 return s
|
|
298 return s
|
|
299
|
|
300 Parse = InterParse()
|