Issues with Skinpools and Ingame Rewards - BLCM/BLCMods GitHub Wiki

It turns out there's some strange interactions which go on between the stock Borderlands 2/TPS Ingame Rewards (where, for instance, you are awarded a skin for killing N enemies with an Assault Rifle, or some mission rewards), and the UCP "Skinpool Fixes" section which reassigns skin and head pools for use by mods. This actually extends to more generic skin/head drops by enemies in the game, as well. This page attempts to detail the situation for anyone who might be curious what happens.

Note that the examples in here are all from Borderlands 2, but The Pre-Sequel has the exact same problem.

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', 
    )

Fig. 1: Vanilla Borderlands Reward Pools

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_Mercenary_Items_MainGame.BalanceDefs.Mercenary_Skin_RedB',
    )
  BalancedItems(2)=( 
        ItmPoolDefinition=None,
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Siren_Items_MainGame.BalanceDefs.Siren_Skin_RedB',
    )
  BalancedItems(3)=( 
        ItmPoolDefinition=None,
        InvBalanceDefinition=InventoryBalanceDefinition'GD_Soldier_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',
    )

Fig. 2: After Skinpool Reassignments

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 some registry pages here at the wiki where mod authors can claim skinpools for use in their mods: Custom Skin and Head Pool Registry and TPS Custom Skin and Head Pool Registry.

So long as only a single item is put into these freed skinpools, everything continues to work exactly as it always has, and the missions, challenges, and enemy drops will continue to provide all the skins/heads they should:

Fig. 3: Single Item in Each Freed Pool

The Problem with Multiple Items in a Skinpool

The problem occurs when you end up adding more than one item into one of the freed skinpools. The exact behavior doesn't seem to necessarily be the same for each pool here, but in general what happens is that the game ends up removing the related skin from the Rewards pool. For instance, if you added two items to the Siren skinpool, you might end up with a situation like this:

Fig. 4: Two Items in a Freed Pool

The Reward pool now only has five items in it, and the Siren skin has become unavailable!

Mission and Challenge Rewards Specifically

Mission and Challenge rewards ends up exacerbating this problem and makes it even more noticeable. Basically, Borderlands does some magic to the Reward pools, for mission and challenge rewards (though not for enemy skin/head drops), so that when you get the reward, you only get the skin/head for the exact character you're playing. In the vanilla setup, it looks like this:

Fig. 5: Vanilla Borderlands Challenge/Mission Reward Pools

This continues to work fine with the skinpool reassignments, too, so long as only one item ever gets put into the skinpools. However, once a second item is added in, this ends up happening:

Fig. 6: Two Items in a Freed Pool w/ Challenge/Mission Rewards

Not only is the Siren skin no longer available, as before, but a Siren player will receive a Soldier skin, a Soldier player will receive a Psycho skin, a Psycho character will receive a Mechromancer, and a Mechromancer won't receive anything at all! In this scenario, Assassins and Mercenaries do receive the proper skin, at least. (It's worth noting again that this is not always the exact thing which happens, but something like this will always end up happening.)

The situation gets worse if you have more than one skinpool with 2+ items:

Fig. 7: More Mismatched skins with 2+ Items

Now nobody's getting the correct skin, and both Psychos and Mechromancers are out of luck. In the most extreme case, if all six skinpools have more than one item in them, the reward will end up dropping literally nothing for any character:

Fig. 8: No skin rewards at all, with all 2+ Items

What To Do About It

Unfortunately, not much, apart from just not putting more than one item into the skinpools. Many methods of getting around this have been tried, but so far none have actually worked. So long as there's only a single item in the used skinpool, no corruption happens to the main Reward pool, but obviously many use cases will require multiple items in a loot pool. So if you want to completely avoid mucking up Reward pools, stick to one-item pools, or figure out another way to provide the drops you want.

In general, since most users at this point probably don't actually care about skin/head drops (they can easily just be hacked into your profile with editors, etc), it's probably not a problem worth spending much energy on, but it's worth keeping in mind if you want to keep side-effects to a minimum.

Affected Reward Pools

A list of what skin/head pools are used in what circumstances can be found at the Borderlands 2 Skinpool Usage and Pre Sequel Skinpool Usage pages. The "Challenge Reward Pools" and "Mission Reward Pools" sections are the ones which are perhaps most important, since those attempt to give the user an appropriate skin for the character in-use, and that gets broken by the behavior described here. The other pools are still technically affected, though, on account of the truncation.

Skinpools To Avoid

The skinpool lists on both the Custom Skin and Head Pool Registry and TPS Custom Skin and Head Pool Registry pages have little (C) and (M) identifiers next to the skinpool name, to let you know which ones are used for challenge rewards and which ones are used for mission rewards. If you're going to be putting more than one item into a skinpool, you'd probably want to avoid using those, because they can screw up those rewards. At that point, it's pretty much just using the relevant Borderlands 2 Skinpool Usage or Pre Sequel Skinpool Usage pages to decide which of the drops you'd be okay interfering with.

Additionally, some of the pools on those lists have a (+) identifier next to them, which labels them as being "safe" to use - basically these are rewards which aren't actually given to characters ingame like the others, so screwing up the Reward pools isn't really a big deal. There aren't very many of those available, though. (There are a good number of them in TPS so long as you're willing to use Claptastic Voyage pools, though.)

The Fine Details

(This section's just here to talk about some of the finer internal details of the problem, and isn't really necessary to understand what's going on, but if you're curious, read on!)

The problem here basically stems from some information inside 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!

However, it's that automatic assignment of the Transient values which seems to screw up the pools, when there's more than one item in them. Something ends up completely cutting out the relevant item in the Reward pool, every time there's a pool with 2+ items, and you can end up with a Reward pool which doesn't even have anything in it, anymore.

This is all probably related to the Reward pools being of the type KeyedItemPoolDefinition instead of just ItemPoolDefinition like most other pool definitions. It's possible that setting some kind of Transient var could maybe prevent this kind of behavior, but so far that's not been found.