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('')
balances.append(f'/Game/PatchDLC/Geranium/Customizations/RoomDeco/RoomDecoration_Geranium_{num}.InvBal_RoomDecoration_Geranium_{num}') for num in [1, 2, 3]: balances.append(f'/Game/PatchDLC/Geranium/Customizations/RoomDeco/RoomDecoration_Geranium_IO_{num}.RoomDecoration_Geranium_IO_{num}') balances.append('/Game/PatchDLC/Geranium/Customizations/RoomDeco/RoomDecoration_KeyToCity.InvBal_RoomDecoration_KeyToCity') mod.comment('Room Decorations') set_pool(mod, '/Game/Pickups/Customizations/_Design/ItemPools/PlayerRoomDeco/ItemPool_Customizations_RoomDeco_Loot.ItemPool_Customizations_RoomDeco_Loot', balances) mod.newline() num_decorations = len(balances) # Now set our weighting on the main customization-drop pool mod.header('Overall customization-type weighting') # Keep the "average" weight in this pool to the default 0.05, in case anything weird happens to the # pool later. target_total = 6*0.05 total_weight = num_heads + num_skins + num_weap_skins + num_trinkets + num_echo_skins + num_decorations for idx, individual_weight in enumerate([ num_heads, num_skins, num_weap_skins, num_trinkets, num_echo_skins, num_decorations, ]): weight = individual_weight/total_weight*target_total mod.reg_hotfix(Mod.PATCH, '', '/Game/GameData/Loot/ItemPools/ItemPool_SkinsAndMisc', 'BalancedItems.BalancedItems[{}].Weight'.format(idx), BVCF(bvc=weight)) mod.close()
'/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]', """( ItemPool={}, PoolProbability={}, NumberOfTimesToSelectFromThisPool={} )""".format( Mod.get_full_cond( '/Game/GameData/Loot/ItemPools/Shields/ItemPool_Shields_All', 'ItemPoolData'), BVCF( bva= '/Game/GameData/Loot/ItemPools/Attributes/Att_Shields_DropOddsWithMayhem_Total' ), BVCF(bvc=1), )) mod.newline() # And done. mod.close()
mod.reg_hotfix( Mod.CHAR, 'MatchAll', '/Game/PatchDLC/BloodyHarvest/Missions/Side/Seasonal/BloodyHarvest_Intro/{}' .format(pool), 'ItemPools.ItemPools[{}].NumberOfTimesToSelectFromThisPool.BaseValueConstant' .format(idx), num_times) mod.newline() # Loot Ghost drops mod.comment( 'Increase quantity of drops from Loot Ghosts, and make legendaries more likely' ) mod.reg_hotfix( Mod.CHAR, 'MatchAll', '/Game/PatchDLC/BloodyHarvest/Enemies/Ghost/_Shared/LootPool/ItemPool_BH_LootGhost', 'Quantity', BVCF(bvc=7)) mod.reg_hotfix( Mod.CHAR, 'MatchAll', '/Game/PatchDLC/BloodyHarvest/Enemies/Ghost/_Shared/LootPool/ItemPool_BH_LootGhost', 'BalancedItems.BalancedItems[4].Weight.BaseValueConstant', 0.032759) mod.newline() if False: # This is something related to twitch streaming integration. I don't actually want # to include anything like that in mods, but figured I'd keep it here for reference. mod.reg_hotfix( Mod.LEVEL, heck, '/Game/GameData/Social/StreamingInteraction/Events/StreamingInteraction_Lootable_RedChest', 'LootableFilterBalanceData.LootableFilterBalanceData[2]', mod.get_full_cond( '/Game/Lootables/_Design/Data/Eridian/LootDef_Eridian_RedChest'
'only_atlas_grenades.bl3hotfix', 'Only Atlas Grenades', 'Apocalyptech', [ "While doing a Zane runthrough, I only really wanted homing grenades,", "since I didn't have a lot of control over when exactly they were", "getting thrown out (or at least I didn't care enough to try and", "control for that). So, I wanted only homing. This does that!", "", "This does *not* affect legendary grenade drops, only the regular", "sort.", ], lic=Mod.CC_BY_SA_40, v='1.0.0', cats='gear-general, gear-grenade', ) for pool_name in [ 'ItemPool_GrenadeMods_01_Common', 'ItemPool_GrenadeMods_02_Uncommon', 'ItemPool_GrenadeMods_03_Rare', 'ItemPool_GrenadeMods_04_VeryRare', ]: for idx in range(1, 6): mod.reg_hotfix( Mod.PATCH, '', '/Game/GameData/Loot/ItemPools/GrenadeMods/{}'.format(pool_name), 'BalancedItems.BalancedItems[{}].Weight'.format(idx), BVCF(bvc=0)) mod.close()
('/Game/GameData/Modifiers/DataTable_Mayhem_CoreMods_Easy', 2), ('/Game/GameData/Modifiers/DataTable_Mayhem_CoreMods_Medium', 5), ('/Game/GameData/Modifiers/DataTable_Mayhem_CoreMods_Hard', 9), ]: mod.table_hotfix(Mod.PATCH, '', table, 'ExpGain_CombatOnly', 'MinValue', default_val * xp_scale) mod.table_hotfix(Mod.PATCH, '', table, 'ExpGain_CombatOnly', 'MaxValue', default_val * xp_scale) mod.newline() # Anoint Chances mod.comment( 'Anoint drop chances -- These are currently identical to what the Farming') mod.comment( 'Frenzy event has set, apart from Mayhem 3+, which is set here to be') mod.comment('guaranteed. Possibly the Farming Frenzy rates are permanent?') for (col, values) in [('PlaythroughOne', (2.3, 1.5, 1, 0)), ('PlaythroughTwoAndBeyond', (2.3, 1.5, 1, 0))]: for row, value in zip([ 'NoneChance', 'NoneChance_Mayhem_01', 'NoneChance_Mayhem_02', 'NoneChance_Mayhem_03', ], values): mod.table_hotfix( Mod.PATCH, '', '/Game/Gear/Weapons/_Shared/_Design/EndGameParts/DropWeight/DataTable_EndGame_DropChance', row, col, BVCF(bvc=value)) mod.close()
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', 'LEGENDARY_BloodOfTerramorphous_HealthRegen', 'Multiplier', BVCF(bvc=0.03)) mod.newline() mod.close()
rapidfire = Config(filename='rapidfire', label='Rapid-Fire', desc=[ "Converts the Fabricator's primary firing mode to full auto single-gun", "firing, and the legendary mode to a full auto shotgun-like blast. The", "quantity of gear dropped on the legendary mode has been buffed up a bit", "as well, which is mildly cheaty.", ], weap_name='Vladof Fabricator', card_ammo='Shoots [skill]guns[/skill] instead of bullets!', card_cost='Requires [skill]1[/skill] Eridium per gun.', itempool_reg=fab_default_reg, itempool_reg_qty=BVCF(bvc=1), firerate_reg=6, reg_cost=1, label_reg='Gun Hose', itempool_leg=fab_default_leg, # Buffing this a bit, so we get at least 2 itempool_leg_qty=BVCF(ai='/Game/GameData/Loot/ItemPools/Init_RandomLootCount_SomeMinOne', bvs=2), firerate_leg=0.75, leg_cost=250, label_leg='Legendary Blast', ) ### ### Eridium config ###
def zero_itempoollist(hf_mode, hf_target, poollist_name, index): global mod mod.reg_hotfix(hf_mode, hf_target, poollist_name, 'ItemPools.ItemPools[{}].PoolProbability'.format(index), BVCF(bvc=0))
toc) in enumerate(data[0]['RuntimePartList']['PartTypeTOC']): if toc['NumParts'] > 0 and toc['StartIndex'] >= 0: for part_idx in range(toc['StartIndex'], toc['StartIndex'] + toc['NumParts']): part_idx_to_apl_idx[part_idx] = apl_idx # Now loop through parts apl_idxes_to_check = set() for (part_idx, part) in enumerate(data[0]['RuntimePartList']['AllParts']): if part['PartData'][1] == aug_name: do_start(mod, last_component) mod.reg_hotfix( Mod.PATCH, '', obj_name, 'RuntimePartList.AllParts.AllParts[{}].Weight'.format( part_idx), BVCF(bvc=0)) apl_idxes_to_check.add(part_idx_to_apl_idx[part_idx]) do_end(mod, last_component) # Check the PartSet for weighting, if we haven't already if len(apl_idxes_to_check) > 0: partset_name = data[0]['PartSetData'][1] partset_cat = '{} Weighting'.format(partset_name.split('/')[-1]) if partset_name not in partset_seen: partset_seen.add(partset_name) partset_data = bl3data.get_data(partset_name) if len(partset_data) != 1: raise Exception( 'PartSet with an unknown export count ({}): {}'.format( len(partset_data), partset_name)) for apl_idx in sorted(apl_idxes_to_check):
# 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: if partsource: mod.comment( 'Anointments: Always choose {} (affects anything using this anoint)' .format(part.short)) mod.reg_hotfix( Mod.PATCH, '', partsource, 'GenericParts.Parts[{}].Weight'.format( part.idx), BVCF(bvc=1)) mod.newline() else: mod.comment('Anointments: Always choose {}'.format( part.short)) mod.reg_hotfix( Mod.PATCH, '', balance_name, 'RuntimeGenericPartList.PartList[{}].Weight'. format(part.idx), BVCF(bvc=1)) mod.newline() elif num in never_vals: if partsource: mod.comment( 'Anointments: Never choose {} (affects anything using this anoint)' .format(part.short)) mod.reg_hotfix(
72), # DLCs ('/Game/PatchDLC/Dandelion/Gear/CM/_D/PartSets/_U/SRN/InvBalD_CM_Siren_DLC1', 72), ('/Game/PatchDLC/Hibiscus/Gear/ClassMods/_Design/SRN/InvBalD_CM_Siren_Hib', 72), ('/Game/PatchDLC/Alisma/Gear/ClassMods/_Design/SRN/InvBalD_CM_Siren_Alisma', 73), ]: # Set the `None` weight to zero mod.reg_hotfix( Mod.PATCH, '', bal_name, 'RuntimePartList.AllParts.AllParts[{}].Weight'.format(part_idx), BVCF(bvc=0)) # Find the category index and partset name to make sure that it's using the weight. bal_obj = data.get_data(bal_name)[0] partset_name = bal_obj['PartSetData'][1] cat_idx = 0 for idx, toc in enumerate(bal_obj['RuntimePartList']['PartTypeTOC']): if toc['StartIndex'] > part_idx: break if toc['NumParts'] > 0: cat_idx = idx # Now do those updates mod.reg_hotfix( Mod.PATCH, '', partset_name, 'ActorPartLists.ActorPartLists[{}].bUseWeightWithMultiplePartSelection'
'MinValue', default_val*xp_scale) mod.table_hotfix(Mod.PATCH, '', table, 'ExpGain_CombatOnly', 'MaxValue', default_val*xp_scale) mod.newline() # Anoint Chances mod.comment('Anoint drop chances -- These are currently identical to what the Farming') mod.comment('Frenzy event has set, apart from Mayhem 3+, which is set here to be') mod.comment('guaranteed. Possibly the Farming Frenzy rates are permanent?') for (col, values) in [ ('PlaythroughOne', (2.3, 1.5, 1, 0)), ('PlaythroughTwoAndBeyond', (2.3, 1.5, 1, 0)) ]: for row, value in zip([ 'NoneChance', 'NoneChance_Mayhem_01', 'NoneChance_Mayhem_02', 'NoneChance_Mayhem_03', ], values): mod.table_hotfix(Mod.PATCH, '', '/Game/Gear/Weapons/_Shared/_Design/EndGameParts/DropWeight/DataTable_EndGame_DropChance', row, col, BVCF(bvc=value)) mod.close()
'TechSlaughter_P', 'Towers_P', 'Watership_P', 'WetlandsBoss_P', 'WetlandsVault_P', 'Wetlands_P', ]: 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()
('/Game/PatchDLC/Alisma/GameData/Loot/EnemyPools/ItemPoolList_StandardEnemyGunsandGear_Alisma', 8), ('/Game/PatchDLC/Alisma/GameData/Loot/EnemyPools/ItemPoolList_BadassEnemyGunsGear_Alisma', 9), # Yep, it's really in there twice ('/Game/PatchDLC/Alisma/GameData/Loot/EnemyPools/ItemPoolList_Boss_Alisma', 3), ('/Game/PatchDLC/Alisma/GameData/Loot/EnemyPools/ItemPoolList_Boss_Alisma', 4), ]: # 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',
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))
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()
'/Game/PatchDLC/Ixora2/Gear/ClassMods/_Design/SRN/L01/InvBalD_CM_Ixora2_SRN_L01', ]: bal = Balance.from_data(data, bal_name) found_part = False part_idx = 0 for cat in bal.categories: for part in cat.partlist: # Our PRIMARY part will always be category index 3 if cat.index == 3 and part.part_name == 'None': # Set the weight of the `None` part to zero mod.reg_hotfix( Mod.PATCH, '', bal_name, 'RuntimePartList.AllParts.AllParts[{}].Weight'.format( part_idx), BVCF(bvc=0)) # Make sure we're using weights mod.reg_hotfix( Mod.PATCH, '', bal.partset_name, 'ActorPartLists.ActorPartLists[{}].bUseWeightWithMultiplePartSelection' .format(cat.index), 'True') # Break out of the loop found_part = True break part_idx += 1 if found_part: break mod.close()