/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Items
{
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.Shared.Inventory;
using Opsive.Shared.Utility;
using Opsive.UltimateCharacterController.Audio;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Inventory;
using Opsive.UltimateCharacterController.Items.Actions;
using Opsive.UltimateCharacterController.Items.AnimatorAudioStates;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
using Opsive.UltimateCharacterController.Networking;
using Opsive.UltimateCharacterController.Networking.Character;
#endif
using Opsive.UltimateCharacterController.Objects.CharacterAssist;
using Opsive.UltimateCharacterController.StateSystem;
using Opsive.UltimateCharacterController.Utility;
#if ULTIMATE_CHARACTER_CONTROLLER_VR
using Opsive.UltimateCharacterController.VR;
#endif
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
///
/// An item represents anything that can be picked up by the character.
///
public class Item : StateBehavior
{
[Tooltip("A reference to the object used to identify the item.")]
[UnityEngine.Serialization.FormerlySerializedAs("m_ItemType")]
[SerializeField] protected ItemDefinitionBase m_ItemDefinition;
[Tooltip("Specifies the inventory slot/spawn location of the item.")]
[SerializeField] protected int m_SlotID;
[Tooltip("Unique ID used for item identification within the animator.")]
[SerializeField] protected int m_AnimatorItemID;
[Tooltip("The movement set ID used for within the animator.")]
[SerializeField] protected int m_AnimatorMovementSetID;
[Tooltip("Does the item control the movement and the UI shown?")]
[SerializeField] protected bool m_DominantItem = true;
[Tooltip("Does the item belong to a unique ItemSet?")]
[SerializeField] protected bool m_UniqueItemSet = true;
[Tooltip("Can the camera zoom when the item is equipped?")]
[SerializeField] protected bool m_AllowCameraZoom = true;
[Tooltip("The GameObject that is dropped when the item is removed from the character.")]
[SerializeField] protected GameObject m_DropPrefab;
#if ULTIMATE_CHARACTER_CONTROLLER_VR
[Tooltip("The multiplier to apply to the velocity when the item is dropped.")]
[SerializeField] protected float m_DropVelocityMultiplier = 4;
#endif
[Tooltip("When the item is dropped should the entire item be dropped? Throwable Items will want this option enabled.")]
[SerializeField] protected bool m_FullInventoryDrop = false;
[Tooltip("Should the consumable items be dropped along with the current item?")]
[SerializeField] protected bool m_DropConsumableItems = true;
[Tooltip("Specifies if the item should wait for the OnAnimatorItemEquip animation event or wait for the specified duration before equipping.")]
[SerializeField] protected AnimationEventTrigger m_EquipEvent = new AnimationEventTrigger(true, 0.3f);
[Tooltip("Specifies if the item should wait for the OnAnimatorItemEquipComplete animation event or wait for the specified duration before stopping the equip ability.")]
[SerializeField] protected AnimationEventTrigger m_EquipCompleteEvent = new AnimationEventTrigger(false, 0f);
[Tooltip("Specifies the animator and audio state from an equip.")]
[SerializeField] protected AnimatorAudioStateSet m_EquipAnimatorAudioStateSet = new AnimatorAudioStateSet();
[Tooltip("Specifies if the item should wait for the OnAnimatorItemUnequip animation event or wait for the specified duration before unequipping.")]
[SerializeField] protected AnimationEventTrigger m_UnequipEvent = new AnimationEventTrigger(true, 0.3f);
[Tooltip("Specifies if the item should wait for the OnAnimatorItemUnequipComplete animation event or wait for the specified duration before stopping the unequip ability.")]
[SerializeField] protected AnimationEventTrigger m_UnequipCompleteEvent = new AnimationEventTrigger(false, 0);
[Tooltip("Specifies the animator and audio state from an unequip.")]
[SerializeField] protected AnimatorAudioStateSet m_UnequipAnimatorAudioStateSet = new AnimatorAudioStateSet();
[Tooltip("The ID of the UI Monitor that the item should use.")]
[SerializeField] protected int m_UIMonitorID;
[Tooltip("The sprite representing the icon.")]
[SerializeField] protected Sprite m_Icon;
[Tooltip("Should the crosshairs be shown when the item aims?")]
[SerializeField] protected bool m_ShowCrosshairsOnAim = true;
[Tooltip("The sprite used for the center crosshairs image.")]
[SerializeField] protected Sprite m_CenterCrosshairs;
[Tooltip("The offset of the quadrant crosshairs sprites.")]
[SerializeField] protected float m_QuadrantOffset = 5f;
[Tooltip("The max spread of the quadrant crosshairs sprites caused by a recoil or reload.")]
[SerializeField] protected float m_MaxQuadrantSpread = 10f;
[Tooltip("The amount of damping to apply to the spread offset.")]
[SerializeField] protected float m_QuadrantSpreadDamping = 0.05f;
[Tooltip("The sprite used for the left crosshairs image.")]
[SerializeField] protected Sprite m_LeftCrosshairs;
[Tooltip("The sprite used for the top crosshairs image.")]
[SerializeField] protected Sprite m_TopCrosshairs;
[Tooltip("The sprite used for the right crosshairs image.")]
[SerializeField] protected Sprite m_RightCrosshairs;
[Tooltip("The sprite used for the bottom crosshairs image.")]
[SerializeField] protected Sprite m_BottomCrosshairs;
[Tooltip("Should the item's full screen UI be shown?")]
[SerializeField] protected bool m_ShowFullScreenUI;
[Tooltip("The ID of the full screen UI. This must match the ID within the FullScreenItemUIMonitor.")]
[SerializeField] protected int m_FullScreenUIID = -1;
[Tooltip("Unity event that is invoked when the item is picked up.")]
[SerializeField] protected UnityEvent m_PickupItemEvent;
[Tooltip("Unity event that is invoked when the item is equipped.")]
[SerializeField] protected UnityEvent m_EquipItemEvent;
[Tooltip("Unity event that is invoked when the item is unequipped.")]
[SerializeField] protected UnityEvent m_UnequipItemEvent;
[Tooltip("Unity event that is invoked when the item is dropped.")]
[SerializeField] protected UnityEvent m_DropItemEvent;
[NonSerialized] public ItemDefinitionBase ItemDefinition {
get { return m_ItemDefinition; }
set { m_ItemDefinition = value; }
}
[NonSerialized] public int SlotID { get { return m_SlotID; } set { m_SlotID = value; } }
[NonSerialized] public int AnimatorItemID { get { return m_AnimatorItemID; } set { m_AnimatorItemID = value; } }
[NonSerialized] public int AnimatorMovementSetID { get { return m_AnimatorMovementSetID; } set { m_AnimatorMovementSetID = value; } }
public bool DominantItem { get { return m_DominantItem; }
set { m_DominantItem = value;
if (Application.isPlaying) { EventHandler.ExecuteEvent(m_Character, "OnItemUpdateDominantItem", this, m_DominantItem); }
} }
public bool UniqueItemSet { get { return m_UniqueItemSet; } set { m_UniqueItemSet = value; } }
public bool AllowCameraZoom { get { return m_AllowCameraZoom; } set { m_AllowCameraZoom = value; } }
public GameObject DropPrefab { get { return m_DropPrefab; } set { m_DropPrefab = value; } }
#if ULTIMATE_CHARACTER_CONTROLLER_VR
public float DropVelocityMultiplier { get { return m_DropVelocityMultiplier; } set { m_DropVelocityMultiplier = value; } }
#endif
public bool FullInventoryDrop { get { return m_FullInventoryDrop; } set { m_FullInventoryDrop = value; } }
public bool DropConsumableItems { get { return m_DropConsumableItems; } set { m_DropConsumableItems = value; } }
public AnimationEventTrigger EquipEvent { get { return m_EquipEvent; } set { m_EquipEvent = value; } }
public AnimationEventTrigger EquipCompleteEvent { get { return m_EquipCompleteEvent; } set { m_EquipCompleteEvent = value; } }
public AnimatorAudioStateSet EquipAnimatorAudioStateSet { get { return m_EquipAnimatorAudioStateSet; } set { m_EquipAnimatorAudioStateSet = value; } }
public AnimationEventTrigger UnequipEvent { get { return m_UnequipEvent; } set { m_UnequipEvent = value; } }
public AnimationEventTrigger UnequipCompleteEvent { get { return m_UnequipCompleteEvent; } set { m_UnequipCompleteEvent = value; } }
public AnimatorAudioStateSet UnequipAnimatorAudioStateSet { get { return m_UnequipAnimatorAudioStateSet; } set { m_UnequipAnimatorAudioStateSet = value; } }
public int UIMonitorID { get { return m_UIMonitorID; } set { m_UIMonitorID = value; } }
public Sprite Icon { get { return m_Icon; } set { m_Icon = value; } }
public bool ShowCrosshairsOnAim { get { return m_ShowCrosshairsOnAim; } set { m_ShowCrosshairsOnAim = value; } }
public Sprite CenterCrosshairs { get { return m_CenterCrosshairs; } }
public float QuadrantOffset { get { return m_QuadrantOffset; } set { m_QuadrantOffset = value; } }
public float MaxQuadrantSpread { get { return m_MaxQuadrantSpread; } set { m_MaxQuadrantSpread = value; } }
public float QuadrantSpreadDamping { get { return m_QuadrantSpreadDamping; } set { m_QuadrantSpreadDamping = value; } }
public Sprite LeftCrosshairs { get { return m_LeftCrosshairs; } }
public Sprite TopCrosshairs { get { return m_TopCrosshairs; } }
public Sprite RightCrosshairs { get { return m_RightCrosshairs; } }
public Sprite BottomCrosshairs { get { return m_BottomCrosshairs; } }
public bool ShowFullScreenUI { get { return m_ShowFullScreenUI; }
set {
m_ShowFullScreenUI = value;
if (Application.isPlaying && DominantItem && IsActive()) {
EventHandler.ExecuteEvent(m_Character, "OnItemShowFullScreenUI", m_FullScreenUIID, m_ShowFullScreenUI);
}
}
}
[NonSerialized] public int FullScreenUIID { get { return m_FullScreenUIID; } set { m_FullScreenUIID = value; } }
public UnityEvent PickupItemEvent { get { return m_PickupItemEvent; } set { m_PickupItemEvent = value; } }
public UnityEvent EquipItemEvent { get { return m_EquipItemEvent; } set { m_EquipItemEvent = value; } }
public UnityEvent UnequipItemEvent { get { return m_UnequipItemEvent; } set { m_UnequipItemEvent = value; } }
public UnityEvent DropItemEvent { get { return m_DropItemEvent; } set { m_DropItemEvent = value; } }
private GameObject m_GameObject;
protected GameObject m_Character;
protected UltimateCharacterLocomotion m_CharacterLocomotion;
private IItemIdentifier m_ItemIdentifier;
protected InventoryBase m_Inventory;
protected PerspectiveItem m_ActivePerspectiveItem;
private PerspectiveItem m_ThirdPersonPerspectiveItem;
#if FIRST_PERSON_CONTROLLER
private PerspectiveItem m_FirstPersonPerspectiveItem;
private GameObject[] m_FirstPersonObjects;
private ChildAnimatorMonitor[] m_FirstPersonObjectsAnimatorMonitor;
private ChildAnimatorMonitor m_FirstPersonPerspectiveItemAnimatorMonitor;
#endif
private ChildAnimatorMonitor m_ThirdPersonItemAnimatorMonitor;
private ItemAction[] m_ItemActions;
private Dictionary m_IDItemActionMap;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
private INetworkInfo m_NetworkInfo;
#endif
#if ULTIMATE_CHARACTER_CONTROLLER_VR
private IVRHandHandler m_HandHandler;
#endif
private bool m_Started;
private bool m_VisibleObjectActive;
private int m_UnequipDropAmount;
private Vector3 m_UnequpDropPosition;
private Quaternion m_UnequipDropRotation;
public PerspectiveItem ActivePerspectiveItem { get { return m_ActivePerspectiveItem; } }
public PerspectiveItem FirstPersonPerspectiveItem { get {
#if FIRST_PERSON_CONTROLLER
return m_FirstPersonPerspectiveItem;
#else
return null;
#endif
}
}
public IItemIdentifier ItemIdentifier { get { return m_ItemIdentifier; } set { m_ItemIdentifier = value; } }
public PerspectiveItem ThirdPersonPerspectiveItem { get { return m_ThirdPersonPerspectiveItem; } }
public ItemAction[] ItemActions { get { return m_ItemActions; } }
public bool VisibleObjectActive { get { return m_VisibleObjectActive; } }
///
/// Initialize the default values.
///
protected override void Awake()
{
m_GameObject = gameObject;
m_CharacterLocomotion = m_GameObject.GetCachedParentComponent();
m_Character = m_CharacterLocomotion.gameObject;
m_Inventory = m_Character.GetCachedComponent();
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
m_NetworkInfo = m_Character.GetCachedComponent();
#endif
#if ULTIMATE_CHARACTER_CONTROLLER_VR
m_HandHandler = m_Character.GetCachedComponent();
#endif
// Item Definitions can be assigned after the item is active.
if (m_ItemDefinition != null && m_ItemIdentifier == null) {
m_ItemIdentifier = m_ItemDefinition.CreateItemIdentifier();
}
base.Awake();
// Find the PerspectiveItems/ItemActions.
var perspectiveItems = GetComponents();
for (int i = 0; i < perspectiveItems.Length; ++i) {
// Initialize the perspective item manually to ensure an Object GameObject exists. This is important because the Item component will execute
// before the FirstPersonPerspectiveItem component, but the FirstPersonPerspectiveItem component may not be completely initialized.
// The FirstPersonPerspectiveItem component must be initialized after Item so Item.Start can be called and add the item to the inventory.
if (!perspectiveItems[i].Initialize(m_Character)) {
continue;
}
if (perspectiveItems[i].FirstPersonItem) {
#if FIRST_PERSON_CONTROLLER
var firstPersonPerspectiveItem = perspectiveItems[i] as FirstPersonController.Items.FirstPersonPerspectiveItem;
if (firstPersonPerspectiveItem.Object != null) {
var baseAnimatorMonitor = firstPersonPerspectiveItem.Object.GetComponent();
if (baseAnimatorMonitor != null) {
m_FirstPersonObjects = new GameObject[firstPersonPerspectiveItem.AdditionalControlObjects.Length + 1];
m_FirstPersonObjectsAnimatorMonitor = new ChildAnimatorMonitor[firstPersonPerspectiveItem.AdditionalControlObjects.Length + 1];
m_FirstPersonObjects[0] = baseAnimatorMonitor.gameObject;
m_FirstPersonObjectsAnimatorMonitor[0] = baseAnimatorMonitor;
for (int j = 0; j < firstPersonPerspectiveItem.AdditionalControlObjects.Length; ++j) {
m_FirstPersonObjects[j + 1] = firstPersonPerspectiveItem.AdditionalControlObjects[j];
m_FirstPersonObjectsAnimatorMonitor[j + 1] = firstPersonPerspectiveItem.AdditionalControlObjects[j].GetComponent();
}
}
} else {
// The character doesn't have a first person perspective setup.
continue;
}
m_FirstPersonPerspectiveItem = perspectiveItems[i];
var visibleItem = firstPersonPerspectiveItem.VisibleItem;
if (visibleItem != null) {
m_FirstPersonPerspectiveItemAnimatorMonitor = visibleItem.GetComponent();
}
#endif
} else {
m_ThirdPersonPerspectiveItem = perspectiveItems[i];
m_ThirdPersonItemAnimatorMonitor = perspectiveItems[i].Object != null ? perspectiveItems[i].Object.GetComponent() : null;
}
// The audio can be played from the actual visible object.
if (perspectiveItems[i].GetVisibleObject() != null) {
AudioManager.Register(perspectiveItems[i].GetVisibleObject());
}
}
// Equip/Unequip will be played from the character with a reserved index of 0.
AudioManager.Register(m_Character);
AudioManager.SetReserveCount(m_Character, 1);
m_ItemActions = GetComponents();
if (m_ItemActions.Length > 1) {
m_IDItemActionMap = new Dictionary();
for (int i = 0; i < m_ItemActions.Length; ++i) {
m_IDItemActionMap.Add(m_ItemActions[i].ID, m_ItemActions[i]);
}
}
m_EquipAnimatorAudioStateSet.DeserializeAnimatorAudioStateSelector(this, m_CharacterLocomotion);
m_UnequipAnimatorAudioStateSet.DeserializeAnimatorAudioStateSelector(this, m_CharacterLocomotion);
m_EquipAnimatorAudioStateSet.Awake(m_GameObject);
m_UnequipAnimatorAudioStateSet.Awake(m_GameObject);
EventHandler.RegisterEvent(m_Character, "OnCharacterChangePerspectives", OnChangePerspectives);
}
///
/// Adds the item to the inventory and initializes the non-local network player.
///
private void Start()
{
// Start may have already been called within Pickup.
if (m_Started) {
return;
}
m_Started = true;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
var remotePlayer = false;
// Perform any initialization for a non-local network player.
if (m_NetworkInfo != null && !m_NetworkInfo.IsLocalPlayer()) {
#if FIRST_PERSON_CONTROLLER
// First person items do not need to be updated for remote players.
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem = null;
m_FirstPersonObjects = null;
m_FirstPersonObjectsAnimatorMonitor = null;
m_FirstPersonPerspectiveItemAnimatorMonitor = null;
}
#endif
// Remote players should always be in the third person view.
OnChangePerspectives(false);
EventHandler.UnregisterEvent(m_Character, "OnCharacterChangePerspectives", OnChangePerspectives);
remotePlayer = true;
}
#endif
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem.ItemStarted();
}
#endif
if (m_ThirdPersonPerspectiveItem != null) {
m_ThirdPersonPerspectiveItem.ItemStarted();
}
SetVisibleObjectActive(false);
// Set the correct visible object for the current perspective.
if (m_CharacterLocomotion.FirstPersonPerspective
#if FIRST_PERSON_CONTROLLER
&& m_FirstPersonPerspectiveItem != null
#endif
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
&& !remotePlayer
#endif
) {
#if FIRST_PERSON_CONTROLLER
m_ActivePerspectiveItem = m_FirstPersonPerspectiveItem;
#endif
} else {
m_ActivePerspectiveItem = m_ThirdPersonPerspectiveItem;
}
// The character should ignore any of the item's colliders.
var colliders = GetComponents();
for (int i = 0; i < colliders.Length; ++i) {
m_CharacterLocomotion.AddIgnoredCollider(colliders[i]);
}
// The item may have already been added at runtime.
if (!m_Inventory.HasItem(this)) {
m_Inventory.AddItem(this, true, false);
}
}
///
/// The item has been picked up by the character.
///
public virtual void Pickup()
{
// The item will not be started if the item is picked up at runtime.
if (!m_Started) {
Start();
}
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem.Pickup();
}
#endif
if (m_ThirdPersonPerspectiveItem != null) {
m_ThirdPersonPerspectiveItem.Pickup();
}
if (m_ItemActions != null) {
for (int i = 0; i < m_ItemActions.Length; ++i) {
m_ItemActions[i].Pickup();
}
}
if (m_PickupItemEvent != null) {
m_PickupItemEvent.Invoke();
}
}
///
/// Returns the ItemAction based on the ID.
///
/// The ID of the ItemAction to retrieve.
/// The ItemAction that corresponds to the specified ID.
public ItemAction GetItemAction(int id)
{
if (m_ItemActions == null || m_ItemActions.Length == 0) {
return null;
}
if (m_ItemActions.Length == 1) {
// The ID must match.
if (m_ItemActions[0].ID == id || id == -1) {
return m_ItemActions[0];
}
return null;
}
// Multiple actions exist - look up the action based on the ID.
ItemAction itemAction;
if (m_IDItemActionMap.TryGetValue(id, out itemAction)) {
return itemAction;
}
// The action with the specified ID wasn't found.
return null;
}
///
/// The item will be equipped.
///
public void WillEquip()
{
if (m_ItemActions != null) {
for (int i = 0; i < m_ItemActions.Length; ++i) {
m_ItemActions[i].WillEquip();
}
}
}
///
/// Starts to equip the item.
///
/// Is the item being equipped immediately? Immediate equips will occur from the default loadout or quickly switching to the item.
public void StartEquip(bool immediateEquip)
{
if (immediateEquip) {
SetVisibleObjectActive(true);
} else {
// The equip AnimatorAudioState is starting.
m_EquipAnimatorAudioStateSet.StartStopStateSelection(true);
m_EquipAnimatorAudioStateSet.NextState();
}
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem.StartEquip(immediateEquip);
}
#endif
if (m_ThirdPersonPerspectiveItem != null) {
m_ThirdPersonPerspectiveItem.StartEquip(immediateEquip);
}
if (immediateEquip) {
SnapAnimator();
}
}
///
/// The item has been equipped within the inventory.
///
/// Is the item being equipped immediately? Immediate equips will occur from the default loadout or quickly switching to the item.
public void Equip(bool immediateEquip)
{
// The item will not be started if the item is picked up at runtime.
if (!m_Started) {
Pickup();
}
SetVisibleObjectActive(true);
if (!immediateEquip) {
if (m_DominantItem) {
// Optionally play an equip sound based upon the equipping animation.
m_EquipAnimatorAudioStateSet.PlayAudioClip(m_Character, 0);
}
// The item has been equipped- inform the state set.
m_EquipAnimatorAudioStateSet.StartStopStateSelection(false);
}
if (m_ItemActions != null) {
for (int i = 0; i < m_ItemActions.Length; ++i) {
m_ItemActions[i].Equip();
}
}
if (m_EquipItemEvent != null) {
m_EquipItemEvent.Invoke();
}
// Update the full screen UI property to handle the case when the preset has already been applied.
ShowFullScreenUI = m_ShowFullScreenUI;
}
///
/// Moves the item according to the horizontal and vertical movement, as well as the character velocity.
///
/// -1 to 1 value specifying the amount of horizontal movement.
/// -1 to 1 value specifying the amount of vertical movement.
public void Move(float horizontalMovement, float verticalMovement)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem.Move(horizontalMovement, verticalMovement);
}
#endif
if (m_ThirdPersonPerspectiveItem != null) {
m_ThirdPersonPerspectiveItem.Move(horizontalMovement, verticalMovement);
}
}
///
/// Starts to unequip the item.
///
/// Is the item being unequipped immediately? Immediate unequips will occur when the character dies.
public void StartUnequip(bool immediateUnequip)
{
if (!immediateUnequip) {
// The unequip AnimatorAudioState is starting.
m_UnequipAnimatorAudioStateSet.StartStopStateSelection(true);
m_UnequipAnimatorAudioStateSet.NextState();
if (m_DominantItem) {
m_UnequipAnimatorAudioStateSet.PlayAudioClip(m_Character, 0);
}
}
// Notify any item actions of the unequip.
if (m_ItemActions != null) {
for (int i = 0; i < m_ItemActions.Length; ++i) {
m_ItemActions[i].StartUnequip();
}
}
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem.StartUnequip();
}
#endif
if (m_ThirdPersonPerspectiveItem != null) {
m_ThirdPersonPerspectiveItem.StartUnequip();
}
}
///
/// The item has been unequipped within the item.
///
public void Unequip()
{
// If the item isn't a dominant item then it doesn't move the transform or set the animator parameters.
if (m_DominantItem) {
SetItemIDParameter(m_SlotID, 0);
}
// The item has been unequipped- inform the state set.
m_UnequipAnimatorAudioStateSet.StartStopStateSelection(false);
// Execute the FullScreenUI event directly without setting the variable so the varaible doesn't get reset when it is being equipped.
if (m_ShowFullScreenUI && m_DominantItem) {
EventHandler.ExecuteEvent(m_Character, "OnItemShowFullScreenUI", m_FullScreenUIID, false);
}
// When the item is unequipped it is no longer visible.
SetVisibleObjectActive(false);
// Notify any item actions of the unequip.
if (m_ItemActions != null) {
for (int i = 0; i < m_ItemActions.Length; ++i) {
m_ItemActions[i].Unequip();
}
}
// Notify the perspective items of the unequip.
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem.Unequip();
}
#endif
if (m_ThirdPersonPerspectiveItem != null) {
m_ThirdPersonPerspectiveItem.Unequip();
}
if (m_UnequipItemEvent != null) {
m_UnequipItemEvent.Invoke();
}
// Drop could have been called before the item was unequipped. Now that the item is unequipped it can be dropped.
if (m_UnequipDropAmount > 0) {
Drop(m_UnequipDropAmount, false);
}
}
///
/// Activates or deactivates the visible objects.
///
/// Should the visible object be activated?
public void SetVisibleObjectActive(bool active)
{
if (!m_Started) {
return;
}
var change = m_VisibleObjectActive != active;
m_VisibleObjectActive = active;
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem.SetActive(active);
}
#endif
if (m_ThirdPersonPerspectiveItem != null) {
m_ThirdPersonPerspectiveItem.SetActive(active);
}
// The ItemActions can execute within Update so also set the enabled state based on the active state.
for (int i = 0; i < m_ItemActions.Length; ++i) {
m_ItemActions[i].enabled = active;
}
if (change && active && m_DominantItem) {
SnapAnimator();
}
}
///
/// Returns the current PerspectiveItem object.
///
/// The current PerspectiveItem object.
public virtual GameObject GetVisibleObject()
{
return m_ActivePerspectiveItem.GetVisibleObject();
}
///
/// Is the item active?
///
/// True if the item is active.
public bool IsActive()
{
return m_VisibleObjectActive && m_ActivePerspectiveItem.IsActive();
}
///
/// Returns true if the camera can zoom.
///
/// True if the camera can zoom.
public virtual bool CanCameraZoom()
{
return m_AllowCameraZoom;
}
///
/// Synchronizes the item Animator paremeters with the character's Animator.
///
public void SnapAnimator()
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SnapAnimator();
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SnapAnimator();
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SnapAnimator();
}
}
///
/// Sets the Animator's Horizontal Movement parameter to the specified value.
///
/// The new value.
/// The time scale of the character.
/// The time allowed for the parameter to reach the value.
public void SetHorizontalMovementParameter(float value, float timeScale, float dampingTime)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetHorizontalMovementParameter(value, timeScale, dampingTime);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetHorizontalMovementParameter(value, timeScale, dampingTime);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetHorizontalMovementParameter(value, timeScale, dampingTime);
}
}
///
/// Sets the Animator's Forward Movement parameter to the specified value.
///
/// The new value.
/// The time scale of the character.
/// The time allowed for the parameter to reach the value.
public void SetForwardMovementParameter(float value, float timeScale, float dampingTime)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetForwardMovementParameter(value, timeScale, dampingTime);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetForwardMovementParameter(value, timeScale, dampingTime);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetForwardMovementParameter(value, timeScale, dampingTime);
}
}
///
/// Sets the Animator's Pitch parameter to the specified value.
///
/// The new value.
/// The time scale of the character.
/// The time allowed for the parameter to reach the value.
public void SetPitchParameter(float value, float timeScale, float dampingTime)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetPitchParameter(value, timeScale, dampingTime);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetPitchParameter(value, timeScale, dampingTime);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetPitchParameter(value, timeScale, dampingTime);
}
}
///
/// Sets the Animator's Yaw parameter to the specified value.
///
/// The new value.
/// The time scale of the character.
/// The time allowed for the parameter to reach the value.
public void SetYawParameter(float value, float timeScale, float dampingTime)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetYawParameter(value, timeScale, dampingTime);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetYawParameter(value, timeScale, dampingTime);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetYawParameter(value, timeScale, dampingTime);
}
}
///
/// Sets the Animator's Moving parameter to the specified value.
///
/// The new value.
public void SetMovingParameter(bool value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetMovingParameter(value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetMovingParameter(value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetMovingParameter(value);
}
}
///
/// Sets the Animator's Aiming parameter to the specified value.
///
/// The new value.
public void SetAimingParameter(bool value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetAimingParameter(value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetAimingParameter(value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetAimingParameter(value);
}
}
///
/// Sets the Animator's Movement Set ID parameter to the specified value.
///
/// The new value.
public void SetMovementSetIDParameter(int value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetMovementSetIDParameter(value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetMovementSetIDParameter(value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetMovementSetIDParameter(value);
}
}
///
/// Sets the Animator's Ability Index parameter to the specified value.
///
/// The new value.
public void SetAbilityIndexParameter(int value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetAbilityIndexParameter(value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetAbilityIndexParameter(value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetAbilityIndexParameter(value);
}
}
///
/// Sets the Animator's Int Data parameter to the specified value.
///
/// The new value.
public void SetAbilityIntDataParameter(int value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetAbilityIntDataParameter(value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetAbilityIntDataParameter(value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetAbilityIntDataParameter(value);
}
}
///
/// Sets the Animator's Float Data parameter to the specified value.
///
/// The new value.
/// The time scale of the character.
/// The time allowed for the parameter to reach the value.
/// True if the parameter was changed.
public void SetAbilityFloatDataParameter(float value, float timeScale, float dampingTime)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetAbilityFloatDataParameter(value, timeScale, dampingTime);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetAbilityFloatDataParameter(value, timeScale, dampingTime);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetAbilityFloatDataParameter(value, timeScale, dampingTime);
}
}
///
/// Sets the Animator's Speed parameter to the specified value.
///
/// The new value.
/// The time scale of the character.
/// The time allowed for the parameter to reach the value.
public void SetSpeedParameter(float value, float timeScale, float dampingTime)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetSpeedParameter(value, timeScale, dampingTime);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetSpeedParameter(value, timeScale, dampingTime);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetSpeedParameter(value, timeScale, dampingTime);
}
}
///
/// Sets the Animator's Height parameter to the specified value.
///
/// The new value.
public void SetHeightParameter(int value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetHeightParameter(value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetHeightParameter(value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetHeightParameter(value);
}
}
///
/// Sets the Animator's Item ID parameter with the indicated slot to the specified value.
///
/// The slot that the item occupies.
/// The new value.
public void SetItemIDParameter(int slotID, int value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetItemIDParameter(slotID, value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetItemIDParameter(slotID, value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetItemIDParameter(slotID, value);
}
}
///
/// Sets the Animator's Item State Index parameter with the indicated slot to the specified value.
///
/// The slot that the item occupies.
/// The new value.
public void SetItemStateIndexParameter(int slotID, int value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetItemStateIndexParameter(slotID, value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetItemStateIndexParameter(slotID, value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetItemStateIndexParameter(slotID, value);
}
}
///
/// Sets the Animator's Item Substate Index parameter with the indicated slot to the specified value.
///
/// The slot of that item that should be set.
/// The new value.
public void SetItemSubstateIndexParameter(int slotID, int value)
{
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonObjectsAnimatorMonitor != null) {
for (int i = 0; i < m_FirstPersonObjectsAnimatorMonitor.Length; ++i) {
if (!m_FirstPersonObjects[i].activeSelf) {
continue;
}
m_FirstPersonObjectsAnimatorMonitor[i].SetItemSubstateIndexParameter(slotID, value);
}
}
if (m_FirstPersonPerspectiveItemAnimatorMonitor != null && m_FirstPersonPerspectiveItem.IsActive()) {
m_FirstPersonPerspectiveItemAnimatorMonitor.SetItemSubstateIndexParameter(slotID, value);
}
#endif
if (m_ThirdPersonItemAnimatorMonitor != null && m_ThirdPersonPerspectiveItem.IsActive()) {
m_ThirdPersonItemAnimatorMonitor.SetItemSubstateIndexParameter(slotID, value);
}
}
///
/// The character perspective between first and third person has changed.
///
/// Is the character in a first person perspective?
protected virtual void OnChangePerspectives(bool firstPersonPerspective)
{
// The object isn't active if it isn't equipped. OnChangePerspective will be sent to all items regardless of whether or not they are equipped.
var isActive = m_ActivePerspectiveItem != null && m_ActivePerspectiveItem.IsActive();
if (firstPersonPerspective) {
#if FIRST_PERSON_CONTROLLER
m_ActivePerspectiveItem = m_FirstPersonPerspectiveItem;
#endif
} else {
m_ActivePerspectiveItem = m_ThirdPersonPerspectiveItem;
}
if (isActive) {
m_ActivePerspectiveItem.SetActive(true);
}
}
///
/// Drop the item from the character.
///
/// Should the item be dropped even if the inventory doesn't contain any count for the item?
/// The amount of ItemIdentifier that should be dropped.
/// Should the item be removed after it is dropped?
public void Drop(int amount, bool forceDrop)
{
Drop(amount, forceDrop, true);
}
///
/// Drop the item from the character.
///
/// Should the item be dropped even if the inventory doesn't contain any count for the item?
/// The amount of ItemIdentifier that should be dropped.
/// Should the item be removed after it is dropped?
public void Drop(int amount, bool forceDrop, bool remove)
{
// The item needs to first be unequipped before it can be dropped.
if (m_VisibleObjectActive && m_CharacterLocomotion.FirstPersonPerspective && remove) {
m_UnequipDropAmount = amount;
var itemObject = GetVisibleObject().transform;
m_UnequpDropPosition = itemObject.position;
m_UnequipDropRotation = itemObject.rotation;
return;
}
ItemPickupBase itemPickup = null;
// If a drop prefab exists then the character should drop a prefab of the item so it can later be picked up.
if (m_DropPrefab != null) {
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo == null || m_NetworkInfo.IsServer()) {
#endif
var existingAmount = m_Inventory.GetItemIdentifierAmount(m_ItemIdentifier);
if (existingAmount > 0) {
// If the usable item prevents the item from being equipped when empty, and the usable item is empty, then the item
// should not be dropped.
for (int i = 0; i < m_ItemActions.Length; ++i) {
var usableItem = (m_ItemActions[i] as UsableItem);
if (usableItem != null && usableItem.GetConsumableItemIdentifier() != null &&
!usableItem.CanEquipEmptyItem && m_Inventory.GetItemIdentifierAmount(usableItem.GetConsumableItemIdentifier()) == 0) {
existingAmount = 0;
break;
}
}
}
// The prefab can be dropped if the inventory contains the item or is force dropped.
if (existingAmount > 0 || forceDrop) {
Vector3 dropPosition;
Quaternion dropRotation;
// If the item is unequipped before it is dropped then it could be holstered so the current transform should not be used.
if (m_UnequipDropAmount > 0) {
dropPosition = m_UnequpDropPosition;
dropRotation = m_UnequipDropRotation;
} else {
var itemObject = GetVisibleObject().transform;
dropPosition = itemObject.position;
dropRotation = itemObject.rotation;
}
var spawnedObject = ObjectPool.Instantiate(m_DropPrefab, dropPosition, dropRotation);
// The ItemPickup component is responsible for allowing characters to pick up the item. Save the ItemIdentifier count
// to the ItemIdentifierAmount array so that same amount can be picked up again.
itemPickup = spawnedObject.GetCachedComponent();
if (itemPickup != null) {
// Return the old.
var itemDefinitionAmounts = itemPickup.GetItemDefinitionAmounts();
var itemDefinitionAmount = new ItemDefinitionAmount(m_ItemIdentifier.GetItemDefinition(), Mathf.Min(existingAmount, amount));
// If the dropped Item is a usable item then the array should be larger to be able to pick up the usable ItemIdentifier.
var consumableItemIdentifiers = 0;
UsableItem usableItem;
if (m_DropConsumableItems) {
for (int i = 0; i < m_ItemActions.Length; ++i) {
if ((usableItem = (m_ItemActions[i] as UsableItem)) != null &&
usableItem.GetConsumableItemIdentifier() != null && usableItem.GetConsumableItemIdentifierAmount() != -1) {
consumableItemIdentifiers++;
}
}
}
// Save the main ItemIdentifier.
var length = consumableItemIdentifiers + 1;
if (itemDefinitionAmounts.Length != length) {
itemDefinitionAmounts = new ItemDefinitionAmount[length];
}
itemDefinitionAmounts[0] = itemDefinitionAmount;
// Save the usable ItemIdentifier if any exist.
if (m_DropConsumableItems) {
IItemIdentifier consumableItemIdentifier;
consumableItemIdentifiers = 1;
for (int i = 0; i < m_ItemActions.Length; ++i) {
if ((usableItem = (m_ItemActions[i] as UsableItem)) != null && (consumableItemIdentifier = usableItem.GetConsumableItemIdentifier()) != null &&
usableItem.GetConsumableItemIdentifierAmount() != -1) {
var consumableDropCount = 0;
// Only remove the remaining inventory if there is just one ItemIdentifier remaining. This will allow the character to keep the consumable ammo
// if only one item is dropped and the character has multiple of the same item.
if (existingAmount == 1) {
consumableDropCount = m_Inventory.GetItemIdentifierAmount(consumableItemIdentifier);
}
var remainingConsumableAmount = usableItem.GetConsumableItemIdentifierAmount(); // The count may be negative (for use by the UI).
var consumableDefinitionAmount = new ItemDefinitionAmount(consumableItemIdentifier.GetItemDefinition(), consumableDropCount + (remainingConsumableAmount > 0 ? remainingConsumableAmount : 0));
itemDefinitionAmounts[consumableItemIdentifiers] = consumableDefinitionAmount;
consumableItemIdentifiers++;
}
}
}
// Enable the ItemPickup.
itemPickup.SetItemDefinitionAmounts(itemDefinitionAmounts);
itemPickup.Initialize(true);
}
// The ItemPickup may have a TrajectoryObject attached instead of a Rigidbody.
var trajectoryObject = spawnedObject.GetCachedComponent();
if (trajectoryObject != null) {
var velocity = m_CharacterLocomotion.Velocity;
#if ULTIMATE_CHARACTER_CONTROLLER_VR
if (m_HandHandler != null) {
velocity += m_HandHandler.GetVelocity(m_SlotID) * m_DropVelocityMultiplier;
}
#endif
trajectoryObject.Initialize(velocity, m_CharacterLocomotion.Torque.eulerAngles, m_Character);
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo != null) {
Networking.Game.NetworkObjectPool.NetworkSpawn(m_DropPrefab, spawnedObject, true);
}
#endif
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
}
#endif
}
if (remove) {
m_UnequipDropAmount = 0;
Remove();
}
if (m_DropItemEvent != null) {
m_DropItemEvent.Invoke();
}
}
///
/// Removes the item from the character.
///
public void Remove()
{
SetVisibleObjectActive(false);
#if FIRST_PERSON_CONTROLLER
if (m_FirstPersonPerspectiveItem != null) {
m_FirstPersonPerspectiveItem.Remove();
}
#endif
if (m_ThirdPersonPerspectiveItem != null) {
m_ThirdPersonPerspectiveItem.Remove();
}
if (m_ItemActions != null) {
for (int i = 0; i < m_ItemActions.Length; ++i) {
m_ItemActions[i].Remove();
}
}
}
///
/// The GameObject has been destroyed.
///
protected virtual void OnDestroy()
{
m_EquipAnimatorAudioStateSet.OnDestroy();
m_UnequipAnimatorAudioStateSet.OnDestroy();
EventHandler.UnregisterEvent(m_Character, "OnCharacterChangePerspectives", OnChangePerspectives);
}
///
/// Spawns the item under the specified character.
///
/// The character that should parent the item.
/// The item that should be spawned.
/// The spawned item GameObject.
public static Item SpawnItem(GameObject character, Item item)
{
// Spawn the item under the character's ItemPlacement GameObject.
var itemPlacement = character.GetComponentInChildren(true);
if (itemPlacement == null) {
Debug.LogError($"Error: ItemPlacement doesn't exist under the character {character.name}.");
return null;
}
var itemGameObject = ObjectPool.Instantiate(item.gameObject, Vector3.zero, Quaternion.identity, itemPlacement.transform);
itemGameObject.name = item.name;
itemGameObject.transform.localPosition = Vector3.zero;
itemGameObject.transform.localRotation = Quaternion.identity;
return itemGameObject.GetComponent- ();
}
}
}