Skip to content

Tutorial: Hotfix Data

CJ Kucera edited this page Jul 10, 2018 · 13 revisions

BE FOREWARNED: HERE BE SMALL DRAGONS

It is best to understand how to use normal set commands first before diving into hotfixes. See Here

(original version of this page thanks to adudney)

What IS a hotfix?

Hotfixes behave exactly like set commands but delay taking effect until you enter the game. This allows for changing things such as skills and enemies, which only load once you're actually in game.

In general, if you can obj dump something from the console at the main menu, you can use a regular set command, but if you can't, then you'll have to use a Hotfix instead.

They are 1 of 3 types, Patch, On Demand, and Level.

  1. Patch types execute right when hitting continue / new game. They work just like normal set lines, and are unnecessary to use most of the time. Generally the only time you'll see these is in official Gearbox hotfixes.
  2. On Demand types execute when a package is loaded (such as character skills). This is best used for skills, since you can load the skill changes when the character loads. For example, GD_Siren_Streaming is loaded whenever Maya is loaded.
  3. Level types execute on changing level (such as entering Sanctuary). This is often used to make changes to enemy or boss behaviors, such as Varkid evolution chances, OOO's evolve chances, loot changes, etc. The level names to use in the hotfix can be found in the Level Name Reference page.

How do I create a hotfix?

BLCMM makes it very easy to create a hotfix: just click the "Hotfix" checkbox at the top of the code edit window. You can use the dropdown to choose whether to create a Patch, On Demand, or Level hotfix, choose the level name or package name, and optionally give the hotfix a descriptive name. The code you write continues to look just like a regular set command that you're already familiar with.

Extra Hotfix Functionality

In addition to giving you access to objects which aren't loaded by default otherwise, and providing level-and-character specific commands, hotfixes also let us do a few other things that we can't do with ordinary set statements.

Targetted Edits

One is that we can "drill into" a data structure. For instance, if you wanted to change Gettle's drop from the Lyuda to the Pitchfork with a regular set statement, which you'd do in GD_Itempools.Runnables.Pool_Gettle, you'd have to set the entire BalancedItems structure, with a statement that looks something like:

set GD_Itempools.Runnables.Pool_Gettle BalancedItems
( 
    ItmPoolDefinition=None, 
    InvBalanceDefinition=WeaponBalanceDefinition'GD_Weap_SniperRifles.A_Weapons_Legendary.Sniper_Dahl_5_Pitchfork', 
    Probability=( 
        BaseValueConstant=0.000000, 
        BaseValueAttribute=None, 
        InitializationDefinition=AttributeInitializationDefinition'GD_Balance.Weighting.Weight_1_Common', 
        BaseValueScaleConstant=1.000000 
    ), 
    bDropOnDeath=True 
)

Whereas if you used a hotfix, you'd be able to do a statement like this:

set GD_Itempools.Runnables.Pool_Gettle BalancedItems[0].InvBalanceDefinition WeaponBalanceDefinition'GD_Weap_SniperRifles.A_Weapons_Legendary.Sniper_Dahl_5_Pitchfork'

Much more concise!

Comparison Edits

The other thing that hotfixes can do is set themselves to only execute if the attribute being changed is already equal to a known value. This is basically never used in community-created mods, but Gearbox uses this in some of their official hotfixes, and there's nothing preventing mod authors from doing it as well. For instance, one of the default Gearbox hotfixes in BL2 is:

set_cmp GD_Balance.WeightingPlayerCount.BugmorphCocoon_PerPlayers_Phase1 ConditionalInitialization.ConditionalExpressionList[4].BaseValueIfTrue.BaseValueConstant 0.7 0.8

So that particular phase of Varkid evolution will be changed to 0.8, but only if it was 0.7 to begin with. If some other statement has already changed the evolution change before that hotfix has a chance to execute, the hotfix won't actually do anything.

Adding to Arrays (TPS only)

The Pre-Sequel added an interesting feature to hotfixes where you can add to an existing array without having to redefine the whole thing. For instance, one of the default Gearbox TPS hotfixes looks like this (edited a bit for length):

set GD_Population_Scavengers.Balance.Outlaws.PawnBalance_ScavWastelandWalker PlayThroughs[0].CustomItemPoolList +(ItemPool=GD_Itempools.Runnables.Pool_ScavBadassSpacemanMidget,...)

Which adds the pool GD_Itempools.Runnables.Pool_ScavBadassSpacemanMidget to Swagman's drop pool. Unfortunately, this syntax is not available in BL2.

Internal structure

FilterTool already abstracted hotfixes so that you don't need to know what they actually look like in the file, and BLCMM takes it further. When constructing hotfixes in BLCMM, you just write set statements like you're used to doing, just with an extra checkbox selected at the top of the window. So, keep in mind that you should never have to actually know any of the information in this section.

If you ever do look into the actual files themselves, though, hotfixes are structured as such:

Patch:
"<object>,<path>,<old_value>,<value>"

On Demand:
"<package>,<object>,<path>,<old_value>,<value>"

Level:
"<level>,<object>,<path>,<old_value>,<value>"

Note that level, package, and old_value can be empty.

Additionally, each hotfix has a name associated with it. If you look at the bottom of a patch file with hotfixes, you'll see two set statements:

set Transient.SparkServiceConfiguration_6 Keys ("SparkLevelPatchEntry-GBX_fixes1",...)
set Transient.SparkServiceConfiguration_6 Values (",GD_Balance.WeightingPlayerCount...",...)

So the names go into Keys and the hotfixes themselves go into Values.

Clone this wiki locally