1from glob import glob 2import json 3import xml.etree.ElementTree 4import os.path 5import traceback 6import sys 7import fnmatch 8import tokenize 9import io 10 11class UnknownArtemisTagError(Exception): 12 def __init__(self, node): 13 super().__init__('%s: %s' % (node.tag, node.attrib)) 14 15def convertString(s): 16 return s.replace('\n', '\\n').replace('\'', '\\\'').replace('"', '\\"').replace('^', '\\n').strip() 17 18def convertFloat(f): 19 try: 20 return str(float(eval(str(f), {}, {}))) 21 except NameError: 22 pass 23 result = '(' 24 for token in tokenize.tokenize(io.BytesIO(str(f).encode('UTF-8')).readline): 25 if token.type == tokenize.ENCODING or token.type == tokenize.ENDMARKER: 26 pass 27 elif token.type == tokenize.NAME: 28 result += 'variable_%s' % (convertName(token.string)) 29 elif token.type == tokenize.OP: 30 result += '%s' % (token.string) 31 elif token.type == tokenize.NUMBER: 32 result += '%s' % (token.string) 33 else: 34 raise ValueError(token) 35 result += ')' 36 return result 37 38def convertPosition(x, z): 39 return convertFloat('20000-(%s)' % (x)), convertFloat('(%s)-100000' % (z)) 40 41def convertName(name): 42 return '%s' % (name.replace(' ', '_').replace('-', '_').replace('*', 'X').replace('.', '__')) 43 44def convertRaceKeys(node, default=None): 45 keys = node.get('raceKeys', default) 46 keys = keys.lower().split(' ') 47 if 'biomech' in keys: 48 return "Ghosts" 49 elif 'friendly' in keys: 50 return "Human Navy" 51 elif 'enemy' in keys: 52 return "Kraylor" 53 elif 'neutral' in keys: 54 return "Independent" 55 raise UnknownArtemisTagError(node) 56 57def convertComparator(node): 58 comparator = node.get('comparator').lower() 59 if comparator == "equals" or comparator == "=": 60 return "==" 61 elif comparator == "not" or comparator == "!=": 62 return "~=" 63 elif comparator == "greater" or comparator == ">": 64 return ">" 65 elif comparator == "less" or comparator == "<": 66 return "<" 67 elif comparator == "greater_equal" or comparator == "<=": 68 return "<=" 69 elif comparator == "less_equal" or comparator == ">=": 70 return ">=" 71 raise UnknownArtemisTagError(node) 72 73def convertSystemName(node): 74 system = node.get('systemType') 75 if system == 'systemBeam': 76 return 'beamweapons' 77 elif system == 'systemTorpedo': 78 return 'missilesystem' 79 elif system == 'systemTactical': # Sensors, we map it to reactor, as we don't have sensor power/damage 80 return 'reactor' 81 elif system == 'systemTurning': 82 return 'maneuver' 83 elif system == 'systemImpulse': 84 return 'impulse' 85 elif system == 'systemWarp': 86 return 'warp' 87 elif system == 'systemFrontShield': 88 return 'frontshield' 89 elif system == 'systemBackShield': 90 return 'rearshield' 91 92 raise UnknownArtemisTagError(node) 93 94class Event: 95 def __init__(self, main_node): 96 self._valid = True 97 self._body = [] 98 self._conditions = [] 99 self._warnings = [] 100 self._done = {} 101 self._ai_info = {} 102 103 for node in main_node: 104 if node.tag == 'big_message': 105 message = convertString(node.get('title', '')) 106 if node.get('subtitle1') is not None: 107 message += '\\n%s' % (convertString(node.get('subtitle1'))) 108 if node.get('subtitle2') is not None: 109 message += '\\n%s' % (convertString(node.get('subtitle2'))) 110 self._body.append('globalMessage("%s");' % (message)); 111 elif node.tag == 'incoming_comms_text': 112 self._body.append('temp_transmission_object:setCallSign("%s"):sendCommsMessage(getPlayerShip(-1), "%s")' % (convertString(node.get('from')), convertString(node.text))); 113 elif node.tag == 'warning_popup_message': 114 self.warning('Ignore', node) 115 elif node.tag == 'start_getting_keypresses_from': 116 self.warning('Ignore', node) 117 elif node.tag == 'end_getting_keypresses_from': 118 self.warning('Ignore', node) 119 elif node.tag == 'set_damcon_members': 120 self.warning('Ignore', node) 121 elif node.tag == 'incoming_message': 122 self.warning('Ignore', node) 123 elif node.tag == 'set_difficulty_level': 124 self.warning('Ignore', node) 125 elif node.tag == 'log': 126 self._body.append('print("%s")' % (convertString(node.get('text')))); 127 128 elif node.tag == 'set_skybox_index': 129 pass #We don't have other skyboxes. So ignore this command. 130 elif node.tag == 'create': 131 self.parseCreate(node) 132 elif node.tag == 'clear_ai': 133 name = convertName(node.get('name')) 134 if name not in self._ai_info: 135 self._ai_info[name] = {} 136 self._ai_info[name]['CLEAR'] = True 137 elif node.tag == 'add_ai': 138 if node.get('name') is None: 139 self.warning('Ignore', node) 140 else: 141 name = convertName(node.get('name')) 142 if name not in self._ai_info: 143 self._ai_info[name] = {} 144 self._ai_info[name][node.get('type').upper()] = node.attrib 145 elif node.tag == 'set_object_property': 146 name = convertName(node.get('name')) 147 property = node.get('property') 148 self._body.append('if %s ~= nil and %s:isValid() then' % (name, name)) 149 if property == 'positionX': 150 self._body.append(' local x, y = %s:getPosition()' % (name)) 151 x, y = convertPosition(node.get('value'), 0) 152 self._body.append(' %s:setPosition(%s, y)' % (name, x)) 153 elif property == 'positionY': 154 pass 155 elif property == 'positionZ': 156 self._body.append(' local x, y = %s:getPosition()' % (name)) 157 x, y = convertPosition(0, node.get('value')) 158 self._body.append(' %s:setPosition(x, %s)' % (name, y)) 159 elif property == 'shieldStateFront': 160 self._body.append(' %s:setFrontShield(%f)' % (name, float(node.get('value')))) 161 elif property == 'shieldStateBack': 162 self._body.append(' %s:setRearShield(%f)' % (name, float(node.get('value')))) 163 elif property == 'shieldMaxStateFront': 164 self._body.append(' %s:setFrontShieldMax(%f)' % (name, float(node.get('value')))) 165 elif property == 'shieldMaxStateBack': 166 self._body.append(' %s:setRearShieldMax(%f)' % (name, float(node.get('value')))) 167 elif property == 'systemDamageBeam': 168 self._body.append(' %s:setSystemHealth("beamweapons", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 169 elif property == 'systemDamageTorpedo': 170 self._body.append(' %s:setSystemHealth("missilesystem", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 171 elif property == 'systemDamageTactical': 172 self.warning('Reactor instead of sensors', node) 173 self._body.append(' %s:setSystemHealth("reactor", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 174 elif property == 'systemDamageTurning': 175 self._body.append(' %s:setSystemHealth("maneuver", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 176 elif property == 'systemDamageImpulse': 177 self._body.append(' %s:setSystemHealth("impulse", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 178 elif property == 'systemDamageWarp': 179 self._body.append(' %s:setSystemHealth("warp", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 180 self._body.append(' %s:setSystemHealth("jumpdrive", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 181 elif property == 'systemDamageFrontShield': 182 self._body.append(' %s:setSystemHealth("frontshield", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 183 elif property == 'systemDamageBackShield': 184 self._body.append(' %s:setSystemHealth("rearshield", %f)' % (name, 1.0 - float(node.get('value')) / 100.0)) 185 elif property == 'willAcceptCommsOrders': 186 self.warning('Ignore', node) 187 elif property == 'eliteAIType': 188 self.warning('Ignore', node) 189 elif property == 'eliteAbilityBits': 190 bits = int(node.get('value')) 191 if (bits & 8) or (bits & 64): 192 self._body.append(' %s:setJumpDrive(True)' % (name)) 193 if bits & 32: 194 self._body.append(' %s:setWarpDrive(True)' % (name)) 195 else: 196 self.warning('Ignore', node) 197 #raise UnknownArtemisTagError(node) 198 self._body.append('end') 199 elif node.tag == 'set_fleet_property': 200 self.warning('Ignore', node) 201 elif node.tag == 'set_timer': 202 self._body.append('timers["%s"] = %f' % (convertName(node.get('name')), float(node.get('seconds')))) 203 elif node.tag == 'set_variable': 204 if node.get('randomIntHigh') is not None: 205 self._body.append('variable_%s = random(%d, %d) --Should be random int...' % (convertName(node.get('name')), int(node.get('randomIntLow')), int(node.get('randomIntHigh')))) 206 elif node.get('randomFloatHigh') is not None: 207 self._body.append('variable_%s = random(%d, %d)' % (convertName(node.get('name')), float(node.get('randomFloatLow')), int(node.get('randomFloatHigh')))) 208 else: 209 self._body.append('variable_%s = %s' % (convertName(node.get('name')), convertFloat(node.get('value')))) 210 elif node.tag == 'set_ship_text': 211 self.warning('Ignore', node) 212 elif node.tag == 'set_relative_position': 213 self._body.append('tmp_x, tmp_y = %s:getPosition()' % (convertName(node.get('name1')))); 214 self._body.append('tmp_x2, tmp_y2 = vectorFromAngle(%s:getRotation() + %f, %f)' % (convertName(node.get('name1')), float(node.get('angle')), float(node.get('distance')))); 215 self._body.append('%s:setPosition(x, y);' % (convertName(node.get('name2')))); 216 elif node.tag == 'end_mission': 217 self._body.append('victory("Independent")') 218 elif node.tag == 'set_player_grid_damage': 219 if convertSystemName(node) == 'warp': 220 self._body.append('getPlayerShip(-1):setSystemHealth("%s", %f)' % ('jumpdrive', 1.0 - float(node.get('value')) * 2.0)) 221 self._body.append('getPlayerShip(-1):setSystemHealth("%s", %f)' % (convertSystemName(node), 1.0 - float(node.get('value')) * 2.0)) 222 elif node.tag == 'destroy': 223 name = convertName(node.get('name')) 224 self._body.append('if %s ~= nil and %s:isValid() then %s:destroy() end' % (name, name, name)) 225 elif node.tag == 'destroy_near': 226 obj_type = node.get('type') 227 if obj_type == 'nebulas': 228 obj_type = 'Nebula' 229 elif obj_type == 'asteroids': 230 obj_type = 'Asteroid' 231 elif obj_type == 'mines': 232 obj_type = 'Mine' 233 else: 234 raise UnknownArtemisTagError(node) 235 if node.get('name'): 236 name = convertName(node.get('name')) 237 self._body.append('if %s ~= nil and %s:isValid() then' % (name, name)) 238 self._body.append(' for _, obj in ipairs(%s:getObjectsInRange(%f)) do' % (name, float(node.get('radius')))) 239 self._body.append(' if obj.typeName == "%s" then obj:destroy() end' % (obj_type)) 240 self._body.append(' end') 241 self._body.append('end') 242 else: 243 x, y = convertPosition(node.get('centerX', 0), node.get('centerZ', 0)) 244 r = float(node.get('radius')) 245 self._body.append('for _, obj in ipairs(getObjectsInRadius(%s, %s, %f)) do' % (x, y, float(node.get('radius')))) 246 self._body.append(' if obj.typeName == "%s" then obj:destroy() end' % (obj_type)) 247 self._body.append('end') 248 249 elif node.tag == 'if_gm_key': 250 self._conditions.append('0') # gm key triggers are never run. 251 self.warning('Ignore', node) 252 elif node.tag == 'if_client_key': 253 self._conditions.append('0') 254 self.warning('Ignore', node) 255 elif node.tag == 'if_variable': 256 self._conditions.append("variable_%s %s (%s)" % (convertName(node.get("name")), convertComparator(node), node.get("value"))) 257 elif node.tag == 'if_timer_finished': 258 self._conditions.append('(timers["%s"] ~= nil and timers["%s"] < 0.0)' % (convertName(node.get("name")), convertName(node.get("name")))) 259 elif node.tag == 'if_outside_box': 260 x1, y1 = convertPosition(node.get('leastX'), node.get('leastZ')) 261 x2, y2 = convertPosition(node.get('mostX'), node.get('mostZ')) 262 self._conditions.append('ifOutsideBox(%s, %s, %s, %s, %s)' % (convertName(node.get("name")), x1, y1, x2, y2)) 263 elif node.tag == 'if_inside_box': 264 x1, y1 = convertPosition(node.get('leastX'), node.get('leastZ')) 265 x2, y2 = convertPosition(node.get('mostX'), node.get('mostZ')) 266 self._conditions.append('ifInsideBox(%s, %s, %s, %s, %s)' % (convertName(node.get("name")), x1, y1, x2, y2)) 267 elif node.tag == 'if_inside_sphere': 268 x1, y1 = convertPosition(node.get('centerX'), node.get('centerZ')) 269 r = float(node.get('radius')) 270 self._conditions.append('ifInsideSphere(%s, %s, %s, %f)' % (convertName(node.get("name")), x1, y1, r)) 271 elif node.tag == 'if_outside_sphere': 272 x1, y1 = convertPosition(node.get('centerX'), node.get('centerZ')) 273 r = float(node.get('radius')) 274 self._conditions.append('ifOutsideSphere(%s, %s, %s, %f)' % (convertName(node.get("name")), x1, y1, r)) 275 elif node.tag == 'if_docked': 276 self._conditions.append('ifdocked(%s)' % (convertName(node.get("name")))) 277 elif node.tag == 'if_fleet_count': 278 self._conditions.append('countFleet(%d) %s %f' % (int(node.get('fleetnumber', 0)), convertComparator(node), float(node.get('value')))) 279 elif node.tag == 'if_distance': 280 self._conditions.append('(%s ~= nil and %s ~= nil and %s:isValid() and %s:isValid() and distance(%s, %s) %s %f)' % (convertName(node.get('name1')), convertName(node.get('name2')), convertName(node.get('name1')), convertName(node.get('name2')), convertName(node.get('name1')), convertName(node.get('name2')), convertComparator(node), float(node.get('value')))) 281 elif node.tag == 'if_exists': 282 self._conditions.append('(%s ~= nil and %s:isValid())' % (convertName(node.get('name')), convertName(node.get('name')))) 283 elif node.tag == 'if_not_exists': 284 self._conditions.append('(%s == nil or not %s:isValid())' % (convertName(node.get('name')), convertName(node.get('name')))) 285 elif node.tag == 'if_player_is_targeting': 286 self._conditions.append('(%s ~= nil and %s:isValid() and getPlayerShip(-1):getTarget() == %s)' % (convertName(node.get('name')), convertName(node.get('name')), convertName(node.get('name')))) 287 else: 288 raise UnknownArtemisTagError(node) 289 self.warning('Ignore', node) 290 291 # Convert the AI statements to EE AI. 292 for name, ai in self._ai_info.items(): 293 ai_list = sorted(list(ai.keys())) 294 if ai_list == ['ATTACK'] or ai_list == ['ATTACK', 'ELITE_AI'] or ai_list == ['ATTACK', 'CLEAR'] or ai_list == ['ATTACK', 'CHASE_NEUTRAL']: 295 self._body.append('%s:orderAttack(%s)' % (name, convertName(ai['ATTACK']['targetName']))) 296 elif ai_list == ['POINT_THROTTLE'] or ai_list == ['FOLLOW_COMMS_ORDERS', 'POINT_THROTTLE'] or ai_list == ['CHASE_PLAYER', 'POINT_THROTTLE']: 297 x, y = convertPosition(ai['POINT_THROTTLE']['value1'], ai['POINT_THROTTLE']['value3']) 298 self._body.append('%s:orderFlyTowards(%s, %s)' % (name, x, y)) 299 elif ai_list == ['CLEAR']: 300 self._body.append('%s:orderIdle()' % (name)) 301 elif ai_list == ['ELITE_AI']: 302 pass 303 else: 304 self.warning('Unknown AI: %s: %s' % (name, ai)) 305 306 def parseCreate(self, node): 307 if node.get('use_gm_position') is not None: 308 return 309 create_type = node.get('type') 310 if create_type == 'player': 311 name = convertName(node.get('name')) 312 x, y = convertPosition(node.get('x'), node.get('z')) 313 self._body.append('%s = PlayerSpaceship():setFaction("Human Navy"):setTemplate("Player Cruiser"):setCallSign("%s"):setPosition(%s, %s)' % (name, node.get('name'), x, y)) 314 elif create_type == 'neutral': 315 name = convertName(node.get('name')) 316 x, y = convertPosition(node.get('x'), node.get('z')) 317 self._body.append('%s = CpuShip():setTemplate("Tug"):setCallSign("%s"):setFaction("%s"):setPosition(%s, %s):orderRoaming()' % (name, node.get('name'), convertRaceKeys(node, 'neutral'), x, y)) 318 self.addToFleet(name, node) 319 elif create_type == 'enemy': 320 name = convertName(node.get('name', 'temp_enemy_name')) 321 x, y = convertPosition(node.get('x'), node.get('z')) 322 self._body.append('%s = CpuShip():setTemplate("Cruiser"):setCallSign("%s"):setFaction("%s"):setPosition(%s, %s):orderRoaming()' % (name, node.get('name'), convertRaceKeys(node, 'enemy'), x, y)) 323 self.addToFleet(name, node) 324 325 self.addToFleet(name, node, 0) # Add every enemy ship to fleet 0 326 elif create_type == 'station': 327 name = convertName(node.get('name')) 328 x, y = convertPosition(node.get('x'), node.get('z')) 329 self._body.append('%s = SpaceStation():setTemplate("Small Station"):setCallSign("%s"):setFaction("%s"):setPosition(%s, %s)' % (name, node.get('name'), convertRaceKeys(node, 'friendly'), x, y)) 330 elif create_type == 'blackHole': 331 name = convertName(node.get('name', 'temp_blackhole_name')) 332 x, y = convertPosition(node.get('x'), node.get('z')) 333 self._body.append('%s = BlackHole():setPosition(%s, %s)' % (name, x, y)) 334 elif create_type == 'whale': 335 self.warning('Ignore', node) 336 elif create_type == 'monster': 337 self.warning('Ignore', node) 338 elif create_type == 'genericMesh': 339 self.warning('Ignore', node) 340 elif create_type == 'anomaly': 341 # Using a supply drop instead of an anomaly 342 output = "" 343 if node.get('name') is not None: 344 name = convertName(node.get('name')) 345 output = "%s = " % (name) 346 x, y = convertPosition(node.get('x'), node.get('z')) 347 output += 'SupplyDrop():setFaction("Human Navy"):setPosition(%s, %s):setEnergy(500):setWeaponStorage("Nuke", 0):setWeaponStorage("Homing", 0):setWeaponStorage("Mine", 0):setWeaponStorage("EMP", 0)' % (x, y) 348 self._body.append(output) 349 elif create_type == 'asteroids': 350 self.parseCreateCount('Asteroid()', node) 351 elif create_type == 'mines': 352 self.parseCreateCount('Mine()', node) 353 elif create_type == 'nebulas': 354 node.set('count', '(%s + 24) / 25' % convertFloat(node.get('count'))) 355 if node.get('randomRange') is not None: 356 node.set('randomRange', '%s - 2500' % convertFloat(node.get('randomRange'))) 357 self.parseCreateCount('Nebula()', node) 358 else: 359 raise UnknownArtemisTagError(node) 360 361 def parseCreateCount(self, object_create_script, node): 362 count = convertFloat(node.get('count')) 363 x, y = convertPosition(node.get('startX', 0), node.get('startZ', 0)) 364 self._body.append('tmp_count = %s' % (count)) 365 self._body.append('for tmp_counter=1,tmp_count do') 366 if node.get('radius') is not None: 367 radius = convertFloat(node.get('radius')) 368 start_angle = float(node.get('startAngle', 0)) - 90 369 end_angle = float(node.get('endAngle', 360)) - 90 370 self._body.append(' tmp_x, tmp_y = vectorFromAngle(%s + (%s - %s) * (tmp_counter - 1) / tmp_count, %s)' % (start_angle, end_angle, start_angle, radius)) 371 self._body.append(' tmp_x, tmp_y = tmp_x + %s, tmp_y + %s' % (x, y)) 372 else: 373 x2, y2 = convertPosition(node.get('endX'), node.get('endZ')) 374 self._body.append(' tmp_x = %s + (%s - %s) * (tmp_counter - 1) / tmp_count' % (x, x2, x)) 375 self._body.append(' tmp_y = %s + (%s - %s) * (tmp_counter - 1) / tmp_count' % (y, y2, y)) 376 if node.get('randomRange') is not None: 377 random_range = convertFloat(node.get('randomRange', 0)) 378 self._body.append(' tmp_x2, tmp_y2 = vectorFromAngle(random(0, 360), random(0, %s))' % (random_range)) 379 self._body.append(' tmp_x, tmp_y = tmp_x + tmp_x2, tmp_y + tmp_y2') 380 self._body.append(' %s:setPosition(tmp_x, tmp_y)' % (object_create_script)) 381 self._body.append('end') 382 383 def addToFleet(self, name, node, fleetnumber=-1): 384 if fleetnumber != -1: 385 fleetnumber = int(node.get('fleetnumber', -1)) 386 if fleetnumber > 0: 387 if 'fleet_check_%d' % (fleetnumber) not in self._done: 388 self._done['fleet_check_%d' % (fleetnumber)] = True 389 self._body.append('if fleet[%d] == nil then fleet[%d] = {} end' % (fleetnumber, fleetnumber)) 390 self._body.append('table.insert(fleet[%d], %s)' % (fleetnumber, name)) 391 392 def warning(self, *args): 393 message = '' 394 for arg in args: 395 if isinstance(arg, str): 396 message += arg + ' ' 397 elif isinstance(arg, xml.etree.ElementTree.Element): 398 message += '<' + arg.tag + '> ' + str(arg.attrib) + ' ' 399 if arg.text is not None: 400 message += convertString(arg.text) 401 else: 402 message += str(arg) 403 self._body.append('--WARNING: %s' % (message)) 404 self._warnings.append(args) 405 406 def getBody(self, indent=1): 407 body = '' 408 for line in self._body: 409 body += (' ' * indent) + line + '\n'; 410 return body 411 412 def getCondition(self): 413 return ' and '.join(self._conditions) 414 415 def getWarnings(self): 416 return self._warnings 417 418 def isValid(self): 419 return self._valid 420 421class Converter: 422 def __init__(self, filename): 423 self._data = xml.etree.ElementTree.XML(open(filename, 'rb').read().replace(b'"<="', b'"<="').replace(b'"<"', b'"<"').replace(b'">="', b'">="').replace(b'">"', b'">"')) 424 425 self._events = [] 426 self._start_event = Event(self._data.find("start")) 427 for node in self._data.findall("event"): 428 self._events.append(Event(node)) 429 430 def export(self, name, filename): 431 f = open(filename, "w") 432 f.write('-- Name: %s\n' % (name)) 433 f.write('-- Description: Converted Artemis mission\n') 434 warnings = [] 435 for line in open("artemis_mission_convert_template.lua", "r"): 436 if line.strip() == '###START###': 437 f.write(self._start_event.getBody()) 438 warnings += self._start_event.getWarnings() 439 elif line.strip() == '###EVENTS###': 440 for event in self._events: 441 if not event.isValid(): 442 continue 443 if event.getCondition() != "": 444 f.write(" if %s then\n" % event.getCondition()) 445 f.write(event.getBody(2)) 446 warnings += event.getWarnings() 447 f.write(" end\n") 448 else: 449 f.write(event.getBody(1)) 450 warnings += event.getWarnings() 451 else: 452 f.write(line) 453 print('Written: %s with %d warnings' % (filename, len(warnings))) 454 warning_types = {} 455 for warning in warnings: 456 for item in warning: 457 if isinstance(item, xml.etree.ElementTree.Element): 458 if item.tag not in warning_types: 459 warning_types[item.tag] = 0 460 warning_types[item.tag] += 1 461 for key, count in warning_types.items(): 462 print("Warning: %s %dx" % (key, count)) 463 return len(warning_types) == 0 464 465if __name__ == "__main__": 466 count = 0 467 success = 0 468 for arg in sys.argv[1:]: 469 if os.path.isfile(arg): 470 filename = arg 471 count += 1 472 print("========================================================"); 473 print("Converting: ", filename); 474 try: 475 c = Converter(filename) 476 name = os.path.splitext(os.path.basename(filename))[0].replace("MISS_", "") 477 c.export(name, "scripts/scenario_99_%s.lua" % (name)) 478 success += 1 479 except: 480 traceback.print_exc() 481 for root, dirnames, filenames in os.walk(arg): 482 for filename in fnmatch.filter(filenames, '*.xml'): 483 filename = os.path.join(root, filename) 484 count += 1 485 print("========================================================"); 486 print("Converting: ", filename); 487 try: 488 c = Converter(filename) 489 name = os.path.splitext(os.path.basename(filename))[0].replace("MISS_", "") 490 if c.export(name, "scripts/scenario_99_%s.lua" % (name)): 491 sys.exit(1) 492 success += 1 493 except: 494 traceback.print_exc() 495 sys.exit(1) 496 print("Converted %d of the %d scripts" % (success, count)) 497