# Inventory

### Adding Inventory Items

1. Open or create a new **Inventory Database** asset. In the desired folder, right-click and select **Create -> UHFPS -> Game -> Inventory Database.**
2. To open the **Inventory Builder** window, double-click the asset or click the **Open Inventory Builder** button.
3. In the **Inventory Builder** window, click on the plus **(+)** button located on the left side near the Inventory Items label to add a new section.

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2F6ewi7wJHpltR3TNdqkyp%2F1.png?alt=media&#x26;token=6d4d7063-3e34-480d-a012-b33475c27776" alt=""><figcaption></figcaption></figure>

4. To add a new item, right-click on the section and select **Add Item**.

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2FhyvGV1rsIl7YHuz2jZYX%2F2.png?alt=media&#x26;token=3cd547f8-679f-4dd0-b212-0fbdfb66b09a" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
In order to select an item icon, you need to click on the **Select** button, which will open up the sprite selection window. It is important to ensure that the **Texture Type** item icon is set to **Sprite (2D and UI)**, otherwise you won't be able to find the icon.
{% endhint %}

5. Define the amount of space that an item will take up in the inventory by adjusting the **Width** and **Height** slider in the **Item Grid View**.

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2FDBMKRu0rA0rZu5lXsvHF%2FScreenshot_1.png?alt=media&#x26;token=b31e6c43-9216-4646-965b-99b2cc5da8c5" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
If the height of the image is greater than the width, you can invert the orientation of the image so that the icon will fit the entire space it occupies in the inventory.
{% endhint %}

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2Fmyg6QnKAXjVKhgLM9yp5%2Finv_1.png?alt=media&#x26;token=9708a3ba-ca9d-48b4-a0b5-9c81d7a7eaa7" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2Fnkt6WqCXs1UhOgzXpHxk%2Finv_2.png?alt=media&#x26;token=2886b169-d16f-4578-a64d-e4c7432bd24a" alt=""><figcaption></figcaption></figure>

6. If you have created a new **Inventory Database**, assign it to the **Inventory** component located in the **GAMEMANAGER** object.

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2Ffm1RM7unxz3cWlBQ0rj2%2F3.png?alt=media&#x26;token=e55a99ce-0133-4b93-8248-b06ebc296962" alt=""><figcaption></figcaption></figure>

7. To pickup your newly created item to the in-game inventory, change the layer of the object to **Interact** and add the **Interactable Item** component to it. Then, change the **Interactable Type** to **Inventory Item** and assign the pickup item with your item.

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2FksLqLbfhDROhqNUgXwX5%2F4.png?alt=media&#x26;token=aba73437-4aab-43c3-b94f-7a744b49465e" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The list of items is automatically generated from the **Inventory Asset** reference from the **Inventory** component. Therefore, it is necessary to have the Inventory component added to the scene and to have the Inventory Asset assigned.
{% endhint %}

{% hint style="info" %}
You can use the item title as an interact or examine title by toggling **Use Inventory Title** or **Use Examine Title** in the **Item Settings**.
{% endhint %}

{% hint style="info" %}
You can define **Item Custom Data** that can be used when using the item. To define the **Item Custom Data**, simply write whatever you want in **JSON** format.
{% endhint %}

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2Ft39JW2QeOI13ZGBG1120%2FScreenshot_2.png?alt=media&#x26;token=29e72269-dc5c-4f08-b13e-dedab5c7eae4" alt=""><figcaption></figcaption></figure>

{% embed url="<https://json.org/example.html>" %}

To access the custom data, you just need to have a reference to an **InventoryItem** that represents the item in the inventory. To get that reference, call the <mark style="color:blue;">**GetInventoryItem**</mark> function from the **Inventory** component.&#x20;

Here's the code snippet for that:

```csharp
using UHFPS.Runtime;
using UnityEngine;

public class InventoryTest : MonoBehaviour
{
    public ItemGuid Item;

    private void Start()
    {
        // get reference to the InventoryItem
        Inventory inventory = Inventory.Instance;
        var inventoryItem = inventory.GetInventoryItem(Item);
        var itemData = inventoryItem.CustomData;

        // get custom data using JObject
        var json = itemData.GetJson();
        string name1 = json["name"].ToString();
        int age1 = (int)json["age"];

        // get custom data using GetValue
        string name2 = itemData.GetValue<string>("age");
        int age2 = itemData.GetValue<int>("age");
    }
}
```

You can also have nested JSON data that you can access using the JObject reference:

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2F6bRGEOMoA6VAywnjwvVa%2FScreenshot_1.png?alt=media&#x26;token=abb6a280-9a85-4e12-841f-c9759c290081" alt=""><figcaption></figcaption></figure>

```csharp
using UHFPS.Runtime;
using UnityEngine;

public class InventoryTest : MonoBehaviour
{
    public ItemGuid Item;

    private void Start()
    {
        Inventory inventory = Inventory.Instance;
        var inventoryItem = inventory.GetInventoryItem(Item);
        var itemData = inventoryItem.CustomData;
    
        // get custom data using JObject
        var json = itemData.GetJson();
        Debug.Log(json.ToString());
    
        string name = json["name"].ToString();
        int durability = (int)json["properties"]["durability"];
        string type = json["properties"]["type"].ToString();
    
        Debug.Log($"Name: {name}, Durability: {durability}, Type: {type}");
    }
}
```

To change a JSON property value, use the JObject reference directly, but instead of casting the value to a type, simply set the value. After changing the values, use the <mark style="color:blue;">**Update()**</mark> function to save the changes in the custom data.

```csharp
using UHFPS.Runtime;
using UnityEngine;

public class InventoryTest : MonoBehaviour
{
    public ItemGuid Item;

    private void Start()
    {
        Inventory inventory = Inventory.Instance;
        var inventoryItem = inventory.GetInventoryItem(Item);
        var itemData = inventoryItem.CustomData;
    
        // set custom data using JObject
        var json = itemData.GetJson();
    
        json["name"] = "lantern";
        json["properties"]["durability"] = 50;
    
        // save json string
        itemData.Update(json);
    }
}
```

### Inventory Item Selector

To open the **Inventory Item Selector**, derive from the **IInventorySelector** interface and call the <mark style="color:blue;">**OpenItemSelector()**</mark> function on the Inventory component.&#x20;

Here's a code snippet to open the item selector:

```csharp
using UnityEngine;
using UHFPS.Runtime;

public class InventorySelector : MonoBehaviour, IInteractStart, IInventorySelector
{
    public void InteractStart()
    {
        // open inventory selection
        Inventory.Instance.OpenItemSelector(this);
    }

    public void OnInventoryItemSelect(Inventory inventory, InventoryItem selectedItem)
    {
        var itemData = selectedItem.CustomData;
        var json = itemData.GetJson();
        Debug.Log(json["name"].ToString());
    }
}
```

{% hint style="info" %}
In the **OnInventoryItemSelect()** function, you will have all the necessary references with selected item, so you can perform any desired actions with the item.
{% endhint %}

{% hint style="info" %}
To check if an item is a specific item, use the **ItemProperty** or **ItemGuid** fields and check if the selected item GUID is equal to the item reference field.
{% endhint %}

```csharp
using UnityEngine;
using UHFPS.Runtime;

public class InventorySelector : MonoBehaviour, IInteractStart, IInventorySelector
{
    public ItemProperty RequiredItem;
    // public ItemGuid RequiredItem;

    public void InteractStart()
    {
        Inventory.Instance.OpenItemSelector(this);
    }

    public void OnInventoryItemSelect(Inventory inventory, InventoryItem selectedItem)
    {
        if (selectedItem.ItemGuid != RequiredItem)
            return;

        // do something
    }
}
```

### Combinable Items

1. To define an item as a combinable item, enable the **Is Combinable** toggle in the item settings.

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2FWCXFA00KGhHI4sqqtstg%2FScreenshot_4.png?alt=media&#x26;token=a3437d31-3a27-49fa-8bec-310aacda3aa3" alt=""><figcaption></figcaption></figure>

2. Go to the **Combine Settings** and add new combinations.
3. To trigger the combine event on the player item after combining it with another item, enable the **Event After Combine** toggle.

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2Fcc434QpdVtnQ44LMq6GB%2FScreenshot_3.png?alt=media&#x26;token=fae041b6-513a-455a-bcba-b4d38d200254" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
The combine event will only trigger on the second item, so you have to make the combination for example from **Battery -> Flashlight**.

Also make sure that the second item (Flashlight) is Usable and the **Usable Typ**e is **Player Item**.
{% endhint %}

4. In the player item script that derives from the **PlayerItemBehaviour**, override the <mark style="color:blue;">**CanCombine()**</mark> and <mark style="color:blue;">**OnItemCombine()**</mark> functions.

```csharp
using UnityEngine;
using UHFPS.Runtime;

public class Flashlight : PlayerItemBehaviour
{
    public ItemGuid BatteryItem;
    private bool isEquipped;
    
    // define when you can combine battery with flashlight
    public override bool CanCombine() => isEquipped;
    
    // this function will be called when you combine battery with flashlight
    public override void OnItemCombine(InventoryItem combineItem)
    {
        if (combineItem.ItemGuid != BatteryItem)
            return;

        // do something on combine
    }
}
```

{% hint style="info" %}
To equip a player item that can only be combined, enable the **Select After Combine** toggle. After enabling this toggle, you can select the **Result Player Item**.
{% endhint %}

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2FTOBWsmWHL720YgovV3XZ%2FScreenshot_5.png?alt=media&#x26;token=737aee4a-bbff-4528-b935-d1dca6dd5ddb" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
To mirror the combine settings with the combine item, click on the **Mirror** button. This will transfer the current combination settings to the second item.
{% endhint %}

{% hint style="info" %}
You can also create craftable combinations. To enable crafting, just toggle the **Is Crafting** property. This allows you to set the required amount of the current and second item to craft the result item. The combination will work as normal, but combining items will only be enabled when the required quantities are met.
{% endhint %}

<figure><img src="https://2665493337-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh8bp6Jx5qkS4c0NEaWR1%2Fuploads%2Fumi1WGiAZ4xCAbWm9pQ1%2FScreenshot_6.png?alt=media&#x26;token=b8fb9d17-eb3c-4c03-9257-c9acc5ec9676" alt=""><figcaption></figcaption></figure>
