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 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 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)
# 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(): if type(point[key]) == str:
'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, caid) in enumerate(partlist['ConsolidatedAttributeInitData']): caids[idx] = Weight(caid).value # Now loop through gun_types = 1 gun_types_no_luneshine = 1 for attr in [ 'BodyPartData', 'GripPartData', 'BarrelPartData', 'SightPartData', 'StockPartData', 'ElementalPartData',
#!/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)))
def get_twos_compliment(val): val = int(val) one = val >> 16 two = val & 0xFF return (one, two) found_trees = set() bpd_stmts = [] disable_stmts = [] 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') if bpd_name: bpd_node = data.get_node_by_full_object(bpd_name) # Remove any delay if we have an immediate AttachItems behavior after # an Event. This may or may not catch everything. bpd_struct = bpd_node.get_structure() for seq_idx, seq in enumerate(bpd_struct['BehaviorSequences']): for cold_idx, cold in enumerate(seq['ConsolidatedOutputLinkData']): if float(cold['ActivateDelay']) > 0: bpd_stmts.append( 'set {} BehaviorSequences[{}].ConsolidatedOutputLinkData[{}].ActivateDelay {}' .format( bpd_name, seq_idx, cold_idx,
) print( "It *does* disable everything BUT the specified popdef, but the other mixes just" ) print("generate no enemies at all. Hrmph.") data = Data('BL2') popdef_name = 'GD_Population_Midget.Balance.PawnBalance_MidgetShotgun' aidef_name = 'GD_AI_DenDef.AIDenDef_Bandits' level_name = 'SouthernShelf_P' mixes = set() for (package_name, package) in data.get_level_package_nodes(level_name): for child in package: if child.name.startswith('PopulationOpportunityDen'): mix_name = Data.get_struct_attr_obj(child.get_structure(), 'PopulationDef') if mix_name: mixes.add(mix_name) for mix_name in mixes: print("set {} AIDef WillowAIDenDefinition'{}'".format( mix_name, aidef_name)) mix = data.get_struct_by_full_object(mix_name) for (aal_idx, aal) in enumerate(mix['ActorArchetypeList']): if aal_idx == 0: sf_name = Data.get_struct_attr_obj(aal, 'SpawnFactory') print("set {} PawnBalanceDefinition AIPawnBalanceDefinition'{}'". format(sf_name, popdef_name)) print( "set {} ActorArchetypeList[0].Probability (BaseValueConstant=1,BaseValueAttribute=None,InitializationDefinition=None,BaseValueScaleConstant=1)" .format(mix_name))
else: raise Exception('Not sure what to do: {}'.format(spawnfactory_name)) popdef_cache[popdef_name] = popdef_set return popdef_set pawnbalance_cache = {} for (level_label, level_name) in levels: # Loop through level to get a list of all popdefs popdefs = set() for (nodename, node) in data.get_level_package_nodes(level_name): for child in node.get_children_with_name('populationopportunityden'): child_struct = child.get_structure() popdef = Data.get_struct_attr_obj(child_struct, 'PopulationDef') if popdef: popdefs.add(popdef) # 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)
# Given the specified popdefs, make them practically guaranteed in # any mix that they happen to belong to. popdef_names = set([ #'GD_Population_Engineer.Balance.PawnBalance_HyperionHawk', #'GD_Population_Midget.Balance.PawnBalance_MidgetRat', #'GD_Allium_PsychoSnow_Midget.Balance.PawnBalance_PsychoSnow_Midget', #'GD_Population_Marauder.Balance.PawnBalance_MarauderGrunt', #'GD_Population_Marauder.Balance.PawnBalance_MarauderIntro', #'GD_Population_Midget.Balance.PawnBalance_MidgetShotgun', #'GD_Population_Nomad.Balance.PawnBalance_NomadPyro', #'GD_Aster_Pop_Knights.Balance.PawnBalance_Knight_Paladin', 'GD_Population_SpiderAnt.Balance.PawnBalance_SpiderantChubby', #'GD_Population_PrimalBeast.Population.Unique.PopDef_PrimalBeast_KingMong', ]) wpd_cache = {} for pfbap_name in data.get_all_by_type('PopulationFactoryBalancedAIPawn'): pfbap = data.get_struct_by_full_object(pfbap_name) pawn_name = Data.get_struct_attr_obj(pfbap, 'PawnBalanceDefinition') if pawn_name in popdef_names: (mix_name, junk) = pfbap_name.split(':', 1) if mix_name not in wpd_cache: wpd_cache[mix_name] = data.get_struct_by_full_object(mix_name) for (aal_idx, aal) in enumerate(wpd_cache[mix_name]['ActorArchetypeList']): sf_name = Data.get_struct_attr_obj(aal, 'SpawnFactory') if sf_name == pfbap_name: print('set {} ActorArchetypeList[{}].Probability (BaseValueConstant=200000,BaseValueAttribute=None,InitializationDefinition=None,BaseValueScaleConstant=1)'.format( mix_name, aal_idx ))
# 'GD_CustomItemPools_crocus.Rewards.Pandoracorn', # 'GD_CustomItemPools_MainGame.Rewards.Borderlands1Skin', # 'GD_CustomItemPools_MainGame.Rewards.DigitalEdSkins', # 'GD_CustomItemPools_MainGame.Rewards.Gearbox', # 'GD_CustomItemPools_MainGame.Rewards.Gray', # 'GD_CustomItemPools_Marigold.Rewards.CypressHead01', # 'GD_CustomItemPools_Marigold.Rewards.CypressSkin01', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldHead07', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldHead08', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldHeadBoss', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldSkin06', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldSkin07', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldSkin11', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldSkin12', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldSkin13', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldSkin14', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldSkin15', # 'GD_CustomItemPools_Marigold.Rewards.MarigoldSkin16', # ] ##reward_pools = reward_pools_challenges + reward_pools_missions ##reward_pools = reward_pools_challenges ##reward_pools = reward_pools_missions #reward_pools = safe_pools #data = Data('TPS') for pool in reward_pools: pool_struct = data.get_node_by_full_object(pool).get_structure() for item in pool_struct['BalancedItems']: innerpool = Data.get_struct_attr_obj(item, 'ItmPoolDefinition') print(innerpool)
print('{}:'.format(parttype)) for part in sorted(part_list): print(part) print('') # Get barrel effects barrel = data.get_struct_attr_obj_real( plc['BarrelPartData']['WeightedParts'][0], 'Part') if 'WeaponAttributeEffects' in barrel and barrel[ 'WeaponAttributeEffects'] != 'None': print('Weapon Attribute Effects:') print('') for effect in barrel['WeaponAttributeEffects']: print(' * {} - {} - {},{},{},{}'.format( Data.get_struct_attr_obj(effect, 'AttributeToModify'), effect['ModifierType'], effect['BaseModifierValue']['BaseValueConstant'], effect['BaseModifierValue']['BaseValueAttribute'], effect['BaseModifierValue']['InitializationDefinition'], effect['BaseModifierValue']['BaseValueScaleConstant'], )) print('') if 'AttributeSlotUpgrades' in barrel and barrel[ 'AttributeSlotUpgrades'] != 'None': print('Weapon Attribute Slot Upgrades:') print('') for upgrade in barrel['AttributeSlotUpgrades']: print(' * {}: {}'.format( upgrade['SlotName'],
pawns = set([ 'GD_Population_Marauder.Balance.PawnBalance_MarauderElite', 'GD_Population_Marauder.Balance.PawnBalance_MarauderRegular', 'GD_Population_Marauder.Balance.PawnBalance_Scavenger', 'GD_Population_Midget.Balance.PawnBalance_MidgetShotgun' ]) commands = [] for popdef_name in popdefs: reported = False popdef = data.get_struct_by_full_object(popdef_name) for (archetype_idx, archetype) in enumerate(popdef['ActorArchetypeList']): prob = Weight(archetype['Probability']) if prob.value > 0: factory_name = Data.get_struct_attr_obj(archetype, 'SpawnFactory') factory = data.get_struct_by_full_object(factory_name) pawn_name = Data.get_struct_attr_obj(factory, 'PawnBalanceDefinition') if pawn_name in pawns: if not reported: print(popdef_name) reported = True print(' * [{}] {} @ {}'.format(archetype_idx, pawn_name, prob.value)) commands.append("""set {} ActorArchetypeList[{}].Probability ( BaseValueConstant=200000, BaseValueAttribute=None, InitializationDefinition=None, BaseValueScaleConstant=1 )""".format(popdef_name, archetype_idx))
shield_loc = 'PlayThroughs[0]' if not has_shields and 'DefaultItemPoolList' in baldef: (has_shields, shield_prob) = find_has_shields(baldef['DefaultItemPoolList']) if has_shields: if has_cipl: shield_loc = 'DIPL (but CIPL clears?)' else: shield_loc = 'DIPL' # Don't bother processing if there's no shields if not has_shields: continue # Now dig down to see if we can find health modifiers archetype_name = Data.get_struct_attr_obj(baldef, 'AIPawnArchetype') if not archetype_name: print('WARNING: No archetype name for {} ({})'.format( pawn_name, classname)) continue archetype = data.get_struct_by_full_object(archetype_name) aiclass_name = Data.get_struct_attr_obj(archetype, 'AIClass') if not aiclass_name: print('WARNING: No AIClass name for {}'.format(archetype_name)) continue aiclass = data.get_struct_by_full_object(aiclass_name) health_modifier = None if ('AttributeStartingValues' in aiclass and aiclass['AttributeStartingValues'] != None and aiclass['AttributeStartingValues'] != ''): for value in aiclass['AttributeStartingValues']:
#!/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))
for game in games: data = Data(game) # Weapons if False: 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 status('Processing {}'.format(baldef_name)) baldef_struct = data.get_struct_by_full_object(baldef_name) partlist_name = Data.get_struct_attr_obj( baldef_struct, 'RuntimePartListCollection') if partlist_name: process_weapon_part_list(data, df, partlist_name, [ 'BodyPartData', 'GripPartData', 'BarrelPartData', 'SightPartData', 'StockPartData', 'ElementalPartData', 'Accessory1PartData', 'Accessory2PartData', ]) # Items if True: found_invalid_invdef_types = set()