Food Consumables

I have implemented a Hunger and a Thirst system as "Abilities" for UCC, this is the code im using:
Code:
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.UltimateCharacterController.Character.Abilities;
using Opsive.UltimateCharacterController.Traits;
using UnityEngine;

/// <summary>
/// Plays a starving animation when the character is out of hunger.
/// </summary>
[DefaultStartType(AbilityStartType.Manual)]
[DefaultAbilityIndex(304)] // Change this to a starving animation TO-DO
[DefaultAllowPositionalInput(false)]
[DefaultAllowRotationalInput(false)]
[DefaultUseGravity(AbilityBoolOverride.False)]
[DefaultEquippedSlots(0)]
public class Hunger : Ability
{
    [Tooltip("The name of the hunger attribute.")]
    [SerializeField] protected string m_HungerAttributeName = "Hunger";

    public string BreathAttributeName { get { return m_HungerAttributeName; } set { m_HungerAttributeName = value; } }

    private Attribute m_Attribute;
    private Attribute.AutoUpdateValue m_AutoUpdateValue;
    private Health m_Health;
    private Respawner m_Respawner;

    public override bool CanStayActivatedOnDeath { get { return true; } }

    /// <summary>
    /// Initialize the default values.
    /// </summary>
    public override void Awake()
    {
        base.Awake();

        if (string.IsNullOrEmpty(m_HungerAttributeName))
        {
            Debug.LogError("Error: A hunger attribute name on the suffocate ability must be specified.");
            return;
        }

        var attributeManager = m_GameObject.GetCachedComponent<AttributeManager>();
        if (attributeManager == null)
        {
            Debug.LogError("Error: The character must have an Attribute Manager.");
            return;
        }

        m_Attribute = attributeManager.GetAttribute(m_HungerAttributeName);
        if (m_Attribute == null)
        {
            Debug.LogError("Error: Unable to find the attribute with name " + m_HungerAttributeName + ".");
            return;
        }

        m_Health = m_GameObject.GetCachedComponent<Health>();
        m_Respawner = m_GameObject.GetCachedComponent<Respawner>();

        EventHandler.RegisterEvent(m_Attribute, "OnAttributeReachedDestinationValue", OnOutOfHunger);
        EventHandler.RegisterEvent(m_GameObject, "OnAnimatorDrownComplete", OnStarveComplete);
    }

    /// <summary>
    /// The character no longer hs any breath left.
    /// </summary>
    private void OnOutOfHunger()
    {
        if (m_Attribute.Value != m_Attribute.MinValue)
        {
            return;
        }

        StartAbility();
    }

    /// <summary>
    /// The ability has started.
    /// </summary>
    protected override void AbilityStarted()
    {
        base.AbilityStarted();

        m_AutoUpdateValue = m_Attribute.AutoUpdateValueType;
        m_Attribute.AutoUpdateValueType = Attribute.AutoUpdateValue.None;

        if (m_Health != null)
        {
            m_Health.ImmediateDeath();
        }
    }

    /// <summary>
    /// The character has finished drowning.
    /// </summary>
    private void OnStarveComplete()
    {
        if (IsActive && m_Respawner != null)
        {
            m_Respawner.Respawn();
        }

        StopAbility();
    }

    /// <summary>
    /// The ability has stopped running.
    /// </summary>
    /// <param name="force">Was the ability force stopped?</param>
    protected override void AbilityStopped(bool force)
    {
        base.AbilityStopped(force);

        m_Attribute.ResetValue();
        m_Attribute.AutoUpdateValueType = m_AutoUpdateValue;
    }

    /// <summary>
    /// The character has been destroyed.
    /// </summary>
    public override void OnDestroy()
    {
        base.OnDestroy();

        if (m_Attribute != null)
        {
            EventHandler.UnregisterEvent(m_Attribute, "OnAttributeReachedDestinationValue", OnOutOfHunger);
            EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorDrownComplete", OnStarveComplete);
        }
    }
}

I want to implement "Item Actions" for Food, a simple system that increases the Attribute of "Hunger" +10 points per food item.
how would you implement this?
 
Based on "DemoConsumneItemAction.cs" ive modified the ssscript to this:
Code:
using Opsive.UltimateInventorySystem.Core.AttributeSystem;
using Opsive.UltimateInventorySystem.Core.DataStructures;
using Opsive.UltimateInventorySystem.Demo.CharacterControl;
using Opsive.UltimateInventorySystem.ItemActions;
using Opsive.UltimateCharacterController.Traits;

/// <summary>
/// Demo Item action used to consume an item.
/// </summary>
[System.Serializable]
public class EatItemAction : ItemAction
{
    protected int m_HungerAmount;

    public int HungerAmount => m_HungerAmount;

    /// <summary>
    /// Default constructor.
    /// </summary>
    public EatItemAction()
    {
        m_Name = "Eat";
    }

    /// <summary>
    /// Can the item action be invoked.
    /// </summary>
    /// <param name="itemInfo">The item info.</param>
    /// <param name="itemUser">The item user (can be null).</param>
    /// <returns>True if it can be invoked.</returns>
    protected override bool CanInvokeInternal(ItemInfo itemInfo, ItemUser itemUser)
    {
        var item = itemInfo.Item;
        var inventory = itemInfo.Inventory;
        var character = itemUser.GetComponent<Character>();
        return item.GetAttribute<Attribute<int>>("HungerAmount") != null
               && character != null
               && inventory.MainItemCollection.HasItem((1, item));
               //&& character.CharacterDamageable.CurrentHp != character.CharacterDamageable.MaxHp;
    }

    /// <summary>
    /// Consume the item.
    /// </summary>
    /// <param name="itemInfo">The item info.</param>
    /// <param name="itemUser">The item user (can be null).</param>
    protected override void InvokeActionInternal(ItemInfo itemInfo, ItemUser itemUser)
    {
        var item = itemInfo.Item;
        var inventory = itemInfo.Inventory;
        var character = itemUser.GetComponent<Character>();
        inventory.MainItemCollection.RemoveItem(item);
        m_HungerAmount = item.GetAttribute<Attribute<int>>("HungerAmount").GetValue();
        var attributeManager = character.GetComponent<AttributeManager>();
        var hunger = attributeManager.GetAttribute("Hunger");
        hunger.Value += m_HungerAmount;
    }
}

How do i get the m_HungerAmount to be specified pper food iitem in game? Pineapples heal different amount than steak for example

P.S: i have no idea what im doing xD still learning the UIS system
 
The DemoConsumneItemAction is meant to be used with the UIS only demo scene.
I think you will find the integration script "CharacterModifyAttributeItemAction" to be more relevant. This is the Item Action we use to heal the Nolan character in the UCC/UIS integration.
There are other Item Actions specific to the UCC/UIS integration. You can find them in the Opsive/UltimateCharacterController/Integrations/UltimateInventorySystem/Scripts folder.

In the UIS editor you can add a "HungerAmount" attribute as an ItemDefinition or Item Attribute. You can get that item attribute using the function GetAttribute just like you did above:

Code:
var hungerAmount = itemInfo.Item.GetAttribute<Attribute<int>>("HungerAmount").GetValue();

You can then use the custom Item Action by setting it in your UI. There will be a video tutorial showcasing this very soon. I filmed a few during the weekend and they are pending on editing.

You'll find these pages to be useful:
 
Top