Skip to content

Borderlands 3 Hotfixes

CJ Kucera edited this page Oct 14, 2019 · 29 revisions

Before we get into the format of Borderlands 3 hotfixes, one thing should be made clear: as of writing (October 10, 2019), there is no real viable method of modding for Borderlands 3, and knowledge about the hotfix syntax doesn't really help much. If you're savvy enough to intercept BL3's hotfix transfer over the wire, and alter it before it gets to the game, then you can technically inject your own hotfixes into the transfer. Programs like Charles or mitmproxy can assist with that. However, you're on your own for implementing that, if it's something you want to try -- you won't find support for it in the Borderlands modding community, because it's complex and not a good solution in the long term.

If you're interested in tracking changes to the hotfixes that GBX provides for Borderlands 3, a github repo was set up which checks for hotfixes hourly and uploads new versions where appropriate. Feel free to check it out over here: https://github.com/BLCM/bl3hotfixes

The hotfixes as of Oct 8, 2019 were uploaded to a Google Sheet, which makes analyzing some of their structure a bit more easily. This may get updated over time, though no promises there: BL3 Hotfixes on Google Sheets.

It's also worth mentioning that it seems likely that this knowledge won't actually be useful for BL3 modding in the future -- BL3 doesn't natively support the set command which made hotfix alteration possible in BL2/TPS, so my personal money is on the SDK work being the way forward. Still, inquiring minds want to know...

Hotfix Keys

BL2/TPS had three different hotfix key types: SparkPatchEntry, SparkOnDemandPatchEntry, and SparkLevelPatchEntry. These were used for globally-applicable hotfixes, package-specific hotfixes (characters and vehicles), and levels-specific hotfixes, respectively.

BL3 currently has at least four hotfix keys which have been used in official hotfixes:

  • SparkPatchEntry - Globally-applicable hotfixes. Interestingly, so far all the modifications to player characters have used this kind of hotfix, which is different from how BL2/TPS would've done it.
  • SparkLevelPatchEntry - Used just like BL2/TPS's version.
  • SparkCharacterLoadedEntry - So far, all the GBX-provided hotfixes have used this to alter enemy data. Data like enemies seems to be loaded much more on-demand than it was in BL2/TPS, so enemy data won't necessarily exist on level-load, which is presumably why this one exists.
  • SparkSaveGameEntry - Presumably used to tweak incorrect values in savegames.

Additionally, there appear to be two other kinds of hotfix keys which have not been seen yet, so it's a bit difficult to know exactly how they would be used:

  • SparkPostLoadedEntry
  • SparkStreamedPackageEntry

Hotfix Values

The hotfixes used in BL3 are at least slightly different from the ones used in both BL2 and TPS, though the general syntax is still the same. Here's an example of a very simple hotfix:

(1,1,1,Crypt_P),/Game/Cinematics/_Design/NPCs/BPCine_Actor_Typhon.BPCine_Actor_Typhon_C:SkeletalMesh_GEN_VARIABLE,bEnableUpdateRateOptimizations,4,True,False

Two things will be obvious to folks already familiar with BL2/TPS hotfixes: the "package" field has been expanded, and there's an extra number inbetween the attribute and the "old" value. For clarity's sake, here's the fields split out:

  1. (1,1,1,Crypt_P)
  2. /Game/Cinematics/_Design/NPCs/BPCine_Actor_Typhon.BPCine_Actor_Typhon_C:SkeletalMesh_GEN_VARIABLE
  3. bEnableUpdateRateOptimizations
  4. 4
  5. True
  6. False

The extra number field (field 4 in the list above) is easy enough to explain: it's simply the string length of the "old" value. The string True has four characters, so the number is 4. This was presumably added in because that way it's easy to include old values which contain commas, without having to worry about quoting the values properly, etc. If the game knows the string length, it can just read that many bytes and then proceed to process the rest of the hotfix. To construct a hotfix which doesn't check for existing values (ie: a set rather than set_cmp, in BLCMM parlance), set the "from" length to zero and leave the next field blank, as usual.

The package field has been expanded to include quite a bit more information. I've been calling it a "package tuple". Two of the elements inside the tuple still have an unknown purpose. The package name, at the end, functions just like it always has - if it's empty inside a SparkLevelPatchEntry hotfix, it'll apply to all levels, etc.

The first of the numbers has always been 1 so far, so it's difficult to tell what that number means.

The second of the numbers determines the type of hotfix, and so far we've seen a few values for that: 1, 2, 4, 6, and 7. This number can have a big effect on anything looking to process hotfixes, and can alter the number of fields that show up in the rest of the hotfixes. I've been calling it a "subtype," though that term's unlikely to be what GBX calls it. See the next section for information on that.

The third number has always been either 0 or 1 so far, and nobody's proposed any ideas as to what it means.

Hotfix Subtypes

The second number in the "package" field determines the subtype of the hotfix, which will alter how the hotfix looks.

Hotfix Subtype 1: "Regular" Hotfixes

This is the most familiar-looking hotfix, such as the example above. The field list for this kind of hotfix is:

  1. Package Tuple
  2. Object Name
  3. Attribute Name
  4. "From" Length
  5. "From" Value
  6. "To" Value

Hotfix Subtype 2: DataTable Alterations

BL3 has a new data structure used in a variety of circumstances which is called a DataTable. These tables seem to have "rows" which can be referenced by name, and hotfix subtype 2 will let you specify which row to act on.

  1. Package Tuple
  2. Object Name
  3. Row Name
  4. Attribute Name
  5. "From" Length
  6. "From" Value
  7. "To" Value

For instance, here's one currently-active hotfix:

(1,2,0,),/Game/GameData/Modifiers/DataTable_Mayhem_CoreMods_Easy.DataTable_Mayhem_CoreMods_Easy,ExpGain_CombatOnly,MinValue,8,2.000000,0.100000
  1. Package: (1,2,0,)
  2. Object: /Game/GameData/Modifiers/DataTable_Mayhem_CoreMods_Easy.DataTable_Mayhem_CoreMods_Easy
  3. Row Name: ExpGain_CombatOnly
  4. Attribute: MinValue
  5. "From" Length: 8
  6. "From" Value: 2.000000
  7. "To" Value: 0.100000

Hotfix Subtype 4: Savegame Alteration?

This subtype has only been seen inside SparkSaveGameEntry hotfixes so far, of which we've only seen two examples. The currently-active one looks like:

(1,4,0,),/Game/Missions/Plot/Mission_Ep02_Sacrifice.Mission_Ep02_Sacrifice_C,1,/Game/Missions/Plot/Mission_Ep02_Sacrifice.Set_WatchMouthpieceMovie_ObjectiveSet,(8,9),(1,0),(2,2)

I haven't taken the time to try and figure out what most of those fields mean:

  1. Package
  2. Object Name
  3. Unknown Number 1
  4. Another Object Name?
  5. Unknown two-digit tuple 1
  6. Unknown two-digit tuple 2 ("from" value?)
  7. Unknown two-digit tuple 3 ("to" value?)

This type is unlikely to be useful to modders anyway, of course.

Hotfix Subtype 6: Number Array Alterations?

This subtype is somewhat mysterious as well. All examples so far have included a pipe-and-comma-delimited array of numbers, but I'm currently at a loss to figure out what it's actually doing. Here's one currently-active example:

(1,6,0,AtlasHQ_P),/Game/Maps/Zone_1/AtlasHQ,/Game/LevelArt/Environments/Promethea/AtlasHQ/Architecture/Pillars/Model/Meshes,SM_AtlasHQ_Pillar_V1,90,"-9392.000000,-2797.000000,928.000000|0.000000,0.000319,0.000000|1.500000,0.750000,1.500000",0
  1. Package
  2. Object Name
  3. Attribute name?
  4. Length of the next field
  5. Pipe-and-comma-delimited array of numbers
  6. A number. In all observed examples so far, it's been either 0 or 1

All of these have so far involved level geometry.

Hotfix Subtype 7: ???

So far, the few examples we have of these have been editing some objects which are related to player character abilities (including one which relates to guardian rank). Here's an example:

(1,7,0,),/Game/PlayerCharacters/Beastmaster/_Shared/_Design/Passives/Ranged1/Passive_Beastmaster_Ranged1.Passive_Beastmaster_Ranged1_C,0,1,ExecuteUbergraph_Passive_Beastmaster_Ranged1,1,312,8:0.100000,3:2.0
  1. Package
  2. Object Name
  3. Unknown Number 1
  4. Unknown Number 2
  5. Attribute Name?
  6. Unknown Number 3
  7. Unknown Number 4
  8. "From" Value, prefixed with the length of the "From" string by use of a colon
  9. "To" Value, prefixed with the length of the "To" string by use of a colon

Conclusion

That's it, so far! As more hotfixes get rolled out, some of the mysteries here could get cleared up. Some mysteries would probably be cleared up by just taking a closer look at the GBX-provided changelogs and matching them up to the downloaded hotfixes. One other thing that would probably help would be to have a good set of dumped data from the game, though BL3 makes that rather more complicated than the easier situation we had with BL2/TPS.

Clone this wiki locally