示例#1
0
        [
            "Pendant of Terramorphous is an Artifact which is in the BL3 data but",
            "was apparently cut sometime before release.  This sets it as a valid",
            "legendary Artifact drop.  It also increases the health regen rate from",
            "the 'default' (which is *extremely* weak, presumably before any balancing",
            "attempts had been made) to something which feels somewhat reasonable.",
        ],
        lic=Mod.CC_BY_SA_40,
        )

art_bal_name = '/Game/Gear/Artifacts/_Design/BalanceDefs/InvBalD_Artifact_05_Legendary'
cat_idx = 1
terra_part = '/Game/Gear/Artifacts/_Design/PartSets/Abilities/_Legendary/Misc/PendantOfTerramorphous/Artifact_Part_Ability_PendantOfTerramorphous'

# Add the part
mod.comment('Set as a valid drop')
data = BL3Data()
art_bal = Balance.from_data(data, art_bal_name)
cat = art_bal.categories[cat_idx]
if len(cat) != 14:
    raise Exception('Expected to find a category with fourteen parts!')
cat.add_part_name(terra_part, 1)
art_bal.hotfix_balance_full(mod)
mod.newline()

# Now buff up its health regen rate -- the default is really anemic (presumably it
# was scrapped before they got around to looking at balancing it).  Default value
# is `0.001`.
mod.comment('Buff health regen')
mod.table_hotfix(Mod.PATCH, '',
        '/Game/Gear/Artifacts/_Design/Balance/Table_Artifact_Abilities2',
示例#2
0
        # Defaults vary depending on pool; for base-game it's 0.5%.
        # Tends to be higher for DLCs, I believe.
        mod.reg_hotfix(Mod.CHAR, 'MatchAll', pool,
                       'ItemPools[{}].PoolProbability'.format(index),
                       BVCF(bvc=rate))

    mod.newline()

    # Some extra things to do if we're disabling entirely.
    if rate == 0:

        # TODO: Still getting some cosmetic drops in DLC2, maybe from badasses?

        mod.header('Remove cosmetics from containers')

        mod.comment('Regular container ItemPools')
        for pool, index in [
            ('/Game/GameData/Loot/ItemPools/ItemPool_ChestFlaps', 5),
            ('/Game/GameData/Loot/ItemPools/ItemPool_RedChestFlaps', 4),
            ('/Game/GameData/Loot/ItemPools/ItemPool_Shields_Skins_Artifacts_GrenadeMods_ClassMods_Deco',
             4),
            ('/Game/GameData/Loot/ItemPools/ItemPool_Shields_Skins_Artifacts_GrenadeMods_ClassMods_Deco',
             5),
            ('/Game/GameData/Loot/ItemPools/ItemPool_Shields_Skins_Artifacts_GrenadeMods_ClassMods_Deco',
             6),
            ('/Game/GameData/Loot/ItemPools/ItemPool_Shields_Skins_Artifacts_GrenadeMods_ClassMods_Deco',
             7),
        ]:
            mod.reg_hotfix(
                Mod.PATCH, '', pool,
                'BalancedItems.BalancedItems[{}].Weight.BaseValueScale'.format(
示例#3
0
     0.001),
    ('/Game/GameData/Weapons/Att_Weapon_RecoilWidthScale', 'ScaleSimple',
     0.001),
]:

    last_part = attr.split('/')[-1]
    full_attr = '{}.{}'.format(attr, last_part)

    attr_effects.append(f"""(
        AttributeToModify=GbxAttributeData'"{full_attr}"',
        ModifierType={mod_type},
        ModifierValue=(BaseValueConstant={mod_val})
    )""")

# Apply all our custom effects
mod.comment('Custom Effects')
mod.reg_hotfix(
    Mod.PATCH,
    '',
    '/Game/PatchDLC/Raid1/Re-Engagement/Weapons/CraderMP5/Parts/Part_SM_DAL_Barrel_CraderMP5',
    'InventoryAttributeEffects',
    '({})'.format(','.join(attr_effects)),
)
mod.newline()

# Also buff movement speed increase.  Stock: 0.25
# No longer doing this, since I figured out a real movement speed mod.
#mod.table_hotfix(Mod.PATCH, '',
#        '/Game/PatchDLC/Raid1/Re-Engagement/Balance/DataTable_ReEngagement1_Weapons.DataTable_ReEngagement1_Weapons',
#        'CraderMP5',
#        'Custom_B_11_6D4E8C1140CC269ED614BC958ECB0E22',
        "Mayhem 2.0 increases the drop rates pretty significantly, and when",
        "combined with my Better Loot mod, it's totally absurd.  I'm happy",
        "with my Better Loot drop weighting, so this should de-scale the",
        "loot so that Mayhem 2.0 modes are no different than in normal.",
    ],
    lic=Mod.CC_BY_SA_40,
    v='1.0.0',
    cats='mayhem, enemy-drops',
)

# There's another column named LootQuality_56_03E220E0495C6B37CD6C7195F5EA289B which
# goes from 1 at M1, to 2 at M10.  No idea what that does, really, though it looks like
# it might only be referenced by a UI element.  So possibly nothing important...

for mayhem_level in range(1, 11):
    mod.comment('Mayhem {}'.format(mayhem_level))
    for col_name in [
            'DropWeightCommonScalar_21_59A2FB124E32B955768A7B9D93C25A99',
            'DropWeightUncommonScalar_25_809615334E7F0DB3B8712DAC221015C3',
            'DropWeightRareScalar_27_A09CF5314C51796896A83EA0806C7520',
            'DropWeightVeryRareScalar_29_F2CA570046CD50A7C514EDB0AE1BE591',
            'DropWeightLegendaryScalar_31_D9DA03C54065EA981BE218B11942C24E',
    ]:
        mod.table_hotfix(
            Mod.PATCH, '',
            '/Game/PatchDLC/Mayhem2/Abilities/CoreModifierSets/Table_Mayhem2CoreModifierSet',
            mayhem_level, col_name, 1)
    mod.newline()

mod.close()
示例#5
0
            elif idx == 5:
                for part in cat.partlist:
                    skill_parts.append(part.part_name)
        assert (modtype_part)
        assert (skill_parts)

        # Now add those in to the base-game COMs
        for idx, cat in enumerate(base_com.categories):
            if idx == 1:
                cat.add_part_name(modtype_part)
            elif idx == 3:
                # While we're in here, fix up the blank Primary part that Siren COMs can
                # spawn with.  The Fix Siren COM Blank Parts mod does this too, but since
                # we're changing the indexes, it won't actually know what to do with this.
                # So that mod should be run first, and then this mod will overwrite the
                # Balance completely.
                if base_char == 'Siren':
                    for part in cat.partlist:
                        if part.part_name == 'None':
                            part.weight = BVC(bvc=0)
            elif idx == 5:
                for part in skill_parts:
                    cat.add_part_name(part)

        # ... and now write out the hotfixes
        mod.comment('{} {}'.format(base_char, rarity))
        base_com.hotfix_balance_full(mod)
        mod.newline()

mod.close()
     1, 1.0, scale_smg, None),
    ('Sniper Rifle: Multiplex',
     '/Game/Gear/Weapons/SniperRifles/Maliwan/Shared/_Design/Parts/Barrel/Barrel_01/Part_MAL_SR_Barrel_01.Part_MAL_SR_Barrel_01',
     1, 1.1, scale_sniper, None),
    ('Sniper Rifle: Particle Rifle',
     '/Game/Gear/Weapons/SniperRifles/Maliwan/Shared/_Design/Parts/Barrel/Barrel_02/Part_MAL_SR_Barrel_02.Part_MAL_SR_Barrel_02',
     1, 0.9, scale_sniper, None),
    ('Sniper Rifle: Proton Rifle',
     '/Game/Gear/Weapons/SniperRifles/Maliwan/Shared/_Design/Parts/Barrel/Barrel_03/Part_MAL_SR_Barrel_03.Part_MAL_SR_Barrel_03',
     1, 1.75, scale_sniper, None),
]:

    if not aspect_obj:
        aspect_obj = 'AspectList_WeaponUseModeSecondaryAspectData'

    mod.comment('{} (default: {})'.format(label, default))
    charge_time(
        mod,
        obj_name,
        default * scale,
        aspect_obj=aspect_obj,
        aspect_list=aspect_num,
    )
    mod.newline()

mod.header('Legendaries/Uniques')
for label, obj_name, default, scale, aspect_obj, aspect_num, aspect_attr, final_attr in [
    ('Beacon',
     '/Game/PatchDLC/Geranium/Gear/Weapon/_Unique/Decoupler/Parts/Part_PS_MAL_Barrel_Decoupler',
     0.7, scale_pistol, None, None, None, None),
    ('Binary Operator',
示例#7
0
        ],
        lic=Mod.CC_BY_SA_40,
        v='1.0.0',
        cats='qol',
        ss='https://raw.githubusercontent.com/BLCM/bl3mods/master/Apocalyptech/qol/more_visible_echo_logs/echo.png',
        )

# default: 85
height = 900
interactive_height = 200

# default = 2.25
width = 15

# This controls the interactive height of the beam
mod.comment('Interactive height')
mod.reg_hotfix(Mod.PATCH, '',
        '/Game/GameData/Loot/RarityData/RarityData_00_Mission',
        'RarityLootBeamHeight',
        interactive_height)
mod.newline()

# These two statements define how big the main bar is, visually.
mod.comment('Visual size')
for (attr, value) in [
        ('Constant.Y', height),
        ('Constant.X', width),
        ]:
    mod.reg_hotfix(Mod.PATCH, '',
            '/Game/Pickups/_Shared/Effects/Systems/PS_ConsumableLocatorStick.PS_ConsumableLocatorStick:ParticleModuleSize_0.DistributionVectorConstant_1',
            attr,
            '/Game/GameData/Loot/ItemPools/ItemPoolList_StandardEnemyGunsandGear.ItemPoolList_StandardEnemyGunsandGear',
            'ItemPools[9].PoolProbability',
            """(
                BaseValueConstant=0.030000,
                DataTableValue=(DataTable=None,RowName="",ValueName=""),
                BaseValueAttribute=None,
                AttributeInitializer=None,
                BaseValueScale=1.000000
            )""")

    mod.newline()

    # The pool has its Quantity set to /Game/GameData/Loot/ItemPools/Init_RandomLootCount_Normal,
    # which seems to sometimes dip below 1, and cause the pool to not produce anything.  It's
    # weird.  Set it to 1 instead, so that every time the pool is chosen, it'll drop.
    mod.comment('Guarantee cosmetic drop when the pool is rolled (which weirdly isn\'t')
    mod.comment('the case, ordinarily.')
    mod.reg_hotfix(Mod.PATCH, '',
            '/Game/GameData/Loot/ItemPools/ItemPool_SkinsAndMisc.ItemPool_SkinsAndMisc',
            'Quantity',
            """(
                BaseValueConstant=1,
                DataTableValue=(DataTable=None,RowName="",ValueName=""),
                BaseValueAttribute=None,
                AttributeInitializer=None,
                BaseValueScale=1
            )""")
    mod.newline()

    # Now the pool expansions.
    mod.header('Customization Pool Expansions')
    ]),
    ('Lasodactyl', 'BPChar_GerRakkLasodactyl', [
        ('/Geranium/Enemies/GerRakk/_Unique/Lasodactyl/_Design/Character/ItemPool_LasoDactyl',
         [PS]),
    ]),
    ('Lectrikor', 'BPChar_Biobeast_PlasmaBeast', [
        ('/Geranium/Enemies/Biobeast/_Unique/PlasmaBeast/_Design/Character/ItemPool_PlasmaBeast',
         [SG]),
    ]),
    ('Waylon Hurd', 'BPChar_GerPsychoMoleMan', [
        ('/Geranium/Enemies/GerPsycho_Male/_Unique/MoleMan/_Design/Character/ItemPool_MoleMan',
         [SG]),
    ]),
]):

    mod.comment(label)
    if char_name is None:
        hf_type = Mod.PATCH
        hf_target = ''
    else:
        hf_type = Mod.CHAR
        hf_target = char_name
    for pool_name, contents in pools:
        for idx, drop_type in enumerate(contents):
            if drop_type is not None:
                mod.reg_hotfix(
                    hf_type, hf_target, pool_name,
                    'BalancedItems.BalancedItems[{}].InventoryBalanceData'.
                    format(idx), 'None')
                mod.reg_hotfix(
                    hf_type, hf_target, pool_name,
# <https://www.gnu.org/licenses/>.

from bl3hotfixmod.bl3hotfixmod import Mod

mod = Mod(
    'broken_hearts_enable.txt',
    'Enable "Broken Hearts" Event',
    'Apocalyptech',
    [
        "Enables the Broken Hearts event.  Will interfere with any other event which",
        "happens to be running.  (Only one can be fully active at a time.)",
    ],
    lic=Mod.CC_BY_SA_40,
)

mod.comment('Global activation switches')

mod.reg_hotfix(Mod.PATCH, '', '/Game/GameData/GameplayGlobals',
               'LeagueInstance', 1)

mod.reg_hotfix(Mod.PATCH, '', '/Game/GameData/GameplayGlobals', 'ActiveLeague',
               'OL_ValentinesDay')

mod.reg_hotfix(
    Mod.PATCH, '', '/Game/GameData/Spawning/GlobalSpawnDLCData', 'DLCs', """(
            (
                Data=/Game/PatchDLC/EventVDay/GameData/SpawnDLCScripts/SpawnDLC_VDay.SpawnDLC_VDay,
                IsEnabled=(BaseValueConstant=1.000000)
            )
        )""")
示例#11
0
    'Manufacturer_Torgue',
    'Manufacturer_Vladof',
    ])

# Elements
unlock_table(mod, label='Element unlocks', rows=[
    'Element_Corrosive',
    'Element_Cryo',
    'Element_Fire',
    'Element_Radiation',
    'Element_Shock',
    ])

# Broken Hearts gear is locked to 53 with a hotfix, at least during the event
# itself.  Superstreamer is locked to 50+.  Unlocking these here.
mod.comment('Allow Terminal Polyaimorous, Wedding Invitation, and Superstreamer to be any level')
for row in [
        'PolyAim',
        'WeddingInvitation',
        ]:
    mod.table_hotfix(Mod.PATCH, '',
            '/Game/PatchDLC/EventVDay/Gear/Weapon/DataTable_WeaponBalance_EventVDay',
            row,
            'MinGameStage_5_E12DB0C74420238367FBC1A5221AFB84',
            1)
mod.reg_hotfix(Mod.PATCH, '',
        '/Game/PatchDLC/EventVDay/Gear/Weapon/_Unique/TwitchPrime/Balance/Balance_SG_TED_Twitch',
        'Manufacturers.Manufacturers[0].GameStageWeight.MinGameStage.BaseValueConstant',
        1)
mod.newline()
        'Apocalyptech',
        [
            "I always felt that the gifts you get from Joy in the mission 'Heart",
            "of Gold' are a bit pathetic.  Not that you need the resources or",
            "anything, but IMO it'd be nicer if it turned out that Joy was sitting",
            "on a small fortune all this time.",
            "",
            "Buffing this up to *actually* impressive levels isn't really possible",
            "but we can at least bump up the quantity and throw in Eridium as well,",
            "which may make it seem more impressive.",
        ],
        lic=Mod.CC_BY_SA_40,
        )

# Improve the pool
mod.comment('Improve Gift Pool')
money_obj = '/Game/Pickups/Money/DA_InventoryBalance_Currency_MoneyTripleStack'
eridium_obj = '/Game/Pickups/Eridium/InvBal_Eridium_Stack'
mod.reg_hotfix(Mod.LEVEL, 'Trashtown_P',
        '/Dandelion/Missions/Side/HeartOfGold/ItemPool_Money_HeartOfGold',
        'BalancedItems',
        """(
            (
                InventoryBalanceData={},
                ResolvedInventoryBalanceData={},
                Weight=(BaseValueConstant=1)
            ),
            (
                InventoryBalanceData={},
                ResolvedInventoryBalanceData={},
                Weight=(BaseValueConstant=0.5)
示例#13
0
            ]),
        ('Hydragoian', 'BPChar_Biobeast_CopyBeast', [
            ('/Geranium/Enemies/Biobeast/_Unique/CopyBeast/_Design/Character/ItemPool_Copybeast', [SM]),
            ]),
        ('Lasodactyl', 'BPChar_GerRakkLasodactyl', [
            ('/Geranium/Enemies/GerRakk/_Unique/Lasodactyl/_Design/Character/ItemPool_LasoDactyl', [PS]),
            ]),
        ('Lectrikor', 'BPChar_Biobeast_PlasmaBeast', [
            ('/Geranium/Enemies/Biobeast/_Unique/PlasmaBeast/_Design/Character/ItemPool_PlasmaBeast', [SG]),
            ]),
        ('Waylon Hurd', 'BPChar_GerPsychoMoleMan', [
            ('/Geranium/Enemies/GerPsycho_Male/_Unique/MoleMan/_Design/Character/ItemPool_MoleMan', [SG]),
            ]),
        ]):

    mod.comment(label)
    if char_name is None:
        hf_type = Mod.PATCH
        hf_target = ''
    else:
        hf_type = Mod.CHAR
        hf_target = char_name
    for pool_name, contents in pools:
        for idx, drop_type in enumerate(contents):
            if drop_type is not None:
                mod.reg_hotfix(hf_type, hf_target,
                        pool_name,
                        'BalancedItems.BalancedItems[{}].InventoryBalanceData'.format(idx),
                        'None')
                mod.reg_hotfix(hf_type, hf_target,
                        pool_name,
示例#14
0
    mod.reg_hotfix(Mod.PATCH, '', '/Game/GameData/GameplayGlobals',
                   'LeagueInstance', instance)

    mod.reg_hotfix(
        Mod.PATCH, '', '/Game/GameData/Spawning/GlobalSpawnDLCData', 'DLCs',
        """(
                (
                    Data=/Game/PatchDLC/BloodyHarvest/GameData/SpawnDLCScripts/SpawnDLC_BloodyHarvest.SpawnDLC_BloodyHarvest,
                    IsEnabled=(BaseValueConstant=1.000000)
                )
            )""")

    mod.newline()

    mod.comment('Activate main menu changes')
    mod.table_hotfix(Mod.PATCH, '',
                     '/Game/Common/_Design/Table_MicropatchSwitches',
                     'MainMenuAltBackground', 'Value',
                     '(BaseValueConstant=3.000000)')
    mod.newline()

    # Challenge Rewards!
    # Challenge_BloodyHarvest_00_MetaChallenge really *looks* like it's set up so that the rewards
    # that are active depend on the current LeagueInstance set above, but they just don't seem to
    # be.  I've not been able to find a way to get it to use anything but LeagueInstance 2, and
    # the game is pretty fussy about the array -- any additions to the array end up just being
    # empty, and removing the second instance altogether crashes the game.  So, we're gonna do it
    # the stupid way and just set the rewards for *both* instances to the year we're looking for.
    # Really we'd only have to do it for instance 2, but eh...
    reward_str = rewards.to_hotfix(mod)
示例#15
0
            '/Game/Gear/Weapons/HeavyWeapons/ATL/_Shared/_Design/PartSets/PartSet_ATL_HW_04_VeryRare', 4, 2),
        ('Common Pistols',
            '/Game/Gear/Weapons/Pistols/Atlas/_Shared/_Design/Balance/Balance_PS_ATL_01_Common', 24,
            '/Game/Gear/Weapons/Pistols/Atlas/_Shared/_Design/PartSets/PartSet_PS_ATL_01_Common', 6, 2),
        ('Uncommon Pistols',
            '/Game/Gear/Weapons/Pistols/Atlas/_Shared/_Design/Balance/Balance_PS_ATL_02_UnCommon', 24,
            '/Game/Gear/Weapons/Pistols/Atlas/_Shared/_Design/PartSets/PartSet_PS_ATL_02_UnCommon', 6, 2),
        ('Rare Pistols',
            '/Game/Gear/Weapons/Pistols/Atlas/_Shared/_Design/Balance/Balance_PS_ATL_03_Rare', 24,
            '/Game/Gear/Weapons/Pistols/Atlas/_Shared/_Design/PartSets/PartSet_PS_ATL_03_Rare', 6, 2),
        ('VeryRare Pistols',
            '/Game/Gear/Weapons/Pistols/Atlas/_Shared/_Design/Balance/Balance_PS_ATL_04_VeryRare', 24,
            '/Game/Gear/Weapons/Pistols/Atlas/_Shared/_Design/PartSets/PartSet_PS_ATL_04_VeryRare', 6, 2),
        ]:

    mod.comment(label)

    balance_last = balance.split('/')[-1]
    balance_full = '{}.{}'.format(balance, balance_last)
    mod.reg_hotfix(Mod.PATCH, '',
            balance_full,
            'RuntimePartList.AllParts[{}].Weight.BaseValueConstant'.format(bal_idx),
            new_weight)

    # The parts list is duplicated, in a more clearly-delineated way, inside the PartSet
    # objects, but those don't seem to be actually used when dropping weapons.  Weird.
    #partset_last = partset.split('/')[-1]
    #partset_full = '{}.{}'.format(partset, partset_last)
    #mod.reg_hotfix(Mod.PATCH, '',
    #        partset_full,
    #        'ActorPartLists.ActorPartLists[{}].Parts[{}].Weight.BaseValueConstant'.format(ps_pl_idx, part_idx),
示例#16
0
        "by my Early Bloomer mod.  The Fabricator (the gun gun) doesn't",
        "interest me, so I'm real unlikely to bother looking into unlocking",
        "that one.",
        "",
        "At the moment, only the Resonator is unlocked.  I've partially figured",
        "out unlocking the Analyzer, though it behaves pretty weirdly so it's",
        "not in here yet.",
        "",
        "NOTE: this'll probably never actually be a standalone mod; if I figure",
        "out other unlocks in the future, I'm likely to just fold it into",
        "Early Bloomer, as I did with the Resonator.",
    ],
    lic=Mod.CC_BY_SA_40,
)

mod.comment('Always allow Resonator (included in Early Bloomer v1.1.0+)')

mod.reg_hotfix(
    Mod.PATCH, '', '/Game/Gear/Game/Resonator/_Design/MeleeData_Resonator',
    'OverrideCondition.Object..Conditions', '({},{})'.format(
        mod.get_full_cond(
            '/Game/Gear/Game/Resonator/_Design/MeleeData_Resonator.MeleeData_Resonator:OverrideCondition_GbxCondition_List.Conditions_Condition_CompareDistance',
            'Condition_CompareDistance_C'),
        mod.get_full_cond(
            '/Game/Gear/Game/Resonator/_Design/MeleeData_Resonator.MeleeData_Resonator:OverrideCondition_GbxCondition_List.Conditions_Condition_CanUseResonator',
            'Condition_CanUseResonator_C'),
    ))

mod.newline()

# Tried doing a bit of this, but the subobject creation didn't work, and I suspect
示例#17
0
            "",
            "Note that if the first thing you take out of the opening chest isn't a gun,",
            "you'll automatically receive a bonus gun from the FirstGun pool, in your",
            "inventory.",
            "",
            "Also updates the car-trunk chest which provides your second and third guns",
            "to pull from the main pistol pool rather than locked to white Jakobs+Dahl",
            "pistols.",
        ],
        contact='https://apocalyptech.com/contact.php',
        lic=Mod.CC_BY_SA_40,
        v='1.0.0',
        cats='chests, cheat',
    )

    mod.comment('Update the chest LootDef')
    stanzas = []
    for (socket, pool) in attachments:
        stanzas.append("""(
                ItemPool=ItemPoolData'"{}"',
                AttachmentPointName={},
                Probability=(BaseValueConstant=1)
            )""".format(Mod.get_full_cond(pool), socket))
    # This does have to be EARLYLEVEL to work, btw.
    mod.reg_hotfix(
        Mod.EARLYLEVEL, 'Recruitment_P',
        '/Game/Missions/Plot/EP01_ChildrenOfTheVault/LootDef_Global_WhiteChest_ChildrenOfTheVault',
        'DefaultLoot.DefaultLoot[0].ItemAttachments',
        '({})'.format(','.join(stanzas)))
    mod.newline()
                "Not yet sure how this interacts with stuff like speed while crouching,",
                "FFYL, climbing ladders, etc.",
            ],
            lic=Mod.CC_BY_SA_40,
            )

    # Player Chars
    mod.header('Player Characters')
    for (label, obj_name) in [
            ('Beastmaster', '/Game/PlayerCharacters/Beastmaster/_Shared/_Design/Character/BPChar_Beastmaster.Default__BPChar_Beastmaster_C'),
            ('Gunner', '/Game/PlayerCharacters/Gunner/_Shared/_Design/Character/BPChar_Gunner.Default__BPChar_Gunner_C'),
            ('Operative', '/Game/PlayerCharacters/Operative/_Shared/_Design/Character/BPChar_Operative.Default__BPChar_Operative_C'),
            ('Siren', '/Game/PlayerCharacters/SirenBrawler/_Shared/_Design/Character/BPChar_Siren.Default__BPChar_Siren_C'),
            ]:

        mod.comment(label)
        do_walk(mod, obj_name, 470, 470, multiplier)
        do_sprint(mod, obj_name, 720, 720, multiplier)
        mod.newline()

    # Iron Bear
    mod.header('Iron Bear')
    mod.comment('Iron Bear')
    obj_name = '/Game/PlayerCharacters/Gunner/_Shared/_Design/IronBear/BPChar_IronBear.Default__BPChar_IronBear_C'
    do_walk(mod, obj_name, 456, 456, multiplier)
    do_sprint(mod, obj_name, 650, 650, multiplier)
    mod.newline()

    # Pets!
    mod.header('Pets')
    for (label, obj_name, walk_val, walk_base, sprint_val, sprint_base) in [
示例#19
0
mod = Mod('no_cryo_penalty.bl3hotfix',
        "No Cryo Penalty",
        'Apocalyptech',
        [
            "Gets rid of the movement penalty you'd otherwise suffer when a cryo",
            "effect is applied to your character, and allows sliding while frozen.",
            "This is obviously rather cheaty!",
        ],
        lic=Mod.CC_BY_SA_40,
        v='1.1.0',
        cats='cheat',
        )

# We could also just redefine the whole curve to only have a single point, but
# whatever.
mod.comment('Remove the speed debuff')
mod.reg_hotfix(Mod.PATCH, '',
		'/Game/GameData/StatusEffects/Cryo_PenaltyCurvePlayer',
		'FloatCurve.Keys.Keys[1].Value',
		1)
mod.reg_hotfix(Mod.PATCH, '',
		'/Game/GameData/StatusEffects/Cryo_PenaltyCurvePlayer',
		'FloatCurve.Keys.Keys[2].Value',
		1)
mod.newline()

# Now make it so we can slide while frozen, too
mod.comment('Allow sliding while frozen')
mod.reg_hotfix(Mod.PATCH, '',
        '/Game/PlayerCharacters/_Shared/_Design/Sliding/ControlledMove_Global_Sliding.Default__ControlledMove_Global_Sliding_C',
        'bSpeedAffectedByCryo',
示例#20
0
    our_seed = int(our_seed)

random.seed(our_seed)

DFL_LEVEL=Mod.EARLYLEVEL
output_filename = args.output
mod = Mod(output_filename,
          'Boss Race',
          'skruntskrunt',
          ["Turns Arm's Race into a weird boss rush"],
          lic=Mod.CC_BY_SA_40,
          v='0.1.2',
          cats='gameplay',
)

mod.comment(f"Seed {our_seed}")
EASY="easy"
MEDIUM="medium"
HARD="hard"

difficulty_pools = {
    EASY:ixorabosses.easy_bosses,
    MEDIUM:ixorabosses.medium_bosses,
    HARD:ixorabosses.hard_bosses,
    "heavy":ixorabosses.heavy_bosses,
    "all":ixorabosses.safe_bosses,
}

# @piggy:~/projects/bl3data/extracted_new/frost-site/pp$ for file in `cat SpawnOptions`; do echo; bash json-of.sh $file | fgrep jwp_object_name | sed -e "s#^#'$file',#"; done | fgrep Factory | sed -e 's/"_jwp_object_name" : //'
raw_ixora_spawn_list = [
    #('/Ixora/Enemies/_Spawning/GearUpBoss/SpawnOptions_FrontRider_Adds',      "Factory_SpawnFactory_OakAI",0),
示例#21
0
        "entirely from the pool list.  We're fixing the DLC2 Standard ones, but",
        "not bothering with Badasses for now.",
        "",
        "For DLC4 standard enemies, they won't drop non-DLC-specific shields, though",
        "I don't know how widespread that issue is.  Regardless, this should fix",
        "it up for the ones that have the problem.  This DLC4 fix is also included",
        "in my DLC Loot De-Emphasizer mod.",
    ],
    contact='https://apocalyptech.com/contact.php',
    lic=Mod.CC_BY_SA_40,
    v='1.1.0',
    cats='bugfix',
)

# DLC2 Fix
mod.comment('DLC2')
mod.reg_hotfix(
    Mod.CHAR, 'MatchAll',
    '/Game/PatchDLC/Hibiscus/GameData/Loot/EnemyPools/ItemPoolList_StandardEnemyGunsandGear_Hibiscus',
    'ItemPools.ItemPools[6].PoolProbability.BaseValueAttribute',
    Mod.get_full_cond(
        '/Game/GameData/Loot/ItemPools/Attributes/Att_Shields_DropOdds',
        'GbxAttributeData'))
mod.newline()

# DLC4 Fix
mod.comment('DLC4')
mod.reg_hotfix(
    Mod.CHAR, 'MatchAll',
    '/Game/PatchDLC/Alisma/GameData/Loot/EnemyPools/ItemPoolList_StandardEnemyGunsandGear_Alisma',
    'ItemPools.ItemPools[5]', """(
示例#22
0
    'Sanctuary3_P',
    'AtlasHQ_P',
    'OrbitalPlatform_P',
    'Mansion_P',
    'CasinoIntro_P',
    'Core_P',
    'Bar_P',
    'Town_P',
]

levels_eridium = [
    'Sanctuary3_P',
    'Bar_P',
]

mod.comment('Money-based machines')
for level in levels_money:
    mod.reg_hotfix(Mod.LEVEL, level,
                   '/Game/UI/InteractionPrompt/UIData_PlaySlots',
                   'Cost.BaseValueScale', 0.2)
mod.newline()

mod.comment('Eridium-based machines')
for level in levels_eridium:
    mod.reg_hotfix(Mod.LEVEL, level,
                   '/Game/UI/InteractionPrompt/UIData_PlaySlotsEridium',
                   'Cost.BaseValueScale', 0.2)
mod.newline()

mod.close()
    'Sisterly Love: More Money',
    'Apocalyptech',
    [
        "I always felt that the malfunctioning-slot-machine money drop in",
        "the DLC2 mission Sisterly Love was pretty anemic and unimpressive.",
        "This mod buffs it up slightly, though it turns out there's not a",
        "*lot* that we can really do with it.",
    ],
    lic=Mod.CC_BY_SA_40,
    v='1.0.0',
    cats='quest-changes',
)

# Default is a single stack; I couldn't find anything bigger than the triple, which is
# still pretty meh.
mod.comment('Use "biggest" money drop')
to_obj_name = '/Game/Pickups/Money/DA_InventoryBalance_Currency_MoneyTripleStack'
mod.reg_hotfix(
    Mod.LEVEL, 'Strip_P',
    '/Dandelion/Missions/Side/BrotherlyLove/ItemPool_Money_BrotherlyLove',
    'BalancedItems.BalancedItems[0]', """(
            InventoryBalanceData={},
            ResolvedInventoryBalanceData={},
            Weight=(BaseValueConstant=1)
        )""".format(to_obj_name,
                    Mod.get_full_cond(to_obj_name, 'InventoryBalanceData')))
mod.newline()

# Default value: 20.  Going to 150 makes a noticeable (though extremely slight) little
# freeze while they're populating, 200 is even more noticeable.  I'd tried 1000 initially
# and thought that I'd frozen the game permanently before it recovered.  So: eh.  This
示例#24
0
    mod = Mod(
        f'atlas_hq_fast_travel_{filename}.bl3hotfix',
        f'Atlas HQ Fast Travel: {title}',
        'Apocalyptech',
        desc,
        lic=Mod.CC_BY_SA_40,
        v='1.0.1',
        cats='qol, maps',
        ss=[
            f'https://raw.githubusercontent.com/BLCM/bl3mods/master/Apocalyptech/qol/atlas_hq_fast_travel/screenshot_{filename}.jpg'
        ],
    )

    # Process the moves
    for station, location in moves:
        mod.comment(station.obj_name_last)
        station.move_to(mod, location)
        mod.newline()

    # Update the location for the station when we're *not* already at Atlas HQ
    # We're assuming here that the first entry in the `moves` list is the one
    # describing where the FT station itself is going.
    loc = moves[0][1]
    mod.header('Update global game map FT location')
    mod.reg_hotfix(
        Mod.PATCH, '',
        '/Game/GameData/ZoneMap/ZoneMapData/ZoneMapData_AtlasHQ',
        'ZoneMapPOIList.ZoneMapPOIList[3].PointOfInterestTransform.Translation',
        f'(x={loc.x},y={loc.y},z={loc.z})')
    mod.newline()
def save_mod(save_filename):
    """
    Save out a mod file.  This actually relies on an awful lot of global variables.
    Apologies.
    """
    mod = Mod(save_filename,
            'Arbitrary Partlocks: {}'.format(bal_last),
            'Apocalyptech',
            [
                'Auto-generated partlocks, chosen with an interactive CLI app.',
            ],
            lic=Mod.CC_BY_SA_40,
            )

    for cat_idx, cat_actions in enumerate(actions):
        cur_cat = categories[cat_idx]
        always_vals = set()
        never_vals = set()
        for action in cat_actions.values():
            if action.action == Action.ALWAYS:
                always_vals.add(action.list_idx)
            else:
                never_vals.add(action.list_idx)

        # Now, loop through each category and assign new weights
        if len(always_vals) > 0 or len(never_vals) > 0:
            if cat_idx == 0:

                # We could try to generalize, but whatever.  Just process anoints separately
                cur_idx = 0
                if cur_cat.cat.partlist:
                    cur_source = cur_cat.cat.partlist[0].anoint_source
                for num, part in enumerate(cur_cat.cat.partlist):

                    # Reset our array index if needed
                    if part.anoint_source != cur_source:
                        cur_idx = 0
                        cur_source = part.anoint_source

                    # If we have any "always" entries, we effectively assume everything else
                    # is a "never", so we process a bit differently
                    if len(always_vals) > 0:
                        if num not in always_vals:
                            never_vals.add(num)

                    # Now write out
                    if part.anoint_source != balance_name:
                        extra_txt = ' (affects anything using this anoint)'
                        attr_ref = 'GenericParts.Parts'
                    else:
                        extra_txt = ''
                        attr_ref = 'RuntimeGenericPartList.PartList'
                    if num in always_vals:
                        mod.comment('Anointments: Always choose {}{}'.format(part.short_name, extra_txt))
                        mod.reg_hotfix(Mod.PATCH, '',
                                part.anoint_source,
                                '{}[{}].Weight'.format(attr_ref, cur_idx),
                                BVCF(bvc=1))
                        mod.newline()
                    elif num in never_vals:
                        mod.comment('Anointments: Never choose {}{}'.format(part.short_name, extra_txt))
                        mod.reg_hotfix(Mod.PATCH, '',
                                part.anoint_source,
                                '{}[{}].Weight'.format(attr_ref, cur_idx),
                                BVCF(bvc=0))
                        mod.newline()

                    # Increment our index
                    cur_idx += 1

            else:

                # Make sure this is set to use weights
                if not cur_cat.cat.use_weight_with_mult:
                    mod.comment('Category {}: Enable weight-based part picking'.format(cat_idx))
                    mod.reg_hotfix(Mod.PATCH, '',
                            balance.partset_name,
                            'ActorPartLists.ActorPartLists[{}].bUseWeightWithMultiplePartSelection'.format(cat_idx-1),
                            'True')
                    mod.newline()

                # Regular parts
                # TODO: If we ever get GPartExpansion objects which do more than add expansions,
                # well have to support it here, too.
                cur_idx = cur_cat.start_part_idx
                for num, part in enumerate(cur_cat.cat.partlist):

                    # If we have any "always" entries, we effectively assume everything else
                    # is a "never", so we process a bit differently
                    if len(always_vals) > 0:
                        if num not in always_vals:
                            never_vals.add(num)

                    # Now write out
                    if num in always_vals:
                        mod.comment('Category {}: Always choose {}'.format(cat_idx, part.short_name))
                        mod.reg_hotfix(Mod.PATCH, '',
                                balance_name,
                                'RuntimePartList.AllParts[{}].Weight'.format(cur_idx),
                                BVCF(bvc=1))
                        mod.newline()
                    elif num in never_vals:
                        mod.comment('Category {}: Never choose {}'.format(cat_idx, part.short_name))
                        mod.reg_hotfix(Mod.PATCH, '',
                                balance_name,
                                'RuntimePartList.AllParts[{}].Weight'.format(cur_idx),
                                BVCF(bvc=0))
                        mod.newline()

                    # Increment index
                    cur_idx += 1

    print('')
    print(color_success + '='*80)
    mod.close()
    print(color_success + '='*80)
    print(color_reset)
    input('Hit Enter to Continue...')
    print('')
示例#26
0
        # Defaults vary depending on pool; for base-game it's 0.5%.
        # Tends to be higher for DLCs, I believe.
        mod.reg_hotfix(Mod.CHAR, 'MatchAll', pool,
                       'ItemPools[{}].PoolProbability'.format(index),
                       BVCF(bvc=rate))

    mod.newline()

    # Some extra things to do if we're disabling entirely.
    if rate == 0:

        # TODO: Still getting some cosmetic drops in DLC2, maybe from badasses?

        mod.header('Remove cosmetics from containers')

        mod.comment('Regular container ItemPools')
        for pool, index in [
            ('/Game/GameData/Loot/ItemPools/ItemPool_ChestFlaps', 5),
            ('/Game/GameData/Loot/ItemPools/ItemPool_RedChestFlaps', 4),
            ('/Game/GameData/Loot/ItemPools/ItemPool_Shields_Skins_Artifacts_GrenadeMods_ClassMods_Deco',
             4),
            ('/Game/GameData/Loot/ItemPools/ItemPool_Shields_Skins_Artifacts_GrenadeMods_ClassMods_Deco',
             5),
            ('/Game/GameData/Loot/ItemPools/ItemPool_Shields_Skins_Artifacts_GrenadeMods_ClassMods_Deco',
             6),
            ('/Game/GameData/Loot/ItemPools/ItemPool_Shields_Skins_Artifacts_GrenadeMods_ClassMods_Deco',
             7),
        ]:
            mod.reg_hotfix(
                Mod.PATCH, '', pool,
                'BalancedItems.BalancedItems[{}].Weight.BaseValueScale'.format(
示例#27
0
    def write_mod(self):

        mod = Mod(
            f'money_grenade_changes_{self.mod_filename}.bl3hotfix',
            f'Money Grenade Changes: {self.mod_label}',
            'Apocalyptech',
            [
                f"Changes the 'Money' grenade part to drop {self.desc_text} instead of money.",
            ],
            contact='https://apocalyptech.com/contact.php',
            lic=Mod.CC_BY_SA_40,
            v='1.0.0',
            cats='joke, gear-grenade, cheat',
            ss=
            f'https://raw.githubusercontent.com/BLCM/bl3mods/master/Apocalyptech/gear_changes/money_grenade_changes/screenshot_{self.mod_filename}.png',
        )

        mod.header('Update item prefixes')
        mod.reg_hotfix(
            Mod.PATCH, '',
            '/Game/Gear/GrenadeMods/_Design/Naming/GrenadeModNamingStrategy',
            'SingleNames.SingleNames[20].NamePart.Object..PartName',
            self.single_name)
        mod.reg_hotfix(
            Mod.PATCH, '',
            '/Game/Gear/GrenadeMods/_Design/Naming/GrenadeModNamingStrategy',
            'TripleNames.TripleNames[11].NamePart.Object..PartName',
            self.triple_name)
        self._combo_name(mod, 19, self.combo_name_mirv)
        self._combo_name(mod, 36, self.combo_name_rain)
        self._combo_name(mod, 52, self.combo_name_nuke)
        self._combo_name(mod, 67, self.combo_name_large)
        self._combo_name(mod, 81, self.combo_name_bouncy)
        self._combo_name(mod, 94, self.combo_name_spring)
        self._combo_name(mod, 106, self.combo_name_sticky)
        self._combo_name(mod, 117, self.combo_name_artillery)
        self._combo_name(mod, 127, self.combo_name_lingering)
        self._combo_name(mod, 136, self.combo_name_divide)
        self._combo_name(mod, 144, self.combo_name_singularity)
        self._combo_name(mod, 151, self.combo_name_roider)
        self._combo_name(mod, 157, self.combo_name_link)
        self._combo_name(mod, 162, self.combo_name_transfusion)
        self._combo_name(mod, 166, self.combo_name_generator)
        self._combo_name(mod, 169, self.combo_name_elemental)
        self._combo_name(mod, 171, self.combo_name_force)
        self._combo_name(mod, 172, self.combo_name_money)
        mod.newline()

        mod.header('Update part name')
        mod.reg_hotfix(
            Mod.PATCH, '',
            '/Game/Gear/GrenadeMods/_Design/PartSets/Part_Behavior/Money/UIStat_Grenade_Money_Icon',
            'Text', self.part_text.upper())
        mod.newline()

        mod.header('Update drop pools and card descriptions')
        for pool_label, rewards, (uistat_name, uistat_text) in [
            ('Single-part grenade', self.rewards1, self.uistat1),
            ('Double-part grenade', self.rewards2, self.uistat2),
            ('Triple-part grenade', self.rewards3, self.uistat3),
        ]:
            mod.comment(pool_label)
            mod.reg_hotfix(Mod.PATCH, '', rewards.pool_name, 'BalancedItems',
                           str(rewards))
            mod.reg_hotfix(Mod.PATCH, '', uistat_name, 'FormatText',
                           uistat_text.format(self.card_text))
            mod.newline()

        # Special-case hardcodes for some mod types
        if self.mod_label == 'Diamond Keys':

            # Fix up the diamond key item so that it looks better when dropped
            # (by default it just looks like eridium, and also doesn't auto-pickup)

            mod.header_lines([
                "Fixing up droppable Diamond Key object",
                "",
                "We're making a few changes here which affect the item card specifically,",
                "though the item card will basically never be seen since we're enabling",
                "auto-pickup as well.  If you *do* get a glimpse of the card (using Photo",
                "Mode or the like) you'll see a bit of weirdness still -- the card might",
                "inherit the visual price of whatever card was last looked at, and the",
                "loot beam icon might inherit the last-looked-at item as well.  In the",
                "end I'm not bothering to track that down, though, since you've gotta",
                "work hard to see the card anyway.",
            ])

            mod.comment('Use an actual key mesh')
            mod.reg_hotfix(
                Mod.PATCH,
                '',
                '/Game/PatchDLC/VaultCard/Data/Currency/BP_DiamondKey_Single.Default__BP_DiamondKey_Single_C',
                'ItemMeshComponent.Object..StaticMesh',

                # Tried lots of various meshes here; I'm tempted to go with one of the keyring ones,
                # but in the end I just went with one of the smaller single-key ones.  Would be nice
                # if I could get that Geranium Key-to-City ones to interact with physics, though
                # that might cause weird problems with the key during the plot (or on Decoration),
                # so eh.  We'll just stick with the tiny key for now.

                # A bit much, though it's a nice big size.  Is definitely a keyring, though.
                #Mod.get_full_cond('/Dandelion/Missions/Plot/Ep04_Trashtown/Janitor_Keyring/Model/Meshes/SM_Janitor_Keyring', 'StaticMesh'),

                # Definitely a keyring; probably better than SM_Janitor_Keyring if I feel okay with that...
                #Mod.get_full_cond('/Ixora2/Missions/02_Eden6/Keyring/Model/Meshes/SM_Key_Ring', 'StaticMesh'),

                # Hah, just a rusty sphere basically
                #Mod.get_full_cond('/Geranium/LevelArt/Lodge/Props/Model/Meshes/SM_Apple_Key', 'StaticMesh'),

                # Very nice (and rightly-sized!) key, but it weirdly doesn't seem to actually interact with physics
                # at all?  Just hangs there in midair.
                #Mod.get_full_cond('/Geranium/InteractiveObjects/MissionAssets/Plot_5/Model/Meshes/SM_Key_to_City', 'StaticMesh'),
                # Same story here; and seemingly identical to the other one.  Almost certainly a copied object.
                #Mod.get_full_cond('/Game/PatchDLC/Geranium/InteractiveObjects/PlayerQuarters/RoomDecoMeshes/Meshes/SM_Key_to_City_RoomDeco', 'StaticMesh'),

                # Perfectly serviceable key, but quite small
                #Mod.get_full_cond('/Hibiscus/InteractiveObjects/MissionSpecific/Plot/EP03/Pickups/SM_Key_GateKey', 'StaticMesh'),
                # Perfectly serviceable key, but quite small
                Mod.get_full_cond(
                    '/Game/LevelArt/Environments/_Global/Props/Keys/Key_Scooters/Model/Meshes/SM_Key_Scooters',
                    'StaticMesh'),
            )
            mod.newline()

            mod.comment('Set a different item card type')
            mod.reg_hotfix(
                Mod.PATCH,
                '',
                '/Game/PatchDLC/VaultCard/Data/Currency/InvData_DiamondKey',
                'ItemCardTypeFrameName',
                #'currencyEridium',
                # Mission is nice; has a diamondy icon, even!
                'Mission',
                # Cash works well
                #'Cash',
            )
            mod.newline()

            mod.comment(
                'Set monetary value to 1; might prevent currency from inheriting from previously-viewed items'
            )
            mod.reg_hotfix(
                Mod.PATCH, '',
                '/Game/PatchDLC/VaultCard/Data/Currency/InvData_DiamondKey',
                'MonetaryValue', BVCF(bvc=1))
            mod.newline()

            mod.comment(
                'Assign Legendary rarity (instead of Eridium), for loot bar + frame color'
            )
            mod.reg_hotfix(
                Mod.PATCH, '',
                '/Game/PatchDLC/VaultCard/Data/Currency/InventoryBalance_DiamondKey',
                'RarityData',
                Mod.get_full_cond(
                    '/Game/GameData/Loot/RarityData/RarityData_05_Legendary',
                    'RarityData'))
            mod.newline()

            mod.comment('Auto-pickup Diamond Keys')
            mod.reg_hotfix(
                Mod.PATCH,
                '',
                '/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_DiamondKey',
                'PickupActionType',
                #'OnUseOnly',
                'OnUseOrTouch',
            )
            mod.newline()

        mod.close()
    [
        "This buffs up sniper rifles by a bit, with a bit of base-damage increase, and",
        "some crit bonus damage as well (which is expanded even more for Jakobs snipers).",
        "This may need some tweaking after more playtesting.",
        "",
        "At current values, the blue Jakobs sniper I was testing with was affected like so:",
        "",
        "   On-Card Damage: 4159 -> 4852",
        "   Non-Crit on Dummy: 4770 -> 5566",
        "   Crit on Dummy: 12k -> 18k",
    ],
    lic=Mod.CC_BY_SA_40,
)

# All Sniper Manufacturers
mod.comment('All Sniper Rifles')
for col, value in [
        # Default: 1.2
    ('CritDamageScale_61_5876F7BA4086CE2615C39F84E7409B3C', 1.4),
        # Default: 1.8
    ('DamageScale_36_150C89A04BB4FCF0061CAC86E39E1A39', 2.1),
]:
    mod.table_hotfix(
        Mod.PATCH, '',
        '/Game/Gear/Weapons/_Shared/_Design/GameplayAttributes/Weapon_Initialization/DataTable_Weapon_Base_Data',
        'SniperRifle', col, value)
mod.newline()

# Specific Jakobs buffs
mod.comment('Jakobs-Specific Buffs')
for row, col, value in [
示例#29
0
        "great instead of way OP.  Could be that I've gone too far (or not far enough)",
        "in some cases.  Launchers especially I don't really have a great feel for.",
    ],
    contact='https://apocalyptech.com/contact.php',
    lic=Mod.CC_BY_SA_40,
    v='1.0.0',
    cats='gear-general',
)

readme_reports = []

# First up, one which doesn't fit the main pattern here.  Wedding Invitation's
# base damage isn't spectacular, but it's got a lot else going on.  Gonna try
# just nerfing the ricochet damage, which appears to be like 3x by default.
mod.header('Broken Hearts')
mod.comment('Wedding Invitation Ricochet Damage (default: 2.928)')
readme_reports.append(
    'Wedding Invitation Ricochet Damage: `{}` -> `{}`'.format(2.928, 1))
mod.table_hotfix(
    Mod.PATCH, '',
    '/Game/PatchDLC/EventVDay/Gear/Weapon/DataTable_WeaponBalance_EventVDay',
    'WeddingInvitation', 'Custom_A_10_6BE78EF448AB3F6F228BC7B266814C86', 1)
mod.newline()

for cat_name, balance_obj, weapons in [
    (
        'Base Game Maliwan Snipers',
        '/Game/Gear/Weapons/_Shared/_Design/GameplayAttributes/_Unique/DataTable_WeaponBalance_Unique_MAL',
        [
            # 4.25 is actually what GBX sets in a hotfix; the on-disk default is 1
            # At 2.5, a Storm's card can out-damage this, but I think it's probaby
    global mod
    mod.reg_hotfix(hf_mode, hf_target, pool_name,
                   'BalancedItems.BalancedItems[{}].Weight'.format(index),
                   BVCF(bvc=0))


###
### DLC1 - Moxxi's Heist of the Handsome Jackpot
###

mod.header("DLC1 - Moxxi's Heist of the Handsome Jackpot")

# Main weapon pool
# The main guns pool actually already points to the global legendary pool, in addition to
# the custom one, so we're just zeroing out the probability of the DLC-specific one.
mod.comment('Main Weapon Pool')
for char_name in [
        # Via ItemPoolList_BadassEnemyGunsGearLoader1
        'BPChar_HyperionTurretBadass',
        'BPChar_LoaderBadass',
        # Via ItemPoolList_StandardEnemyGunsandGearLoader
        'BPChar_HyperionTurretBasic',
        'BPChar_LoaderShared',
        'BPChar_WeeLoaderBasic',
        'BPChar_DefenseCannonSuperBadass',
        'BPChar_DefenseCannonBasic',
        # Via ItemPoolList_BadassEnemyGunsGear_Dandelion
        'BPChar_SisterlyLove_DebtCollectorLoader',
        'BPChar_GreatEscape_Rudy',
        'BPChar_RagingBot_MachineGunMikey',
        'BPChar_EnforcerBadass_Looter',