2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
|
|
|
|
2012-09-23 18:09:57 -04:00
|
|
|
#include "Inventory.h"
|
2013-08-19 05:39:13 -04:00
|
|
|
#include "Entities/Player.h"
|
2012-09-23 18:09:57 -04:00
|
|
|
#include "ClientHandle.h"
|
2012-09-23 13:19:34 -04:00
|
|
|
#include "UI/Window.h"
|
2012-09-23 18:09:57 -04:00
|
|
|
#include "Item.h"
|
|
|
|
#include "Root.h"
|
2013-05-19 14:22:37 -04:00
|
|
|
#include "World.h"
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-11-27 03:17:25 -05:00
|
|
|
#include "json/json.h"
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2012-09-29 09:59:32 -04:00
|
|
|
#include "Items/ItemHandler.h"
|
2012-08-11 15:54:57 -04:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-19 14:22:37 -04:00
|
|
|
cInventory::cInventory(cPlayer & a_Owner) :
|
2013-05-24 03:30:39 -04:00
|
|
|
m_ArmorSlots (1, 4), // 1 x 4 slots
|
|
|
|
m_InventorySlots(9, 3), // 9 x 3 slots
|
|
|
|
m_HotbarSlots (9, 1), // 9 x 1 slots
|
2013-05-19 14:22:37 -04:00
|
|
|
m_Owner(a_Owner)
|
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
// Ask each ItemGrid to report changes to us:
|
|
|
|
m_ArmorSlots.AddListener(*this);
|
|
|
|
m_InventorySlots.AddListener(*this);
|
|
|
|
m_HotbarSlots.AddListener(*this);
|
|
|
|
|
2013-05-19 14:22:37 -04:00
|
|
|
SetEquippedSlotNum(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
void cInventory::Clear(void)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
m_ArmorSlots.Clear();
|
|
|
|
m_InventorySlots.Clear();
|
|
|
|
m_HotbarSlots.Clear();
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
int cInventory::HowManyCanFit(const cItem & a_ItemStack, bool a_ConsiderEmptySlots)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
return HowManyCanFit(a_ItemStack, 0, invNumSlots - 1, a_ConsiderEmptySlots);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
int cInventory::HowManyCanFit(const cItem & a_ItemStack, int a_BeginSlotNum, int a_EndSlotNum, bool a_ConsiderEmptySlots)
|
|
|
|
{
|
2013-12-22 09:28:47 -05:00
|
|
|
|
|
|
|
UNUSED(a_ConsiderEmptySlots);
|
2013-05-24 03:30:39 -04:00
|
|
|
if ((a_BeginSlotNum < 0) || (a_BeginSlotNum >= invNumSlots))
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARNING("%s: Bad BeginSlotNum, got %d, there are %d slots; correcting to 0.", __FUNCTION__, a_BeginSlotNum, invNumSlots - 1);
|
|
|
|
a_BeginSlotNum = 0;
|
|
|
|
}
|
|
|
|
if ((a_EndSlotNum < 0) || (a_EndSlotNum >= invNumSlots))
|
|
|
|
{
|
|
|
|
LOGWARNING("%s: Bad EndSlotNum, got %d, there are %d slots; correcting to %d.", __FUNCTION__, a_BeginSlotNum, invNumSlots, invNumSlots - 1);
|
|
|
|
a_EndSlotNum = invNumSlots - 1;
|
|
|
|
}
|
|
|
|
if (a_BeginSlotNum > a_EndSlotNum)
|
|
|
|
{
|
|
|
|
std::swap(a_BeginSlotNum, a_EndSlotNum);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
char NumLeft = a_ItemStack.m_ItemCount;
|
|
|
|
int MaxStack = ItemHandler(a_ItemStack.m_ItemType)->GetMaxStackSize();
|
|
|
|
for (int i = a_BeginSlotNum; i <= a_EndSlotNum; i++)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
const cItem & Slot = GetSlot(i);
|
|
|
|
if (Slot.IsEmpty())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
NumLeft -= MaxStack;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2014-01-16 14:00:49 -05:00
|
|
|
else if (Slot.IsEqual(a_ItemStack))
|
2013-05-24 03:30:39 -04:00
|
|
|
{
|
|
|
|
NumLeft -= MaxStack - Slot.m_ItemCount;
|
|
|
|
}
|
|
|
|
if (NumLeft <= 0)
|
|
|
|
{
|
|
|
|
// All items fit
|
|
|
|
return a_ItemStack.m_ItemCount;
|
|
|
|
}
|
|
|
|
} // for i - m_Slots[]
|
|
|
|
return a_ItemStack.m_ItemCount - NumLeft;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-03 09:56:11 -04:00
|
|
|
int cInventory::AddItem(const cItem & a_Item, bool a_AllowNewStacks, bool a_tryToFillEquippedFirst)
|
2012-10-24 08:48:25 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
cItem ToAdd(a_Item);
|
|
|
|
int res = 0;
|
2012-10-24 08:48:25 -04:00
|
|
|
|
2014-07-19 19:22:58 -04:00
|
|
|
// When the item is a armor, try to set it directly to the armor slot.
|
|
|
|
if (ItemCategory::IsArmor(a_Item.m_ItemType))
|
|
|
|
{
|
2014-08-25 11:25:39 -04:00
|
|
|
for (int i = 0; i < m_ArmorSlots.GetNumSlots(); i++)
|
2014-07-19 19:22:58 -04:00
|
|
|
{
|
|
|
|
if (m_ArmorSlots.GetSlot(i).IsEmpty() && cSlotAreaArmor::CanPlaceArmorInSlot(i, a_Item))
|
|
|
|
{
|
|
|
|
m_ArmorSlots.SetSlot(i, a_Item);
|
|
|
|
return a_Item.m_ItemCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-03 09:56:11 -04:00
|
|
|
res += m_HotbarSlots.AddItem(ToAdd, a_AllowNewStacks, a_tryToFillEquippedFirst ? m_EquippedSlotNum : -1);
|
2013-05-24 03:30:39 -04:00
|
|
|
ToAdd.m_ItemCount = a_Item.m_ItemCount - res;
|
|
|
|
if (ToAdd.m_ItemCount == 0)
|
|
|
|
{
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
res += m_InventorySlots.AddItem(ToAdd, a_AllowNewStacks);
|
|
|
|
return res;
|
2012-10-24 08:48:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-03 09:56:11 -04:00
|
|
|
int cInventory::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, bool a_tryToFillEquippedFirst)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
int TotalAdded = 0;
|
|
|
|
for (cItems::iterator itr = a_ItemStackList.begin(); itr != a_ItemStackList.end();)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-07-03 09:56:11 -04:00
|
|
|
int NumAdded = AddItem(*itr, a_AllowNewStacks, a_tryToFillEquippedFirst);
|
2013-05-24 03:30:39 -04:00
|
|
|
if (itr->m_ItemCount == NumAdded)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
itr = a_ItemStackList.erase(itr);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
else
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
itr->m_ItemCount -= NumAdded;
|
|
|
|
++itr;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
TotalAdded += NumAdded;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
return TotalAdded;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-18 17:11:59 -04:00
|
|
|
int cInventory::RemoveItem(const cItem & a_ItemStack)
|
|
|
|
{
|
|
|
|
int RemovedItems = m_HotbarSlots.RemoveItem(a_ItemStack);
|
|
|
|
|
|
|
|
if (RemovedItems < a_ItemStack.m_ItemCount)
|
|
|
|
{
|
|
|
|
cItem Temp(a_ItemStack);
|
|
|
|
Temp.m_ItemCount -= RemovedItems;
|
|
|
|
RemovedItems += m_InventorySlots.RemoveItem(Temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return RemovedItems;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
bool cInventory::RemoveOneEquippedItem(void)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
if (m_HotbarSlots.GetSlot(m_EquippedSlotNum).IsEmpty())
|
2013-05-19 14:22:37 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
return false;
|
2013-05-19 14:22:37 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
|
|
|
|
m_HotbarSlots.ChangeSlotCount(m_EquippedSlotNum, -1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cInventory::HowManyItems(const cItem & a_Item)
|
|
|
|
{
|
|
|
|
return
|
|
|
|
m_ArmorSlots.HowManyItems(a_Item) +
|
|
|
|
m_InventorySlots.HowManyItems(a_Item) +
|
|
|
|
m_HotbarSlots.HowManyItems(a_Item);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cInventory::HasItems(const cItem & a_ItemStack)
|
|
|
|
{
|
|
|
|
int CurrentlyHave = HowManyItems(a_ItemStack);
|
|
|
|
return (CurrentlyHave >= a_ItemStack.m_ItemCount);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-19 14:22:37 -04:00
|
|
|
void cInventory::SetSlot(int a_SlotNum, const cItem & a_Item)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
if ((a_SlotNum < 0) || (a_SlotNum >= invNumSlots))
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Ignoring.", __FUNCTION__, a_SlotNum, invNumSlots - 1);
|
2013-05-19 14:22:37 -04:00
|
|
|
return;
|
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
|
|
|
|
int GridSlotNum = 0;
|
|
|
|
cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Grid == nullptr)
|
2013-05-19 14:22:37 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARNING("%s(%d): requesting an invalid itemgrid. Ignoring.", __FUNCTION__, a_SlotNum);
|
|
|
|
return;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
Grid->SetSlot(GridSlotNum, a_Item);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cInventory::SetArmorSlot(int a_ArmorSlotNum, const cItem & a_Item)
|
|
|
|
{
|
|
|
|
m_ArmorSlots.SetSlot(a_ArmorSlotNum, a_Item);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
void cInventory::SetInventorySlot(int a_InventorySlotNum, const cItem & a_Item)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
m_InventorySlots.SetSlot(a_InventorySlotNum, a_Item);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cInventory::SetHotbarSlot(int a_HotBarSlotNum, const cItem & a_Item)
|
|
|
|
{
|
|
|
|
m_HotbarSlots.SetSlot(a_HotBarSlotNum, a_Item);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-05-09 17:10:02 -04:00
|
|
|
void cInventory::SendEquippedSlot()
|
|
|
|
{
|
|
|
|
int EquippedSlotNum = cInventory::invArmorCount + cInventory::invInventoryCount + GetEquippedSlotNum();
|
|
|
|
SendSlot(EquippedSlotNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-19 14:22:37 -04:00
|
|
|
const cItem & cInventory::GetSlot(int a_SlotNum) const
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
if ((a_SlotNum < 0) || (a_SlotNum >= invNumSlots))
|
2013-05-19 14:22:37 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Returning the first inventory slot instead.", __FUNCTION__, a_SlotNum, invNumSlots - 1);
|
|
|
|
return m_InventorySlots.GetSlot(0);
|
2013-05-19 14:22:37 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
int GridSlotNum = 0;
|
|
|
|
const cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Grid == nullptr)
|
2013-05-24 03:30:39 -04:00
|
|
|
{
|
|
|
|
// Something went wrong, but we don't know what. We must return a value, so return the first inventory slot
|
|
|
|
LOGWARNING("%s(%d): requesting an invalid ItemGrid, returning the first inventory slot instead.", __FUNCTION__, a_SlotNum);
|
|
|
|
return m_InventorySlots.GetSlot(0);
|
|
|
|
}
|
|
|
|
return Grid->GetSlot(GridSlotNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const cItem & cInventory::GetArmorSlot(int a_ArmorSlotNum) const
|
|
|
|
{
|
|
|
|
if ((a_ArmorSlotNum < 0) || (a_ArmorSlotNum >= invArmorCount))
|
|
|
|
{
|
|
|
|
LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Returning the first one instead", __FUNCTION__, a_ArmorSlotNum, invArmorCount - 1);
|
|
|
|
return m_ArmorSlots.GetSlot(0);
|
|
|
|
}
|
|
|
|
return m_ArmorSlots.GetSlot(a_ArmorSlotNum);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
const cItem & cInventory::GetInventorySlot(int a_InventorySlotNum) const
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
if ((a_InventorySlotNum < 0) || (a_InventorySlotNum >= invInventoryCount))
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Returning the first one instead", __FUNCTION__, a_InventorySlotNum, invInventoryCount - 1);
|
|
|
|
return m_InventorySlots.GetSlot(0);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
return m_InventorySlots.GetSlot(a_InventorySlotNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const cItem & cInventory::GetHotbarSlot(int a_SlotNum) const
|
|
|
|
{
|
|
|
|
if ((a_SlotNum < 0) || (a_SlotNum >= invHotbarCount))
|
|
|
|
{
|
|
|
|
LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Returning the first one instead", __FUNCTION__, a_SlotNum, invHotbarCount - 1);
|
|
|
|
return m_HotbarSlots.GetSlot(0);
|
|
|
|
}
|
|
|
|
return m_HotbarSlots.GetSlot(a_SlotNum);
|
2013-05-19 14:22:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const cItem & cInventory::GetEquippedItem(void) const
|
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
return GetHotbarSlot(m_EquippedSlotNum);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-19 14:22:37 -04:00
|
|
|
void cInventory::SetEquippedSlotNum(int a_SlotNum)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
if ((a_SlotNum < 0) || (a_SlotNum >= invHotbarCount))
|
2012-09-20 09:25:54 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARNING("%s: requesting invalid slot index: %d out of %d. Setting 0 instead.", __FUNCTION__, a_SlotNum, invHotbarCount - 1);
|
2013-05-19 14:22:37 -04:00
|
|
|
m_EquippedSlotNum = 0;
|
2012-09-20 09:25:54 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
m_EquippedSlotNum = a_SlotNum;
|
2012-09-20 09:25:54 -04:00
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-19 14:22:37 -04:00
|
|
|
bool cInventory::DamageEquippedItem(short a_Amount)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
return DamageItem(invHotbarOffset + m_EquippedSlotNum, a_Amount);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-26 15:50:06 -04:00
|
|
|
int cInventory::ChangeSlotCount(int a_SlotNum, int a_AddToCount)
|
|
|
|
{
|
|
|
|
int GridSlotNum = 0;
|
|
|
|
cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Grid == nullptr)
|
2013-07-26 15:50:06 -04:00
|
|
|
{
|
|
|
|
LOGWARNING("%s: invalid slot number, expected 0 .. %d, got %d; ignoring", __FUNCTION__, invNumSlots, a_SlotNum);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return Grid->ChangeSlotCount(GridSlotNum, a_AddToCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-19 14:22:37 -04:00
|
|
|
bool cInventory::DamageItem(int a_SlotNum, short a_Amount)
|
2012-08-24 03:58:26 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
if ((a_SlotNum < 0) || (a_SlotNum >= invNumSlots))
|
2013-05-19 14:22:37 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARNING("%s: requesting an invalid slot index: %d out of %d", __FUNCTION__, a_SlotNum, invNumSlots - 1);
|
2013-05-19 14:22:37 -04:00
|
|
|
return false;
|
|
|
|
}
|
2014-07-23 10:32:09 -04:00
|
|
|
if (a_Amount <= 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2013-05-19 14:22:37 -04:00
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
int GridSlotNum = 0;
|
|
|
|
cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Grid == nullptr)
|
2013-05-19 14:22:37 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARNING("%s(%d, %d): requesting an invalid grid, ignoring.", __FUNCTION__, a_SlotNum, a_Amount);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!Grid->DamageItem(GridSlotNum, a_Amount))
|
|
|
|
{
|
|
|
|
// The item has been damaged, but did not break yet
|
2014-05-07 14:59:25 -04:00
|
|
|
SendSlot(a_SlotNum);
|
2013-05-19 14:22:37 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The item has broken, remove it:
|
2013-10-18 12:01:19 -04:00
|
|
|
Grid->EmptySlot(GridSlotNum);
|
2013-05-19 14:22:37 -04:00
|
|
|
return true;
|
2012-08-24 03:58:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
void cInventory::CopyToItems(cItems & a_Items)
|
|
|
|
{
|
|
|
|
m_ArmorSlots.CopyToItems(a_Items);
|
|
|
|
m_InventorySlots.CopyToItems(a_Items);
|
|
|
|
m_HotbarSlots.CopyToItems(a_Items);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-08-24 04:04:58 -04:00
|
|
|
void cInventory::SendSlot(int a_SlotNum)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-19 14:22:37 -04:00
|
|
|
cItem Item(GetSlot(a_SlotNum));
|
|
|
|
if (Item.IsEmpty())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-19 14:22:37 -04:00
|
|
|
// Sanitize items that are not completely empty (ie. count == 0, but type != empty)
|
|
|
|
Item.Empty();
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
m_Owner.GetClientHandle()->SendInventorySlot(0, a_SlotNum + 5, Item); // Slots in the client are numbered "+ 5" because of crafting grid and result
|
2012-08-11 15:54:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
/*
|
2012-08-19 07:51:17 -04:00
|
|
|
int cInventory::MoveItem(short a_ItemType, short a_ItemDamage, int a_Count, int a_BeginSlot, int a_EndSlot)
|
2012-08-11 15:54:57 -04:00
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
for (int i = a_BeginSlot; i <= a_EndSlot; i++)
|
|
|
|
{
|
|
|
|
if (
|
|
|
|
m_Slots[i].IsEmpty() ||
|
2013-01-11 23:46:01 -05:00
|
|
|
((m_Slots[i].m_ItemType == a_ItemType) && (m_Slots[i].m_ItemDamage == a_ItemDamage))
|
2012-08-11 15:54:57 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
int MaxCount = ItemHandler(a_ItemType)->GetMaxStackSize();
|
|
|
|
ASSERT(m_Slots[i].m_ItemCount <= MaxCount);
|
2012-08-14 04:33:09 -04:00
|
|
|
int NumToMove = std::min(a_Count, MaxCount - m_Slots[i].m_ItemCount);
|
2012-08-11 15:54:57 -04:00
|
|
|
m_Slots[i].m_ItemCount += NumToMove;
|
2013-01-11 23:46:01 -05:00
|
|
|
m_Slots[i].m_ItemDamage = a_ItemDamage;
|
|
|
|
m_Slots[i].m_ItemType = a_ItemType;
|
2012-08-11 15:54:57 -04:00
|
|
|
SendSlot(i);
|
|
|
|
res += NumToMove;
|
|
|
|
a_Count -= NumToMove;
|
|
|
|
if (a_Count <= 0)
|
|
|
|
{
|
|
|
|
// No more items to distribute
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // for i - m_Slots[]
|
|
|
|
// No more space to distribute to
|
|
|
|
return res;
|
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
*/
|
2012-08-11 15:54:57 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
int cInventory::ArmorSlotNumToEntityEquipmentID(short a_ArmorSlotNum)
|
2013-05-19 14:22:37 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
switch (a_ArmorSlotNum)
|
2013-05-19 14:22:37 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
case 0: return 4; // Helmet
|
|
|
|
case 1: return 3; // Chestplate
|
|
|
|
case 2: return 2; // Leggings
|
|
|
|
case 3: return 1; // Boots
|
2013-05-19 14:22:37 -04:00
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
LOGWARN("%s: invalid armor slot number: %d", __FUNCTION__, a_ArmorSlotNum);
|
2013-05-19 14:22:37 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
#if 0
|
2014-07-21 09:19:48 -04:00
|
|
|
bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size, bool* a_bChangedSlots, int a_Mode /* = 0 */)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
// Fill already present stacks
|
2014-07-21 09:19:48 -04:00
|
|
|
if (a_Mode < 2)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2012-10-24 08:48:25 -04:00
|
|
|
int MaxStackSize = cItemHandler::GetItemHandler(a_Item.m_ItemType)->GetMaxStackSize();
|
2014-07-20 17:10:31 -04:00
|
|
|
for (int i = 0; i < a_Size; i++)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2014-12-05 06:56:53 -05:00
|
|
|
if (
|
|
|
|
(m_Slots[i + a_Offset].m_ItemType == a_Item.m_ItemType) &&
|
|
|
|
(m_Slots[i + a_Offset].m_ItemCount < MaxStackSize) &&
|
|
|
|
(m_Slots[i + a_Offset].m_ItemDamage == a_Item.m_ItemDamage)
|
|
|
|
)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2012-10-24 08:48:25 -04:00
|
|
|
int NumFree = MaxStackSize - m_Slots[i + a_Offset].m_ItemCount;
|
2014-07-21 09:19:48 -04:00
|
|
|
if (NumFree >= a_Item.m_ItemCount)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
|
2014-07-21 09:19:48 -04:00
|
|
|
// printf("1. Adding %i items ( free: %i)\n", a_Item.m_ItemCount, NumFree);
|
2012-06-14 09:06:06 -04:00
|
|
|
m_Slots[i + a_Offset].m_ItemCount += a_Item.m_ItemCount;
|
|
|
|
a_Item.m_ItemCount = 0;
|
|
|
|
a_bChangedSlots[i + a_Offset] = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-07-21 09:19:48 -04:00
|
|
|
// printf("2. Adding %i items\n", NumFree);
|
2012-06-14 09:06:06 -04:00
|
|
|
m_Slots[i + a_Offset].m_ItemCount += (char)NumFree;
|
|
|
|
a_Item.m_ItemCount -= (char)NumFree;
|
|
|
|
a_bChangedSlots[i + a_Offset] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-21 09:19:48 -04:00
|
|
|
if (a_Mode > 0)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
// If we got more left, find first empty slot
|
2014-12-05 06:56:53 -05:00
|
|
|
for (int i = 0; (i < a_Size) && (a_Item.m_ItemCount > 0); i++)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2014-07-21 09:19:48 -04:00
|
|
|
if (m_Slots[i + a_Offset].m_ItemType == -1)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
m_Slots[i + a_Offset] = a_Item;
|
|
|
|
a_Item.m_ItemCount = 0;
|
|
|
|
a_bChangedSlots[i + a_Offset] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
#endif
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-17 09:27:12 -05:00
|
|
|
void cInventory::UpdateItems(void)
|
|
|
|
{
|
|
|
|
const cItem & Slot = GetEquippedItem();
|
|
|
|
|
|
|
|
if (Slot.IsEmpty())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (Slot.m_ItemType)
|
|
|
|
{
|
|
|
|
case E_ITEM_MAP:
|
|
|
|
{
|
|
|
|
ItemHandler(Slot.m_ItemType)->OnUpdate(m_Owner.GetWorld(), &m_Owner, Slot);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
void cInventory::SaveToJson(Json::Value & a_Value)
|
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
// The JSON originally included the 4 crafting slots and the result, so we have to put empty items there, too:
|
|
|
|
cItem EmptyItem;
|
|
|
|
Json::Value EmptyItemJson;
|
|
|
|
EmptyItem.GetJson(EmptyItemJson);
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
|
|
{
|
|
|
|
a_Value.append(EmptyItemJson);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The 4 armor slots follow:
|
|
|
|
for (int i = 0; i < invArmorCount; i++)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
Json::Value JSON_Item;
|
2013-05-24 03:30:39 -04:00
|
|
|
m_ArmorSlots.GetSlot(i).GetJson(JSON_Item);
|
|
|
|
a_Value.append(JSON_Item);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next comes the main inventory:
|
|
|
|
for (int i = 0; i < invInventoryCount; i++)
|
|
|
|
{
|
|
|
|
Json::Value JSON_Item;
|
|
|
|
m_InventorySlots.GetSlot(i).GetJson(JSON_Item);
|
|
|
|
a_Value.append(JSON_Item);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The hotbar is the last:
|
|
|
|
for (int i = 0; i < invHotbarCount; i++)
|
|
|
|
{
|
|
|
|
Json::Value JSON_Item;
|
|
|
|
m_HotbarSlots.GetSlot(i).GetJson(JSON_Item);
|
|
|
|
a_Value.append(JSON_Item);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cInventory::LoadFromJson(Json::Value & a_Value)
|
|
|
|
{
|
|
|
|
int SlotIdx = 0;
|
2012-09-20 09:25:54 -04:00
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
for (Json::Value::iterator itr = a_Value.begin(); itr != a_Value.end(); ++itr, SlotIdx++)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-05-24 03:30:39 -04:00
|
|
|
cItem Item;
|
|
|
|
Item.FromJson(*itr);
|
|
|
|
|
|
|
|
// The JSON originally included the 4 crafting slots and the result slot, so we need to skip the first 5 items:
|
|
|
|
if (SlotIdx < 5)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we loaded all the slots, stop now, even if the JSON has more:
|
|
|
|
if (SlotIdx - 5 >= invNumSlots)
|
2013-05-19 14:22:37 -04:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
|
|
|
|
int GridSlotNum = 0;
|
|
|
|
cItemGrid * Grid = GetGridForSlotNum(SlotIdx - 5, GridSlotNum);
|
2014-10-20 16:55:07 -04:00
|
|
|
ASSERT(Grid != nullptr);
|
2013-05-24 03:30:39 -04:00
|
|
|
Grid->SetSlot(GridSlotNum, Item);
|
|
|
|
} // for itr - a_Value[]
|
2012-06-14 09:06:06 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-24 03:30:39 -04:00
|
|
|
|
|
|
|
const cItemGrid * cInventory::GetGridForSlotNum(int a_SlotNum, int & a_GridSlotNum) const
|
|
|
|
{
|
|
|
|
ASSERT(a_SlotNum >= 0);
|
|
|
|
|
|
|
|
if (a_SlotNum < invArmorCount)
|
|
|
|
{
|
|
|
|
a_GridSlotNum = a_SlotNum;
|
|
|
|
return &m_ArmorSlots;
|
|
|
|
}
|
|
|
|
a_SlotNum -= invArmorCount;
|
|
|
|
if (a_SlotNum < invInventoryCount)
|
|
|
|
{
|
|
|
|
a_GridSlotNum = a_SlotNum;
|
|
|
|
return &m_InventorySlots;
|
|
|
|
}
|
|
|
|
a_GridSlotNum = a_SlotNum - invInventoryCount;
|
|
|
|
return &m_HotbarSlots;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cItemGrid * cInventory::GetGridForSlotNum(int a_SlotNum, int & a_GridSlotNum)
|
|
|
|
{
|
|
|
|
ASSERT(a_SlotNum >= 0);
|
|
|
|
|
|
|
|
if (a_SlotNum < invArmorCount)
|
|
|
|
{
|
|
|
|
a_GridSlotNum = a_SlotNum;
|
|
|
|
return &m_ArmorSlots;
|
|
|
|
}
|
|
|
|
a_SlotNum -= invArmorCount;
|
|
|
|
if (a_SlotNum < invInventoryCount)
|
|
|
|
{
|
|
|
|
a_GridSlotNum = a_SlotNum;
|
|
|
|
return &m_InventorySlots;
|
|
|
|
}
|
|
|
|
a_GridSlotNum = a_SlotNum - invInventoryCount;
|
|
|
|
return &m_HotbarSlots;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cInventory::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
|
|
|
|
{
|
|
|
|
// Send the neccessary updates to whoever needs them
|
|
|
|
|
|
|
|
if (m_Owner.IsDestroyed())
|
|
|
|
{
|
|
|
|
// Owner is not (yet) valid, skip for now
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Armor update needs broadcast to other players:
|
|
|
|
cWorld * World = m_Owner.GetWorld();
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((a_ItemGrid == &m_ArmorSlots) && (World != nullptr))
|
2013-05-24 03:30:39 -04:00
|
|
|
{
|
|
|
|
World->BroadcastEntityEquipment(
|
|
|
|
m_Owner, ArmorSlotNumToEntityEquipmentID(a_SlotNum),
|
|
|
|
m_ArmorSlots.GetSlot(a_SlotNum), m_Owner.GetClientHandle()
|
|
|
|
);
|
|
|
|
}
|
2014-07-23 10:32:09 -04:00
|
|
|
|
|
|
|
// Broadcast the Equipped Item, if the Slot is changed.
|
|
|
|
if ((a_ItemGrid == &m_HotbarSlots) && (m_EquippedSlotNum == a_SlotNum))
|
|
|
|
{
|
|
|
|
m_Owner.GetWorld()->BroadcastEntityEquipment(m_Owner, 0, GetEquippedItem(), m_Owner.GetClientHandle());
|
|
|
|
}
|
2013-05-24 03:30:39 -04:00
|
|
|
|
|
|
|
// Convert the grid-local a_SlotNum to our global SlotNum:
|
|
|
|
int Base = 0;
|
|
|
|
if (a_ItemGrid == &m_ArmorSlots)
|
|
|
|
{
|
|
|
|
Base = invArmorOffset;
|
|
|
|
}
|
|
|
|
else if (a_ItemGrid == &m_InventorySlots)
|
|
|
|
{
|
|
|
|
Base = invInventoryOffset;
|
|
|
|
}
|
|
|
|
else if (a_ItemGrid == &m_HotbarSlots)
|
|
|
|
{
|
|
|
|
Base = invHotbarOffset;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ASSERT(!"Unknown ItemGrid calling OnSlotChanged()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendSlot(Base + a_SlotNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|