I've been trying to create items and item sets through code for quite a bit now, What i've done is create a new class that basically has some copy-pasta from the ItemPickup.cs in the following way:
* Using the CharacterAssist namespace
* Adding a custom ItemPickup.PickupSet[] that would eventually hold all weapons available in the game
* Fetching the player prefab, inventoryBase, ItemCollection, ItemSetManager and ItemPlacement on demand
* looping through the PickupSet[] on keypress (would later be done through network RPC's) to find an item of a certain type name
* trying to add the coresponding PickupSet to the itemSetManager with eg. itemSetManager.AddItemSet(item, itemset, default);
* instantiate and place the item on the player
* finally add the item to the inventory
So basically just like the pickup script works, just without all the parts about having to actually go to a pickup and collide with it.
The problem i'm facing (for the moment) is that i get an IndexOutOfRangeException: Index was outside the bounds of the array.
Which happens when trying to add the item set to the itemsetmanager, and i'm at a loss for any more ideas on how to fix this so I hope someone here could point me in the right direction.
(Any and all points in the direction of how to accomplish: Adding a variable weapon to the player, and players inventory, so they can equip it, all via Code and not any pre-defined pickup gameobjects placed in the world, will all be extremely helpful, the caveat here is that i don't want to: 1) pre-add the items to the players in editor-mode because the inventories are dynamic and read from a database, 2) use pickup-objects that you have to collide with, since the items once again will be added from the server-side through network RPC's)
Full code in code segment below
EDIT: Found some things to change (base class for one) and now it sort of works, except i have to press '2' twice before a sword is equipped, which feels a bit weird, anyone know why this is?
* Using the CharacterAssist namespace
* Adding a custom ItemPickup.PickupSet[] that would eventually hold all weapons available in the game
* Fetching the player prefab, inventoryBase, ItemCollection, ItemSetManager and ItemPlacement on demand
* looping through the PickupSet[] on keypress (would later be done through network RPC's) to find an item of a certain type name
* trying to add the coresponding PickupSet to the itemSetManager with eg. itemSetManager.AddItemSet(item, itemset, default);
* instantiate and place the item on the player
* finally add the item to the inventory
So basically just like the pickup script works, just without all the parts about having to actually go to a pickup and collide with it.
(Any and all points in the direction of how to accomplish: Adding a variable weapon to the player, and players inventory, so they can equip it, all via Code and not any pre-defined pickup gameobjects placed in the world, will all be extremely helpful, the caveat here is that i don't want to: 1) pre-add the items to the players in editor-mode because the inventories are dynamic and read from a database, 2) use pickup-objects that you have to collide with, since the items once again will be added from the server-side through network RPC's)
Full code in code segment below
EDIT: Found some things to change (base class for one) and now it sort of works, except i have to press '2' twice before a sword is equipped, which feels a bit weird, anyone know why this is?
C#:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
using System.Linq;
// Opsive
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Events;
using Opsive.UltimateCharacterController.Game;
using Opsive.UltimateCharacterController.Inventory;
using Opsive.UltimateCharacterController.Items;
using Opsive.UltimateCharacterController.Utility;
using Opsive.UltimateCharacterController.Objects.CharacterAssist;
[System.Serializable]
public class WeaponEquip : ItemPickup
{
[Tooltip("The item types we got")]
[SerializeField] protected List<ItemType> m_ItemTypes = new List<ItemType>();
[Tooltip("All weapons we got")]
[SerializeField] protected PickupSet[] m_WeaponPickupSets;
[Tooltip("The number of ItemType that the character should receive.")]
[SerializeField] protected int m_Count = 1;
bool hasBeenGranted = false;
private InventoryBase inventory;
private ItemCollection itemCollection;
private GameObject player;
private ItemSetManager itemSetManager;
private ItemPlacement itemPlacement;
// Start is called before the first frame update
void Start()
{
player = GetMyAvatar();
itemSetManager = player.GetCachedComponent<ItemSetManager>();
itemCollection = itemSetManager.ItemCollection;
inventory = player.GetComponent<InventoryBase>();
itemPlacement = player.GetComponentInChildren<ItemPlacement>(true);
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyUp(KeyCode.Alpha2))
{
Debug.Log("Trying to aquire sword..");
foreach(var wps in m_WeaponPickupSets)
{
if(wps.ItemSet.Slots.First().name == "Sword")
{
var item = wps.Item.GetCachedComponent<Item>();
if(itemSetManager != null)
{
itemSetManager.AddItemSet(item, wps.ItemSet, wps.Default);
// Instantiate and add the item to the character.
if (!inventory.HasItem(item))
{
var itemGameObject = ObjectPool.Instantiate(wps.Item, Vector3.zero, Quaternion.identity, itemPlacement.transform);
itemGameObject.name = wps.Item.name;
itemGameObject.transform.localPosition = Vector3.zero;
itemGameObject.transform.localRotation = Quaternion.identity;
item = itemGameObject.GetComponent<Item>();
inventory.AddItem(item, false);
// Pickup item here
AddToInventory("Sword");
}
}
}
}
}
}
ItemType GetItemTypeByName(string itemTypeName)
{
var itemType = itemCollection.ItemTypes.Where(i => i.name == itemTypeName).FirstOrDefault();
return itemType;
}
GameObject GetMyAvatar()
{
var avatars = GameObject.FindGameObjectsWithTag("Player");
foreach(var ava in avatars)
{
if(ava.GetComponent<NetworkIdentity>().isLocalPlayer)
{
return ava;
}
}
return new GameObject();
}
void AddToInventory(string itemType)
{
// Get the players avatar
var ava = GetMyAvatar();
// Use generic function to do the rest.
_AddToInventory(ava, itemType);
}
// Overload for server use.
void AddToInventory(GameObject ava, string itemType)
{
// Just use the private function
_AddToInventory(ava, itemType);
}
private void _AddToInventory(GameObject ava, string itemTypeName)
{
if (inventory == null)
{
return;
}
var itemType = itemCollection.ItemTypes.Where(i => i.name == itemTypeName).FirstOrDefault();
if(itemType)
{
inventory.PickupItemType(itemType, m_Count, -1, true, false);
}
}
}
Last edited: