This commit is contained in:
2026-06-09 09:18:17 +07:00
parent 3578a2750c
commit 71a096556a
5777 changed files with 6675 additions and 13 deletions

View File

@@ -1,43 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Inventory;
using Opsive.Shared.Utility;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// A Category contains a grouping of ItemTypes.
/// </summary>
[System.Serializable]
public class Category : ScriptableObject, IItemCategoryIdentifier
{
[Tooltip("The ID of the category.")]
[SerializeField] protected uint m_ID;
public uint ID { get { if (RandomID.IsIDEmpty(m_ID)) { m_ID = RandomID.Generate(); } return m_ID; } set { m_ID = value; } }
private Category[] m_Parents;
public Category[] Parents { set { m_Parents = value; } }
/// <summary>
/// Returns a read only array of the direct parents of the current category.
/// </summary>
/// <returns>The direct parents of the current category.</returns>
public IReadOnlyList<IItemCategoryIdentifier> GetDirectParents()
{
return m_Parents as IReadOnlyList<IItemCategoryIdentifier>;
}
/// <summary>
/// Returns a string representation of the object.
/// </summary>
/// <returns>A string representation of the object.</returns>
public override string ToString() { return name; }
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3ee2c1a75ff367a42ba5f16bd97e5519
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 60a4914a9917cb94c81ebda228bd3488, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,273 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Inventory;
using Opsive.UltimateCharacterController.Items;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Implements InventoryBase - adds a basic inventory to the character controller.
/// </summary>
public class Inventory : InventoryBase
{
[Tooltip("Items to load when the Inventory is initially created or on a character respawn.")]
[UnityEngine.Serialization.FormerlySerializedAs("m_ItemTypeCount")]
[SerializeField] protected ItemDefinitionAmount[] m_DefaultLoadout;
private Dictionary<IItemIdentifier, Item>[] m_ItemIdentifierMap;
private Dictionary<IItemIdentifier, int> m_ItemIdentifierAmount = new Dictionary<IItemIdentifier, int>();
private Item[] m_ActiveItem;
public ItemDefinitionAmount[] DefaultLoadout { get { return m_DefaultLoadout; } set { m_DefaultLoadout = value; } }
/// <summary>
/// Initialize the default values.
/// </summary>
protected override void Awake()
{
base.Awake();
m_ItemIdentifierMap = new Dictionary<IItemIdentifier, Item>[m_SlotCount];
for (int i = 0; i < m_SlotCount; ++i) {
m_ItemIdentifierMap[i] = new Dictionary<IItemIdentifier, Item>();
}
m_ActiveItem = new Item[m_SlotCount];
}
/// <summary>
/// Pick up each ItemIdentifier within the DefaultLoadout.
/// </summary>
public override void LoadDefaultLoadout()
{
if (m_DefaultLoadout != null) {
for (int i = 0; i < m_DefaultLoadout.Length; ++i) {
Pickup(m_DefaultLoadout[i].ItemIdentifier, m_DefaultLoadout[i].Amount, -1, true, false);
}
}
}
/// <summary>
/// Internal method which determines if the character has the specified item.
/// </summary>
/// <param name="item">The item to check against.</param>
/// <returns>True if the character has the item.</returns>
protected override bool HasItemInternal(Item item)
{
if (item == null) {
return false;
}
return GetItemInternal(item.ItemIdentifier, item.SlotID) != null;
}
/// <summary>
/// Adds the item to the inventory. This does not add the actual ItemIdentifier - PickupItem does that.
/// </summary>
/// <param name="item">The item to add.</param>
/// <returns>True if the item was added to the inventory.</returns>
protected override bool AddItemInternal(Item item)
{
if (item.ItemDefinition == null) {
Debug.LogError($"Error: Item {item.gameObject.name} has no ItemDefinition.");
return false;
}
if (m_ItemIdentifierMap == null) {
Debug.LogError($"Error: Unable to add {item.gameObject.name} because the inventory component doesn't exist.");
return false;
}
if (item.SlotID >= m_ItemIdentifierMap.Length) {
Debug.LogError($"Error: Unable to add {item.gameObject.name} because the slot id is greater than the number of slots that exist in the inventory.");
return false;
}
var itemIdentifier = item.ItemIdentifier;
if (itemIdentifier == null) {
itemIdentifier = item.ItemDefinition.CreateItemIdentifier();
}
// The item may already exist in the inventory.
if (m_ItemIdentifierMap[item.SlotID].ContainsKey(itemIdentifier)) {
return false;
}
// The item doesn't exist - add it.
m_ItemIdentifierMap[item.SlotID].Add(itemIdentifier, item);
// The item can be added without being picked up yet - add to the ItemIdentifierAmount so the item can safely be removed.
if (!m_ItemIdentifierAmount.ContainsKey(itemIdentifier)) {
m_ItemIdentifierAmount.Add(itemIdentifier, 0);
}
return true;
}
/// <summary>
/// Adds the specified amount of the ItemIdentifier to the inventory.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to add.</param>
/// <param name="amount">The amount of ItemIdentifier to add.</param>
/// <returns>True if the ItemIdentifier was picked up.</returns>
protected override bool PickupInternal(IItemIdentifier itemIdentifier, int amount)
{
if (!m_ItemIdentifierAmount.TryGetValue(itemIdentifier, out var existingAmount)) {
if (itemIdentifier is ItemType) {
var itemType = itemIdentifier as ItemType;
m_ItemIdentifierAmount.Add(itemIdentifier, Mathf.Min(amount, itemType.Capacity));
} else {
m_ItemIdentifierAmount.Add(itemIdentifier, amount);
}
} else {
if (itemIdentifier is ItemType) {
var itemType = itemIdentifier as ItemType;
// The ItemType was not picked up if it is already at capacity.
if (existingAmount == itemType.Capacity) {
return false;
}
m_ItemIdentifierAmount[itemIdentifier] = Mathf.Clamp(existingAmount + amount, 0, itemType.Capacity);
} else {
m_ItemIdentifierAmount[itemIdentifier] = existingAmount + amount;
}
}
return true;
}
/// <summary>
/// Internal method which returns the active item in the specified slot.
/// </summary>
/// <param name="slotID">The ID of the slot which the item belongs to.</param>
/// <returns>The active item which occupies the specified slot. Can be null.</returns>
protected override Item GetActiveItemInternal(int slotID)
{
if (slotID < -1 || slotID >= m_ItemIdentifierMap.Length) {
return null;
}
return m_ActiveItem[slotID];
}
/// <summary>
/// Internal method which returns the item that corresponds to the specified ItemIdentifier.
/// </summary>
/// <param name="slotID">The ID of the slot which the item belongs to.</param>
/// <param name="itemIdentifier">The ItemIdentifier of the item.</param>
/// <returns>The item which occupies the specified slot. Can be null.</returns>
protected override Item GetItemInternal(IItemIdentifier itemIdentifier, int slotID)
{
if (itemIdentifier == null || slotID < -1 || slotID >= m_ItemIdentifierMap.Length) {
return null;
}
if (m_ItemIdentifierMap[slotID].TryGetValue(itemIdentifier, out var item)) {
return item;
}
return null;
}
/// <summary>
/// Internal method which equips the ItemIdentifier in the specified slot.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to equip.</param>
/// <param name="slotID">The ID of the slot.</param>
/// <returns>The item which corresponds to the ItemIdentifier. Can be null.</returns>
protected override Item EquipItemInternal(IItemIdentifier itemIdentifier, int slotID)
{
if (itemIdentifier == null || slotID < -1 || slotID >= m_ItemIdentifierMap.Length) {
return null;
}
// The ItemIdentifier has to exist in the inventory.
if (!m_ItemIdentifierMap[slotID].TryGetValue(itemIdentifier, out var item)) {
Debug.LogError($"Error: Unable to equip item with ItemIdentifier {itemIdentifier}: the itemIdentifier hasn't been added to the inventory.");
return null;
}
m_ActiveItem[slotID] = item;
return item;
}
/// <summary>
/// Internal method which unequips the item in the specified slot.
/// </summary>
/// <param name="slotID">The ID of the slot.</param>
/// <returns>The item that was unequipped.</returns>
protected override Item UnequipItemInternal(int slotID)
{
if (slotID < -1 || slotID >= m_ItemIdentifierMap.Length) {
return null;
}
var prevItem = m_ActiveItem[slotID];
m_ActiveItem[slotID] = null;
return prevItem;
}
/// <summary>
/// Internal method which returns the amount of the specified ItemIdentifier.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to get the amount of.</param>
/// <returns>The amount of the specified ItemIdentifier.</returns>
protected override int GetItemIdentifierAmountInternal(IItemIdentifier itemIdentifier)
{
m_ItemIdentifierAmount.TryGetValue(itemIdentifier, out var amount);
return amount;
}
/// <summary>
/// Internal method which adjusts the amount of the specified ItemIdentifier.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to adjust.</param>
/// <param name="amount">The amount of ItemIdentifier to adjust.</param>
protected override void AdjustItemIdentifierAmountInternal(IItemIdentifier itemIdentifier, int amount)
{
if (!m_ItemIdentifierAmount.TryGetValue(itemIdentifier, out var existingAmount)) {
Debug.LogError($"Error: Trying to use item {itemIdentifier} when the ItemIdentifier doesn't exist.");
return;
}
if (itemIdentifier is ItemType) {
var itemType = itemIdentifier as ItemType;
m_ItemIdentifierAmount[itemIdentifier] = Mathf.Clamp(existingAmount + amount, 0, itemType.Capacity);
} else {
m_ItemIdentifierAmount[itemIdentifier] = existingAmount + amount;
}
}
/// <summary>
/// Internal method which removes the ItemIdentifier from the inventory.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to remove.</param>
/// <param name="slotID">The ID of the slot.</param>
/// <param name="amount">The amount of ItemIdentifier that should be removed.</param>
/// <returns>The item that was removed (can be null).</returns>
protected override void RemoveItemIdentifierInternal(IItemIdentifier itemIdentifier, int slotID, int amount)
{
if (itemIdentifier == null || !(itemIdentifier is ItemType) || slotID < -1 ||
slotID >= m_ItemIdentifierMap.Length || !m_ItemIdentifierAmount.TryGetValue(itemIdentifier, out var existingAmount)) {
return;
}
if (!m_ItemIdentifierMap[slotID].TryGetValue(itemIdentifier, out var item)) {
// Remove the ItemIdentifier. This ItemIdentifier does not correspond to an item so it should be completely removed.
m_ItemIdentifierAmount[itemIdentifier] = 0;
return;
}
// Remove a single Item. The character may be carrying multiple of the same ItemIdentifier in the case of dual wielding.
var itemType = itemIdentifier as ItemType;
m_ItemIdentifierAmount[itemType] = Mathf.Clamp(item.FullInventoryDrop ? 0 : (existingAmount - 1), 0, itemType.Capacity);
if (slotID == -1) {
return;
}
// The item should no longer be equipped.
if (m_ActiveItem[slotID] != null && m_ActiveItem[slotID].ItemIdentifier == itemIdentifier) {
m_ActiveItem[slotID] = null;
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e2fc3c5ec9fe8c241bc7a9c89fb57734
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -102
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,649 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Events;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
using Opsive.Shared.Game;
#endif
using Opsive.Shared.Inventory;
using Opsive.UltimateCharacterController.Events;
using Opsive.UltimateCharacterController.Items;
using Opsive.UltimateCharacterController.Items.Actions;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
using Opsive.UltimateCharacterController.Networking;
using Opsive.UltimateCharacterController.Networking.Character;
#endif
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Provides a common base class for any character Inventory.
/// </summary>
public abstract class InventoryBase : MonoBehaviour
{
[Tooltip("Should all of the IItemIdentifier be removed when the character dies?")]
[SerializeField] protected bool m_RemoveAllOnDeath = true;
[Tooltip("Should the default loadout be loaded when the character respawns?")]
[SerializeField] protected bool m_LoadDefaultLoadoutOnRespawn = true;
[Tooltip("The name of the state when the inventory is unequipped.")]
[SerializeField] protected string m_UnequippedStateName = "Unequipped";
[Tooltip("Unity event that is invoked when an item is initially added to the inventory.")]
[SerializeField] protected UnityItemEvent m_OnAddItemEvent;
[Tooltip("Unity event that is invoked when an IItemIdentifier is picked up.")]
[SerializeField] protected UnityItemIdentifierFloatBoolBoolEvent m_OnPickupItemIdentifierEvent;
[Tooltip("Unity event that is invoked when an item is picked up.")]
[SerializeField] protected UnityItemFloatBoolBoolEvent m_OnPickupItemEvent;
[Tooltip("Unity event that is invoked when an item is equipped.")]
[SerializeField] protected UnityItemIntEvent m_OnEquipItemEvent;
[Tooltip("Unity event that is invoked when an IItemIdentifier is adjusted.")]
[SerializeField] protected UnityItemIdentifierFloatEvent m_OnAdjustItemIdentifierAmountEvent;
[Tooltip("Unity event that is invoked when an item is unequipped.")]
[SerializeField] protected UnityItemIntEvent m_OnUnequipItemEvent;
[Tooltip("Unity event that is invoked when an item is removed.")]
[SerializeField] protected UnityItemIntEvent m_OnRemoveItemEvent;
public bool RemoveAllOnDeath { get { return m_RemoveAllOnDeath; } set { m_RemoveAllOnDeath = value; } }
public bool LoadDefaultLoadoutOnRespawn { get { return m_LoadDefaultLoadoutOnRespawn; } set { m_LoadDefaultLoadoutOnRespawn = value; } }
public string UnequippedStateName { get { return m_UnequippedStateName; } set { m_UnequippedStateName = value; } }
public UnityItemEvent OnAddItemEvent { get { return m_OnAddItemEvent; } set { m_OnAddItemEvent = value; } }
public UnityItemIdentifierFloatBoolBoolEvent OnPickupItemIdentifierEvent { get { return m_OnPickupItemIdentifierEvent; } set { m_OnPickupItemIdentifierEvent = value; } }
public UnityItemFloatBoolBoolEvent OnPickupItemEvent { get { return m_OnPickupItemEvent; } set { m_OnPickupItemEvent = value; } }
public UnityItemIntEvent OnEquipItemEvent { get { return m_OnEquipItemEvent; } set { m_OnEquipItemEvent = value; } }
public UnityItemIdentifierFloatEvent OnAdjustItemIdentifierAmountEvent { get { return m_OnAdjustItemIdentifierAmountEvent; } set { m_OnAdjustItemIdentifierAmountEvent = value; } }
public UnityItemIntEvent OnUnequipItemEvent { get { return m_OnUnequipItemEvent; } set { m_OnUnequipItemEvent = value; } }
public UnityItemIntEvent OnRemoveItemEvent { get { return m_OnRemoveItemEvent; } set { m_OnRemoveItemEvent = value; } }
protected GameObject m_GameObject;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
private INetworkInfo m_NetworkInfo;
private INetworkCharacter m_NetworkCharacter;
#endif
protected int m_SlotCount = 1;
private List<Item> m_AllItems = new List<Item>();
private List<IItemIdentifier> m_AllItemIdentifiers = new List<IItemIdentifier>();
public int SlotCount { get {
#if UNITY_EDITOR
if (!Application.isPlaying) { DetermineSlotCount(); }
#endif
return m_SlotCount;
} }
/// <summary>
/// Initialize the default values.
/// </summary>
protected virtual void Awake()
{
m_GameObject = gameObject;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
m_NetworkInfo = m_GameObject.GetCachedComponent<INetworkInfo>();
m_NetworkCharacter = m_GameObject.GetCachedComponent<INetworkCharacter>();
#endif
DetermineSlotCount();
EventHandler.RegisterEvent<Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", OnDeath);
EventHandler.RegisterEvent(m_GameObject, "OnRespawn", OnRespawn);
}
/// <summary>
/// Determines the number of slots on the character.
/// </summary>
public void DetermineSlotCount()
{
// The number of slots depends on the maximum number of ItemSlot IDs.
var itemSlots = GetComponentsInChildren<ItemSlot>(true);
for (int i = 0; i < itemSlots.Length; ++i) {
if (m_SlotCount <= itemSlots[i].ID) {
m_SlotCount = itemSlots[i].ID + 1;
}
}
}
/// <summary>
/// Loads the default loadout.
/// </summary>
protected virtual void Start()
{
// The character starts out unequipped.
if (!string.IsNullOrEmpty(m_UnequippedStateName)) {
StateSystem.StateManager.SetState(m_GameObject, m_UnequippedStateName, true);
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo == null || m_NetworkInfo.IsLocalPlayer()) {
if (m_NetworkInfo != null) {
// Load the default loadout on the network first to ensure it is received before any equip events.
m_NetworkCharacter.LoadDefaultLoadout();
}
#endif
LoadDefaultLoadout();
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
}
#endif
EventHandler.ExecuteEvent(m_GameObject, "OnCharacterSnapAnimator");
}
/// <summary>
/// Pick up each ItemIdentifier within the DefaultLoadout.
/// </summary>
public abstract void LoadDefaultLoadout();
/// <summary>
/// Determines if the character has the specified item.
/// </summary>
/// <param name="item">The item to check against.</param>
/// <returns>True if the character has the item.</returns>
public bool HasItem(Item item) { return HasItemInternal(item); }
/// <summary>
/// Internal method which determines if the character has the specified item.
/// </summary>
/// <param name="item">The item to check against.</param>
/// <returns>True if the character has the item.</returns>
protected abstract bool HasItemInternal(Item item);
/// <summary>
/// Adds the item to the inventory. This does not add the actual ItemIdentifier - PickupItem does that.
/// </summary>
/// <param name="item">The Item to add.</param>
/// <param name="immediateEquip">Can the item be equipped immediately?</param>
/// <param name="forcePickup">Should the item be force equipped?</param>
public void AddItem(Item item, bool immediateEquip, bool forceEquip)
{
if (AddItemInternal(item)) {
m_AllItems.Add(item);
// Notify those interested that an item has been added.
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryAddItem", item);
if (m_OnAddItemEvent != null) {
m_OnAddItemEvent.Invoke(item);
}
// The ItemIdentifier event should also be called in cases where the amount is greater than 0.
// This allows the ItemIdentifier to be picked up before the item has been added.
if (GetItemIdentifierAmount(item.ItemIdentifier) > 0) {
ItemIdentifierPickedUp(item.ItemIdentifier, 1, item.SlotID, immediateEquip, forceEquip);
}
}
}
/// <summary>
/// Internal method which adds the item to the Inventory. This does not add the actual IItemIdentifier - PickupItem does that.
/// </summary>
/// <param name="item">The item to add.</param>
/// <returns>True if the item was added to the inventory.</returns>
protected abstract bool AddItemInternal(Item item);
/// <summary>
/// Adds the specified amount of the ItemIdentifier to the inventory.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to add.</param>
/// <param name="amount">The amount of ItemIdentifier to add.</param>
/// <param name="slotID">The slot ID that picked up the item. A -1 value will indicate no specified slot.</param>
/// <param name="immediatePickup">Should the item be picked up immediately?</param>
/// <param name="forceEquip">Should the item be force equipped?</param>
/// <returns>True if the ItemIdentifier was picked up.</returns>
public bool Pickup(IItemIdentifier itemIdentifier, int amount, int slotID, bool immediatePickup, bool forceEquip)
{
return Pickup(itemIdentifier, amount, slotID, immediatePickup, forceEquip, true);
}
/// <summary>
/// Adds the specified amount of the ItemIdentifier to the inventory.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to add.</param>
/// <param name="amount">The amount of ItemIdentifier to add.</param>
/// <param name="slotID">The slot ID that picked up the item. A -1 value will indicate no specified slot.</param>
/// <param name="immediatePickup">Should the item be picked up immediately?</param>
/// <param name="forceEquip">Should the item be force equipped?</param>
/// <param name="notifyOnPickup">Should other objects be notified that the ItemIdentifier was picked up?</param>
/// <returns>True if the ItemIdentifier was picked up.</returns>
public bool Pickup(IItemIdentifier itemIdentifier, int amount, int slotID, bool immediatePickup, bool forceEquip, bool notifyOnPickup)
{
// Prevent pickup when the inventory isn't enabled.
if (itemIdentifier == null || !enabled || amount == 0) {
return false;
}
var pickedUp = PickupInternal(itemIdentifier, amount);
// Notify those interested that an item has been picked up.
if (pickedUp && notifyOnPickup) {
if (slotID == -1) {
// Find the slot that the item belongs to (if any).
for (int i = 0; i < m_SlotCount; ++i) {
if (GetItem(itemIdentifier, i) != null) {
ItemIdentifierPickedUp(itemIdentifier, amount, i, immediatePickup, forceEquip);
slotID = i;
}
}
if (slotID == -1) {
// The ItemIdentifier doesn't correspond to an item so execute the event once.
ItemIdentifierPickedUp(itemIdentifier, amount, -1, immediatePickup, forceEquip);
}
} else {
ItemIdentifierPickedUp(itemIdentifier, amount, slotID, immediatePickup, forceEquip);
}
// If the slot ID isn't -1 then AddItem has already run. Add the item if it hasn't already been added. This will occur if the item is removed
// and then later added again.
if (slotID != -1) {
var item = GetItem(itemIdentifier, slotID);
if (item != null && !m_AllItems.Contains(item)) {
m_AllItems.Add(item);
}
}
}
return pickedUp;
}
/// <summary>
/// Internal method which adds the specified amount of the ItemIdentifier to the inventory.
/// </summary>
/// <param name="itemIdentifier">The IItemIdentifier to add.</param>
/// <param name="amount">The amount of ItemIdentifier to add.</param>
/// <returns>True if the ItemIdentifier was picked up successfully.</returns>
protected abstract bool PickupInternal(IItemIdentifier itemIdentifier, int amount);
/// <summary>
/// The ItemIdentifier has been picked up. Notify interested objects.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier that was picked up.</param>
/// <param name="amount">The number of ItemIdentifier picked up.</param>
/// <param name="slotID">The ID of the slot which the item belongs to.</param>
/// <param name="immediatePickup">Was the item be picked up immediately?</param>
/// <param name="forcePickup">Should the item be force equipped?</param>
protected void ItemIdentifierPickedUp(IItemIdentifier itemIdentifier, int amount, int slotID, bool immediatePickup, bool forceEquip)
{
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo != null && m_NetworkInfo.IsLocalPlayer()) {
m_NetworkCharacter.ItemIdentifierPickup(itemIdentifier.ID, amount, slotID, immediatePickup, forceEquip);
}
#endif
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryPickupItemIdentifier", itemIdentifier, amount, immediatePickup, forceEquip);
if (m_OnPickupItemIdentifierEvent != null) {
m_OnPickupItemIdentifierEvent.Invoke(itemIdentifier, amount, immediatePickup, forceEquip);
}
if (slotID != -1) {
var item = GetItem(itemIdentifier, slotID);
if (item != null) {
item.Pickup();
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryPickupItem", item, amount, immediatePickup, forceEquip);
if (m_OnPickupItemEvent != null) {
m_OnPickupItemEvent.Invoke(item, amount, immediatePickup, forceEquip);
}
}
}
if (!m_AllItemIdentifiers.Contains(itemIdentifier)) {
m_AllItemIdentifiers.Add(itemIdentifier);
}
}
/// <summary>
/// Returns the active item in the specified slot.
/// </summary>
/// <param name="slotID">The ID of the slot.</param>
/// <returns>The active item which occupies the specified slot. Can be null.</returns>
public Item GetActiveItem(int slotID) { return GetActiveItemInternal(slotID); }
/// <summary>
/// Internal method which returns the active item in the specified slot.
/// </summary>
/// <param name="slotID">The ID of the slot which the item belongs to.</param>
/// <returns>The active item which occupies the specified slot. Can be null.</returns>
protected abstract Item GetActiveItemInternal(int slotID);
/// <summary>
/// Returns the item that corresponds to the specified ItemIdentifier.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier of the item.</param>
/// <param name="slotID">The ID of the slot which the item belongs to.</param>
/// <returns>The item which occupies the specified slot. Can be null.</returns>
public Item GetItem(IItemIdentifier itemIdentifier, int slotID) { return GetItemInternal(itemIdentifier, slotID); }
/// <summary>
/// Internal method which returns the item that corresponds to the specified IItemIdentifier.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier of the item.</param>
/// <param name="slotID">The ID of the slot which the item belongs to.</param>
/// <returns>The item which occupies the specified slot. Can be null.</returns>
protected abstract Item GetItemInternal(IItemIdentifier itemIdentifier, int slotID);
/// <summary>
/// Returns a list of all of the items in the inventory.
/// </summary>
/// <returns>A list of all of the items in the inventory.</returns>
public List<Item> GetAllItems() { return m_AllItems; }
/// <summary>
/// Returns a list of all of the ItemIdentifier in the inventory. Only used by the editor for the inventory inspector.
/// </summary>
/// <returns>A list of all of the ItemIdentifier in the inventory.</returns>
public List<IItemIdentifier> GetAllItemIdentifiers() { return m_AllItemIdentifiers; }
/// <summary>
/// Equips the ItemIdentifier in the specified slot.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to equip.</param>
/// <param name="slotID">The ID of the slot.</param>
/// <param name="immediateEquip">Is the item being equipped immediately? Immediate equips will occur from the default loadout or quickly switching to the item.</param>
public void EquipItem(IItemIdentifier itemIdentifier, int slotID, bool immediateEquip)
{
if (itemIdentifier == null) {
return;
}
var currentItem = GetActiveItem(slotID);
if (currentItem != null && currentItem.ItemIdentifier != itemIdentifier) {
UnequipItem(slotID);
}
var item = EquipItemInternal(itemIdentifier, slotID);
if (item != null) {
item.Equip(immediateEquip);
// Notify those interested that an item has been equipped.
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryEquipItem", item, slotID);
if (m_OnEquipItemEvent != null) {
m_OnEquipItemEvent.Invoke(item, slotID);
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo != null && m_NetworkInfo.IsLocalPlayer()) {
m_NetworkCharacter.EquipUnequipItem(itemIdentifier.ID, slotID, true);
}
#endif
if (!string.IsNullOrEmpty(m_UnequippedStateName)) {
StateSystem.StateManager.SetState(m_GameObject, m_UnequippedStateName, false);
}
}
}
/// <summary>
/// Internal method which equips the ItemIdentifier in the specified slot.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to equip.</param>
/// <param name="slotID">The ID of the slot.</param>
/// <returns>The item which corresponds to the ItemIdentifier. Can be null.</returns>
protected abstract Item EquipItemInternal(IItemIdentifier itemIdentifier, int slotID);
/// <summary>
/// Unequips the specified ItemIdentifier in the specified slot.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to unequip. If the ItemIdentifier isn't currently equipped then no changes will be made.</param>
/// <param name="slotID">The ID of the slot.</param>
public void UnequipItem(IItemIdentifier itemIdentifier, int slotID)
{
// No need to unequip if the item is already unequipped or the ItemIdentifier don't match.
var currentItem = GetActiveItem(slotID);
if (currentItem == null || currentItem.ItemIdentifier != itemIdentifier) {
return;
}
UnequipItem(slotID);
}
/// <summary>
/// Unequips the item in the specified slot.
/// </summary>
/// <param name="slotID">The ID of the slot.</param>
public void UnequipItem(int slotID)
{
// No need to unequip if the item is already unequipped.
var currentItem = GetActiveItem(slotID);
if (currentItem == null) {
return;
}
var item = UnequipItemInternal(slotID);
if (item != null) {
item.Unequip();
// Notify those interested that an item has been unequipped.
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryUnequipItem", item, slotID);
if (m_OnUnequipItemEvent != null) {
m_OnUnequipItemEvent.Invoke(item, slotID);
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo != null && m_NetworkInfo.IsLocalPlayer()) {
m_NetworkCharacter.EquipUnequipItem(item.ItemIdentifier.ID, slotID, false);
}
#endif
// Optionally enable a state when the inventory is unequipped.
if (!string.IsNullOrEmpty(m_UnequippedStateName)) {
var unequipped = true;
for (int i = 0; i < m_SlotCount; ++i) {
if (i == slotID) {
continue;
}
if (GetActiveItem(i) != null) {
unequipped = false;
}
}
if (unequipped) {
StateSystem.StateManager.SetState(m_GameObject, m_UnequippedStateName, true);
}
}
}
}
/// <summary>
/// Internal method which unequips the item in the specified slot.
/// </summary>
/// <param name="slotID">The ID of the slot.</param>
/// <returns>The item that was unequipped.</returns>
protected abstract Item UnequipItemInternal(int slotID);
/// <summary>
/// Returns the amount of the specified ItemIdentifier.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to get the amount of.</param>
/// <returns>The amount of the specified ItemIdentifier.</returns>
public int GetItemIdentifierAmount(IItemIdentifier itemIdentifier) { if (itemIdentifier == null) { return 0; } return GetItemIdentifierAmountInternal(itemIdentifier); }
/// <summary>
/// Internal method which returns the amount of the specified ItemIdentifier.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to get the amount of.</param>
/// <returns>The amount of the specified ItemIdentifier.</returns>
protected abstract int GetItemIdentifierAmountInternal(IItemIdentifier itemIdentifier);
/// <summary>
/// Adjusts the amount of the specified ItemIdentifier.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to adjust.</param>
/// <param name="amount">The amount of ItemIdentifier to adjust.</param>
public void AdjustItemIdentifierAmount(IItemIdentifier itemIdentifier, int amount)
{
if (itemIdentifier == null || amount == 0) {
return;
}
AdjustItemIdentifierAmountInternal(itemIdentifier, amount);
// Notify those interested that an item has been adjusted.
var remaining = GetItemIdentifierAmount(itemIdentifier);
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryAdjustItemIdentifierAmount", itemIdentifier, remaining);
if (m_OnAdjustItemIdentifierAmountEvent != null) {
m_OnAdjustItemIdentifierAmountEvent.Invoke(itemIdentifier, remaining);
}
}
/// <summary>
/// Internal method which adjusts the amount of the specified ItemIdentifier.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to adjust.</param>
/// <param name="amount">The amount of ItemIdentifier to adjust.</param>
protected abstract void AdjustItemIdentifierAmountInternal(IItemIdentifier itemIdentifier, int amount);
/// <summary>
/// Removes the ItemIdentifier from the inventory.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to remove.</param>
/// <param name="slotID">The ID of the slot.</param>
/// <param name="amount">The amount of the ItemIdentnfier that should be removed.</param>
/// <param name="drop">Should the item be dropped when removed?</param>
public void RemoveItem(IItemIdentifier itemIdentifier, int slotID, int amount, bool drop)
{
var item = GetItem(itemIdentifier, slotID);
if (item != null) {
// The item should be dropped before unequipped so the drop position will be correct.
if (drop) {
item.Drop(amount, false);
}
// An equipped item needs to be unequipped.
UnequipItem(itemIdentifier, slotID);
// If the item isn't dropped then it is removed immediately.
if (!drop) {
item.Remove();
}
if (item.DropConsumableItems) {
var itemActions = item.ItemActions;
if (itemActions != null) {
IUsableItem usableItem;
IItemIdentifier consumableItemIdentifier;
for (int i = 0; i < itemActions.Length; ++i) {
if (((usableItem = itemActions[i] as IUsableItem) != null) && (consumableItemIdentifier = usableItem.GetConsumableItemIdentifier()) != null) {
usableItem.RemoveConsumableItemIdentifierAmount();
// Any consumable ItemIdentifier should also be removed if there are no more of the same items remaining.
if (GetItemIdentifierAmount(itemIdentifier) == 1) {
RemoveItemIdentifierInternal(consumableItemIdentifier, slotID, amount);
m_AllItemIdentifiers.Remove(consumableItemIdentifier);
}
// Notify those interested of the removed amount.
SendItemIdentifierAdjustmentEvents(consumableItemIdentifier);
}
}
}
}
m_AllItems.Remove(item);
}
// The ItemIdentifier should be removed from the inventory.
RemoveItemIdentifierInternal(itemIdentifier, slotID, amount);
if (GetItemIdentifierAmount(itemIdentifier) == 0) {
m_AllItemIdentifiers.Remove(itemIdentifier);
}
// Notify those interested that the item will be removed.
if (item != null) {
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryRemoveItem", item, slotID);
if (m_OnRemoveItemEvent != null) {
m_OnRemoveItemEvent.Invoke(item, slotID);
}
} else {
SendItemIdentifierAdjustmentEvents(itemIdentifier);
}
}
/// <summary>
/// Sends the ItemIdentifier adjustment events.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to remove.</param>
private void SendItemIdentifierAdjustmentEvents(IItemIdentifier itemIdentifier)
{
// Notify those interested of the removed amount.
var amount = GetItemIdentifierAmount(itemIdentifier);
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryAdjustItemIdentifierAmount", itemIdentifier, amount);
if (m_OnAdjustItemIdentifierAmountEvent != null) {
m_OnAdjustItemIdentifierAmountEvent.Invoke(itemIdentifier, amount);
}
if (amount == 0) {
m_AllItemIdentifiers.Remove(itemIdentifier);
}
}
/// <summary>
/// Internal method which removes the ItemIdentifier from the inventory.
/// </summary>
/// <param name="itemIdentifier">The ItemIdentifier to remove.</param>
/// <param name="slotID">The ID of the slot.</param>
/// <param name="amount">The amount of the ItemIdentifier that should be removed.</param>
protected abstract void RemoveItemIdentifierInternal(IItemIdentifier itemIdentifier, int slotID, int amount);
/// <summary>
/// The character has died.
/// </summary>
/// <param name="position">The position of the force.</param>
/// <param name="force">The amount of force which killed the character.</param>
/// <param name="attacker">The GameObject that killed the character.</param>
private void OnDeath(Vector3 position, Vector3 force, GameObject attacker)
{
enabled = false;
// The item's drop method will call RemoveItem within the inventory.
if (m_RemoveAllOnDeath) {
RemoveAllItems(true);
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo != null && m_NetworkInfo.IsLocalPlayer()) {
m_NetworkCharacter.RemoveAllItems();
}
#endif
}
}
/// <summary>
/// Removes all of the items from the inventory.
/// </summary>
/// <param name="drop">Should the item be dropped when removed?</param>
public void RemoveAllItems(bool drop)
{
var allItems = GetAllItems();
for (int i = allItems.Count - 1; i >= 0; --i) {
// Multiple items may be dropped at the same time.
if (allItems.Count <= i) {
continue;
}
var itemIdentifier = allItems[i].ItemIdentifier;
var slotID = allItems[i].SlotID;
while (GetItemIdentifierAmount(itemIdentifier) > 0) {
RemoveItem(itemIdentifier, slotID, 1, drop);
}
}
}
/// <summary>
/// The character has respawned.
/// </summary>
private void OnRespawn()
{
enabled = true;
if (m_LoadDefaultLoadoutOnRespawn) {
LoadDefaultLoadout();
}
// Notify others that the inventory has respawned - allows EquipUnequip to equip any previously equipped items.
EventHandler.ExecuteEvent(m_GameObject, "OnInventoryRespawned");
}
/// <summary>
/// The object has been destroyed.
/// </summary>
private void OnDestroy()
{
EventHandler.UnregisterEvent<Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", OnDeath);
EventHandler.UnregisterEvent(m_GameObject, "OnRespawn", OnRespawn);
}
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: dad7778b4145ade479574c5454d1bd47
timeCreated: 1497574362
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,48 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Inventory;
using UnityEngine;
/// <summary>
/// The ItemCollection ScriptableObject is a container for the static item data.
/// </summary>
public class ItemCollection : ScriptableObject
{
[Tooltip("An array of all of the possible Categories.")]
[SerializeField] protected Category[] m_Categories;
[Tooltip("An array of all of the possible ItemTypes.")]
[SerializeField] protected ItemType[] m_ItemTypes;
public Category[] Categories { get { return m_Categories; } set { m_Categories = value; } }
public ItemType[] ItemTypes { get { return m_ItemTypes; } set { m_ItemTypes = value; } }
/// <summary>
/// Returns the category that has the specified ID.
/// </summary>
/// <param name="id">The ID of the category.</param>
/// <returns>The category that has the specified ID. Returns null if no categories are found.</returns>
public Category GetCategory(uint id)
{
if (m_Categories == null) {
return null;
}
for (int i = 0; i < m_Categories.Length; ++i) {
if (m_Categories[i] == null) {
Debug.LogError($"The category at index {i} doesn't exist. Ensure the new categories have been created within the Item Type Manager.");
continue;
}
if (m_Categories[i].ID == id) {
return m_Categories[i];
}
}
return null;
}
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: cd29761419510c7469e993b29ea117d8
timeCreated: 1500584109
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 693572ffb4740d04a9dbad616c8864e1, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,50 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Inventory;
using UnityEngine;
/// <summary>
/// Specifies the amount of each ItemDefinitionBase that the character can pickup or is loaded with the default inventory.
/// </summary>
[System.Serializable]
public struct ItemDefinitionAmount
{
[Tooltip("The type of item.")]
[UnityEngine.Serialization.FormerlySerializedAs("m_ItemType")]
[UnityEngine.Serialization.FormerlySerializedAs("m_ItemDefinition")]
[SerializeField] public ItemDefinitionBase ItemDefinition;
[Tooltip("The number of ItemIdentifier units to pickup.")]
[UnityEngine.Serialization.FormerlySerializedAs("m_Count")]
[UnityEngine.Serialization.FormerlySerializedAs("m_Amount")]
[SerializeField] public int Amount;
private IItemIdentifier m_ItemIdentifier;
public IItemIdentifier ItemIdentifier {
get {
if (Application.isPlaying && m_ItemIdentifier == null) {
m_ItemIdentifier = ItemDefinition.CreateItemIdentifier();
}
return m_ItemIdentifier;
}
}
/// <summary>
/// ItemDefinitionAmount constructor with two parameters.
/// </summary>
/// <param name="itemDefinition">The definition of item.</param>
/// <param name="amount">The amount of ItemDefinitionBase.</param>
public ItemDefinitionAmount(ItemDefinitionBase itemDefinition, int amount)
{
ItemDefinition = itemDefinition;
Amount = amount;
m_ItemIdentifier = null;
}
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 7c413552fe1ebb94c946da11a965ed58
timeCreated: 1500999671
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1 +0,0 @@
// Intentionally left blank in version 2.2.4. Will be removed in the future.

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 523c186f0cc4e5d43948105be5e6490e
timeCreated: 1500999671
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,272 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.Shared.Inventory;
using Opsive.Shared.Utility;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Character.Abilities.Items;
using Opsive.UltimateCharacterController.StateSystem;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Represents a set of ItemIdentifiers that can be equipped at the same time.
/// </summary>
[System.Serializable]
public class ItemSet : StateObject
{
[Tooltip("The Item Definitions that occupy the inventory slots.")]
[SerializeField] protected ItemDefinitionBase[] m_Slots;
[Tooltip("The state to change to when the ItemSet is active.")]
[SerializeField] protected string m_State;
[Tooltip("Is the ItemSet enabled?")]
[SerializeField] protected bool m_Enabled = true;
[Tooltip("Can the ItemSet be switched to by the EquipNext/EquipPrevious abilities?")]
[SerializeField] protected bool m_CanSwitchTo = true;
[Tooltip("The ItemSet index that should be activated when the current ItemSet is active and disabled.")]
[SerializeField] protected int m_DisabledIndex = -1;
[NonSerialized] public ItemDefinitionBase[] Slots { get { return m_Slots; } set { m_Slots = value; } }
[NonSerialized] public string State { get { return m_State; } set { m_State = value; } }
public bool Enabled { get { return m_Enabled; } set { m_Enabled = value; } }
public bool CanSwitchTo { get { return m_CanSwitchTo; } set { m_CanSwitchTo = value; } }
public int DisabledIndex { get { return m_DisabledIndex; } set { m_DisabledIndex = value; } }
private ItemSetManagerBase m_ItemSetManager;
private EquipUnequip m_EquipUnequip;
private int m_CategoryIndex;
private int m_Index;
private IItemIdentifier[] m_ItemIdentifiers;
private bool m_Active;
private bool m_EmptyItemSet;
public IItemIdentifier[] ItemIdentifiers { get { return m_ItemIdentifiers; } set { m_ItemIdentifiers = value; } }
public int Index { set { m_Index = value; } }
public bool Active { set { m_Active = value; } }
/// <summary>
/// Default ItemSet constructor.
/// </summary>
public ItemSet()
{
m_Enabled = true;
}
/// <summary>
/// ItemSet constructor which copies the parameters from an existing ItemSet.
/// </summary>
/// <param name="itemSet">The ItemSet to copy the values of.</param>
public ItemSet(ItemSet itemSet)
{
m_Slots = new ItemDefinitionBase[itemSet.Slots.Length];
System.Array.Copy(itemSet.Slots, m_Slots, itemSet.Slots.Length);
m_State = itemSet.State;
m_Enabled = itemSet.Enabled;
m_CanSwitchTo = itemSet.CanSwitchTo;
m_DisabledIndex = itemSet.DisabledIndex;
m_ItemIdentifiers = new IItemIdentifier[itemSet.Slots.Length];
if (itemSet.ItemIdentifiers != null && itemSet.ItemIdentifiers.Length > 0) {
System.Array.Copy(itemSet.ItemIdentifiers, m_ItemIdentifiers, itemSet.ItemIdentifiers.Length);
}
if (itemSet.States != null && itemSet.States.Length > 1) {
m_States = new State[itemSet.States.Length];
System.Array.Copy(itemSet.States, m_States, itemSet.States.Length);
}
}
/// <summary>
/// Four parameter ItemSet constructor.
/// </summary>
/// <param name="slotCount">The number of slots used by the ItemSet.</param>
/// <param name="slotID">The ID of the slot that will use the ItemSet.</param>
/// <param name="itemDefinition">The ItemDefinition of the ItemSet.</param>
/// <param name="itemIdentifier">The ItemIdentifier of the ItemSet.</param>
/// <param name="state">The state to change to when the ItemSet is active.</param>
public ItemSet(int slotCount, int slotID, ItemDefinitionBase itemDefinition, IItemIdentifier itemIdentifier, string state)
{
m_Slots = new ItemDefinitionBase[slotCount];
m_Slots[slotID] = itemDefinition;
m_State = state;
m_Enabled = true;
m_ItemIdentifiers = new IItemIdentifier[slotCount];
m_ItemIdentifiers[slotID] = itemIdentifier;
}
/// <summary>
/// Initializes the default values.
/// </summary>
/// <param name="gameObject">The GameObject this object is attached to.</param>
/// <param name="itemSetManager">The ItemSetManager which owns the ItemSet.</param>
/// <param name="categoryID">The ID of the category that the ItemSet belongs to.</param>
/// <param name="categoryIndex">The index of the category that the ItemSet belongs to.</param>
/// <param name="index">The index of the ItemSet.</param>
public void Initialize(GameObject gameObject, ItemSetManagerBase itemSetManager, uint categoryID, int categoryIndex, int index)
{
// The ItemSet may have already been initialized.
if (m_ItemSetManager != null) {
return;
}
base.Initialize(gameObject);
m_ItemSetManager = itemSetManager;
var equipUnequipAbilities = gameObject.GetCachedComponent<UltimateCharacterLocomotion>().GetAbilities<EquipUnequip>();
if (equipUnequipAbilities != null) {
for (int i = 0; i < equipUnequipAbilities.Length; ++i) {
if (equipUnequipAbilities[i].ItemSetCategoryID == categoryID) {
m_EquipUnequip = equipUnequipAbilities[i];
break;
}
}
}
m_CategoryIndex = categoryIndex;
m_Index = index;
if (m_ItemIdentifiers == null) {
m_ItemIdentifiers = new IItemIdentifier[m_Slots.Length];
}
m_EmptyItemSet = true;
for (int i = 0; i < m_Slots.Length; ++i) {
if (m_Slots[i] != null) {
m_EmptyItemSet = false;
return;
}
}
EventHandler.RegisterEvent<int, int>(m_ItemSetManager.gameObject, "OnItemSetManagerUpdateItemSet", OnUpdateItemSet);
}
/// <summary>
/// Callback when the StateManager has changed the active state on the current object.
/// </summary>
public override void StateChange()
{
base.StateChange();
// The item set is active and the enabled state changed then the item set should be activated or deactivated. This is done through the Equip Unequip ability.
if (m_Active) {
if (m_Enabled) {
var targetItemSetIndex = m_EquipUnequip.IsActive ? m_EquipUnequip.ActiveItemSetIndex : m_ItemSetManager.ActiveItemSetIndex[m_CategoryIndex];
if ((targetItemSetIndex == -1 || targetItemSetIndex == m_ItemSetManager.GetDefaultItemSetIndex(m_CategoryIndex)) && targetItemSetIndex != m_Index) {
m_EquipUnequip.StartEquipUnequip(m_Index);
}
} else {
if (m_DisabledIndex == -1) {
var defaultItemSetIndex = m_ItemSetManager.GetDefaultItemSetIndex(m_CategoryIndex);
if (m_Index == defaultItemSetIndex || !m_ItemSetManager.IsItemSetValid(m_CategoryIndex, defaultItemSetIndex, false)) {
// The current item set is equal to the ItemSet being disabled. Equip an empty item set.
m_EquipUnequip.StartEquipUnequip(-1);
} else {
m_EquipUnequip.StartEquipUnequip(defaultItemSetIndex);
}
} else {
if (m_ItemSetManager.IsItemSetValid(m_CategoryIndex, m_DisabledIndex, false)) {
m_EquipUnequip.StartEquipUnequip(m_DisabledIndex);
} else {
m_EquipUnequip.StartEquipUnequip(-1);
}
}
}
} else if (m_Enabled && (m_EmptyItemSet || m_ItemSetManager.IsItemSetValid(m_CategoryIndex, m_Index, false))) {
// If the item set is not active and it is enabled then the item set should be enabled if it can be.
var targetItemSetIndex = m_EquipUnequip.IsActive ? m_EquipUnequip.ActiveItemSetIndex : m_ItemSetManager.ActiveItemSetIndex[m_CategoryIndex];
if (targetItemSetIndex == -1) {
m_EquipUnequip.StartEquipUnequip(m_Index);
}
}
}
/// <summary>
/// The ItemSet has changed.
/// </summary>
/// <param name="categoryIndex">The index of the changed category.</param>
/// <param name="itemSetIndex">The index of the changed ItemSet.</param>
private void OnUpdateItemSet(int categoryIndex, int itemSetIndex)
{
if (categoryIndex == m_CategoryIndex || !m_Enabled) {
return;
}
var activeItemSetIndex = m_ItemSetManager.ActiveItemSetIndex[m_CategoryIndex];
if (activeItemSetIndex != -1) {
return;
}
// The ItemSet may need to be enabled.
if (!m_EquipUnequip.IsActive) {
m_EquipUnequip.StartEquipUnequip(m_Index);
}
}
/// <summary>
/// The ItemSet has been destroyed.
/// </summary>
public void OnDestroy()
{
if (m_ItemSetManager == null) {
return;
}
EventHandler.UnregisterEvent<int, int>(m_ItemSetManager.gameObject, "OnItemSetManagerUpdateItemSet", OnUpdateItemSet);
}
}
/// <summary>
/// Contains a list of ItemSets which belong in the same grouping.
/// </summary>
[System.Serializable]
public class CategoryItemSet
{
[Tooltip("The ID of the category.")]
[SerializeField] protected uint m_CategoryID;
[Tooltip("The name of the category.")]
[SerializeField] protected string m_CategoryName;
[Tooltip("The index of the ItemSet that should be activated when no other ItemSets are activated.")]
[SerializeField] protected int m_DefaultItemSetIndex = -1;
[Tooltip("A list of the belonging ItemSets.")]
[SerializeField] protected List<ItemSet> m_ItemSetList;
public uint CategoryID {
get {
if (RandomID.IsIDEmpty(m_CategoryID)) { m_CategoryID = RandomID.Generate(); }
return m_CategoryID;
}
set { m_CategoryID = value; }
}
public string CategoryName { get { return m_CategoryName; } set { m_CategoryName = value; } }
public int DefaultItemSetIndex { get { return m_DefaultItemSetIndex; } set { m_DefaultItemSetIndex = value; } }
public List<ItemSet> ItemSetList { get { return m_ItemSetList; } set { m_ItemSetList = value; } }
private IItemCategoryIdentifier m_ItemCategory;
public IItemCategoryIdentifier ItemCategory { get { return m_ItemCategory; } set { m_ItemCategory = value; } }
/// <summary>
/// CategoryItemSet default constructor.
/// </summary>
public CategoryItemSet()
{
m_ItemSetList = new List<ItemSet>();
}
/// <summary>
/// CategoryItemSet constructor with a single parameter.
/// </summary>
/// <param name="categoryID">The ID of the category.</param>
/// <param name="categoryName">The name of the category.</param>
/// <param name="itemCategory">The category that the ItemSet belongs to.</param>
public CategoryItemSet(uint categoryID, string categoryName, IItemCategoryIdentifier itemCategory)
{
CategoryID = categoryID;
m_CategoryName = categoryName;
m_ItemCategory = itemCategory;
m_ItemSetList = new List<ItemSet>();
}
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 45b0baacfd4bada4bbf4b5b061efd12f
timeCreated: 1501855421
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,83 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Inventory;
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// The ItemSetManager manages the ItemSets belonging to the character.
/// </summary>
public class ItemSetManager : ItemSetManagerBase
{
[Tooltip("A reference to the ItemCollection that the inventory is using.")]
[SerializeField] protected ItemCollection m_ItemCollection;
public ItemCollection ItemCollection { get { return m_ItemCollection; } set { var prevItemCollection = m_ItemCollection;
m_ItemCollection = value;
Initialize(prevItemCollection != m_ItemCollection); } }
/// <summary>
/// Initializes the ItemSetManager.
/// </summary>
/// <param name="force">Should the ItemSet be force initialized?</param>
public override void Initialize(bool force)
{
if (m_Initialized && !force) {
return;
}
m_Initialized = true;
if (m_ItemCollection == null) {
m_CategoryItemSets = null;
return;
}
// The ItemTypes get their categories from the ItemCollection.
for (int i = 0; i < m_ItemCollection.ItemTypes.Length; ++i) {
m_ItemCollection.ItemTypes[i].Initialize(m_ItemCollection);
}
// Initialize the categories.
if ((m_CategoryItemSets == null || m_CategoryItemSets.Length == 0)) {
if (m_ItemCollection.Categories.Length > 0) {
m_CategoryItemSets = new CategoryItemSet[m_ItemCollection.Categories.Length];
}
} else if (m_CategoryItemSets.Length != m_ItemCollection.Categories.Length) {
System.Array.Resize(ref m_CategoryItemSets, m_ItemCollection.Categories.Length);
}
if (m_CategoryIndexMap == null) {
m_CategoryIndexMap = new Dictionary<IItemCategoryIdentifier, int>();
} else {
m_CategoryIndexMap.Clear();
}
m_ActiveItemSetIndex = new int[m_CategoryItemSets.Length];
m_NextItemSetIndex = new int[m_ActiveItemSetIndex.Length];
for (int i = 0; i < m_CategoryItemSets.Length; ++i) {
m_ActiveItemSetIndex[i] = -1;
m_NextItemSetIndex[i] = -1;
if (m_CategoryItemSets[i] == null) {
m_CategoryItemSets[i] = new CategoryItemSet(m_ItemCollection.Categories[i].ID, m_ItemCollection.Categories[i].name, m_ItemCollection.Categories[i]);
} else {
m_CategoryItemSets[i].CategoryID = m_ItemCollection.Categories[i].ID;
m_CategoryItemSets[i].CategoryName = m_ItemCollection.Categories[i].name;
m_CategoryItemSets[i].ItemCategory = m_ItemCollection.Categories[i];
}
// Create a mapping between the category and index.
var category = m_ItemCollection.GetCategory(m_CategoryItemSets[i].CategoryID);
m_CategoryIndexMap.Add(category, i);
// The ItemSet must be initialized.
for (int j = 0; j < m_CategoryItemSets[i].ItemSetList.Count; ++j) {
m_CategoryItemSets[i].ItemSetList[j].Initialize(gameObject, this, m_CategoryItemSets[i].CategoryID, i, j);
}
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 2f59e0e14fa9a35469fc458f939083de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 166
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,944 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.Shared.Inventory;
using Opsive.UltimateCharacterController.Items;
using Opsive.UltimateCharacterController.Items.Actions;
using Opsive.UltimateCharacterController.Utility;
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// The ItemSetManager manages the ItemSets belonging to the character.
/// </summary>
public abstract class ItemSetManagerBase : MonoBehaviour
{
[Tooltip("Sepcifies the order that the items can be equipped.")]
[SerializeField] protected CategoryItemSet[] m_CategoryItemSets;
public CategoryItemSet[] CategoryItemSets { get { return m_CategoryItemSets; } set { m_CategoryItemSets = value; } }
[System.NonSerialized] protected bool m_Initialized;
protected GameObject m_GameObject;
protected InventoryBase m_Inventory;
protected int[] m_ActiveItemSetIndex;
protected int[] m_NextItemSetIndex;
private HashSet<IItemIdentifier> m_CheckedItemIdentifiers = new HashSet<IItemIdentifier>();
protected Dictionary<IItemCategoryIdentifier, int> m_CategoryIndexMap;
public int[] ActiveItemSetIndex { get { return m_ActiveItemSetIndex; } }
public int[] NextItemSetIndex { get { return m_NextItemSetIndex; } }
/// <summary>
/// Initialize the ItemCollection and ItemSet.
/// </summary>
private void Awake()
{
m_GameObject = gameObject;
m_Inventory = m_GameObject.GetCachedComponent<InventoryBase>();
Initialize(true);
EventHandler.RegisterEvent<Item>(m_GameObject, "OnInventoryAddItem", OnAddItem);
}
/// <summary>
/// Initializes the ItemSetManager.
/// </summary>
/// <param name="force">Should the ItemSet be force initialized?</param>
public abstract void Initialize(bool force);
/// <summary>
/// Returns the corresponding category index which maps to the category.
/// </summary>
/// <param name="category">The interested category.</param>
/// <returns>The corresponding category index which maps to the category.</returns>
public int CategoryToIndex(IItemCategoryIdentifier category)
{
if (category == null) {
return -1;
}
if (m_CategoryIndexMap.TryGetValue(category, out var index)) {
return index;
}
return -1;
}
/// <summary>
/// Returns the corresponding category index which maps to the ID.
/// </summary>
/// <param name="categoryID">The ID of the category to get.</param>
/// <returns>The corresponding category index which maps to the ID.</returns>
public int CategoryIDToIndex(uint categoryID)
{
for (int i = 0; i < m_CategoryItemSets.Length; ++i) {
if (m_CategoryItemSets[i].CategoryID == categoryID) {
return i;
}
}
Debug.LogError($"Error: Category with ID {categoryID} cannot be found.");
return -1;
}
/// <summary>
/// Returns true if the ItemDefinition belongs to the category with the specified index.
/// </summary>
/// <param name="itemDefinition">The ItemDefinition to determine if it belongs to the category.</param>
/// <param name="categoryIndex">The index of the category which the ItemIdentifier may belong to.</param>
/// <returns>True if the ItemDefinition belongs to the category with the specified index.</returns>
public bool IsCategoryMember(ItemDefinitionBase itemDefinition, int categoryIndex)
{
// If an ItemDefinition doesn't have a category it is a member of every category.
if (itemDefinition.GetItemCategory() == null) {
return true;
}
return IsCategoryMember(itemDefinition.GetItemCategory(), categoryIndex);
}
/// <summary>
/// Returns true if the CategoryIdentifier belongs to the category with the specified index.
/// </summary>
/// <param name="itemCategory">The CategoryIdentifier to determine if it belongs to the category.</param>
/// <param name="categoryIndex">The index of the category which the ItemIdentifier may belong to.</param>
/// <returns>True if the ItemIdentifier belongs to the category with the specified index.</returns>
private bool IsCategoryMember(IItemCategoryIdentifier itemCategory, int categoryIndex)
{
if (categoryIndex >= m_CategoryItemSets.Length) {
return false;
}
if (itemCategory == m_CategoryItemSets[categoryIndex].ItemCategory) {
return true;
}
// Recursively search the parents.
var categoryParents = itemCategory.GetDirectParents();
if (categoryParents == null) {
return false;
}
for (int i = 0; i < categoryParents.Count; ++i) {
if (IsCategoryMember(categoryParents[i], categoryIndex)) {
return true;
}
}
return false;
}
/// <summary>
/// Returns true if the ItemDefinitionrepresents the default ItemCategory.
/// </summary>
/// <param name="itemIdentifier">The ItemDefinition to determine if it is the default ItemCategory.</param>
/// <returns>True if the ItemDefinition represents the default ItemCategory.</returns>
public bool IsDefaultItemCategory(ItemDefinitionBase itemDefinition)
{
if (itemDefinition == null) {
return false;
}
var category = itemDefinition.GetItemCategory();
if (category == null) {
return false;
}
return IsDefaultItemCategory(itemDefinition, category);
}
/// <summary>
/// Returns true if the ItemCategory represents the default ItemCategory.
/// </summary>
/// <param name="itemDefinition">The ItemDefinition to determine if it is the default ItemCategory.</param>
/// <param name="itemCategory">The ItemCategory to determine if it is the default ItemCategory.</param>
/// <returns>True if the ItemCategory represents the default ItemCategory.</returns>
private bool IsDefaultItemCategory(ItemDefinitionBase itemDefinition, IItemCategoryIdentifier itemCategory)
{
var categoryParents = itemCategory.GetDirectParents();
if (categoryParents != null) {
for (int i = 0; i < categoryParents.Count; ++i) {
if (IsDefaultItemCategory(itemDefinition, categoryParents[i])) {
return true;
}
}
}
var index = CategoryToIndex(itemCategory);
if (index == -1) {
return false;
}
// The default category does not match the active category. Return false.
if (m_CategoryItemSets[index].DefaultItemSetIndex != m_ActiveItemSetIndex[index]) {
return false;
}
// The default category is active. Ensure the ItemDefinition is in that ItemSet.
var hasItemDefinition = false;
var itemSetList = m_CategoryItemSets[index].ItemSetList[m_ActiveItemSetIndex[index]];
for (int i = 0; i < itemSetList.Slots.Length; ++i) {
if (IsChildOf(itemDefinition, itemSetList.Slots[i])) {
hasItemDefinition = true;
break;
}
}
if (!hasItemDefinition) {
return false;
}
return true;
}
/// <summary>
/// The inventory has added the specified item.
/// </summary>
/// <param name="item">The item that was added.</param>
private void OnAddItem(Item item)
{
AddItem(item, item.ItemDefinition.GetItemCategory());
}
/// <summary>
/// Adds the item with the specified ItemCategoryIdentifier.
/// </summary>
/// <param name="item">The item that should be added.</param>
/// <param name="category">The category that the item should be aded to.</param>
private void AddItem(Item item, IItemCategoryIdentifier category)
{
if (category == null) {
Debug.LogError("Error: No category has been specified. Ensure the ItemIdentifier has been added to a category.");
return;
}
AddItemSet(item, category);
// The category can have multiple parents. Keep trying to add the item to all of the possible ItemSets.
var categoryParents = category.GetDirectParents();
if (categoryParents != null) {
for (int i = 0; i < categoryParents.Count; ++i) {
AddItem(item, categoryParents[i]);
}
}
}
/// <summary>
/// Adds a new ItemSet for the specified item if it doesn't already exist.
/// </summary>
/// <param name="item">The item to add the ItemSet for.</param>
/// <param name="category">The category that the item should be aded to.</param>
private void AddItemSet(Item item, IItemCategoryIdentifier category)
{
// The category may not have been added to the ItemSetManager.
if (category == null || !m_CategoryIndexMap.TryGetValue(category, out var categoryIndex)) {
return;
}
var addItemSet = item.UniqueItemSet;
List<ItemSet> itemSetList;
for (int i = 0; i < m_CategoryItemSets.Length; ++i) {
itemSetList = m_CategoryItemSets[i].ItemSetList;
for (int j = 0; j < itemSetList.Count; ++j) {
// If the item instance has already been added then no new item set needs to be created.
if (itemSetList[j].ItemIdentifiers[item.SlotID] == item.ItemIdentifier) {
addItemSet = false;
break;
}
// The ItemDefinition exists but the ItemIdentifier does not. Populate the ItemIdentifier with the current item and then stop searching.
if (itemSetList[j].ItemIdentifiers[item.SlotID] == null && itemSetList[j].Slots[item.SlotID] == item.ItemDefinition) {
itemSetList[j].ItemIdentifiers[item.SlotID] = item.ItemIdentifier;
// The item definition matches. Newly added items need to have an ItemSet to themselves.
var dedicatedItemDefinition = true;
for (int k = 0; k < itemSetList[j].Slots.Length; ++k) {
if (k == item.SlotID) {
continue;
}
if (itemSetList[j].Slots[k] != null) {
dedicatedItemDefinition = false;
break;
}
}
if (dedicatedItemDefinition) {
addItemSet = false; // Do not break within the loop because multiple definitions may exist for the same identifier.
}
}
}
}
// If no ItemSet exists with the added Item then add a new ItemSet.
itemSetList = m_CategoryItemSets[categoryIndex].ItemSetList;
if (addItemSet) {
var itemSet = new ItemSet(m_Inventory.SlotCount, item.SlotID, item.ItemDefinition, item.ItemIdentifier, string.Empty);
// If the parent ItemIdentifier is not null then the new ItemSet should be added after the ItemSets with the same parent.
if (item.ItemDefinition.GetParent() != null) {
var insertIndex = -1;
for (int i = 0; i < itemSetList.Count; ++i) {
if (IsChildOf(item.ItemDefinition, itemSetList[i].Slots[item.SlotID])) {
// The other slot elements must be empty.
var canInsert = true;
for (int j = 0; j < itemSetList[i].Slots.Length; ++j) {
if (j == item.SlotID) {
continue;
}
if (itemSetList[i].Slots[j] != null) {
canInsert = false;
break;
}
}
if (canInsert) {
insertIndex = i + 1;
}
} else if (insertIndex != -1) {
// The ItemSet should be inserted after the last ItemSet with the same parent.
break;
}
}
// Insert the ItemSet with the child ItemDefinition.
insertIndex = insertIndex != -1 ? insertIndex : itemSetList.Count;
itemSetList.Insert(insertIndex, itemSet);
// If the ItemSet was inserted before the default or active index then the index needs to update to stay accurate.
if (insertIndex <= m_CategoryItemSets[categoryIndex].DefaultItemSetIndex) {
m_CategoryItemSets[categoryIndex].DefaultItemSetIndex += 1;
}
if (insertIndex <= m_ActiveItemSetIndex[categoryIndex]) {
m_ActiveItemSetIndex[categoryIndex] += 1;
EventHandler.ExecuteEvent(m_GameObject, "OnItemSetIndexChange", categoryIndex, m_ActiveItemSetIndex[categoryIndex]);
}
// The ItemSet must be duplicated for any ItemDefinition that has a similar parent.
for (int i = itemSetList.Count - 1; i >= 0; --i) {
if (IsChildOf(item.ItemDefinition, itemSetList[i].Slots[item.SlotID])) {
// Another ItemDefinition must exist in order for the ItemSet to be duplicated.
for (int j = 0; j < itemSetList[i].Slots.Length; ++j) {
if (j == item.SlotID) {
continue;
}
// The ItemSet is unique. Duplicate it.
if (itemSetList[i].Slots[j] != null) {
DuplicateItemSet(item, categoryIndex, i);
break;
}
}
}
}
} else {
// The ItemDefinition doesn't have a parent. Add the ItemSet to the end of the list.
itemSet.Initialize(m_GameObject, this, m_CategoryItemSets[categoryIndex].CategoryID, categoryIndex, itemSetList.Count);
// The ItemDefinition may already exists within the ItemSetList. Use the same state name.
for (int i = 0; i < itemSetList.Count; ++i) {
if (IsChildOf(item.ItemDefinition, itemSetList[i].Slots[item.SlotID]) && !string.IsNullOrEmpty(itemSetList[i].State)) {
var dedicatedItemSet = true;
for (int j = 0; j < itemSetList[i].Slots.Length; ++j) {
if (j == item.SlotID) {
continue;
}
if (itemSetList[i].Slots[j] != null) {
dedicatedItemSet = false;
break;
}
}
if (dedicatedItemSet) {
itemSet.State = itemSetList[i].State;
break;
}
}
}
itemSetList.Add(itemSet);
}
} else if (!item.UniqueItemSet) {
// The individual ItemSet doesn't need to be added, but it may need to duplicate an existing ItemSet.
for (int i = 0; i < itemSetList.Count; ++i) {
if (itemSetList[i].Slots[item.SlotID] != item.ItemDefinition || itemSetList[i].ItemIdentifiers[item.SlotID] == item.ItemIdentifier) {
continue;
}
for (int j = 0; j < itemSetList[i].Slots.Length; ++j) {
if (j == item.SlotID) {
continue;
}
if (itemSetList[i].Slots[j] != null) {
DuplicateItemSet(item, categoryIndex, i);
break;
}
}
}
}
}
/// <summary>
/// Returns true if the possible child ItemDefinition is a child of the possible parent ItemDefinition.
/// </summary>
/// <param name="possibleChild">The ItemDefinition that may be a child of the specified parent.</param>
/// <param name="categoryIndex">The ItemDefinition that may be a parent of the specified child.</param>
/// <returns>True if the child ItemDefinition is a child of the parent ItemDefinition.</returns>
private bool IsChildOf(ItemDefinitionBase possibleChild, ItemDefinitionBase possibleParent)
{
if (possibleChild == null || possibleParent == null) {
return false;
}
var itemDefinition = possibleChild;
while (itemDefinition != null) {
if (itemDefinition == possibleParent) {
return true;
}
itemDefinition = itemDefinition.GetParent();
}
return false;
}
/// <summary>
/// Duplicates the ItemSet at the specified index.
/// </summary>
/// <param name="item">The item that triggered the duplication.</param>
/// <param name="categoryIndex">The index of the ItemSet category.</param>
/// <param name="itemSetIndex">The index of the ItemSet that should be duplicated.</param>
private void DuplicateItemSet(Item item, int categoryIndex, int itemSetIndex)
{
var itemSetList = m_CategoryItemSets[categoryIndex].ItemSetList;
var duplicatedItemSet = new ItemSet(itemSetList[itemSetIndex]);
duplicatedItemSet.State = itemSetList[itemSetIndex].State;
duplicatedItemSet.Slots[item.SlotID] = item.ItemDefinition;
duplicatedItemSet.ItemIdentifiers[item.SlotID] = item.ItemIdentifier;
duplicatedItemSet.Initialize(m_GameObject, this, m_CategoryItemSets[categoryIndex].CategoryID, categoryIndex, itemSetIndex + 1);
itemSetList.Insert(itemSetIndex + 1, duplicatedItemSet);
// All of the subsequent ItemSets need to update their index.
for (int i = itemSetIndex + 2; i < itemSetList.Count; ++i) {
itemSetList[i].Index = i;
}
// If the ItemSet was inserted before the default or active index then the index needs to update to stay accurate.
if (itemSetIndex + 1 <= m_CategoryItemSets[categoryIndex].DefaultItemSetIndex) {
m_CategoryItemSets[categoryIndex].DefaultItemSetIndex += 1;
}
if (itemSetIndex + 1 <= m_ActiveItemSetIndex[categoryIndex]) {
m_ActiveItemSetIndex[categoryIndex] += 1;
EventHandler.ExecuteEvent(m_GameObject, "OnItemSetIndexChange", categoryIndex, m_ActiveItemSetIndex[categoryIndex]);
}
}
/// <summary>
/// Adds the ItemSet for the specified item if it doesn't already exist.
/// </summary>
/// <param name="item">The item to add the ItemSet for.</param>
/// <param name="itemSet">The ItemSet to add.</param>
/// <param name="defaultItemSet">Is the ItemSet the default ItemSet within the category?</param>
public void AddItemSet(Item item, ItemSet itemSet, bool defaultItemSet)
{
AddItemSet(item, itemSet, defaultItemSet, item.ItemDefinition.GetItemCategory());
}
/// <summary>
/// Adds the ItemSet for the specified item if it doesn't already exist.
/// </summary>
/// <param name="item">The item to add the ItemSet for.</param>
/// <param name="itemSet">The ItemSet to add.</param>
/// <param name="defaultItemSet">Is the ItemSet the default ItemSet within the category?</param>
/// <param name="category">The category that the ItemSet is trying to be added to.</param>
private void AddItemSet(Item item, ItemSet itemSet, bool defaultItemSet, IItemCategoryIdentifier category)
{
// The category can have multiple parents. Keep trying to add the ItemSet to all of the possible categories.
var categoryParents = category.GetDirectParents();
if (categoryParents != null) {
for (int i = 0; i < categoryParents.Count; ++i) {
AddItemSet(item, itemSet, defaultItemSet, categoryParents[i]);
}
}
// The category may not have been added to the ItemSetManager.
if (!m_CategoryIndexMap.TryGetValue(category, out var categoryIndex)) {
return;
}
var addItemSet = true;
var itemSetList = m_CategoryItemSets[categoryIndex].ItemSetList;
for (int i = 0; i < itemSetList.Count; ++i) {
var slots = itemSetList[i].Slots;
var slotMatch = true;
for (int j = 0; j < slots.Length; ++j) {
if (slots[j] != itemSet.Slots[j]) {
slotMatch = false;
break;
}
}
if (slotMatch) {
addItemSet = false;
break;
}
}
// If the ItemSet doesn't exist then add it to the list.
if (addItemSet) {
AddItemSet(itemSet, defaultItemSet, categoryIndex);
}
}
/// <summary>
/// Adds the ItemSet if it doesn't already exist.
/// </summary>
/// <param name="itemSet">The ItemSet to add.</param>
/// <param name="defaultItemSet">Is the ItemSet the default ItemSet within the category?</param>
/// <param name="category">The category that the ItemSet is trying to be added to.</param>
/// <param name="addParents">Should ItemSets be added to the category parents?</param>
public void AddItemSet(ItemSet itemSet, bool defaultItemSet, IItemCategoryIdentifier category, bool addParents)
{
// The ItemSet must have at least one slot filled.
var validItemSet = false;
for (int i = 0; i < itemSet.Slots.Length; ++i) {
if (itemSet.Slots[i] != null) {
validItemSet = true;
break;
}
}
if (!validItemSet) {
return;
}
// The category can have multiple parents. Keep trying to add the ItemSet to all of the possible categories.
if (addParents) {
var categoryParents = category.GetDirectParents();
if (categoryParents != null) {
for (int i = 0; i < categoryParents.Count; ++i) {
AddItemSet(itemSet, defaultItemSet, categoryParents[i], addParents);
}
}
}
// The category may not have been added to the ItemSetManager.
if (!m_CategoryIndexMap.TryGetValue(category, out var categoryIndex)) {
return;
}
// Ensure the ItemSet is unique.
var itemSetList = m_CategoryItemSets[categoryIndex].ItemSetList;
for (int i = 0; i < itemSetList.Count; ++i) {
var itemDefinitionMatch = true;
for (int j = 0; j < itemSetList[i].Slots.Length; ++j) {
if (itemSet.Slots[j] != itemSetList[i].Slots[j]) {
itemDefinitionMatch = false;
break;
}
}
if (itemDefinitionMatch) {
return;
}
}
// The ItemSet is unique. Add it to the list.
AddItemSet(itemSet, defaultItemSet, categoryIndex);
}
/// <summary>
/// Adds the ItemSet.
/// </summary>
/// <param name="itemSet">The ItemSet to add.</param>
/// <param name="defaultItemSet">Is the ItemSet the default ItemSet within the category?</param>
/// <param name="categoryIndex">The index of the category that the ItemSet is being added to.</param>
private void AddItemSet(ItemSet itemSet, bool defaultItemSet, int categoryIndex)
{
var itemSetList = m_CategoryItemSets[categoryIndex].ItemSetList;
itemSet = new ItemSet(itemSet);
itemSetList.Add(itemSet);
// The ItemSet must be initialized.
itemSet.Initialize(m_GameObject, this, m_CategoryItemSets[categoryIndex].CategoryID, categoryIndex, itemSetList.Count - 1);
// The ItemSet can be default if no existing ItemSets are the default ItemSet.
if (defaultItemSet && m_CategoryItemSets[categoryIndex].DefaultItemSetIndex == -1) {
m_CategoryItemSets[categoryIndex].DefaultItemSetIndex = itemSetList.Count - 1;
}
}
/// <summary>
/// Returns the ItemSet that the item belongs to.
/// </summary>
/// <param name="item">The item to get the ItemSet of.</param>
/// <param name="categoryIndex">The index of the ItemSet category.</param>
/// <param name="checkIfValid">Should the ItemSet be checked to see if it is valid?.</param>
/// <returns>The ItemSet that the item belongs to.</returns>
public int GetItemSetIndex(Item item, int categoryIndex, bool checkIfValid)
{
if (categoryIndex == -1) {
return -1;
}
// The ItemSet may be in the process of being changed. Test the next item set first to determine if this item set should be returned.
List<ItemSet> itemSetList;
if (m_NextItemSetIndex[categoryIndex] != -1) {
itemSetList = m_CategoryItemSets[categoryIndex].ItemSetList;
var itemSet = itemSetList[m_NextItemSetIndex[categoryIndex]];
if (itemSet.ItemIdentifiers[item.SlotID] == item.ItemIdentifier && (!checkIfValid || IsItemSetValid(categoryIndex, m_NextItemSetIndex[categoryIndex], false))) {
return m_NextItemSetIndex[categoryIndex];
}
}
var itemCount = m_Inventory.GetItemIdentifierAmount(item.ItemIdentifier);
// Search through all of the ItemSets for one that contains the specified item.
itemSetList = m_CategoryItemSets[categoryIndex].ItemSetList;
var validItemSet = -1;
for (int i = 0; i < itemSetList.Count; ++i) {
// The ItemSet must contain the item at the specified slot in addition to being a valid ItemSet.
if (itemSetList[i].ItemIdentifiers[item.SlotID] == item.ItemIdentifier && (!checkIfValid || IsItemSetValid(categoryIndex, i, false))) {
// The ItemSet is valid, but do not return it immediately if the ItemSet uses more than one ItemDefinitions. This will prevent a dual wield ItemSet from equipping
// when a single item was picked up.
var validSlotCount = 1;
for (int j = 0; j < itemSetList[i].ItemIdentifiers.Length; ++j) {
if (j == item.SlotID) {
continue;
}
if (IsChildOf(item.ItemDefinition, itemSetList[i].Slots[j])) {
validSlotCount++;
}
}
if (itemCount == validSlotCount) {
return i;
} else if (validItemSet == -1) {
validItemSet = i;
}
}
}
return validItemSet;
}
/// <summary>
/// Returns the default ItemSet index for the specified category index.
/// </summary>
/// <param name="categoryIndex">The index of the cateogry to get the default ItemSet index of.</param>
/// <returns>The default ItemSet index for the specified category index.</returns>
public int GetDefaultItemSetIndex(int categoryIndex)
{
if (categoryIndex == -1) {
return -1;
}
return m_CategoryItemSets[categoryIndex].DefaultItemSetIndex;
}
/// <summary>
/// Returns the target ItemSet index for the specified category index based on the allowed slots bitwise mask.
/// </summary>
/// <param name="categoryIndex">The index of the cateogry to get the target ItemSet index of.</param>
/// <param name="allowedSlotsMask">The bitwise mask indicating which slots are allowed.</param>
/// <returns>The target ItemSet index for the specified category index.</returns>
public int GetTargetItemSetIndex(int categoryIndex, int allowedMask)
{
if (categoryIndex == -1) {
return -1;
}
var itemSetIndex = m_ActiveItemSetIndex[categoryIndex];
if (IsItemSetValid(categoryIndex, itemSetIndex, false, allowedMask)) {
return itemSetIndex;
}
// Check the special cases before looping through the entire item set list.
// Determine if the previous item set is similar to the current item set.
var itemSetListCount = m_CategoryItemSets[categoryIndex].ItemSetList.Count;
var prevItemSetIndex = itemSetIndex - 1;
if (prevItemSetIndex < 0) {
prevItemSetIndex = itemSetListCount - 1;
}
if (itemSetIndex != -1 && prevItemSetIndex != itemSetIndex && IsItemSetValid(categoryIndex, prevItemSetIndex, false, allowedMask)) {
for (int i = 0; i < m_CategoryItemSets[categoryIndex].ItemSetList[prevItemSetIndex].Slots.Length; ++i) {
var prevSlots = m_CategoryItemSets[categoryIndex].ItemSetList[prevItemSetIndex].Slots;
if (m_CategoryItemSets[categoryIndex].ItemSetList[itemSetIndex].Slots[i] == prevSlots[i] && prevSlots[i] != null) {
// At least one definition matches. Switch to that ItemSet.
return prevItemSetIndex;
}
}
}
// Check the default item set.
if (IsItemSetValid(categoryIndex, m_CategoryItemSets[categoryIndex].DefaultItemSetIndex, false, allowedMask)) {
return m_CategoryItemSets[categoryIndex].DefaultItemSetIndex;
}
// Keep checking the ItemSets until a valid item set exists.
var iterCount = 0;
do {
if (iterCount == itemSetListCount) {
// No valid ItemSet was found.
return -1;
}
iterCount++;
itemSetIndex = (itemSetIndex + 1) % itemSetListCount;
} while (itemSetIndex == prevItemSetIndex || itemSetIndex == m_CategoryItemSets[categoryIndex].DefaultItemSetIndex || !IsItemSetValid(categoryIndex, itemSetIndex, false, allowedMask));
return itemSetIndex;
}
/// <summary>
/// Returns true if the specified ItemSet is valid. A valid ItemSet means the character has all of the items specified in the inventory.
/// </summary>
/// <param name="categoryIndex">The index of the ItemSet category.</param>
/// <param name="itemSetIndex">The ItemSet within the category.</param>
/// <param name="checkIfCanSwitchTo">Should the ItemSet be checked if it can be switched to?</param>
/// <param name="allowedSlotsMask">The bitwise mask indicating which slots are allowed.</param>
/// <returns>True if the specified ItemSet is valid.</returns>
public bool IsItemSetValid(int categoryIndex, int itemSetIndex, bool checkIfCanSwitchTo, int allowedSlotsMask = -1)
{
if (itemSetIndex == -1 || itemSetIndex >= m_CategoryItemSets[categoryIndex].ItemSetList.Count) {
return false;
}
var itemSet = m_CategoryItemSets[categoryIndex].ItemSetList[itemSetIndex];
// The ItemSet isn't valid if it isn't enabled.
if (!itemSet.Enabled) {
return false;
}
// The ItemSet may not be able to be switched to.
if (checkIfCanSwitchTo && !itemSet.CanSwitchTo) {
return false;
}
var requiredCount = 0;
var availableCount = 0;
m_CheckedItemIdentifiers.Clear();
for (int i = 0; i < itemSet.Slots.Length; ++i) {
if (itemSet.Slots[i] == null) {
continue;
}
// If the ItemIdentifier is null then the item hasn't been added yet.
if (itemSet.ItemIdentifiers[i] == null) {
return false;
}
// The item may not be in the allowed layer mask.
if (allowedSlotsMask != -1 && m_CategoryItemSets[categoryIndex].DefaultItemSetIndex != itemSetIndex && !MathUtility.InLayerMask(i, allowedSlotsMask)) {
return false;
}
// It only takes one item for the ItemSet not to be valid.
var item = m_Inventory.GetItem(itemSet.ItemIdentifiers[i], i);
if (item == null) {
return false;
}
// Usable items may not be able to be equipped if they don't have any consumable ItemIdentifiers left.
for (int j = 0; j < item.ItemActions.Length; ++j) {
var usableItem = item.ItemActions[j] as IUsableItem;
if (usableItem != null) {
if (!usableItem.CanEquipEmptyItem && usableItem.GetConsumableItemIdentifier() != null && m_Inventory.GetItemIdentifierAmount(usableItem.GetConsumableItemIdentifier()) == 0) {
return false;
}
}
}
// Remember the count to ensure the correct number of items exist within the inventory.
requiredCount++;
if (!m_CheckedItemIdentifiers.Contains(item.ItemIdentifier)) {
availableCount += m_Inventory.GetItemIdentifierAmount(item.ItemIdentifier);
m_CheckedItemIdentifiers.Add(item.ItemIdentifier);
}
}
// Ensure the inventory has the number of items required for the current ItemSet.
if (availableCount < requiredCount) {
return false;
}
return true;
}
/// <summary>
/// Returns the index of the ItemSet that is next or previous in the list.
/// </summary>
/// <param name="categoryIndex">The category of ItemSets to get.</param>
/// <param name="currentItemSetIndex">The current ItemSet index.</param>
/// <param name="next">Should the next ItemSet be retrieved? If false the previous ItemSet will be retrieved.</param>
/// <returns>The index of the ItemSet that is next or previous in the list.</returns>
public int NextActiveItemSetIndex(int categoryIndex, int currentItemSetIndex, bool next)
{
if (currentItemSetIndex == -1) {
return -1;
}
var itemSetListCount = m_CategoryItemSets[categoryIndex].ItemSetList.Count;
// The ItemSet can't be switched if there are zero or only one ItemSets.
if (itemSetListCount <= 1) {
return -1;
}
var itemSetIndex = currentItemSetIndex;
do {
itemSetIndex = (itemSetIndex + (next ? 1 : -1)) % itemSetListCount;
if (itemSetIndex < 0) {
itemSetIndex = itemSetListCount - 1;
}
} while (itemSetIndex != currentItemSetIndex && !IsItemSetValid(categoryIndex, itemSetIndex, true));
return itemSetIndex;
}
/// <summary>
/// Updates the next ItemSet to the specified value.
/// </summary>
/// <param name="categoryIndex">The category to update the ItemSet within.</param>
/// <param name="itemSetIndex">The ItemSet to set.</param>
public void UpdateNextItemSet(int categoryIndex, int itemSetIndex)
{
// No updates are necessary if the indicies are the same.
var nextItemSetIndex = m_NextItemSetIndex[categoryIndex];
if (nextItemSetIndex == itemSetIndex) {
return;
}
var prevItemSetIndex = nextItemSetIndex != -1 ? nextItemSetIndex : m_ActiveItemSetIndex[categoryIndex];
m_NextItemSetIndex[categoryIndex] = itemSetIndex;
EventHandler.ExecuteEvent(m_GameObject, "OnItemSetManagerUpdateNextItemSet", categoryIndex, prevItemSetIndex, itemSetIndex);
}
/// <summary>
/// Updates the active ItemSet to the specified value.
/// </summary>
/// <param name="categoryIndex">The category to update the ItemSet within.</param>
/// <param name="itemSetIndex">The ItemSet to set.</param>
/// <param name="itemIdentifiers">The active ItemIdentifiers.</param>
public void UpdateActiveItemSet(int categoryIndex, int itemSetIndex)
{
// No updates are necessary if the indicies are the same.
var activeItemSetIndex = m_ActiveItemSetIndex[categoryIndex];
if (activeItemSetIndex == itemSetIndex) {
return;
}
if (m_ActiveItemSetIndex[categoryIndex] != -1) {
m_CategoryItemSets[categoryIndex].ItemSetList[m_ActiveItemSetIndex[categoryIndex]].Active = false;
}
m_ActiveItemSetIndex[categoryIndex] = itemSetIndex;
m_NextItemSetIndex[categoryIndex] = -1;
if (itemSetIndex != -1) {
m_CategoryItemSets[categoryIndex].ItemSetList[itemSetIndex].Active = true;
}
string state, newState = null;
if (itemSetIndex != -1) {
if (!string.IsNullOrEmpty((state = m_CategoryItemSets[categoryIndex].ItemSetList[itemSetIndex].State))) {
StateSystem.StateManager.SetState(m_GameObject, state, true);
// Store the new state name for testing against.
newState = state;
}
}
if (activeItemSetIndex != -1 && !string.IsNullOrEmpty((state = m_CategoryItemSets[categoryIndex].ItemSetList[activeItemSetIndex].State))) {
// If the new state is null or different, then deactivate the state of the old item set.
if (string.IsNullOrEmpty(newState) || state != newState) {
StateSystem.StateManager.SetState(m_GameObject, state, false);
}
}
EventHandler.ExecuteEvent(m_GameObject, "OnItemSetManagerUpdateItemSet", categoryIndex, itemSetIndex);
}
/// <summary>
/// Sets the default ItemSet for the specified category.
/// </summary>
/// <param name="categoryIndex">The category to set the default itemset of.</param>
public void SetDefaultItemSet(int categoryIndex)
{
var itemSetIndex = GetDefaultItemSetIndex(categoryIndex);
if (IsItemSetValid(categoryIndex, itemSetIndex, false)) {
UpdateActiveItemSet(categoryIndex, itemSetIndex);
}
}
/// <summary>
/// Returns the ItemIdentifier which should be equipped for the specified slot.
/// </summary>
/// <param name="slot">The slot to get the ItemIdentifier of.</param>
/// <returns>The ItemIdentifier which should be equipped for the specified slot. Can be null.</returns>
public IItemIdentifier GetEquipItemIdentifier(int slot)
{
if (slot == -1 || slot >= m_Inventory.SlotCount) {
return null;
}
for (int i = 0; i < m_CategoryItemSets.Length; ++i) {
if (m_ActiveItemSetIndex[i] != -1) {
var itemSet = m_CategoryItemSets[i].ItemSetList[m_ActiveItemSetIndex[i]];
if (itemSet.Enabled && itemSet.ItemIdentifiers[slot] != null) {
return itemSet.ItemIdentifiers[slot];
}
}
}
return null;
}
/// <summary>
/// Returns the ItemIdentifier which should be equipped for the specified categoryIndex and slot.
/// </summary>
/// <param name="categoryIndex">The category to get the ItemIdentifier of.</param>
/// <param name="slot">The slot to get the ItemIdentifier of.</param>
/// <returns>The ItemIdentifier which should be equipped for the specified slot. Can be null.</returns>
public IItemIdentifier GetEquipItemIdentifier(int categoryIndex, int slot)
{
if (categoryIndex == -1 || categoryIndex >= m_CategoryItemSets.Length || slot == -1 || slot >= m_Inventory.SlotCount) {
return null;
}
if (m_ActiveItemSetIndex[categoryIndex] != -1) {
var itemSet = m_CategoryItemSets[categoryIndex].ItemSetList[m_ActiveItemSetIndex[categoryIndex]];
return itemSet.ItemIdentifiers[slot];
}
return null;
}
/// <summary>
/// Returns the ItemIdentifier which should be equipped for the specified categoryIndex, ItemSet, and slot.
/// </summary>
/// <param name="categoryIndex">The category to get the ItemIdentifier of.</param>
/// <param name="targetItemSetIndex">The ItemSet to get the ItemIdentifier of.</param>
/// <param name="slot">The slot to get the ItemIdentifier of.</param>
/// <returns>The ItemIdentifier which should be equipped for the specified categoryIndex, ItemIdentifier, and slot. Can be null.</returns>
public IItemIdentifier GetEquipItemIdentifier(int categoryIndex, int targetItemSetIndex, int slot)
{
if (categoryIndex == -1 || categoryIndex >= m_CategoryItemSets.Length ||
targetItemSetIndex == -1 || targetItemSetIndex >= m_CategoryItemSets[categoryIndex].ItemSetList.Count ||
slot == -1 || slot >= m_Inventory.SlotCount) {
return null;
}
return m_CategoryItemSets[categoryIndex].ItemSetList[targetItemSetIndex].ItemIdentifiers[slot];
}
/// <summary>
/// Returns the ItemIdentifier which is going to be equipped next.
/// </summary>
/// <param name="slot">The slot to get the ItemIdentifier of.</param>
/// <param name="categoryIndex">The category index of the found ItemIdentifier.</param>
/// <returns>The ItemIdentifier which is going to be equipped next. Can be null.</returns>
public IItemIdentifier GetNextItemIdentifier(int slot, out int categoryIndex)
{
categoryIndex = -1;
if (slot == -1 || slot >= m_Inventory.SlotCount) {
return null;
}
for (int i = 0; i < m_CategoryItemSets.Length; ++i) {
var index = m_NextItemSetIndex[i] != -1 ? m_NextItemSetIndex[i] : m_ActiveItemSetIndex[i];
if (index == -1) {
continue;
}
categoryIndex = i;
return m_CategoryItemSets[i].ItemSetList[index].ItemIdentifiers[slot];
}
return null;
}
/// <summary>
/// The character has been destroyed.
/// </summary>
private void OnDestroy()
{
for (int i = 0; i < m_CategoryItemSets.Length; ++i) {
for (int j = 0; j < m_CategoryItemSets[i].ItemSetList.Count; ++j) {
m_CategoryItemSets[i].ItemSetList[j].OnDestroy();
}
}
EventHandler.UnregisterEvent<Item>(gameObject, "OnInventoryAddItem", OnAddItem);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 03f1fdf9852f9f3488c47fb78a8896bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 165
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,95 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Inventory
{
using Opsive.Shared.Inventory;
using UnityEngine;
/// <summary>
/// An ItemType is a static representation of an item. Each item that interacts with the inventory must have an ItemType.
/// </summary>
public class ItemType : ItemDefinitionBase, IItemIdentifier
{
[Tooltip("The unique ID of the object within the collection.")]
[SerializeField] protected uint m_ID;
[Tooltip("The ID of the categories that the ItemType belongs to.")]
[SerializeField] protected uint[] m_CategoryIDs = new uint[] { };
[Tooltip("Describes what the ItemType represents.")]
[SerializeField] protected string m_Description;
[Tooltip("The maximum number of ItemTypes the character can hold.")]
[SerializeField] protected int m_Capacity = int.MaxValue;
public uint ID { get { return m_ID; } set { m_ID = value; } }
public uint[] CategoryIDs { get { return m_CategoryIDs; } set { m_CategoryIDs = value; } }
public string Description { get { return m_Description; } set { m_Description = value; } }
public int Capacity { get { return m_Capacity; } set { m_Capacity = value; } }
private IItemCategoryIdentifier m_Category;
/// <summary>
/// Creates an IItemIdentifier based off of the ItemDefinitionBase.
/// </summary>
/// <returns>An IItemIdentifier based off of the ItemDefinitionBase.</returns>
public override IItemIdentifier CreateItemIdentifier()
{
return this; // ItemTypes act as both definitions and identifiers.
}
/// <summary>
/// Initializes the categories which belong to the ItemCollection.
/// </summary>
/// <param name="itemCollection">The ItemCollection that contain the categories.</param>
public void Initialize(ItemCollection itemCollection)
{
if (CategoryIDs == null || CategoryIDs.Length == 0) {
return;
}
if (CategoryIDs.Length > 1) {
// Multiple categories are specified. Create a new runtime category that has multiple parents.
var categoryParents = new Category[CategoryIDs.Length];
for (int i = 0; i < CategoryIDs.Length; ++i) {
categoryParents[i] = itemCollection.GetCategory(CategoryIDs[i]);
}
var category = ScriptableObject.CreateInstance<Category>();
category.hideFlags = HideFlags.HideAndDontSave;
category.Parents = categoryParents;
m_Category = category;
} else {
m_Category = itemCollection.GetCategory(CategoryIDs[0]);
}
}
/// <summary>
/// Returns the parent of the current identifier.
/// </summary>
/// <returns>The parent of the current identifier. Can be null.</returns>
public override ItemDefinitionBase GetParent() { return null; }
/// <summary>
/// Returns the category of the current identifier.
/// </summary>
/// <returns>The category of the current identifier. Can be null.</returns>
public override IItemCategoryIdentifier GetItemCategory() { return m_Category; }
/// <summary>
/// Returns the ItemDefinition that the identifier uses.
/// </summary>
/// <returns>The ItemDefinition that the identifier uses.</returns>
public ItemDefinitionBase GetItemDefinition()
{
return this; // ItemTypes act as both definitions and identifiers.
}
/// <summary>
/// Returns a string representation of the object.
/// </summary>
/// <returns>A string representation of the object.</returns>
public override string ToString() { return name; }
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 4e74c32144565264eb86dc7514aca7f7
timeCreated: 1498048636
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 0cd8dbda5671b674982a1a18863b87c0, type: 3}
userData:
assetBundleName:
assetBundleVariant: