# Custom Loot Generation Algorithm

As development on your project progresses, you may wish to augment the chances a player has of discovering specific loot, or higher quality loot. To do this, you'll likely want to adjust the loot generation algorithm. The **Party Based RPG demo game** demo scene has an example of this, in the "Lucky" treasure box.

{% hint style="info" %}
In my own game, "*Legend of the Stones*", players will have a "*Luck*" `Stat`, and I want this value to affect the chances loot being spawned and of `ItemAttributes` being added to spawned loot.
{% endhint %}

In the demo, notice that *Lucky Treasure Box* has a new component which *Small Treasure Box* does not have. The `GenerateItemModificaitonDemo.cs` script is where the custom code lives. Open that up to check it out. It implements `IHandleLootBoxes`. (If you'd like, duplicate this script to make your own version!

<figure><img src="/files/Nv6qcUj0ZMRDOv1ayubR" alt=""><figcaption></figcaption></figure>

For the purposes of the demo, I've included a slider for a `float luckValue`, valued between `0.1f` and `1f`.  I started by copying the following methods from LootBox.cs into this new script:

* `GenerateItems()`
* `SpawnChance()`
* `GenerateAttributes()`

And I created a new method, `PlayerIsLucky()`, which returns true if a random `float` value between `0f` and `1f` is less than the set `luckValue`.

The methods were modified in only a few places, to take into account whether the `PlayerIsLucky()`.&#x20;

```csharp
// ORIGINAL
if (spawnChance < 1f && RandomFloat() > spawnChance) // If a random value is > our chances, do not spawn
{
     .....

// LUCKY VERSION
var spawnChance = SpawnChance(i, totalItemsToSpawn, itemsSetting); // Compute spawn chancesif (spawnChance < 1f 
     && (PlayerIsLucky() ? RandomFloatBestOf() : RandomFloat()) > spawnChance // If a random value is > our chances, do not spawn
{
     .....
```

The original version, if the `spawnChance` is not 100%, checks to see if a `RandomFloat()` -- a value between `0f` and `1f` -- is greater than the `spawnChance`. If true, it means we will not spawn the item. If `stopAfterFirstFailure` is `true`, then we will `return` the current list of `generatedItems`, otherwise we'll continue, and the script will move on to the next potential item.

The modified version first only checks random values if `spawnChance` is not 100%, like the original. If the `PlayerIsLucky()`, then the script will return a `float` value using the method `RandomFloatBestOf(false)`, which will give the lower of two random `float` values between `0f` and `1f`. Otherwise, the script will act as the original does, with a single `float`.&#x20;

In essence this gives a lucky player a slightly better chance of having the item spawned. There are similar modifications to the other methods. Have a look at the code to see those changes.

{% hint style="success" %}
`RandomFloatBestOf()` is a method in the `Utilities` class, under the `InfinityPBR.Modules` namespace. The default options are to provide the higher value of two rolls between `0f` and `1f`. However, you can adjust the number of rolls, the min and max values, as well as whether higher is better.

For example, this code will provide the highest value between `1f` and `10f`, out of 4 random value rolls.

`RandomFloatBestOf(true, 4, 1f, 10f);`
{% endhint %}

## How does this custom code get used?

`GameLootBox.cs` has this field, which will take in an `IHandleLootBoxes` component, such as `GenerateItemModificaitonDemo.cs` , which is populated on `Awake()`. As long as a script which implements `IHandleLootBoxes` is attached to the same object as `GameLootBox`, it will be used here.

{% code title="GameLootBox.cs" %}

```csharp
private IHandleLootBoxes _customLootBoxHandler;

private void Awake()
{
     _customLootBoxHandler = GetComponent<IHandleLootBoxes>();
}
```

{% endcode %}

When `GenerateLoot()` is called, it will pass along `IHandleLootBoxes`, which may be `null`, or may be popualted with a custom script.

{% code title="GameLootBox.cs" %}

```csharp
public void GenerateLoot(bool overwrite = true)
{
     if (!overwrite && _generated) return;
     itemObjectList = LootBox.GenerateLoot(_customLootBoxHandler).Clone(); 
     _generated = true;
            
     HandleLoot();
}
```

{% endcode %}

The `LootBox` Scriptable Object is used to compute the final items generated with the method `GenerateItems()`. However, if the handler is not null, it will call `handler.GenerateItems()` instead.

{% code title="LootBox.cs" %}

```csharp
public virtual GameItemObjectList GenerateLoot(IHandleLootBoxes handler)
{
     GameItemObjectList newList = new GameItemObjectList();
     if (handler != null)
     {
          newList.list.AddRange(itemsSettings.SelectMany(handler.GenerateItems).ToList());
     }
     else
     {
          newList.list.AddRange(itemsSettings.SelectMany(GenerateItems).ToList());
     }
     return newList;
}
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://infinitypbr.gitbook.io/magic-pig-games/game-modules-4/module-documentation/loot/custom-loot-generation-algorithm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
