nipl = {} for (label, pool) in pools: dipl[pool] = [] pt_cipl[pool] = [] level_ipl[pool] = [] dl_ia[pool] = [] nipl[pool] = [] # Now loop through and find out what we need to find out for (label, pool) in pools: full_cat = '{}_{}'.format(pool, weight) if full_cat in categories: (orig_pools, to_change) = categories[full_cat] for object_name in to_change: node = data.get_node_by_full_object(object_name) parsed = node.get_structure() found = False if 'DefaultItemPoolList' in parsed: for (dipl_idx, pool_list) in enumerate(parsed['DefaultItemPoolList']): if 'ItemPool' in pool_list: for check_pool in orig_pools: if check_pool in pool_list['ItemPool']: dipl[pool].append((dipl_idx, object_name)) dipl_count += 1 found = True break if 'NewItemPoolList' in parsed:
from ftexplorer.data import Data from modprocessor import ModProcessor data = Data('BL2') lines = [] lines.append('BL2') lines.append('#<omg>') lines.append('') # Loop through levels for (label, level) in data.get_levels(): lines.append('#<{}>'.format(label)) lines.append('') for package in data.get_level_package_names(level): main_node = data.get_node_by_full_object(package) for soundvol in main_node.get_children_with_name('wwisesoundvolume'): soundvolstruct = soundvol.get_structure() if 'EnvironmentalEffects' in soundvolstruct and soundvolstruct[ 'EnvironmentalEffects'] != '': for (idx, effect) in enumerate( soundvolstruct['EnvironmentalEffects']): lines.append( 'level {} set {}.{} EnvironmentalEffects[{}].Effect None' .format(level, package, soundvol.name, idx)) lines.append('') lines.append('#</{}>'.format(label)) lines.append('') lines.append('') lines.append('#</omg>')
if processing: if start_stop_str in line or extra_stop_str in line: processing = False else: line = line.strip() if line == '': continue match = re.search('<value>",(.*?),BalancedItems\[(\d+)\]\.(.*),,(.*?)"', line) if match: main_pool = match.group(1) bal_idx = int(match.group(2)) var_changed = match.group(3) changed_to = match.group(4) if var_changed == 'ItmPoolDefinition' and changed_to == 'None': if main_pool not in pool_cache: pool_cache[main_pool] = data.get_node_by_full_object(main_pool).get_structure() (junk, destination, junk2) = pool_cache[main_pool]['BalancedItems'][bal_idx]['ItmPoolDefinition'].split("'", 2) freed_pools.add(destination) if destination not in pool_cache: pool_cache[destination] = data.get_node_by_full_object(destination).get_structure() if len(pool_cache[destination]['BalancedItems']) > 1: raise Exception('Pool {} has {} items'.format(destination, len(pool_cache[destination]['BalancedItems']))) (junk, ultimate, junk2) = pool_cache[destination]['BalancedItems'][0]['InvBalanceDefinition'].split("'", 2) from_values['{}_{}'.format(main_pool, bal_idx)] = ultimate elif var_changed == 'InvBalanceDefinition' and 'InventoryBalanceDefinition' in changed_to: (junk, new_inv, junk2) = changed_to.split("'", 2) to_values['{}_{}'.format(main_pool, bal_idx)] = new_inv else: raise Exception('Unknown line found: {}'.format(line)) else: if start_stop_str in line:
('Axton', 'GD_Soldier_Streaming.Pawn_Soldier', 'GD_Soldier.Character.CharClass_Soldier'), ('Gaige', 'GD_Tulip_Mechro_Streaming.Pawn_Mechromancer', 'GD_Tulip_Mechromancer.Character.CharClass_Mechromancer'), ('Krieg', 'GD_Lilac_Psycho_Streaming.Pawn_LilacPlayerClass', 'GD_Lilac_PlayerClass.Character.CharClass_LilacPlayerClass'), ('Maya', 'GD_Siren_Streaming.Pawn_Siren', 'GD_Siren.Character.CharClass_Siren'), ('Salvador', 'GD_Mercenary_Streaming.Pawn_Mercenary', 'GD_Mercenary.Character.CharClass_Mercenary'), ('Zero', 'GD_Assassin_Streaming.Pawn_Assassin', 'GD_Assassin.Character.CharClass_Assassin'), ]: print('{}:'.format(name)) struct_streaming = data.get_node_by_full_object( streaming_obj).get_structure() struct_player = data.get_node_by_full_object(player_obj).get_structure() print(' * Player GroundSpeed: {}'.format(struct_player['GroundSpeed'])) print(' * Streaming GroundSpeed: {}'.format( struct_streaming['GroundSpeed'])) print(' * Streaming GroundSpeedBaseValue: {}'.format( struct_streaming['GroundSpeedBaseValue'])) print(' * Player AirSpeed: {}'.format(struct_player['AirSpeed'])) print(' * Streaming AirSpeed: {}'.format(struct_streaming['AirSpeed'])) print(' * Streaming AirSpeedBaseValue: {}'.format( struct_streaming['AirSpeedBaseValue'])) print(' * Player JumpZ: {}'.format(struct_player['JumpZ'])) print(' * Streaming JumpZ: {}'.format(struct_streaming['JumpZ'])) print(' * Streaming JumpZBaseValue: {}'.format( struct_streaming['JumpZBaseValue'])) print(' * Player CrouchedPct: {}'.format(struct_player['CrouchedPct']))
'GD_Petunia_Weapons.AssaultRifles.AR_Bandit_3_CryBaby', 'GD_Cork_Weap_SniperRifles.A_Weapons_Legendary.Sniper_Vladof_5_Longnail', ]) print('Loading TPS index') data = Data('TPS') print('Checking data') hotfix_idx = 0 create_luneshine_attachments = [] for weapon_obj in weapons: if weapon_obj in weap_exclude: continue node = data.get_node_by_full_object(weapon_obj) struct = node.get_structure() if 'RuntimePartListCollection' in struct: (junk1, runtime_parts, junk2) = struct['RuntimePartListCollection'].split("'", 2) else: raise Exception('No runtime part list found for {}'.format(weapon_obj)) if runtime_parts: partnode = data.get_node_by_full_object(runtime_parts) struct = partnode.get_structure() parts = struct['GripPartData']['WeightedParts'] if len(parts) == 1: print('{}: {}'.format(weapon_obj, len(parts)))
mod_version = '1.1.0' output_filename = '{}.blcm'.format(mod_name) output_source_filename = '{}-source.txt'.format(mod_name) ### ### Processing the mod ### data = Data('TPS') free_count = 0 prefix = ' ' * (2 * 4) hotfix_output = [] saved_pools = [] for keyed in sorted(data.get_all_by_type('KeyedItemPoolDefinition')): structure = data.get_node_by_full_object(keyed).get_structure() for (bi_idx, item) in enumerate(structure['BalancedItems']): (junk, pool, junk2) = item['ItmPoolDefinition'].split("'") saved_pools.append(pool) innerpool = data.get_node_by_full_object(pool).get_structure() if len(innerpool['BalancedItems']) != 1: raise Exception('Inner pool {} has {} items'.format( pool, len(innerpool['BalancedItems']))) (junk, actualcustom, junk2 ) = innerpool['BalancedItems'][0]['InvBalanceDefinition'].split("'") # Hotfix to unlink the intermediate pool hotfix_output.append( '{}level None set {} BalancedItems[{}].ItmPoolDefinition None'. format( prefix,
rv = child_distance <= distance return (rv, '({:0.1f}, {:0.1f}, {:0.1f}) @ {:0.1f}'.format( child_x, child_y, child_z, child_distance)) types = [ ('WillowPopulationOpportunityPoint_', 'Location', 'PopulationDef'), ('PopulationOpportunityPoint_', 'Location', 'PopulationDef'), ('InterpActor_', 'Location', 'ReplicatedMesh'), ('WillowInteractiveObject_', 'Location', 'InteractiveObjectDefinition'), # Eh, nothing useful to report on this one. #('StaticMeshActor_', 'Location', 'foo'), ] for (package_name, data_type) in data.get_level_package_nodes(level_package): node = data.get_node_by_full_object(package_name) for child in node.children.values(): for (type_prefix, loc_attr, report_attr) in types: if child.name.startswith(type_prefix): struct = child.get_structure() if loc_attr in struct: (match, suffix) = is_close(struct[loc_attr]['X'], struct[loc_attr]['Y'], struct[loc_attr]['Z']) if match: print('{prefix}.{name} - {report} {suffix}'.format( prefix=package_name, name=child.name, report=struct[report_attr], suffix=suffix, ))
('Rotgut Distillery', 'Distillery_P'), ('Wam Bam Island', 'Easter_P'), ], } for game, levelnames in control.items(): popdefs = {} print('Processing {}'.format(game)) print('==============') print('') data = Data(game) for (english, levelname) in levelnames: # Get the info on what objects we need to load. level_packages = ['{}.TheWorld:PersistentLevel'.format(levelname)] node = data.get_node_by_full_object('{}.TheWorld'.format(levelname)) for childname, child in node.children.items(): if childname[:14].lower() == 'levelstreaming': childstruct = child.get_structure() if childstruct['LoadedLevel'] != 'None': level_packages.append(childstruct['LoadedLevel'].split("'", 2)[1]) # Report #print(levelname) #for package in level_packages: # print(' * {}'.format(package)) #print('') # Now loop through 'em to get all the population definitions traps = set() for package in level_packages:
('Rotgut Distillery', 'Distillery_P'), ('Wam Bam Island', 'Easter_P'), ], } for game, levelnames in control.items(): popdefs = {} print('Processing {}'.format(game)) print('==============') print('') data = Data(game) for (english, levelname) in levelnames: # Get the info on what objects we need to load. level_packages = ['{}.TheWorld:PersistentLevel'.format(levelname)] node = data.get_node_by_full_object('{}.TheWorld'.format(levelname)) for childname, child in node.children.items(): if childname[:14].lower() == 'levelstreaming': childstruct = child.get_structure() if childstruct['LoadedLevel'] != 'None': level_packages.append(childstruct['LoadedLevel'].split( "'", 2)[1]) # Report #print(levelname) #for package in level_packages: # print(' * {}'.format(package)) #print('') # Now loop through 'em to get all the population definitions traps = set()
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: from ftexplorer.data import Data data = Data('BL2') for aidef in data.get_all_by_type('AIClassDefinition'): structure = data.get_node_by_full_object(aidef).get_structure() chance_modifier = None duration_modifier = None damage_impact_modifier = None damage_status_modifier = None report = False if 'BaseShockChanceResistanceModifier' in structure: value = round( float(structure['BaseShockChanceResistanceModifier'] ['BaseValueConstant']), 6) if value != 1: chance_modifier = value report = True if 'BaseShockDurationResistanceModifier' in structure: value = round( float(structure['BaseShockDurationResistanceModifier'] ['BaseValueConstant']), 6) if value != 1: duration_modifier = value report = True if 'BaseShockDamageModifiers' in structure: value = round( float(structure['BaseShockDamageModifiers']['ResistanceToImpact'] ['BaseValueConstant']), 6)
# Loop through popdefs to get a list of all pawnbalances which can spawn pawnbalances = set() for popdef in popdefs: for pawnbalance in get_spawns_from_popdef(popdef, data): pawnbalances.add(pawnbalance) print('{} ({})'.format(level_label, level_name)) print('') same = [] for pawnbalance in sorted(pawnbalances): if pawnbalance in pawnbalance_cache: same.append(pawnbalance) else: print(' * {}'.format(pawnbalance)) pb_struct = data.get_node_by_full_object(pawnbalance).get_structure() pawnbalance_cache[pawnbalance] = pb_struct print_blank_line = False have_cipl_on_first = False if ('PlayThroughs' in pb_struct and pb_struct['PlayThroughs'] != '' and len(pb_struct['PlayThroughs']) > 0): for (pt_idx, pt) in enumerate(pb_struct['PlayThroughs']): print_blank_line = True if 'CustomItemPoolList' in pt and pt['CustomItemPoolList'] != '': found_shield = False if pt_idx == 0 and int(pt['PlayThrough']) == 1: have_cipl_on_first = True for (cipl_idx, cipl) in enumerate(pt['CustomItemPoolList']): if shield_pool in cipl['ItemPool']: found_shield = True
data = Data('TPS') filenames = [ 'resources/TPS/dumps/WeaponPartListCollectionDefinition.dump.xz', 'resources/TPS/dumps/ItemPartListCollectionDefinition.dump.xz', ] part_hotfix_idx = 0 for filename in filenames: with lzma.open(filename, 'rt', encoding='latin1') as df: for line in df.readlines(): match = re.match(r"^\*\*\* Property dump for object '\S+ (\S+)' \*\*\*", line) if match: obj_name = match.group(1) struct = data.get_node_by_full_object(obj_name).get_structure() if 'ConsolidatedAttributeInitData' not in struct: # Should maybe keep track of which of these doesn't have it... continue # Figure out our caid values caid = struct['ConsolidatedAttributeInitData'] caid_values = [] for caid_val in caid: caid_values.append(float(caid_val['BaseValueConstant'])) # Now loop through all our items. caid_updates = set() for key, val in struct.items(): if key[-8:] == 'PartData':
import sys from ftexplorer.data import Data def striptype(obj_name): (junk1, name, junk2) = obj_name.split("'", 2) return name def dotnode(obj_name): name_parts = obj_name.split('.') return name_parts[-1].lower().replace('-', '_') data = Data('BL2') with open('b2missions.dot', 'w') as df: print('digraph b2 {', file=df) for mission_obj in data.get_all_by_type('MissionDefinition'): node = data.get_node_by_full_object(mission_obj) mission = node.get_structure() dot_name = dotnode(mission_obj) print(' {} [label=<{}>];'.format(dot_name, mission['MissionName']), file=df) print('{} ({})'.format(mission['MissionName'], mission_obj)) if 'Dependencies' in mission: main_deps = set() for dep in mission['Dependencies']: print(' * {}'.format(dep)) if dep[:17] != 'MissionDefinition': raise Exception('Unknown mission dep type: {}'.format(dep)) depname = striptype(dep) main_deps.add(depname) depname_dot = dotnode(depname)
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: from ftexplorer.data import Data #data = Data('BL2') data = Data('TPS') affected = {} for challenge_def in data.get_all_by_type('ChallengeDefinition'): challenge_struct = data.get_node_by_full_object( challenge_def).get_structure() if 'Levels' in challenge_struct: for (idx, level) in enumerate(challenge_struct['Levels']): reward = Data.get_struct_attr_obj(level, 'RewardItemPool') if reward: affected[reward] = ( challenge_struct['ChallengeName'], challenge_struct['Description'], idx + 1, ) print('Pool | Name | Level | Description') print('--- | --- | --- | ---') for reward in sorted(affected.keys()): (name, desc, num) = affected[reward] print('`{}` | {} | {} | {}'.format(reward, name, num, desc))
weight = round(bvc * bvsc, 6) self.total += weight self.items.append((title, weight)) def get_report(self): if self.total == 0: return "" ret_list = [] for (title, weight) in self.items: prob = weight / self.total * 100 if prob >= 1: prob = round(prob) else: prob = round(prob, 2) ret_list.append("\t{}%: {}".format(prob, title)) return "\n".join(ret_list) data = Data('TPS') with open('/home/pez/Programs/games/borderlands_tps/ucp/enemy_use.txt') as df: for line in df.readlines(): if line[:3] == 'GD_': pool = line.strip() structure = data.get_node_by_full_object(pool).get_structure() bal = Balanced() for item in structure['BalancedItems']: bal.add_item(item) print(pool) print(bal.get_report()) print('')
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: from ftexplorer.data import Data # So, I've seen this coming for awhile. We've never actually handled quotes # properly, and I've gotten away with it because nothing I've wanted to # programmatically deal with has ever had a quoted comma in it. Well, # the BPD grapher finally came across one of those, specifically: # # GD_Shields.Skills.Spike_Shield_Skill_CorrosiveLegendary:BehaviorProviderDefinition_0 # # So, just a little util to trigger that parsing, so that I can finally # address that. # # ... and actually, the "fix" for this probably only really handles one # specific case. I wouldn't be surprised if something else comes to bite # me related to quotes again. data = Data('TPS') node = data.get_node_by_full_object( 'GD_Shields.Skills.Spike_Shield_Skill_CorrosiveLegendary:BehaviorProviderDefinition_0' ) node_struct = node.get_structure() print(node_struct)
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: import sys import argparse from ftexplorer.data import Data data = Data('TPS') for obj_name in data.get_all_by_type('WeaponNamePartDefinition'): obj = data.get_node_by_full_object(obj_name).get_structure() if 'PartName' not in obj or obj['PartName'] == '' or obj[ 'PartName'] == 'None': print(obj_name)
def investigate_pool(pool, report): """ Looks into a pool to see if we should report it. """ if (pool['ItemPool'] != 'None' and 'AmmoAndResourcePools' not in pool['ItemPool'] and 'EnemyUse' not in pool['ItemPool'] and 'Pool_GunsAndGear_Weighted' not in pool['ItemPool'] and 'ItemPool_MoxxiPicture' not in pool['ItemPool'] and 'Pool_GrenadeMods_All' not in pool['ItemPool'] and 'GD_CustomItemPools' not in pool['ItemPool'] and 'Pool_SpellGrenade' not in pool['ItemPool'] and 'Pool_Shields_All_01_Common' not in pool['ItemPool'] ): prob = pool['PoolProbability'] if is_fixed(prob): print(report) for classname in data.get_all_by_type('AIPawnBalanceDefinition'): pawn = data.get_node_by_full_object(classname).get_structure() if 'DefaultItemPoolList' in pawn: for (dipl, pool) in enumerate(pawn['DefaultItemPoolList']): investigate_pool(pool, '{} DefaultItemPoolList[{}]'.format(classname, dipl)) if 'PlayThroughs' in pawn: for (pt_idx, pt) in enumerate(pawn['PlayThroughs']): if ('CustomItemPoolList' in pt and pt['CustomItemPoolList'] is not None and pt['CustomItemPoolList'] != ''): for (cipl, pool) in enumerate(pt['CustomItemPoolList']): investigate_pool(pool, '{} PlayThroughs[{}].CustomItemPoolList[{}]'.format(classname, pt_idx, cipl))
(link_index, link_length) = compliment(link) print('{}Links at {}, length {}'.format(prefix, link_index, link_length)) for cold_index in range(link_index, link_index + link_length): cold = cold_data[cold_index] (link_id, bindex) = compliment(cold['LinkIdAndLinkedBehavior']) behavior = behavior_data[bindex] print('{}* (delay {}) Behavior {}: {}'.format( prefix, round(float(cold['ActivateDelay'])), bindex, behavior['Behavior'])) follow(behavior['OutputLinks']['ArrayIndexAndLength'], cold_data, behavior_data, prefix='{} '.format(prefix)) bpd = data.get_node_by_full_object(bpd_name).get_structure() seq0 = bpd['BehaviorSequences'][0] event_data = seq0['EventData2'] behavior_data = seq0['BehaviorData2'] variable_data = seq0['VariableData'] cold_data = seq0['ConsolidatedOutputLinkData'] var_data = seq0['ConsolidatedVariableLinkData'] link_data = seq0['ConsolidatedLinkedVariables'] for event in event_data: if event['UserData']['bEnabled'] == 'True': print('Event {}:'.format(event['UserData']['EventName'])) follow(event['OutputLinks']['ArrayIndexAndLength'], cold_data, behavior_data,
mod_version = '1.0.0' output_filename = '{}.txt'.format(mod_name) ### ### Processing the mod ### data = Data('TPS') hfs = Hotfixes() free_count = 0 prefix = ' '*(2*4) hotfix_output = [] saved_pools = [] for keyed in sorted(data.get_all_by_type('KeyedItemPoolDefinition')): structure = data.get_node_by_full_object(keyed).get_structure() for (bi_idx, item) in enumerate(structure['BalancedItems']): (junk, pool, junk2) = item['ItmPoolDefinition'].split("'") saved_pools.append(pool) innerpool = data.get_node_by_full_object(pool).get_structure() if len(innerpool['BalancedItems']) != 1: raise Exception('Inner pool {} has {} items'.format(pool, len(innerpool['BalancedItems']))) (junk, actualcustom, junk2) = innerpool['BalancedItems'][0]['InvBalanceDefinition'].split("'") # Hotfix to unlink the intermediate pool hf_id = 'unlink_{}'.format(free_count) hfs.add_level_hotfix(hf_id, 'TPSSkinpool', ',{},BalancedItems[{}].ItmPoolDefinition,,None'.format( keyed, bi_idx, ))