예제 #1
0
#!/usr/bin/env python
# vim: set expandtab tabstop=4 shiftwidth=4:

import struct
from ftexplorer.data import Data

for game in ['BL2', 'TPS']:
    linkids = {}
    data = Data(game)
    bpd_names = []
    bpd_names.extend(data.get_all_by_type('BehaviorProviderDefinition'))
    bpd_names.extend(data.get_all_by_type('AIBehaviorProviderDefinition'))
    for bpd_name in sorted(bpd_names):
        bpd = data.get_struct_by_full_object(bpd_name)
        for bs_idx, bs in enumerate(bpd['BehaviorSequences']):
            for cold_idx, cold in enumerate(bs['ConsolidatedOutputLinkData']):
                link = int(cold['LinkIdAndLinkedBehavior'])
                packed = struct.pack('>i', link)
                linkid = packed[0]
                if packed[1] != 0:
                    print(
                        '{} BehaviorSequences[{}].ConsolidatedOutputLinkData[{}] - {} second byte is: {}'
                        .format(
                            bpd_name,
                            bs_idx,
                            cold_idx,
                            link,
                            packed[1],
                        ))
                if linkid == 255:
                    linkid = -1
# 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')
kismet_events = {}
예제 #3
0
#!/usr/bin/env python
# vim: set expandtab tabstop=4 shiftwidth=4:

# Trying to find references to D_Attributes.Balance.PlayThroughCount inside
# AttributeInitializationDefinition objects which reference something other
# than 1 and 2.

from ftexplorer.data import Data, Weight

data = Data('BL2')

for aid_name in sorted(
        data.get_all_by_type('AttributeInitializationDefinition')):
    aid = data.get_struct_by_full_object(aid_name)
    ci = aid['ConditionalInitialization']
    if ci['bEnabled'] == 'True':
        for ce in ci['ConditionalExpressionList']:
            for exp in ce['Expressions']:
                if 'PlayThroughCount' in exp['AttributeOperand1']:
                    numval = float(exp['ConstantOperand2'])
                    if numval != 1 and numval != 2:
                        print('{}: {}'.format(aid_name, numval))
                    elif numval == 2:
                        print('{} - 2'.format(aid_name))
예제 #4
0
#!/usr/bin/env python
# vim: set expandtab tabstop=4 shiftwidth=4:

from ftexplorer.data import Data

data = Data('BL2')
for gbdef in data.get_all_by_type('GameBalanceDefinition'):
    gb = data.get_struct_by_full_object(gbdef)
    if 'BalanceByRegion' in gb:
        for (balidx, bal) in enumerate(gb['BalanceByRegion']):
            print('set {} BalanceByRegion[{}].MaxDefaultGameStage.BaseValueConstant 80'.format(
                gbdef, balidx,
                ))
            if 'MissionOverrides' in bal and bal['MissionOverrides'] is not None and bal['MissionOverrides'] != '' and bal['MissionOverrides'] != 'None':
                for (overidx, over) in enumerate(bal['MissionOverrides']):
                    print('set {} BalanceByRegion[{}].MissionOverrides[{}].MaxGameStage.BaseValueConstant 80'.format(
                        gbdef, balidx, overidx,
                        ))
예제 #5
0
                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:
        caid_values.append(float(caid_val['BaseValueConstant']))

    # Now loop through all our items.
    caid_updates = set()
    for key, val in obj_struct.items():
        if key[-8:] == 'PartData':
예제 #6
0
def find_has_shields(poollist):
    if poollist is None or poollist == '':
        return (False, None)
    for pool in poollist:
        if 'Pool_Shields_Standard_EnemyUse' in pool['ItemPool']:
            shieldweight = Weight(pool['PoolProbability'])
            if shieldweight.value > 0:
                return (True, shieldweight.value)
    return (False, None)


data = Data('TPS')
for classname in data.get_all_by_type('AIPawnBalanceDefinition'):

    # Get BalDef
    baldef = data.get_struct_by_full_object(classname)
    try:
        pawn_name = baldef['PlayThroughs'][0]['DisplayName']
    except KeyError as e:
        #print('WARNING: No PlayThroughs for {}'.format(classname))
        pawn_name = '(unknown)'

    # Find out if this enemy has a chance to use shields
    has_shields = False
    shield_loc = None
    shield_prob = None
    has_cipl = False
    if ('PlayThroughs' in baldef and baldef['PlayThroughs'] is not None
            and baldef['PlayThroughs'] != ''):
        if (len(baldef['PlayThroughs']) > 0
                and 'CustomItemPoolList' in baldef['PlayThroughs'][0]
예제 #7
0
        if self.phaselock_time is None:
            data.append('')
        else:
            data.append(self.phaselock_time)
        data.extend(self.fire.get_data())
        data.extend(self.corrosive.get_data())
        data.extend(self.shock.get_data())
        data.extend(self.slag.get_data())
        return data

startvals = {}
ret_list = []
shown_header = False
writer = csv.writer(sys.stdout)
for pawnbal_name in sorted(data.get_all_by_type('AIPawnBalanceDefinition')):
    pawnbal = data.get_struct_by_full_object(pawnbal_name)
    if 'PlayThroughs' in pawnbal:
        aipawn = data.get_struct_attr_obj_real(pawnbal, 'AIPawnArchetype')
        allegiance = Data.get_attr_obj(aipawn['Allegiance'])
        if allegiance not in friendly_allegiances:
            aiclass_name = Data.get_attr_obj(aipawn['AIClass'])
            aiclass = data.get_struct_attr_obj_real(aipawn, 'AIClass')

            # Loop through all playthroughs to gather stats
            pawn_stats = []
            for (idx, pt) in enumerate(pawnbal['PlayThroughs']):
                display_name = get_display_name(pt['DisplayName'])
                pawn_stats.append(AttributeSet(display_name, pawnbal_name, idx+1, pawnbal, aiclass))

            # Loop through playthroughs one more time to combine any playthroughs
            # which have identical data (this could probably be done in the
예제 #8
0
#!/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():
# 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
                    ))
예제 #10
0
# somehow, which only exists for Sal and Zer0, I believe.

# Data types here were chosen just by searching for WillowGame.WillowDmgSource_Skill

print('Classes which appear to cause *only* Skill damage:')
print('')

data = Data('BL2')
found_types = set()
names = data.get_all_by_type('Behavior_CauseDamage')
names.extend(data.get_all_by_type('Behavior_FireBeam'))
names.extend(data.get_all_by_type('MeleeDefinition'))
names.extend(data.get_all_by_type('WillowDamageArea'))

for cd_name in names:
    cd = data.get_struct_by_full_object(cd_name)
    if 'WillowGame.WillowDmgSource_Skill' in cd['DamageSource']:
        if cd['DamageTypeDefinition'] == 'None':
            print(' * {}'.format(cd_name))
        else:
            found_types.add(cd['DamageTypeDefinition'])

for exp_name in data.get_all_by_type('Behavior_Explode'):
    exp = data.get_struct_by_full_object(exp_name)
    if 'WillowGame.WillowDmgSource_Skill' in exp['DamageSource']:
        expdef = data.get_struct_attr_obj_real(exp, 'Definition')
        if expdef['DamageTypeDef'] == 'None':
            print(' * {}'.format(exp_name))
        else:
            found_types.add(expdef['DamageTypeDef'])
예제 #11
0
# vim: set expandtab tabstop=4 shiftwidth=4:

import sys
from ftexplorer.data import Data

print('This is just used to compare some basic info between versions')
print('of guns.  Only prints out some real basic info, does not include')
print('things like firing mode definitions, BPDs, etc...')
print('')
print(sys.argv[1])
print('-' * len(sys.argv[1]))
print('')

data = Data('BL2')

bal = data.get_struct_by_full_object(sys.argv[1])
plc = data.get_struct_attr_obj_real(bal, 'RuntimePartListCollection')

for parttype in [
        'Body', 'Grip', 'Barrel', 'Sight', 'Stock', 'Elemental', 'Accessory1'
]:
    part_list = []
    for pd in plc['{}PartData'.format(parttype)]['WeightedParts']:
        part_list.append(' * {}'.format(pd['Part'].split("'")[1]))

    print('{}:'.format(parttype))
    for part in sorted(part_list):
        print(part)
    print('')

# Get barrel effects
예제 #12
0
        'GD_Population_Psycho.Population.PopDef_Psycho',
        'GD_Population_Psycho.Population.PopDef_PsychoBurning',
        'GD_Population_Psycho.Population.PopDef_PsychoSuicide',
    ]
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, 
예제 #13
0
# Finding all AttributeStartingValues attributes in use by game pawns.

asvs = set()


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)


data = Data('TPS')
for classdef_name in data.get_all_by_type('AIClassDefinition'):
    get_asvs(data.get_struct_by_full_object(classdef_name), asvs)
for pawnbal_name in data.get_all_by_type('AIPawnBalanceDefinition'):
    pawnbal = data.get_struct_by_full_object(pawnbal_name)
    if 'PlayThroughs' in pawnbal and pawnbal['PlayThroughs'] != '' and pawnbal[
            'PlayThroughs'] != 'None':
        for pt in pawnbal['PlayThroughs']:
            get_asvs(pt, asvs)

print('ASVs found:')
print('')
for asv in sorted(asvs):
    print(asv)
print('')
예제 #14
0
#!/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)))
예제 #15
0
#!/usr/bin/env python
# vim: set expandtab tabstop=4 shiftwidth=4:

import sys
from ftexplorer.data import Data

game = sys.argv[1]
obj = sys.argv[2]

data = Data(game.upper())
val = data.get_struct_by_full_object(obj)
print(val)

예제 #16
0
        '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,
                 caid) in enumerate(partlist['ConsolidatedAttributeInitData']):
                caids[idx] = Weight(caid).value

            # Now loop through
            gun_types = 1
            gun_types_no_luneshine = 1
            for attr in [
예제 #17
0
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:
            print(
                "set {} ActorArchetypeList[{}].Probability (BaseValueConstant=0,BaseValueAttribute=None,InitializationDefinition=None,BaseValueScaleConstant=0)"
                .format(mix_name, aal_idx))
예제 #18
0
lines.append(
    '    # the prefix "The" from all fast travel names, so they also sort')
lines.append('    # *correctly.*')
lines.append('')
lines.append('    #<Alphabetical By Default>')
lines.append('')
lines.append(
    '        # Many thanks to Our Lord and Savior Gabe Newell for this!')
lines.append('')
lines.append('        set FastTravelStationGFxMovie SortMode 1')
lines.append('')
lines.append('    #</Alphabetical By Default>')
lines.append('')
lines.append('    #<Remove Level Prefixes>')
lines.append('')
for ftdef in ftdefs:
    ft = data.get_struct_by_full_object(ftdef)
    if ft['StationDisplayName'].startswith('The '):
        lines.append('        set {} StationDisplayName {}'.format(
            ftdef,
            ft['StationDisplayName'][4:],
        ))
        lines.append('')
lines.append('    #</Remove Level Prefixes>')
lines.append('')
lines.append('#</{}>'.format(mod_name))

# Write out to the file
mp.human_str_to_blcm_filename("\n".join(lines), output_filename)
print('Wrote mod to {}'.format(output_filename))

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,
예제 #20
0

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:
                partlist = data.get_struct_attr_obj_real(
                    baldef_struct, 'WeaponPartListCollection')
            # Only really interested in the Barrel, since I'm after red-text guns.
            for part_dict in partlist['BarrelPartData']['WeightedParts']:
                partdef = data.get_struct_attr_obj_real(part_dict, 'Part')
                prefixes = get_names(data, partdef, 'PrefixList')
                (names, customs) = get_names(data,
                                             partdef,
                                             'TitleList',
                                             get_customs=True)
                if len(prefixes) == 0:
예제 #21
0
#!/usr/bin/env python
# vim: set expandtab tabstop=4 shiftwidth=4:

import struct
from ftexplorer.data import Data

data = Data('BL2')

#bpd = data.get_struct_by_full_object('GD_ButtStallion_Proto.Character.AIDef_ButtStallion_Proto:AIBehaviorProviderDefinition_1')
bpd = data.get_struct_by_full_object(
    'gd_slotmachine.SlotMachine:BehaviorProviderDefinition_0')
behavior_linkids = {}
for idx, cold in enumerate(
        bpd['BehaviorSequences'][1]['ConsolidatedOutputLinkData']):
    compliment = int(cold['LinkIdAndLinkedBehavior'])
    # Use big-endian just for clarity's sake
    packed = struct.pack('>i', compliment)
    #print('{:08b} {:08b} {:08b} {:08b}'.format(packed[0], packed[1], packed[2], packed[3]))
    #linkid = compliment >> 16
    #linkid = compliment >> 24
    linkid = packed[0]
    behavior = compliment & 0xFF
    if behavior not in behavior_linkids:
        behavior_linkids[behavior] = {}
    if linkid not in behavior_linkids[behavior]:
        behavior_linkids[behavior][linkid] = 1
    else:
        behavior_linkids[behavior][linkid] += 1
    print('[{:3d}] {:9d} ({:08b} {:08b} {:08b} {:08b}): {}, {}'.format(
        idx, compliment, packed[0], packed[1], packed[2], packed[3], linkid,
        behavior))