Exemple #1
0
            "the event, so you get as close to the \"live\" event experience as",
            "possible.",
            "",
            "This version of the mod will enable the {} version of the event.".
            format(year),
            "The only difference between it and other years is the rewards you",
            "get for completing challenges, which is tracked separately",
            "between years.",
        ],
        contact='https://apocalyptech.com/contact.php',
        lic=Mod.CC_BY_SA_40,
        v='1.1.1',
        cats='event',
    )

    mod.header('Global activation switches')

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

    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)
                )
            )""")
Exemple #2
0
data = BL3Data()

level = 'Prologue_P'
den_obj = '/Game/Maps/Zone_0/Prologue/Prologue_Dynamic.Prologue_Dynamic:PersistentLevel.OakSpawner_EridiumCrystals.SpawnerComponent.SpawnerStyle_SpawnerStyle_Den'
coords_from = (43460, 20822)
coords_to = (47673, 26232)
coord_z = 0

# Pull apart our Den object
submap_first, obj_after = den_obj.split(':PersistentLevel.')
submap_base, submap_short = submap_first.rsplit('.', 1)
spawner_short = obj_after.split('.')[0]

# Grab map data
mod.header(f'Processing {spawner_short} objects in {submap_short}')
obj = data.get_data(submap_base)
for export in obj:
    if export['_jwp_object_name'] == spawner_short:
        sc = obj[export['SpawnerComponent']['export'] - 1]
        objects = []
        for sp in sc['SpawnPoints']:
            objects.append('{}:PersistentLevel.{}'.format(
                submap_first,
                sp['_jwp_export_dst_name'],
            ))

        # Calculate our deltas
        per_side = math.floor(math.sqrt(len(objects)))
        delta_x = (coords_to[0] - coords_from[0]) / per_side
        delta_y = (coords_to[1] - coords_from[1]) / per_side
                   'ItemPools.ItemPools[{}].PoolProbability'.format(index),
                   BVCF(bvc=0))


def zero_pool(hf_mode, hf_target, pool_name, index):
    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',
Exemple #4
0
        "    Siren: Ascetic",
    ],
    contact='https://apocalyptech.com/contact.php',
    lic=Mod.CC_BY_SA_40,
    v='1.0.0',
    cats='gear-com',
    ss=[
        'https://raw.githubusercontent.com/BLCM/bl3mods/master/Apocalyptech/loot_changes/world_drop_designers_cut_coms/com_beastmaster.png',
        'https://raw.githubusercontent.com/BLCM/bl3mods/master/Apocalyptech/loot_changes/world_drop_designers_cut_coms/com_gunner.png',
        'https://raw.githubusercontent.com/BLCM/bl3mods/master/Apocalyptech/loot_changes/world_drop_designers_cut_coms/com_operative.png',
        'https://raw.githubusercontent.com/BLCM/bl3mods/master/Apocalyptech/loot_changes/world_drop_designers_cut_coms/com_siren.png',
    ],
)

# Original is misspelled "Acsetic"
mod.header('Fix Siren COM Name')
mod.reg_hotfix(
    Mod.PATCH,
    '',
    '/Game/PatchDLC/Ixora/Gear/_GearExtension/NamingStrategies/NamingStrategyExtension_Ixora_CM_Siren',
    'SingleNames.SingleNames[1].NamePart.Object..PartName',
    'Ascetic',
)
mod.newline()

# Now the bulk of the mod
mod.header('Add in DLC5 COMs')
data = BL3Data()
for base_char, dlc5_dir, dlc5_char in [
    ('Beastmaster', 'BSM', 'BSM'),
    ('Gunner', 'GUN', 'GUN'),
    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()
Exemple #6
0
        '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()

    # Close
    mod.close()
        prev_val = ''
    else:
        prev_val = '(BaseValue={:.6f})'.format(prev_val)
    mod.reg_hotfix(
        Mod.PATCH,
        '',
        '{}:{}.{}'.format(Mod.get_full_cond(obj_name), aspect_obj,
                          aspect_attr),
        'AspectList.AspectList[{}].Object..Component.Object..{}'.format(
            aspect_list, final_attr),
        '(BaseValue={:.6f})'.format(new_val),
        prev_val=prev_val)


# Put in our improvements
mod.header('Generic Weapons')
for (label, obj_name, aspect_num, default, scale, aspect_obj) in [
    ('Pistol: Atomizer',
     '/Game/Gear/Weapons/Pistols/Maliwan/_Shared/_Design/Parts/Barrel/Barrel_01/Part_PS_MAL_Barrel_01',
     2, 0.5, scale_pistol, 'WeaponUseModeSecondaryAspectData_0'),
    ('Pistol: Melter',
     '/Game/Gear/Weapons/Pistols/Maliwan/_Shared/_Design/Parts/Barrel/Barrel_02/Part_PS_MAL_Barrel_02',
     2, 1, scale_pistol, 'WeaponUseModeSecondaryAspectData_1'),
    ('Pistol: Blaster',
     '/Game/Gear/Weapons/Pistols/Maliwan/_Shared/_Design/Parts/Barrel/Barrel_03/Part_PS_MAL_Barrel_03.Part_PS_MAL_Barrel_03',
     0, 0.7, scale_pistol, None),
    ('Shotgun: Terminator',
     '/Game/Gear/Weapons/Shotguns/Maliwan/_Shared/_Design/Parts/Barrel/Barrel_01/Part_SG_MAL_Barrel_01.Part_SG_MAL_Barrel_01',
     1, 0.7, scale_shotgun, None),
    ('Shotgun: Shockwave',
     '/Game/Gear/Weapons/Shotguns/Maliwan/_Shared/_Design/Parts/Barrel/Barrel_02/Part_SG_MAL_Barrel_02.Part_SG_MAL_Barrel_02',
    for row_name in [
            'Rare',
            'VeryRare',
            'SuperRare',
    ]:
        mod.table_hotfix(
            Mod.LEVEL, level_name,
            '/Game/GameData/Balance/RareSpawns/Table_Async_RareSpawnRarities',
            row_name, 'Value', BVCF(bvc=100))
mod.newline()

# Some individual spawn rates which apparently don't use those values above
# TODO: I think Brood Mother (Pyre of Stars) needs something similar.  GBX
# has said that Brood Mother's spawn actually depends on killing mobs outside
# her lair, so I should look into that...
mod.header('Individual Spawn rates')

mod.comment('Wick and Warty')
mod.reg_hotfix(
    Mod.LEVEL, 'Towers_P',
    '/Game/Maps/Zone_1/Towers/Towers_Combat.Towers_Combat:PersistentLevel.OakMissionRareSpawner_VicAndWarty',
    'PercentChanceToSpawn', BVCF(bvc=100))
mod.newline()

mod.comment('Amach')
mod.reg_hotfix(
    Mod.LEVEL, 'Village_P',
    '/Hibiscus/Maps/Village/Village_Combat.Village_Combat:PersistentLevel.OakMissionRareSpawner_1',
    'PercentChanceToSpawn', BVCF(bvc=100))
mod.newline()
Exemple #9
0
mod = Mod('mayhem_modifier_nerfs.bl3hotfix',
        'Mayhem Modifier Nerfs',
        'Apocalyptech',
        [
            "Applying some nerfs to Mayhem 2.0 modifiers that I enjoy, but wish",
            "were a little less intrusive.  Cheaty!  Though the Lootsplosion",
            "modifier change is technically *against* the player rather than for.",
        ],
        contact='https://apocalyptech.com/contact.php',
        lic=Mod.CC_BY_SA_40,
        v='1.0.0',
        cats='mayhem, cheat',
        )

mod.header('Actual Stat Changes')

infusion_pct = 0.25
infusion_rpt = int(infusion_pct*100)

switcheroo_scale = -0.02
switcheroo_rpt = int(abs(switcheroo_scale*100))

ticked_scale = 0.3
ticked_rpt = int((1-ticked_scale)*100)

critfail_scale = 0.5
critfail_rpt = int((1-critfail_scale)*100)

holycrit_noncrit_scale = 0.65
holycrit_noncrit_rpt = int((1-holycrit_noncrit_scale)*100)
            '/Game/Maps/Zone_0/Prologue/Prologue_Combat.Prologue_Combat:PersistentLevel.BPIO_Lootable_Global_WhiteCrate_3',
            '/Game/Maps/Zone_0/Prologue/Prologue_Combat.Prologue_Combat:PersistentLevel.BPIO_Lootable_Global_WhiteCrate_396',
            '/Game/Maps/Zone_0/Prologue/Prologue_Combat.Prologue_Combat:PersistentLevel.BPIO_Lootable_Global_WhiteCrate_4',
            '/Game/Maps/Zone_0/Prologue/Prologue_Combat.Prologue_Combat:PersistentLevel.BPIO_Lootable_Global_WhiteCrate_8',
            '/Game/Maps/Zone_0/Prologue/Prologue_Dynamic.Prologue_Dynamic:PersistentLevel.BPIO_Lootable_Global_WhiteCrate_2',
            '/Game/Maps/Zone_0/Prologue/Prologue_Dynamic.Prologue_Dynamic:PersistentLevel.BPIO_Lootable_Global_WhiteCrate_3',
            '/Game/Maps/Zone_0/Prologue/Prologue_Terrain.Prologue_Terrain:PersistentLevel.BPIO_Lootable_Global_WhiteCrate_0',
            '/Game/Maps/Zone_0/Prologue/Prologue_Terrain.Prologue_Terrain:PersistentLevel.BPIO_Lootable_Global_WhiteCrate_2',
        ],
        (48173, 27754, -3768),
        (47247, 26181, -3768),
        (0, 240, 90),
    ),
]:

    mod.header(label)

    if len(objects) > 1:
        delta_x = (lineend[0] - linestart[0]) / (len(objects) - 1)
        delta_y = (lineend[1] - linestart[1]) / (len(objects) - 1)
        delta_z = (lineend[2] - linestart[2]) / (len(objects) - 1)
    else:
        delta_x = 0
        delta_y = 0
        delta_z = 0

    cur_x, cur_y, cur_z = linestart
    for obj_name in objects:
        mod.reg_hotfix(Mod.LEVEL,
                       level,
                       f'{obj_name}.Mesh_Chest1',
Exemple #11
0
    mod.newline()

    mod.comment('Main Menu')
    mod.table_hotfix(Mod.PATCH, '',
                     '/Game/Common/_Design/Table_MicropatchSwitches',
                     'MainMenuAltBackground', 'Value', BVC(bvc=5))
    mod.newline()

    # Challenge Rewards!
    # This object *looks* like it's set up so that the rewards that are active depend on the current
    # LeagueInstance set above, but for Bloody Harvest 2020, that didn't seem to *actually* work.
    # I have not tested this on Broken Hearts or Cartels 2021, but I'm just assuming it's similarly
    # broken, so we're setting *both* instances to the same rewards, just like we do on my Bloody
    # Harvest Enable and Broken Hearts Enable mods.
    reward_str = rewards.to_hotfix(mod)
    mod.header('Hardcode Challenge Rewards')
    mod.reg_hotfix(
        Mod.PATCH, '',
        '/Game/PatchDLC/Event2/GameData/Challenges/EventChallenges/BP_Challenge_Cartels_00_MetaChallenge.Default__BP_Challenge_Cartels_00_MetaChallenge_C',
        'TierRewardsPerInstance', f"""(
                (
                    LeagueInstance=1,
                    TierRewards={reward_str}
                ),
                (
                    LeagueInstance=2,
                    TierRewards={reward_str}
                )
            )""")
    mod.newline()
        format(level_to),
        "starting gear, then hop in to the first fight area to level up your",
        "character.  Exit the game, disable this mod, and hop back in.",
        "You'll have yourself a max-levelled character with max-level testing",
        "gear, right from the start of the game.",
        "",
        "This is obviously intended to be used alongside my EM-P5 and",
        "Transformer Super Buff mods.",
    ],
    lic=Mod.CC_BY_SA_40,
    v='1.1.0',
    cats='cheat',
)

# Taken directly from first_gun_testing_gear.bl3hotfix
mod.header('First Gun Chest Contents')

mod.reg_hotfix(
    Mod.EARLYLEVEL, 'Recruitment_P',
    '/Game/Missions/Plot/EP01_ChildrenOfTheVault/LootDef_Global_WhiteChest_ChildrenOfTheVault',
    'DefaultLoot.DefaultLoot[0].ItemAttachments', """(
            (
                ItemPool=ItemPoolData'"/Game/GameData/Loot/ItemPools/Guns/Pistols/ItemPool_Pistols_FirstGun.ItemPool_Pistols_FirstGun"',
                AttachmentPointName=TopLeft,
                Probability=(BaseValueConstant=1)
            ),
            (
                ItemPool=ItemPoolData'"/Game/Gear/Shields/_Design/_Uniques/Transformer/Balance/ItemPool_Shield_Recharger.ItemPool_Shield_Recharger"',
                AttachmentPointName=BottomRight,
                Probability=(BaseValueConstant=1)
            )
Exemple #13
0
            '/Geranium/Maps/Lodge/Lodge_TheLegendOfMcSmugger_Geo.Lodge_TheLegendOfMcSmugger_Geo:PersistentLevel.IO_GeraniumPlant_Rocksploder_3',
        ]),
        ('Town_P', [
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_10',
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_13',
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_17',
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_2',
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_21',
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_28',
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_31',
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_35',
            '/Geranium/Maps/Town/Town_Interior.Town_Interior:PersistentLevel.IO_GeraniumPlant_Rocksploder_6',
        ]),
    ]),
]:

    mod.header(attr_label)

    for level_name, io_names in data:

        mod.comment(LVL_TO_ENG[level_name])

        for io_name in io_names:

            mod.reg_hotfix(Mod.LEVEL, level_name, f'{io_name}.{attr_name}',
                           'ObjectiveRef', objref_stanza)

        mod.newline()

mod.close()
Exemple #14
0
     'gun_idx'),
    ('Artifacts',
     '/Game/GameData/Loot/ItemPools/Attributes/Att_Artifact_DropOdds',
     'artifact_idx'),
    ('COMs', '/Game/GameData/Loot/ItemPools/Attributes/Att_ClassMods_DropOdds',
     'com_idx'),
    ('Grenade Mods',
     '/Game/GameData/Loot/ItemPools/Attributes/Att_GrenadeMod_DropOdds',
     'grenade_idx'),
    ('Shields',
     '/Game/GameData/Loot/ItemPools/Attributes/Att_Shields_DropOdds',
     'shield_idx'),
    ('Eridium Sticks',
     '/Game/GameData/Loot/ItemPools/Attributes/Att_EridiumStick_DropOdds',
     'eridium_idx'),
]:
    new_att_full = Mod.get_full_cond(new_att, 'GbxAttributeData')
    mod.header(section_label)
    for poollist in poollists:
        index = getattr(poollist, attr_name)
        if index is not None:
            mod.comment(poollist.label)
            for char in poollist.chars:
                mod.reg_hotfix(
                    Mod.CHAR, char, poollist.obj_name,
                    'ItemPools.ItemPools[{}].PoolProbability.BaseValueAttribute'
                    .format(index), new_att_full)
            mod.newline()

mod.close()
        "(In other words: each customization in the pools should have an equal chance of",
        "dropping.)  This does assume you're using my No Wasted Gear mod, and playing in",
        "single player, in terms of head/skin drops.",
        "",
        "Slot machine rewards are unaffected!",
        ])

    mod = Mod(filename_full,
            'Expanded Customization Pools: {}'.format(label),
            'Apocalyptech',
            full_desc,
            lic=Mod.CC_BY_SA_40,
            )

    # Cosmetics at 3%, same as Better Loot.
    mod.header('Increased Cosmetic chances')
    mod.reg_hotfix(Mod.CHAR, 'MatchAll',
            '/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
    'MotorcadeFestival_P',
    'Lake_P',
}
cyclone_levels = {
    'Convoy_P',
    'Wetlands_P',
    'MotorcadeFestival_P',
    'Desert_P',
    'Motorcade_P',
    'CityVault_P',
    'Desolate_P',
    'City_P',
}
all_levels = outrunner_levels | technical_levels | cyclone_levels

mod.header('Remove level restrictions for parts')

for (label, table, col_name, rows) in [
    ('Vehicle Parts (table 1)',
     '/Game/Vehicles/_Shared/Design/Balance/Data/DataTable_VehiclePartsData',
     'MinGameStage_15_D986BDE142AA94D9995403BC41D5DA70', [
         'Technical_StickyBombs',
         'Technical_FlakCannon',
         'Technical_ToxicBooster',
         'Technical_FuelBarrels',
         'Outrunner_TwitchyWheels',
         'Outrunner_HoverWheels',
         'Outrunner_TeslaCoil',
         'Outrunner_FlameThrower',
         'Outrunner_ShotgunMissile',
         'Outrunner_SwarmerMissile',
    # Mod header
    mod_filename = 'movement_speed_cheats_{}.txt'.format(suffix)
    mod = Mod(mod_filename,
            'Movement Speed Cheats - {}'.format(label),
            'Apocalyptech',
            [
                "Increases character (and pet, and Iron Bear) movement speed by {}x,".format(multiplier),
                "",
                "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')
# but I had no other ideas, and this one comes from the same scene as the quote from
# the Spy mod, so it seemed fitting.
#
# Re: proc chance, the value in the on-disk datatable corresponding to chance is actually
# 50%, but that seems awfully high.  We're seeing it down to the 10% that the item card
# was reporting in its vanilla broken state.
com_name = 'Provocateur'
flavor = "First you have to know -- not fear -- know that someday you're gonna die."
proc_chance = 0.1
extra_time = 8

# Naming - we're reusing a naming object from the unreleased (and very uninteresting)
# Portals and S***e Atlas AR to do this, since this COM has no naming object of its
# own.

mod.header('Add a name to the COM')

mod.reg_hotfix(Mod.PATCH, '',
        title,
        'PartName',
        com_name,
        )

bits = []
for part, part_title in [
        ('/Game/PatchDLC/Ixora/Gear/ClassMods/_Design/OPE/L01/Part_CM_Ixora_OPE_L01',
            'NamePart_InventoryNamePartData'),
        ('/Game/PatchDLC/Ixora/Gear/ClassMods/_Design/OPE/PartSets/ClassMod_Part_Mod_Operative_Ixora_01',
            'NamePart_InventoryNamePartData_1'),
        ('/Game/PatchDLC/Ixora/Gear/ClassMods/_Design/OPE/Skills/CM_Part_Skill_OPE_DLCSkill_12',
            'NamePart_InventoryNamePartData_2'),
Exemple #19
0
]:

    full_filename = 'customization_drop_rate_{}.bl3hotfix'.format(filename)

    mod = Mod(
        full_filename,
        'Customization Drop Rate: {}'.format(label),
        'Apocalyptech',
        desc,
        contact='https://apocalyptech.com/contact.php',
        lic=Mod.CC_BY_SA_40,
        v='1.2.1',
        cats='enemy-drops',
    )

    mod.header('Set cosmetics drop chance to {}'.format(rate))
    for pool, index in [
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_StandardEnemyGunsandGear',
         9),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_BadassEnemyGunsGear', 9),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_AnointedEnemyGunsGear',
         7),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_Boss', 6),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_MiniBoss', 6),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_VaultBossEnemy', 6),
        ('/Game/PatchDLC/Dandelion/Enemies/Loader/_Shared/_Design/ItemPools/ItemPoolList_StandardEnemyGunsandGearLoader',
         9),
        ('/Game/PatchDLC/Dandelion/Enemies/Loader/_Shared/_Design/ItemPools/ItemPoolList_BadassEnemyGunsGearLoader1',
         9),
        ('/Game/PatchDLC/Dandelion/GameData/Loot/EnemyPools/ItemPoolList_StandardEnemyGunsandGear_Dandelion',
         9),
         '/Game/PatchDLC/Mayhem2/Gear/ItemPoolExpansion_Mayhem2/ItemPoolExpansion_Mayhem2_AR_Legendary',
         0, None),
        ('Pain', 'BPChar_Terror',
         '/Game/PatchDLC/Mayhem2/Gear/ItemPoolExpansion_Mayhem2/ItemPoolExpansion_Mayhem2_HW_Legendary1',
         0, None),
        ('Warden', 'BPChar_Goliath_CageArena',
         '/Game/PatchDLC/Mayhem2/Gear/ItemPoolExpansion_Mayhem2/ItemPoolExpansion_Mayhem2_HW_Legendary2',
         0, None),
        ('Anathema the Relentless', 'BPChar_GuardianBruteMiniboss',
         '/Game/PatchDLC/Takedown2/GameData/Loot/ItemPool_TD2_Miniboss', 3,
         None),
        ('Scourge the Invincible Martyr', 'BPChar_GuardianBruteBoss',
         '/Game/PatchDLC/Takedown2/GameData/Loot/ItemPool_TD2_Boss', 4, None),
    ]),
]:
    mod.header('Main Mayhem {} Unlocks'.format(mayhem_level))
    for char_name, char_obj, exp_obj, idx, att in sorted(data):
        mod.comment(char_name)
        if att:
            value = Mod.get_full_cond(att, 'GbxAttributeData')
        else:
            value = 'None'
        mod.reg_hotfix(
            Mod.CHAR, char_obj, exp_obj,
            'BalancedItems.BalancedItems[{}].Weight.BaseValueAttribute'.format(
                idx), value)
        mod.newline()

# Now update the itempool itself
mod.header('Maliwan Takedown Mayhem 4 Unlocks (Wotan / Valkyrie Squad)')
Exemple #21
0
# No read our data dumps to find the SpawnFactory objects we'll modify
for subdir in subdirs:

    # Ixora has some duplicate-short-name'd spawnoptions objects...
    if subdir == 'dlc5':
        options_dict = spawnoptions_ixora
    else:
        options_dict = spawnoptions

    full_subdir = os.path.join(base_dir, subdir)
    for level in os.listdir(full_subdir):
        print('Processing {}...'.format(level))
        #if level != 'Lake_P':
        #    continue
        mod.header('{} ({})'.format(
            LVL_TO_ENG[level],
            level,
            ))
        obj_file = os.path.join(full_subdir, level, 'UE4Tools_ObjectsDump.txt.xz')
        with lzma.open(obj_file, 'rt', encoding='utf-8') as df:
            for line in df:
                match = spawn_re.search(line)
                if match:
                    raw_number = int(match.group('raw_number'))
                    assert(raw_number > 0)
                    if match.group('spawnoption') in options_dict:
                        obj_real = '{}.{}:SpawnFactory_OakAI_{}'.format(
                                options_dict[match.group('spawnoption')],
                                match.group('spawnoption'),
                                raw_number-1,
                                )
                        mod.reg_hotfix(Mod.EARLYLEVEL, level,
Exemple #22
0
        "The mod also improves the Fabricator's recoil quite a bit.",
        "Basically just intended as a joke -- enjoy!",
        ])

    mod = Mod(f'fabricator_{config.filename}.bl3hotfix',
            f'Fabricator: {config.label}',
            'Apocalyptech',
            full_desc,
            contact='https://apocalyptech.com/contact.php',
            lic=Mod.CC_BY_SA_40,
            v='1.0.0',
            cats='joke, gear-heavy',
            videos=config.video,
            )

    mod.header('Global Definitions')

    # A rather stupid way to make the Fabricator's primary firing mode free.  Was from my initial tests,
    # but this is harder to "undo," obvs.  Leaving this in here for... uh... reasons.
    #mod.reg_hotfix(Mod.PATCH, '',
    #        base_obj,
    #        'AspectList.AspectList[5]',
    #        'None')

    # Tighten up the gear-launch spread (didn't end up bothering with this; was primarily an artifact
    # from when I wanted to try and weaponize the gun pickups themselves).
    #mod.reg_hotfix(Mod.PATCH, '',
    #        '/Game/Gear/Weapons/HeavyWeapons/Eridian/_Shared/_Design/Firing/FiringPattern_EridianFabricator',
    #        'Samples',
    #        """(
    #            StartRotation=(Pitch=0,Yaw=0,Roll=0),
Exemple #23
0
    ]),
]:

    full_filename = 'customization_drop_rate_{}.bl3hotfix'.format(filename)

    mod = Mod(
        full_filename,
        'Customization Drop Rate: {}'.format(label),
        'Apocalyptech',
        desc,
        lic=Mod.CC_BY_SA_40,
        v='1.1.0',
        cats='enemy-drops',
    )

    mod.header('Set cosmetics drop chance to {}'.format(rate))
    for pool, index in [
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_StandardEnemyGunsandGear',
         9),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_BadassEnemyGunsGear', 9),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_AnointedEnemyGunsGear',
         7),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_Boss', 6),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_MiniBoss', 6),
        ('/Game/GameData/Loot/ItemPools/ItemPoolList_VaultBossEnemy', 6),
        ('/Game/PatchDLC/Dandelion/Enemies/Loader/_Shared/_Design/ItemPools/ItemPoolList_StandardEnemyGunsandGearLoader',
         9),
        ('/Game/PatchDLC/Dandelion/Enemies/Loader/_Shared/_Design/ItemPools/ItemPoolList_BadassEnemyGunsGearLoader1',
         9),
        ('/Game/PatchDLC/Dandelion/GameData/Loot/EnemyPools/ItemPoolList_StandardEnemyGunsandGear_Dandelion',
         9),
     'BPIO_Ali_Lootable_Hyperion_RedChest'),  # Alisma
    ('Atlas Red Chests', 'BPIO_Lootable_Atlas_RedChest'),
    ('CoV Red Chests', 'BPIO_Lootable_COV_RedCrate'),
    ('Cultist Red Chests', 'BPIO_Hib_Lootable_Cultist_RedChest'),  # Hibiscus
    ('Eridian Red Chests', 'BPIO_Lootable_Eridian_RedChest'),
    ('Frostbiters Red Chests',
     'BPIO_Hib_Lootable_FrostBiters_RedChest'),  # Hibiscus
    ('Hyperion Red Chests', 'BPIO_Lootable_Hyperion_RedChest'),  # Dandelion
    ('Jakobs Red Chests', 'BPIO_Lootable_Jakobs_RedChest'),
    ('Maliwan Red Chests', 'BPIO_Lootable_Maliwan_RedChest'),
    ('Portal Red Chests', 'BPIO_Hib_Lootable_PortalChest'),  # Hibiscus
]:

    object_class = f'{object_class}_C'
    print(f'Processing {object_class}...')
    mod.header(f'{label} ({object_class})')

    cur_level = None
    for level, object_path in mo.get_by_type(object_class):

        # Mini-header if we're processing a new level
        if level != cur_level:
            if cur_level is not None:
                mod.newline()
            mod.comment(LVL_TO_ENG_LOWER[level.lower()])
            cur_level = level

        # Hotfixes
        mod.reg_hotfix(Mod.LEVEL, cur_level, object_path,
                       'PersistenceData.bStoreInSaveGame', 'False')
Exemple #25
0
        "a bunch of gear and fiddled with the numbers until the gear seems merely",
        "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
Exemple #26
0
        ],
        contact='https://apocalyptech.com/contact.php',
        lic=Mod.CC_BY_SA_40,
        v='1.0.0',
        cats='maps, vendor',
        )

# Blarg.
data = BL3Data()
spawnoption = '/Game/PatchDLC/Ixora2/InteractiveObjects/GameSystemMachines/VendingMachine/_Shared/SpawnOption_BlackMarketVendingMachine'

# First, remove the respawn timer for these.  Yes, we actually do need a Char-based hotfix
# here -- it seems that the object doesn't exist early enough for Level hotfixes (Early or
# otherwise), but Char gets it fast enough.  Go figure!  Perhaps these `Default__` values
# apply even after the objects are instantiated?
mod.header('Remove Black Market Machine Respawn Timer')
mod.comment('Yes, we *do* need a Char-based hotfix here.  It\'s a thing.')
mod.reg_hotfix(Mod.CHAR, 'MatchAll',
        '/Game/PatchDLC/Ixora2/InteractiveObjects/GameSystemMachines/VendingMachine/_Shared/BP_VendingMachine_BlackMarket.Default__BP_VendingMachine_BlackMarket_C',
        'PostUseRespawnDelaySeconds',
        0)
mod.newline()

# Now find everywhere the machine can spawn and enable each spawnpoint.
for mapobj_name in sorted(data.get_refs_to(spawnoption)):

    # I don't know that this is generally true for *all* maps in the game, but it's
    # at least true for the base-game maps which show up in here, so Good Enough.
    map_name, map_eng_name = Mod.get_level_info('{}_P'.format(mapobj_name.split('/')[-2]))
    mod.header(map_eng_name)