Skip to content

Issues with Skinpools and Challenge Rewards

CJ Kucera edited this page Jun 30, 2018 · 9 revisions

It turns out there's some strange interactions which go on between the stock Borderlands 2 Challenge Rewards (where, for instance, you are awarded a skin for killing N enemies with an Assault Rifle, etc), and the UCP "Skinpool Fixes" section which reassigns skin and head pools for use by mods. This page attempts to detail the situation for anyone who might be curious what happens.

Reward Pools, and How UCP Tweaks Them

Basically, Borderlands has a "Rewards" pool for each flavor of skin/head, which contains a BalancedItems section, one for each character. For instance, here is a very abbreviated version of the BalancedItems array for GD_CustomItemPools_MainGame.Rewards.RedBoldAccent:

  BalancedItems(0)=( 
        ItmPoolDefinition=ItemPoolDefinition'GD_CustomItemPools_MainGame.Assassin.RedBoldAccent', 
        InvBalanceDefinition=None,
    )
  BalancedItems(1)=( 
        ItmPoolDefinition=ItemPoolDefinition'GD_CustomItemPools_MainGame.Mercenary.RedBoldAccent', 
        InvBalanceDefinition=None,
    )
  BalancedItems(2)=( 
        ItmPoolDefinition=ItemPoolDefinition'GD_CustomItemPools_MainGame.Siren.RedBoldAccent', 
        InvBalanceDefinition=None,
    )
  BalancedItems(3)=( 
        ItmPoolDefinition=ItemPoolDefinition'GD_CustomItemPools_MainGame.Soldier.RedBoldAccent', 
        InvBalanceDefinition=None,
    )
  BalancedItems(4)=( 
        ItmPoolDefinition=ItemPoolDefinition'GD_CustomItemPools_Lilac.Psycho.RedBoldAccent', 
        InvBalanceDefinition=None,
    )
  BalancedItems(5)=( 
        ItmPoolDefinition=ItemPoolDefinition'GD_CustomItemPools_tulip.Mechro.RedBoldAccent', 
        InvBalanceDefinition=None,
    )

Each of those sub-pools that it calls out to have a BalancedItems array itself, but with just a single item in it, which uses InvBalanceDefinition instead of ItmPoolDefinition. For instance, GD_CustomItemPools_MainGame.Assassin.RedBoldAccent looks like this:

  BalancedItems(0)=( 
        ItmPoolDefinition=None, 
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Assassin_Items_MainGame.BalanceDefs.Assassin_Skin_RedB', 
    )

So what UCP does in this "Skinpool Fixes" section, is to cut out the middleman and move the InvBalanceDefinitions up into the main Rewards pool. Nothing ever calls those middle pools directly, so they become freed up for any mod to make use of. The main Rewards pool above, for instance, ends up looking like this after all the hotfixes:

  BalancedItems(0)=( 
        ItmPoolDefinition=None,
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Assassin_Items_MainGame.BalanceDefs.Assassin_Skin_RedB',
    )
  BalancedItems(1)=( 
        ItmPoolDefinition=None,
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Assassin_Items_MainGame.BalanceDefs.Mercenary_Skin_RedB',
    )
  BalancedItems(2)=( 
        ItmPoolDefinition=None,
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Assassin_Items_MainGame.BalanceDefs.Siren_Skin_RedB',
    )
  BalancedItems(3)=( 
        ItmPoolDefinition=None,
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Assassin_Items_MainGame.BalanceDefs.Soldier_Skin_RedB',
    )
  BalancedItems(4)=( 
        ItmPoolDefinition=None,
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Psycho_Items_Lilac.BalanceDefs.Psycho_Skin_RedB',
    )
  BalancedItems(5)=( 
        ItmPoolDefinition=None, 
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Mechro_Items_Tulip.BalanceDefs.Mechro_Skin_RedB',
    )

So all six of those original pools, from GD_CustomItemPools_MainGame.Assassin.RedBoldAccent to GD_CustomItemPools_tulip.Mechro.RedBoldAccent, are now free for use. There's even a registry page here at the wiki where mod authors can claim skinpools for use in their mods: Custom Skin and Head Pool Registry

The problem with Challenge Rewards

In general, using those freed skinpools works great, and many folks might never notice any problems. But it turns out that there's an unwanted side effect relating to how Borderlands hands out challenge rewards. It turns out to be related to the Probability sections inside the main Rewards pools. I abbreviated the dump up at the top, but the full dump for one of the items in the Rewards pool looks like this:

  BalancedItems(0)=( 
        ItmPoolDefinition=ItemPoolDefinition'GD_CustomItemPools_MainGame.Assassin.RedBoldAccent', 
        InvBalanceDefinition=None, 
        Probability=( 
            BaseValueConstant=1.000000, 
            BaseValueAttribute=None, 
            InitializationDefinition=AttributeInitializationDefinition'Transient.AttributeInitializationDefinition_10', 
            BaseValueScaleConstant=1.000000 
        ), 
        bDropOnDeath=True 
    )

The problem happens because of that InitializationDefinition attribute. This is something which Borderlands dynamically assigns to the skinpools. You can try changing the ID on these pools all you want, but the game will always silently overwrite your efforts with a new Transient ID. If you dig into those objects a bit with obj dump on the console, you'll eventually find that they reference the character class that they're associated with. For instance, if you dig into that one, you'll find this:

*** Property dump for object 'PlayerClassAttributeValueResolver Transient.AttributeInitializationDefinition_10:AttributeDefinition_21.PlayerClassAttributeValueResolver_10' ***
=== PlayerClassAttributeValueResolver properties === 
  PlayerClassId=PlayerClassIdentifierDefinition'GD_PlayerClassId.Assassin'

When giving out rewards for challenges, these Transient values end up resolving to 1 if they match the class you're currently playing, or 0 otherwise. The upshot being that when you complete a challenge to the required level, and the challenge rewards you from the Rewards pool, the only item which can drop is the one which matches your character. Nifty!

Well, not so nifty, because it turns out that actually using one of our freed skinpools ends up screwing up all these Transient attributes. Sometimes, the wrong Transient IDs end up getting assigned to the wrong characters' skinpools. So for instance if you're a Siren you might end up with a Gunzerker skin. In other cases, there might end up being no skin which can drop for your given class. Very frequently, this automatic Transient magic will even end up lopping off the very last entry in the Reward pool, which means that Mechromancers won't get any rewards at all!

Clone this wiki locally