def get_manufacturers(baldef_name, data): manufs = set() baldef = data.get_struct_by_full_object(baldef_name) if 'Manufacturers' in baldef: for manuf in baldef['Manufacturers']: manufs.add(Data.get_attr_obj(manuf['Manufacturer'])) elif 'BaseDefinition' in baldef: basedef_full = baldef['BaseDefinition'] if basedef_full != 'None': manufs |= get_manufacturers( Data.get_attr_obj(baldef['BaseDefinition']), data) return manufs
def follow(link, cold_data, behavior_data, seq_idx, cold_followed): """ Follows the given `link` (being a compound number of the sort found in BPDs) through the given `behavior_data`, using `cold_data` as the glue. `seq_idx` is our current BPD index. """ to_ret = set() (link_index, link_length) = parse_arrayindexandlength(link) for (cold_order_idx, cold_index) in enumerate(range(link_index, link_index + link_length)): full_cold_index = '{}_{}'.format(seq_idx, cold_index) if full_cold_index in cold_followed: continue else: cold_followed.add(full_cold_index) try: cold = cold_data[cold_index] except IndexError: return to_ret (link_id, bindex) = parse_linkidandlinkedbehavior( cold['LinkIdAndLinkedBehavior']) behavior = behavior_data[bindex] to_ret.add(Data.get_struct_attr_obj(behavior, 'Behavior')) to_ret |= follow( behavior['OutputLinks']['ArrayIndexAndLength'], cold_data, behavior_data, seq_idx, cold_followed, ) return to_ret
def go(object_name): global data global base obj = data.get_struct_by_full_object(object_name) (first, last) = object_name.rsplit('.', 1) print(' {};'.format(last)) linkcount = 0 if 'OutputLinks' in obj: ol = obj['OutputLinks'] if ol and ol != '': for l in ol: if 'Links' in l: links = l['Links'] if links and links != '': for link in links: op = Data.get_struct_attr_obj(link, 'LinkedOp') if op.startswith(base): print(' {} -> {} [taillabel={}];'.format( last, op[len(base) + 1:], linkcount)) go(op) else: print(' {};'.format(op)) print(' {} -> {} [taillabel={}];'.format( last, op, linkcount)) linkcount += 1
def __init__(self): print('Initializing...') self.games = {} for game in self.gamelist: self.games[game.lower()] = Data(game) print('Done.')
def get_asvs(obj, asvs): if 'AttributeStartingValues' in obj and obj[ 'AttributeStartingValues'] != '' and obj[ 'AttributeStartingValues'] != 'None': for asv in obj['AttributeStartingValues']: asv_val = Data.get_struct_attr_obj(asv, 'Attribute') if asv_val is not None: asvs.add(asv_val)
def title_from_partdef(data, partlist): for part_def in partlist['WeightedParts']: part = data.get_struct_attr_obj_real(part_def, 'Part') if part: if 'TitleList' in part: for title_def in part['TitleList']: title = data.get_struct_by_full_object( Data.get_attr_obj(title_def)) print(title['PartName']) else: raise Exception('No definitions!')
def get_names(data, partdef, attr_name, get_customs=False): names = set() customs = set() if attr_name in partdef and partdef[attr_name] != '': for namepart_full in partdef[attr_name]: namepart_name = Data.get_attr_obj(namepart_full) namepart = data.get_struct_by_full_object(namepart_name) if 'PartName' in namepart and namepart['PartName'] != '': names.add(namepart['PartName']) if get_customs: customs |= get_presentations(data, namepart) if get_customs: return (list(names), list(customs)) else: return list(names)
def process_part_list_inner(df, wp, caids, label): """ Given a struct `wp` which contains the attribute 'WeightedParts`, and a dict `caids` which contains the processed `ConsolidatedAttributeInitData` data, process the part list and write to `df` """ attr_parts = [] for part in wp['WeightedParts']: part_name = Data.get_attr_obj(part['Part']).split('.')[-1] try: if caids[int(part['MinGameStageIndex'])] >= 100: print('') print('Skipping 100+ MinGameStageIndex in {} {}'.format( partlist_name, label)) continue except KeyError: # This happens at least in GD_Anemone_Weapons.Rocket_Launcher.RL_Maliwan_5_Pyrophobia # ... we don't understand BVA, and the mingamestageindex happens to point to a # CAID which has one of those. It's the only one in there, though, and this # check is less important anyway, so whatever. Ignore it. print('Couldn\'t get MinGameStageIndex for {} {}'.format( partlist_name, label)) pass if 'Manufacturers' not in part or not part['Manufacturers'] or part[ 'Manufacturers'] == '': attr_parts.append((part_name, 100)) elif part['Manufacturers'][0]['Manufacturer'] is None or part[ 'Manufacturers'][0]['Manufacturer'] == 'None': attr_parts.append( (part_name, caids[int(part['DefaultWeightIndex'])])) else: print('') raise Exception('Have not implemented Manufacturer yet...') total_weight = sum([p[1] for p in attr_parts]) for (part, weight) in attr_parts: df.writerow({ 'game': game, 'balance': baldef_name, 'parttype': label, 'part': part, 'ind_weight': weight, 'total_weight': total_weight, 'pct': round(weight / total_weight * 100, 1), })
def get_presentations(data, base_obj): customs = set() if 'CustomPresentations' in base_obj and base_obj[ 'CustomPresentations'] != '': for cp_full in base_obj['CustomPresentations']: cp_name = Data.get_attr_obj(cp_full) cp = data.get_struct_by_full_object(cp_name) if 'NoConstraintText' in cp and cp['NoConstraintText'] != '': customs.add((cp_name, cp['NoConstraintText'])) if 'Description' in cp and cp['Description'] != '': # Have to work around a deficiency in our data processing # (should probably just check for `type(foo) == dict` and solve it more generally, eh?) if cp['Description'] == {'E ': ' mc^(OMG)/wtf'}: customs.add((cp_name, 'E = mc^(OMG)/wtf')) elif cp['Description'] == {'5+7+1': 'Zero'}: customs.add((cp_name, '5+7+1=Zero')) else: customs.add((cp_name, cp['Description'])) return customs
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: # Attempting to find some pattern to the bandit coolers near the # Denial Subroutine battle which don't actually work. import sys from ftexplorer.data import Data, Weight data = Data('TPS') cooler_points = [] points = data.get_all_by_type('WillowPopulationOpportunityPoint') for point_name in sorted(points): if point_name.startswith( 'Ma_RightCluster_Combat.TheWorld:PersistentLevel'): point = data.get_struct_by_full_object(point_name) popdef_name = Data.get_struct_attr_obj(point, 'PopulationDef') if popdef_name and popdef_name == 'GD_Population_Treasure.Lootables.BanditCooler': cooler_points.append(point) if point[ 'PhysicsVolume'] == "BehaviorVolume'Ma_RightCluster_Combat.TheWorld:PersistentLevel.BehaviorVolume_6'": #print("set {} PhysicsVolume DefaultPhysicsVolume'Loader.TheWorld:PersistentLevel.DefaultPhysicsVolume_2'".format(point_name)) print( "set {} PopulationDef PopulationDefinition'GD_Ma_Population_Treasure.Lootables.BanditAmmo_Marigold'" .format(point_name)) print('Found {} coolers'.format(len(cooler_points))) print('') keys = {} for point in cooler_points: for key in point.keys():
#!/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)
import sys from ftexplorer.data import Data print(""" This doesn't actually work, btw. As far as I can tell, it *should* work, but no such luck. My theory is that all the vehicle-blocking stuff gets computed before the hotfix gets fired, so even though the parameter looks updated with an `obj dump`, it doesn't actually have an effect. Just a theory, though. Anyway, a command to diable ALL blocking meshes, which actually works, is: set Engine.BlockingMeshComponent bIsDisabled True """) data = Data('TPS') levelname = 'Deadsurface_P' print('Level hotfixes in {}'.format(levelname)) for (nodename, node) in data.get_level_package_nodes(levelname): for child in node.get_children_with_name('blockingmeshactor'): for meshchild in child.children.values(): full_obj = '{}.{}.{}'.format(nodename, child.name, meshchild.name) structure = meshchild.get_structure() if 'ScalarParameterValues' in structure: block_player = False block_vehicle = False vehicle_idx = -1 for (idx, param_value) in enumerate( structure['ScalarParameterValues']): if param_value['ParameterName'] == '"Players"':
'GD_Weap_Pistol.A_Weapons_Elemental.Pistol_Maliwan_2_Fire', 'GD_Weap_Pistol.A_Weapons_Unique.Pistol_Dahl_Starter', 'GD_Weap_SMG.A_Weapons_Unique.SMG_Gearbox_1', 'GD_Weap_SniperRifles.A_Weapons_Unique.Sniper_Gearbox_1', 'gd_cork_weap_assaultrifle.A_Weapons_Unique.AR_Starter_Vladof_Athena', # Boo, updated data packages don't like these now: 'GD_Cork_Weap_SniperRifles.A_Weapons_Unique.Sniper_Jakobs_3_Trespasser', 'GD_Weap_Pistol.A_Weapons_Unique.Pistol_Maliwan_3_Rubi', ]), } for game in ['BL2', 'TPS']: total_count = 0 total_count_no_luneshine = 0 data = Data(game) for baldef_name in sorted(data.get_all_by_type('WeaponBalanceDefinition')): # Don't process anything in the blacklist if baldef_name in blacklist[game]: continue baldef_struct = data.get_struct_by_full_object(baldef_name) partlist_name = Data.get_struct_attr_obj(baldef_struct, 'RuntimePartListCollection') if partlist_name: partlist = data.get_struct_by_full_object(partlist_name) # First get our CAID data caids = {} for (idx,
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: import sys import argparse from ftexplorer.data import Data data = Data('BL2') objects = [] objects.extend(data.get_all_by_type('AIBehaviorProviderDefinition')) objects.extend(data.get_all_by_type('BehaviorProviderDefinition')) found_event_names = {} for bpd_name in objects: bpd = data.get_node_by_full_object(bpd_name).get_structure() if 'BehaviorSequences' in bpd and bpd[ 'BehaviorSequences'] != 'None' and bpd['BehaviorSequences'] != '': for seq in bpd['BehaviorSequences']: if 'EventData2' in seq and seq['EventData2'] != 'None' and seq[ 'EventData2'] != '': for event in seq['EventData2']: if 'UserData' in event and event[ 'UserData'] != 'None' and event['UserData'] != '': event_name = event['UserData']['EventName'] if 'NPC' in event_name: if event_name not in found_event_names: found_event_names[event_name] = set() found_event_names[event_name].add(bpd_name)
# contained in *PartListCollectionDefinition objects, via ConsolidatedAttributeInitData # structures) available from the beginning of the game. The hotfixes just touch # the ConsolidatedAttributeInitData structure itself. Intended to be run from # ft-explorer's homedir, since we're using that to get some handy structured data for # the objects we're interested in. # # Note that ft-explorer does *not* give us any handy way to retrieve all objects by # type, so we're actually looping through a couple files and looking for object names # that way, which is a bit lame, but whatever. import re import sys import lzma from ftexplorer.data import Data 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()
for namepart_full in partdef[attr_name]: namepart_name = Data.get_attr_obj(namepart_full) namepart = data.get_struct_by_full_object(namepart_name) if 'PartName' in namepart and namepart['PartName'] != '': names.add(namepart['PartName']) if get_customs: customs |= get_presentations(data, namepart) if get_customs: return (list(names), list(customs)) else: return list(names) for game in games: data = Data(game) # Weapons if True: for baldef_name in sorted( data.get_all_by_type('WeaponBalanceDefinition')): # Don't process anything in the blacklist if baldef_name in blacklist[game]: continue baldef_struct = data.get_struct_by_full_object(baldef_name) try: partlist = data.get_struct_attr_obj_real( baldef_struct, 'RuntimePartListCollection') except KeyError:
man_num, )) grenade_unlock_list.append( 'level None set GD_GrenadeMods.A_Item.GM_{}_4_VeryRare Manufacturers[{}].Grades[0].GameStageRequirement.MinGameStage 0' .format( gm_type, man_num, )) prefix = ' ' * (4 * 2) grenade_unlock = "\n\n".join( ['{}{}'.format(prefix, s) for s in grenade_unlock_list]) # Generate an exhaustive list of part unlocks, using my ft-explorer # data introspection routines. exhaustive_unlocks_list = [] data = Data('TPS') classnames = sorted( data.get_all_by_type('WeaponPartListCollectionDefinition') + data.get_all_by_type('ItemPartListCollectionDefinition'), key=str.lower) for classname in classnames: obj_struct = data.get_struct_by_full_object(classname) if 'ConsolidatedAttributeInitData' not in obj_struct: # Should maybe keep track of which of these doesn't have it... continue # Figure out our caid values caid = obj_struct['ConsolidatedAttributeInitData'] caid_values = [] for caid_val in caid:
def print_title(bal_name): try: bal_struct = data.get_struct_by_full_object(bal_name) if 'ItemName' in bal_struct: top_level = 'ItemName' elif 'RuntimePartListCollection' in bal_struct: top_level = 'RuntimePartListCollection' elif 'PartListCollection' in bal_struct: top_level = 'PartListCollection' else: raise Exception('Unknown top-level attribute') if bal_struct[top_level] == 'None': # This should match on shields if 'InventoryDefinition' in bal_struct: inv_def = data.get_struct_attr_obj_real( bal_struct, 'InventoryDefinition') if 'TitleList' in inv_def: for title_def in inv_def['TitleList']: title = data.get_struct_by_full_object( Data.get_attr_obj(title_def)) print(title['PartName']) else: for partlist_name in [ 'AlphaParts', 'BetaParts', 'GammaParts', 'DeltaParts' ]: if partlist_name in inv_def and inv_def[ partlist_name] != 'None': partlist = data.get_struct_attr_obj_real( inv_def, partlist_name) title_from_partdef(data, partlist) #elif 'AlphaParts' in inv_def: # #print(inv_def) # #title_from_partdef(data, inv_def, 'AlphaParts') #else: # raise Exception('No mid-level attribute found') else: raise Exception('Exhausted possible top-level attributes') else: # This should match on weapons, relics, and grenade mods if top_level == 'ItemName': # This'll match on relics print(bal_struct['ItemName']) else: # Weapons and grenade mods partlist = data.get_struct_attr_obj_real(bal_struct, top_level) if 'BarrelPartData' in partlist: to_get = 'BarrelPartData' elif 'AlphaPartData' in partlist: to_get = 'AlphaPartData' else: raise Exception('No understood part type found') title_from_partdef(data, partlist[to_get]) except Exception as e: (ex_type, ex_val, ex_tb) = sys.exc_info() print('Error getting title: {}: {}'.format(ex_type.__name__, e)) print('') traceback.print_exception(*sys.exc_info(), file=sys.stderr)
'GD_Weap_SMG.A_Weapons_Unique.SMG_Maliwan_3_Frostfire', 'GD_Weap_SniperRifles.A_Weapons_Unique.Sniper_Hyperion_3_FremingtonsEdge', ] # Some weapons get a pass because they have custom Luneshine attachments # (or, in some cases, are glitch guns) weap_exclude = set([ 'GD_Cork_Weap_SMG.A_Weapons_Unique.SMG_Bandit_3_MareksMouth', 'GD_Ma_Weapons.A_Weapons_Unique.Laser_Dahl_6_Glitch_HeartfullSplodger', 'GD_Ma_Weapons.A_Weapons_Unique.SMG_Bandit_6_Glitch_CutieKiller', '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:
# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL CJ KUCERA BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import sys from ftexplorer.data import Data data = Data('BL2') for (name, streaming_obj, player_obj) in [ ('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'), ]:
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: from ftexplorer.data import Data # Attempts to find some cases where we might have a BPD -> Seq -> BPD link. # *shudder* data = Data('BL2') # First gather our BPD EventName mappings print('Gathering BPD EventName mappings') bpd_events = {} events_bpd = {} for bpd_name in sorted(data.get_all_by_type('BehaviorProviderDefinition')): bpd_events[bpd_name.lower()] = set() bpd_struct = data.get_struct_by_full_object(bpd_name) if 'BehaviorSequences' in bpd_struct and bpd_struct[ 'BehaviorSequences'] != '': for seq in bpd_struct['BehaviorSequences']: if 'EventData2' in seq and seq['EventData2'] != '': for event in seq['EventData2']: event_name = event['UserData']['EventName'].replace( '"', '') if event_name.lower() not in events_bpd: events_bpd[event_name.lower()] = set() events_bpd[event_name.lower()].add(bpd_name.lower()) bpd_events[bpd_name.lower()].add(event_name.lower()) # Now gather our Kismet EventName mappings print('Gathering Kismet EventName mappings')
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: import sys import traceback from ftexplorer.data import Data print('Note: this does not find class mod titles, which have') print('parts like weapons/grenades but whose titles are found') print('via their InventoryDefinition instead.') print('') data = Data('BL2') def title_from_partdef(data, partlist): for part_def in partlist['WeightedParts']: part = data.get_struct_attr_obj_real(part_def, 'Part') if part: if 'TitleList' in part: for title_def in part['TitleList']: title = data.get_struct_by_full_object( Data.get_attr_obj(title_def)) print(title['PartName']) else: raise Exception('No definitions!') def print_title(bal_name): try: bal_struct = data.get_struct_by_full_object(bal_name)
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: import sys from ftexplorer.data import Data data = Data('BL2') baldef_names = data.get_all_by_type('InventoryBalanceDefinition') + \ data.get_all_by_type('WeaponBalanceDefinition') for baldef_name in sorted(baldef_names): baldef = data.get_struct_by_full_object(baldef_name) if ('Manufacturers' in baldef and baldef['Manufacturers'] is not None and baldef['Manufacturers'] != ''): for (man_idx, man) in enumerate(baldef['Manufacturers']): if ('Grades' in man and man['Grades'] is not None and man['Grades'] != ''): for (grade_idx, grade) in enumerate(man['Grades']): if ('GameStageRequirement' in grade and grade['GameStageRequirement'] is not None and grade['GameStageRequirement'] != ''): req = grade['GameStageRequirement'] min_stage = req['MinGameStage'] if int(min_stage) > 1: print( 'set {} Manufacturers[{}].Grades[{}].GameStageRequirement.MinGameStage 1' .format( baldef_name, man_idx, grade_idx, ))
('Winged Storm', 'DungeonRaid_P'), ('Raid on Digistruct Peak', 'TestingZone_P'), ('Hallowed Hollow', 'Pumpkin_Patch_P'), ('Gluttony Gulch', 'Hunger_P'), ('Marcus\'s Mercenary Shop', 'Xmas_P'), ('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('they exist here as well, and actually you\'ll also need data for') print( 'FastTravelStationDefinition objects imported into FT/BLCMM Explorer') print('as well, which will be a hassle if you\'re Not Me. Sorry for the') print('bother!') print( '********************************************************************') print('') sys.exit(1) # Control Vars mod_name = 'BL2 Sorted Fast Travel' mod_version = '1.0.1' output_filename = '{}.blcm'.format(mod_name) data = Data('BL2') ftdefs = data.get_all_by_type('FastTravelStationDefinition') if len(ftdefs) == 0: raise Exception( 'No FastTravelStationDefinitions found! FT/BLCMM Explorer does not have those by default...' ) # Construct the mod lines = [] lines.append('BL2') lines.append('#<{}>'.format(mod_name)) lines.append('') lines.append(' # {} v{}'.format(mod_name, mod_version)) lines.append(' # by Apocalyptech') lines.append(' # Licensed under Public Domain / CC0 1.0 Universal') lines.append(' #')
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: # For Our Lord, &c. 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('')
sys.exit(1) ### ### Output variables ### mod_name = 'TPS Skinpool Reassignments' 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
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: import re from ftexplorer.data import Data patchfile = '/home/pez/git/b2patching/BLCMods/Borderlands 2 mods/Shadowevil/Patch.txt' start_stop_str = "Skinpool Fixes (Don't uncheck this)" extra_stop_str = 'VendorFix' data = Data('BL2') pool_cache = {} from_values = {} to_values = {} freed_pools = set() # One hard-coded pool which is freed up in a slightly different way than # everything else freed_pools.add('GD_ItemPools_Shop.WeaponPools.Shoppool_FeaturedItem_WeaponMachine_Skins') with open(patchfile) as df: processing = False for line in df.readlines(): if processing: if start_stop_str in line or extra_stop_str in line: processing = False else: line = line.strip() if line == '':
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: from ftexplorer.data import Data def get_twos_compliment(val): val = int(val) one = val >> 16 two = val & 0xFF return (one, two) data = Data('BL2') for obj_name in sorted(data.get_all_by_type('InteractiveObjectDefinition')): obj_struct = data.get_struct_by_full_object(obj_name) bpd_name = Data.get_struct_attr_obj(obj_struct, 'BehaviorProviderDefinition') shown_title = False if bpd_name: bpd_node = data.get_node_by_full_object(bpd_name) # Output a statement to ensure that attached items are immediately # available children = list( bpd_node.get_children_with_name('behavior_attachitems')) if len(children) > 1: print('{}: {}'.format(bpd_name, len(children)))
import sys from ftexplorer.data import Data # Pools we're using #data = Data('TPS') #pools = [ # ('Shields', 'shield'), # ('All Weapons', 'all'), # ('AR-Weighted', 'ar'), # ('Launchers Only', 'launcher'), # ('Shotguns Only', 'shotgun'), # ('Snipers Only', 'sniper'), # ('Lasers Only', 'laser_only'), # ('Laser-Weighted', 'laser'), # ] data = Data('BL2') pools = [ ('AR-Weighted', 'ar'), ('Pistol-Weighted', 'pistols'), ('Shotgun-Weighted', 'shotguns'), ('SMG-Weighted', 'smg'), ('All Weapons', 'all'), ('Launchers Only', 'launchers'), ('Snipers Only', 'snipers'), ('Shotguns Only', 'only_shotguns'), ('ARs Only', 'only_ar'), ('Shields', 'shields'), ] # Read in categories categories = {}
#!/usr/bin/env python # vim: set expandtab tabstop=4 shiftwidth=4: import sys from ftexplorer.data import Data data = Data('TPS') bpd_name = 'GD_DahlFanatic.Character.AIDef_DahlFanatic:AIBehaviorProviderDefinition_0' def compliment(number): """ Returns a two's-compliment tuple for the given number. """ number = int(number) one = (number >> 16) two = (number & 0xFF) return (one, two) def follow(link, cold_data, behavior_data, prefix=''): (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'],
print('') sys.exit(1) ### ### Output variables ### mod_name = 'TPS Skinpool Reassignments' 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("'")