/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "StdAfx.h"
#include "Item.h"
#include "Container.h"
#include "ItemPrototype.h"
#include "Player.h"
//
//-------------------------------------------------------------------//
ItemInterface::ItemInterface( Player *pPlayer )
{
m_pOwner = pPlayer;
memset(m_pItems, 0, sizeof(Item*)*MAX_INVENTORY_SLOT);
memset(m_pBuyBack, 0, sizeof(Item*)*MAX_BUYBACK_SLOT);
}
//-------------------------------------------------------------------//
ItemInterface::~ItemInterface()
{
for(int i = 0; i < MAX_INVENTORY_SLOT; i++)
{
if(m_pItems[i])
{
if(m_pItems[i]->IsContainer())
{
delete ((Container*)(m_pItems[i]));
}
else
{
delete m_pItems[i];
}
}
}
}
//-------------------------------------------------------------------// 100%
uint32 ItemInterface::m_CreateForPlayer(ByteBuffer *data)
{
ASSERT(m_pOwner != NULL);
uint32 count = 0;
for(int i = 0; i < MAX_INVENTORY_SLOT; i++)
{
if(m_pItems[i])
{
if(m_pItems[i]->IsContainer())
{
count += ((Container*)(m_pItems[i]))->BuildCreateUpdateBlockForPlayer(data, m_pOwner);
if(m_pItems[i]->GetProto())
{
for(uint32 e=0; e < m_pItems[i]->GetProto()->ContainerSlots; e++)
{
Item *pItem = ((Container*)(m_pItems[i]))->GetItem(e);
if(pItem)
{
if(pItem->IsContainer())
{
count += ((Container*)(pItem))->BuildCreateUpdateBlockForPlayer( data, m_pOwner );
}
else
{
count += pItem->BuildCreateUpdateBlockForPlayer( data, m_pOwner );
}
}
}
}
}
else
{
count += m_pItems[i]->BuildCreateUpdateBlockForPlayer(data, m_pOwner);
}
}
}
return count;
}
//-------------------------------------------------------------------// 100%
void ItemInterface::m_DestroyForPlayer()
{
ASSERT(m_pOwner != NULL);
for(int i = 0; i < MAX_INVENTORY_SLOT; i++)
{
if(m_pItems[i])
{
if(m_pItems[i]->IsContainer())
{
if(m_pItems[i]->GetProto())
{
for(uint32 e=0; e < m_pItems[i]->GetProto()->ContainerSlots; e++)
{
Item *pItem = ((Container*)(m_pItems[i]))->GetItem(e);
if(pItem)
{
if(pItem->IsContainer())
{
((Container*)(pItem))->DestroyForPlayer( m_pOwner );
}
else
{
pItem->DestroyForPlayer( m_pOwner );
}
}
}
}
((Container*)(m_pItems[i]))->DestroyForPlayer( m_pOwner );
}
else
{
m_pItems[i]->DestroyForPlayer( m_pOwner );
}
}
}
}
//-------------------------------------------------------------------//
//Description: Creates and adds a item that can be manipulated after
//-------------------------------------------------------------------//
Item *ItemInterface::SafeAddItem(uint32 ItemId, int8 ContainerSlot, int8 slot)
{
Item *pItem;
ItemPrototype *pProto = ItemPrototypeStorage.LookupEntry(ItemId);
if(!pProto) { return NULL; }
if(pProto->InventoryType == INVTYPE_BAG)
{
pItem = (Item*)new Container(HIGHGUID_CONTAINER,objmgr.GenerateLowGuid(HIGHGUID_CONTAINER));
static_cast(pItem)->Create( ItemId, m_pOwner);
if(m_AddItem(pItem, ContainerSlot, slot))
{
return pItem;
}
else
{
delete pItem;
return NULL;
}
}
else
{
pItem = new Item(HIGHGUID_ITEM,objmgr.GenerateLowGuid(HIGHGUID_ITEM));
pItem->Create( ItemId, m_pOwner);
if(m_AddItem(pItem, ContainerSlot, slot))
{
return pItem;
}
else
{
delete pItem;
return NULL;
}
}
return NULL;
}
//-------------------------------------------------------------------//
//Description: Creates and adds a item that can be manipulated after
//-------------------------------------------------------------------//
bool ItemInterface::SafeAddItem(Item *pItem, int8 ContainerSlot, int8 slot)
{
return m_AddItem(pItem, ContainerSlot, slot);
}
//-------------------------------------------------------------------//
//Description: adds items to player inventory, this includes all types of slots.
//-------------------------------------------------------------------//
bool ItemInterface::m_AddItem(Item *item, int8 ContainerSlot, int8 slot)
{
ASSERT(slot < MAX_INVENTORY_SLOT);
ASSERT(ContainerSlot < MAX_INVENTORY_SLOT);
ASSERT(item != NULL);
item->m_isDirty = true;
if(item->GetProto())
{
//case 1, item is from backpack container
if(ContainerSlot == INVENTORY_SLOT_NOT_SET)
{
//ASSERT(m_pItems[slot] == NULL);
if(GetInventoryItem(slot) != NULL /*|| (slot == EQUIPMENT_SLOT_OFFHAND && !m_pOwner->HasSkillLine(118))*/)
{
//sLog.outError("bugged inventory: %u %u", m_pOwner->GetName(), item->GetGUID());
SlotResult result = this->FindFreeInventorySlot(item->GetProto());
// send message to player
sChatHandler.BlueSystemMessageToPlr(m_pOwner, "A duplicated item, `%s` was found in your inventory. We've attempted to add it to a free slot in your inventory, if there is none this will fail. It will be attempted again the next time you log on.",
item->GetProto()->Name1);
if(result.Result == true)
{
// Found a new slot for that item.
slot = result.Slot;
ContainerSlot = result.ContainerSlot;
}
else
{
// don't leak memory!
if(item->IsContainer())
delete ((Container*)item);
else
delete item;
return false;
}
}
if(!GetInventoryItem(slot)) //slot is free, add item.
{
item->SetOwner( m_pOwner );
item->SetUInt64Value(ITEM_FIELD_CONTAINED, m_pOwner->GetGUID());
m_pItems[(int)slot] = item;
if (item->GetProto()->Bonding == ITEM_BIND_ON_PICKUP)
item->SoulBind();
if( m_pOwner->IsInWorld() && !item->IsInWorld())
{
//item->AddToWorld();
item->PushToWorld(m_pOwner->GetMapMgr());
ByteBuffer buf(2500);
uint32 count = item->BuildCreateUpdateBlockForPlayer( &buf, m_pOwner );
m_pOwner->PushCreationData(&buf, count);
}
m_pOwner->SetUInt64Value(PLAYER_FIELD_INV_SLOT_HEAD + (slot*2), item->GetGUID());
}
else
{
return false;
}
}
else //case 2: item is from a bag container
{
if(GetInventoryItem(ContainerSlot) && GetInventoryItem(ContainerSlot)->IsContainer() &&
slot < (int32)GetInventoryItem(ContainerSlot)->GetProto()->ContainerSlots) //container exists
{
bool result = static_cast(m_pItems[(int)ContainerSlot])->AddItem(slot, item);
if(!result)
{
return false;
}
}
else
{
return false;
}
}
}
else
{
return false;
}
if ( slot < EQUIPMENT_SLOT_END && ContainerSlot == INVENTORY_SLOT_NOT_SET )
{
int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 16);
if(VisibleBase > PLAYER_VISIBLE_ITEM_19_0)
{
printf("Slot warning: slot: %d\n", slot);
OutputCrashLogLine("Slot warning: slot: %d\n", slot);
}
else
{
m_pOwner->SetUInt32Value(VisibleBase, item->GetUInt32Value(OBJECT_FIELD_ENTRY));
m_pOwner->SetUInt32Value(VisibleBase + 1, item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT));
m_pOwner->SetUInt32Value(VisibleBase + 2, item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 3));
m_pOwner->SetUInt32Value(VisibleBase + 3, item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 6));
m_pOwner->SetUInt32Value(VisibleBase + 4, item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 9));
m_pOwner->SetUInt32Value(VisibleBase + 5, item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 12));
m_pOwner->SetUInt32Value(VisibleBase + 6, item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 15));
m_pOwner->SetUInt32Value(VisibleBase + 7, item->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 18));
m_pOwner->SetUInt32Value(VisibleBase + 8, item->GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID));
}
}
if( m_pOwner->IsInWorld() && slot < INVENTORY_SLOT_BAG_END && ContainerSlot == INVENTORY_SLOT_NOT_SET)
{
m_pOwner->ApplyItemMods( item,slot, true );
}
if(ContainerSlot == INVENTORY_SLOT_NOT_SET && slot == EQUIPMENT_SLOT_OFFHAND && item->GetProto()->Class == ITEM_CLASS_WEAPON)
m_pOwner->SetDuelWield(true);
return true;
}
//-------------------------------------------------------------------//
//Description: Checks if the slot is a Bag slot
//-------------------------------------------------------------------//
bool ItemInterface::IsBagSlot(int8 slot)
{
if((slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END) || (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END))
{
return true;
}
return false;
}
//-------------------------------------------------------------------//
//Description: removes the item safely and returns it back for usage
//-------------------------------------------------------------------//
Item *ItemInterface::SafeRemoveAndRetreiveItemFromSlot(int8 ContainerSlot, int8 slot, bool destroy)
{
ASSERT(slot < MAX_INVENTORY_SLOT);
ASSERT(ContainerSlot < MAX_INVENTORY_SLOT);
Item *pItem = NULL;
if(ContainerSlot == INVENTORY_SLOT_NOT_SET)
{
pItem = GetInventoryItem(ContainerSlot,slot);
if (pItem == NULL) { return NULL; }
if(pItem->GetProto()->ContainerSlots > 0 && ((Container*)pItem)->HasItems())
{
/* sounds weird? no. this will trigger a callstack display due to my other debug code. */
pItem->DeleteFromDB();
return false;
}
m_pItems[(int)slot] = NULL;
pItem->m_isDirty = true;
m_pOwner->SetUInt64Value(PLAYER_FIELD_INV_SLOT_HEAD + (slot*2), 0 );
if ( slot < EQUIPMENT_SLOT_END )
{
m_pOwner->ApplyItemMods( pItem, slot, false );
int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 16);
for (int i = VisibleBase; i < VisibleBase + 12; ++i)
{
m_pOwner->SetUInt32Value(i, 0);
}
}
else if ( slot < INVENTORY_SLOT_BAG_END )
m_pOwner->ApplyItemMods( pItem, slot, false );
if(slot == EQUIPMENT_SLOT_OFFHAND)
m_pOwner->SetDuelWield(false);
if(destroy)
{
if (pItem->IsInWorld())
{
pItem->RemoveFromWorld();
}
pItem->DeleteFromDB();
}
}
else
{
Item *pContainer = GetInventoryItem(ContainerSlot);
if(pContainer && pContainer->IsContainer())
{
pItem = static_cast(pContainer)->SafeRemoveAndRetreiveItemFromSlot(slot, destroy);
if (pItem == NULL) { return NULL; }
}
}
return pItem;
}
//-------------------------------------------------------------------//
//Description: removes the item safely by guid and returns it back for usage, supports full inventory
//-------------------------------------------------------------------//
Item *ItemInterface::SafeRemoveAndRetreiveItemByGuid(uint64 guid, bool destroy)
{
int8 i = 0;
for(i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeRemoveAndRetreiveItemFromSlot(INVENTORY_SLOT_NOT_SET, i, destroy);
}
}
for(i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeRemoveAndRetreiveItemFromSlot(INVENTORY_SLOT_NOT_SET, i, destroy);
}
}
for(i = INVENTORY_KEYRING_START; i < INVENTORY_KEYRING_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeRemoveAndRetreiveItemFromSlot(INVENTORY_SLOT_NOT_SET, i, destroy);
}
}
for(i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item && item->GetGUID() == guid)
{
return this->SafeRemoveAndRetreiveItemFromSlot(INVENTORY_SLOT_NOT_SET, i, destroy);
}
else
{
if(item && item->IsContainer() && item->GetProto())
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots; j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2 && item2->GetGUID() == guid)
{
return ((Container*)item)->SafeRemoveAndRetreiveItemFromSlot(j, destroy);
}
}
}
}
}
for(i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeRemoveAndRetreiveItemFromSlot(INVENTORY_SLOT_NOT_SET, i, destroy);
}
}
for(i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeRemoveAndRetreiveItemFromSlot(INVENTORY_SLOT_NOT_SET, i, destroy);
}
else
{
if(item && item->IsContainer() && item->GetProto())
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots; j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2 && item2->GetGUID() == guid)
{
return ((Container*)item)->SafeRemoveAndRetreiveItemFromSlot(j, destroy);
}
}
}
}
}
return NULL;
}
//-------------------------------------------------------------------//
//Description: completely removes item from player
//Result: true if item removal was succefull
//-------------------------------------------------------------------//
bool ItemInterface::SafeFullRemoveItemFromSlot(int8 ContainerSlot, int8 slot)
{
ASSERT(slot < MAX_INVENTORY_SLOT);
ASSERT(ContainerSlot < MAX_INVENTORY_SLOT);
if(ContainerSlot == INVENTORY_SLOT_NOT_SET)
{
Item *pItem = GetInventoryItem(slot);
if (pItem == NULL) { return false; }
if(pItem->GetProto()->ContainerSlots > 0 && ((Container*)pItem)->HasItems())
{
/* sounds weird? no. this will trigger a callstack display due to my other debug code. */
pItem->DeleteFromDB();
return false;
}
m_pItems[(int)slot] = NULL;
pItem->m_isDirty = true;
m_pOwner->SetUInt64Value(PLAYER_FIELD_INV_SLOT_HEAD + (slot*2), 0 );
if ( slot < EQUIPMENT_SLOT_END )
{
m_pOwner->ApplyItemMods(pItem, slot, false );
int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * 16);
for (int i = VisibleBase; i < VisibleBase + 12; ++i)
{
m_pOwner->SetUInt32Value(i, 0);
}
}
else if( slot < INVENTORY_SLOT_BAG_END )
m_pOwner->ApplyItemMods(pItem, slot, false ); //watch containers that give attackspeed and stuff ;)
if(slot == EQUIPMENT_SLOT_OFFHAND)
m_pOwner->SetDuelWield(false);
if (pItem->IsInWorld())
{
pItem->RemoveFromWorld();
}
pItem->DeleteFromDB();
delete pItem;
}
else
{
Item *pContainer = GetInventoryItem(ContainerSlot);
if(pContainer && pContainer->IsContainer())
{
static_cast(pContainer)->SafeFullRemoveItemFromSlot(slot);
}
}
return true;
}
//-------------------------------------------------------------------//
//Description: removes the item safely by guid, supports full inventory
//-------------------------------------------------------------------//
bool ItemInterface::SafeFullRemoveItemByGuid(uint64 guid)
{
int8 i = 0;
for(i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
}
}
for(i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
}
}
for(i = INVENTORY_KEYRING_START; i < INVENTORY_KEYRING_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
}
}
for(i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item && item->GetGUID() == guid)
{
return this->SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
}
else
{
if(item && item->IsContainer() && item->GetProto())
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots; j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2 && item2->GetGUID() == guid)
{
return ((Container*)item)->SafeFullRemoveItemFromSlot(j);
}
}
}
}
}
for(i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if (item && item->GetGUID() == guid)
{
return this->SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
}
}
for(i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item && item->GetGUID() == guid)
{
return this->SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
}
else
{
if(item && item->IsContainer() && item->GetProto())
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots; j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2 && item2->GetGUID() == guid)
{
return ((Container*)item)->SafeFullRemoveItemFromSlot(j);
}
}
}
}
}
return false;
}
//-------------------------------------------------------------------//
//Description: Gets a item from Inventory
//-------------------------------------------------------------------//
Item *ItemInterface::GetInventoryItem(int8 slot)
{
if(slot == INVENTORY_SLOT_NOT_SET || slot > MAX_INVENTORY_SLOT)
{
return NULL;
}
return m_pItems[(int)slot];
}
//-------------------------------------------------------------------//
//Description: Gets a Item from inventory or container
//-------------------------------------------------------------------//
Item *ItemInterface::GetInventoryItem(int8 ContainerSlot, int8 slot)
{
if(ContainerSlot == INVENTORY_SLOT_NOT_SET)
{
if(slot == INVENTORY_SLOT_NOT_SET || slot > MAX_INVENTORY_SLOT)
{
return NULL;
}
return m_pItems[(int)slot];
}
else
{
if(IsBagSlot(ContainerSlot))
{
if(m_pItems[(int)ContainerSlot])
{
return static_cast(m_pItems[(int)ContainerSlot])->GetItem(slot);
}
}
}
return NULL;
}
//-------------------------------------------------------------------//
//Description: checks for stacks that didnt reached max capacity
//-------------------------------------------------------------------//
Item* ItemInterface::FindItemLessMax(uint32 itemid, uint32 cnt, bool IncBank)
{
uint32 i = 0;
for(i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if (item)
{
if((item->GetEntry() == itemid) && (item->GetProto()->MaxCount >= (item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + cnt)))
{
return item;
}
}
}
for(i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item)
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots; j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2)
{
if((item2->GetProto()->ItemId == itemid) && (item2->GetProto()->MaxCount >= (item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + cnt)))
{
return item2;
}
}
}
}
}
if(IncBank)
{
for(i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if (item)
{
if((item->GetEntry() == itemid) && (item->GetProto()->MaxCount >= (item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + cnt)))
{
return item;
}
}
}
for(i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item)
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots; j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2)
{
if((item2->GetProto()->ItemId == itemid) && (item2->GetProto()->MaxCount >= (item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT) + cnt)))
{
return item2;
}
}
}
}
}
}
return NULL;
}
//-------------------------------------------------------------------//
//Description: finds item ammount on inventory, banks not included
//-------------------------------------------------------------------//
uint32 ItemInterface::GetItemCount(uint32 itemid, bool IncBank)
{
uint32 cnt = 0;
uint32 i = 0;
for(i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if (item)
{
if(item->GetEntry() == itemid)
{
cnt += item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) ? item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) : 1;
}
}
}
for(i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item)
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots;j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2)
{
if (item2->GetEntry() == itemid)
{
cnt += item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT) ? item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT) : 1;
}
}
}
}
}
for(i = INVENTORY_KEYRING_START; i < INVENTORY_KEYRING_END; i++)
{
Item *item = GetInventoryItem(i);
if (item)
{
if(item->GetProto()->ItemId == itemid)
{
cnt += item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) ? item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) : 1;
}
}
}
if(IncBank)
{
for(i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if (item)
{
if(item->GetProto()->ItemId == itemid)
{
cnt += item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) ? item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) : 1;
}
}
}
for(i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item)
{
if(item->IsContainer())
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots; j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2)
{
if(item2->GetProto()->ItemId == itemid)
{
cnt += item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT) ? item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT) : 1;
}
}
}
}
}
}
}
return cnt;
}
//-------------------------------------------------------------------//
//Description: Removes a ammount of items from inventory
//-------------------------------------------------------------------//
uint32 ItemInterface::RemoveItemAmt(uint32 id, uint32 amt)
{
//this code returns shit return value is fucked
if (GetItemCount(id) < amt)
{
return 0;
}
uint32 i;
for(i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if (item)
{
if(item->GetEntry() == id)
{
if(item->GetProto()->ContainerSlots > 0 && ((Container*)item)->HasItems())
{
/* sounds weird? no. this will trigger a callstack display due to my other debug code. */
item->DeleteFromDB();
continue;
}
if (item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) > amt)
{
item->SetCount(item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) - amt);
item->m_isDirty = true;
return amt;
}
else if (item->GetUInt32Value(ITEM_FIELD_STACK_COUNT)== amt)
{
bool result = SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
if(result)
{
return amt;
}
else
{
return 0;
}
}
else
{
amt -= item->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
}
}
}
}
for(i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item)
{
for (uint32 j =0; j < item->GetProto()->ContainerSlots;j++)
{
Item *item2 = ((Container*)item)->GetItem(j);
if (item2)
{
if (item2->GetProto()->ItemId == id)
{
if (item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT) > amt)
{
item2->SetCount(item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT) - amt);
item2->m_isDirty = true;
return amt;
}
else if (item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT)== amt)
{
bool result = SafeFullRemoveItemFromSlot(i, j);
if(result)
{
return amt;
}
else
{
return 0;
}
}
else
{
amt -= item2->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
SafeFullRemoveItemFromSlot(i, j);
}
}
}
}
}
}
for(i = INVENTORY_KEYRING_START; i < INVENTORY_KEYRING_END; i++)
{
Item *item = GetInventoryItem(i);
if (item)
{
if(item->GetProto()->ItemId == id)
{
if (item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) > amt)
{
item->SetCount(item->GetUInt32Value(ITEM_FIELD_STACK_COUNT) - amt);
item->m_isDirty = true;
return amt;
}
else if (item->GetUInt32Value(ITEM_FIELD_STACK_COUNT)== amt)
{
bool result = SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
if(result)
{
return amt;
}
else
{
return 0;
}
}
else
{
amt -= item->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, i);
}
}
}
}
return 0;
}
//-------------------------------------------------------------------//
//Description: Gets slot number by itemid, banks not included
//-------------------------------------------------------------------//
int8 ItemInterface::GetInventorySlotById(uint32 ID)
{
for(uint32 i=0;iGetProto()->ItemId == ID)
{
return i;
}
}
}
for(uint32 i=INVENTORY_KEYRING_START; iGetProto()->ItemId == ID)
{
return i;
}
}
}
return ITEM_NO_SLOT_AVAILABLE;
}
//-------------------------------------------------------------------//
//Description: Gets slot number by item guid, banks not included
//-------------------------------------------------------------------//
int8 ItemInterface::GetInventorySlotByGuid(uint64 guid)
{
for(uint32 i=EQUIPMENT_SLOT_START ;iGetGUID() == guid)
{
return i;
}
}
}
for(uint32 i=INVENTORY_KEYRING_START; iGetGUID() == guid)
{
return i;
}
}
}
return ITEM_NO_SLOT_AVAILABLE; //was changed from 0 cuz 0 is the slot for head
}
//-------------------------------------------------------------------//
//Description: Adds a Item to a free slot
//-------------------------------------------------------------------//
bool ItemInterface::AddItemToFreeSlot(Item *item)
{
if(!item) { return false; }
uint32 i = 0;
//detect special bag item
if(item->GetProto()->BagFamily)
{
if(item->GetProto()->BagFamily == ITEM_TYPE_KEYRING)
{
for(i=INVENTORY_KEYRING_START; iGetProto()->BagFamily == item->GetProto()->BagFamily)
{
if(m_pItems[i]->IsContainer())
{
bool result = static_cast(m_pItems[i])->AddItemToFreeSlot(item);
if (result) { return true; }
}
}
}
}
}
}
//INVENTORY
for(i=INVENTORY_SLOT_ITEM_START;iGetProto()->BagFamily == 0) //special bags ignored
{
for (uint32 j =0; j < m_pItems[i]->GetProto()->ContainerSlots;j++)
{
Item *item2 = ((Container*)m_pItems[i])->GetItem(j);
if (item2 == NULL)
{
return SafeAddItem(item, i, j);
}
}
}
}
return false;
}
//-------------------------------------------------------------------//
//Description: Calculates inventory free slots, bag inventory slots not included
//-------------------------------------------------------------------//
uint32 ItemInterface::CalculateFreeSlots(ItemPrototype *proto)
{
uint32 count = 0;
uint32 i;
if(proto)
{
if(proto->BagFamily)
{
if(proto->BagFamily == ITEM_TYPE_KEYRING)
{
for(uint32 i = INVENTORY_KEYRING_START; i < INVENTORY_KEYRING_END; i++)
{
if(m_pItems[i] == NULL)
{
count++;
}
}
}
else
{
for(uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END;i++)
{
if(m_pItems[i] && m_pItems[i]->IsContainer())
{
if (m_pItems[i]->GetProto()->BagFamily == proto->BagFamily)
{
int8 slot = ((Container*)m_pItems[i])->FindFreeSlot();
if(slot != ITEM_NO_SLOT_AVAILABLE)
{
count++;
}
}
}
}
}
}
}
for(i=INVENTORY_SLOT_ITEM_START;iIsContainer() && !m_pItems[i]->GetProto()->BagFamily)
{
for (uint32 j =0; j < m_pItems[i]->GetProto()->ContainerSlots;j++)
{
Item *item2 = ((Container*)m_pItems[i])->GetItem(j);
if (item2 == NULL)
{
count++;
}
}
}
}
}
return count;
}
//-------------------------------------------------------------------//
//Description: finds a free slot on the backpack
//-------------------------------------------------------------------//
int8 ItemInterface::FindFreeBackPackSlot()
{
//search for backpack slots
for(int8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if(!item)
{
return i;
}
}
return ITEM_NO_SLOT_AVAILABLE; //no slots available
}
//-------------------------------------------------------------------//
//Description: converts bank bags slot ids into player bank byte slots(0-5)
//-------------------------------------------------------------------//
int8 ItemInterface::GetInternalBankSlotFromPlayer(int8 islot)
{
switch(islot)
{
case BANK_SLOT_BAG_1:
{
return 1;
}
case BANK_SLOT_BAG_2:
{
return 2;
}
case BANK_SLOT_BAG_3:
{
return 3;
}
case BANK_SLOT_BAG_4:
{
return 4;
}
case BANK_SLOT_BAG_5:
{
return 5;
}
case BANK_SLOT_BAG_6:
{
return 6;
}
case BANK_SLOT_BAG_7:
{
return 7;
}
default:
return 8;
}
}
//-------------------------------------------------------------------//
//Description: checks if the item can be equiped on a specific slot
//-------------------------------------------------------------------//
int8 ItemInterface::CanEquipItemInSlot(int8 DstInvSlot, int8 slot, ItemPrototype *proto, bool ignore_combat)
{
uint32 type=proto->InventoryType;
if((slot < INVENTORY_SLOT_BAG_END && DstInvSlot == INVENTORY_SLOT_NOT_SET) || (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END && DstInvSlot == INVENTORY_SLOT_NOT_SET))
{
if (!ignore_combat && m_pOwner->isInCombat())
return INV_ERR_CANT_DO_IN_COMBAT;
// Check to see if we have the correct race
if(!(proto->AllowableRace& (1<getRace())))
return INV_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
// Check to see if we have the correct class
if(!(proto->AllowableClass & (1<<(m_pOwner->getClass()-1))))
return INV_ERR_YOU_CAN_NEVER_USE_THAT_ITEM2;
// Check to see if we have the reqs for that reputation
if(proto->RequiredFaction)
{
Standing current_standing = Player::GetReputationRankFromStanding(m_pOwner->GetStanding(proto->RequiredFaction));
if(current_standing < (Standing)proto->RequiredFactionStanding) // Not enough rep rankage..
return INV_ERR_ITEM_REPUTATION_NOT_ENOUGH;
}
// Check to see if we have the correct level.
if(proto->RequiredLevel>m_pOwner->GetUInt32Value(UNIT_FIELD_LEVEL))
return INV_ERR_YOU_MUST_REACH_LEVEL_N;
if(proto->Class == 4)
{
if(!(m_pOwner->GetArmorProficiency()&(((uint32)(1))<SubClass)))
return INV_ERR_NO_REQUIRED_PROFICIENCY;
}
else if(proto->Class == 2)
{
if(!(m_pOwner->GetWeaponProficiency()&(((uint32)(1))<SubClass)))
return INV_ERR_NO_REQUIRED_PROFICIENCY;
}
/*
uint32 SubClassSkill = GetSkillByProto(proto);
// removed those loops, use the skill lookup functions
if(SubClassSkill)
{
if(!HasSkillLine(SubClassSkill))
return INV_ERR_NO_REQUIRED_PROFICIENCY;
}*/
if(proto->RequiredSkill)
if (proto->RequiredSkillRank > m_pOwner->_GetSkillLineCurrent(proto->RequiredSkill,true))
return INV_ERR_SKILL_ISNT_HIGH_ENOUGH;
// You are dead !
if(m_pOwner->getDeathState() == DEAD)
return INV_ERR_YOU_ARE_DEAD;
}
switch(slot)
{
case EQUIPMENT_SLOT_HEAD:
{
if(type == INVTYPE_HEAD)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_NECK:
{
if(type == INVTYPE_NECK)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_SHOULDERS:
{
if(type == INVTYPE_SHOULDERS)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_BODY:
{
if(type == INVTYPE_BODY)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_CHEST:
{
if(type == INVTYPE_CHEST || type == INVTYPE_ROBE)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_WAIST:
{
if(type == INVTYPE_WAIST)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_LEGS:
{
if(type == INVTYPE_LEGS)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_FEET:
{
if(type == INVTYPE_FEET)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_WRISTS:
{
if(type == INVTYPE_WRISTS)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_HANDS:
{
if(type == INVTYPE_HANDS)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_FINGER1:
case EQUIPMENT_SLOT_FINGER2:
{
if(type == INVTYPE_FINGER)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_TRINKET1:
case EQUIPMENT_SLOT_TRINKET2:
{
if(type == INVTYPE_TRINKET)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_BACK:
{
if(type == INVTYPE_CLOAK)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_MAINHAND:
{
if(type == INVTYPE_WEAPON || type == INVTYPE_WEAPONMAINHAND ||
(type == INVTYPE_2HWEAPON && !GetInventoryItem(EQUIPMENT_SLOT_OFFHAND)))
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_OFFHAND:
{
if(type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND)
{
Item* mainweapon = GetInventoryItem(EQUIPMENT_SLOT_MAINHAND);
if(mainweapon) //item exists
{
if(mainweapon->GetProto())
{
if(mainweapon->GetProto()->InventoryType != INVTYPE_2HWEAPON)
{
if(m_pOwner->_HasSkillLine(SKILL_DUAL_WIELD))
return 0;
else
return INV_ERR_CANT_DUAL_WIELD;
}
else
return INV_ERR_CANT_EQUIP_WITH_TWOHANDED;
}
}
else
{
if(m_pOwner->_HasSkillLine(SKILL_DUAL_WIELD))
return 0;
else
return INV_ERR_CANT_DUAL_WIELD;
}
}
else if(type == INVTYPE_SHIELD || type == INVTYPE_HOLDABLE)
{
Item* mainweapon = GetInventoryItem(EQUIPMENT_SLOT_MAINHAND);
if(mainweapon) //item exists
{
if(mainweapon->GetProto())
{
if(mainweapon->GetProto()->InventoryType != INVTYPE_2HWEAPON)
{
return 0;
}
else
return INV_ERR_CANT_EQUIP_WITH_TWOHANDED;
}
}
else
{
return 0;
}
}
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
case EQUIPMENT_SLOT_RANGED:
{
if(type == INVTYPE_RANGED || type == INVTYPE_THROWN || type == INVTYPE_RANGEDRIGHT || type == INVTYPE_RELIC)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT;//6;
}
case EQUIPMENT_SLOT_TABARD:
{
if(type == INVTYPE_TABARD)
return 0;
else
return INV_ERR_ITEM_DOESNT_GO_TO_SLOT; // 6;
}
case BANK_SLOT_BAG_1:
case BANK_SLOT_BAG_2:
case BANK_SLOT_BAG_3:
case BANK_SLOT_BAG_4:
case BANK_SLOT_BAG_5:
case BANK_SLOT_BAG_6:
case BANK_SLOT_BAG_7:
{
int32 bytes,slots;
int8 islot;
if(!GetInventoryItem(INVENTORY_SLOT_NOT_SET,slot))
{
//check if player got that slot.
bytes = m_pOwner->GetUInt32Value(PLAYER_BYTES_2);
slots =(uint8) (bytes >> 16);
islot = GetInternalBankSlotFromPlayer(slot);
if(slots < islot)
{
return INV_ERR_MUST_PURCHASE_THAT_BAG_SLOT;
}
//in case bank slot exists, check if player can put the item there
if(type == INVTYPE_BAG)
{
return 0;
}
else
{
return INV_ERR_NOT_A_BAG;
}
}
else
{
if(GetInventoryItem(INVENTORY_SLOT_NOT_SET,slot)->GetProto()->BagFamily)
{
if((IsBagSlot(slot) && DstInvSlot == INVENTORY_SLOT_NOT_SET))
{
if(proto->InventoryType == INVTYPE_BAG )
{
return 0;
}
}
if(proto->BagFamily == GetInventoryItem(INVENTORY_SLOT_NOT_SET,slot)->GetProto()->BagFamily)
{
return 0;
}
else
{
return INV_ERR_ITEM_DOESNT_GO_INTO_BAG;
}
}
else
{
return 0;
}
}
}
case INVENTORY_SLOT_BAG_1:
case INVENTORY_SLOT_BAG_2:
case INVENTORY_SLOT_BAG_3:
case INVENTORY_SLOT_BAG_4:
{
//this chunk of code will limit you to equip only 1 Ammo Bag. Later i found out that this is not blizzlike so i will remove it when it's blizzlike
//we are trying to equip an Ammo Bag
if(proto->Class==ITEM_CLASS_QUIVER)
{
//check if we already have an AB equiped
FindAmmoBag();
//we do have amo bag but we are not swaping them then we send error
if(result.Slot!=ITEM_NO_SLOT_AVAILABLE && result.Slot != slot)
{
return INV_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH;
}
}
if(GetInventoryItem(INVENTORY_SLOT_NOT_SET,slot))
{
if(GetInventoryItem(INVENTORY_SLOT_NOT_SET,slot)->GetProto()->BagFamily)
{
if((IsBagSlot(slot) && DstInvSlot == INVENTORY_SLOT_NOT_SET))
{
if(proto->InventoryType == INVTYPE_BAG )
{
return 0;
}
}
if(proto->BagFamily == GetInventoryItem(INVENTORY_SLOT_NOT_SET,slot)->GetProto()->BagFamily)
{
return 0;
}
else
{
return INV_ERR_ITEM_DOESNT_GO_INTO_BAG;
}
}
else
{
return 0;
}
}
else
{
if(type == INVTYPE_BAG)
{
return 0;
}
else
{
return INV_ERR_NOT_A_BAG;
}
}
}
case INVENTORY_SLOT_ITEM_1:
case INVENTORY_SLOT_ITEM_2:
case INVENTORY_SLOT_ITEM_3:
case INVENTORY_SLOT_ITEM_4:
case INVENTORY_SLOT_ITEM_5:
case INVENTORY_SLOT_ITEM_6:
case INVENTORY_SLOT_ITEM_7:
case INVENTORY_SLOT_ITEM_8:
case INVENTORY_SLOT_ITEM_9:
case INVENTORY_SLOT_ITEM_10:
case INVENTORY_SLOT_ITEM_11:
case INVENTORY_SLOT_ITEM_12:
case INVENTORY_SLOT_ITEM_13:
case INVENTORY_SLOT_ITEM_14:
case INVENTORY_SLOT_ITEM_15:
case INVENTORY_SLOT_ITEM_16:
{
return 0;
}
case INVENTORY_KEYRING_1:
case INVENTORY_KEYRING_2:
case INVENTORY_KEYRING_3:
case INVENTORY_KEYRING_4:
case INVENTORY_KEYRING_5:
case INVENTORY_KEYRING_6:
case INVENTORY_KEYRING_7:
case INVENTORY_KEYRING_8:
case INVENTORY_KEYRING_9:
case INVENTORY_KEYRING_10:
case INVENTORY_KEYRING_11:
case INVENTORY_KEYRING_12:
case INVENTORY_KEYRING_13:
case INVENTORY_KEYRING_14:
case INVENTORY_KEYRING_15:
case INVENTORY_KEYRING_16:
case INVENTORY_KEYRING_17:
case INVENTORY_KEYRING_18:
case INVENTORY_KEYRING_19:
case INVENTORY_KEYRING_20:
case INVENTORY_KEYRING_21:
case INVENTORY_KEYRING_22:
case INVENTORY_KEYRING_23:
case INVENTORY_KEYRING_24:
case INVENTORY_KEYRING_25:
case INVENTORY_KEYRING_26:
case INVENTORY_KEYRING_27:
case INVENTORY_KEYRING_28:
case INVENTORY_KEYRING_29:
case INVENTORY_KEYRING_30:
case INVENTORY_KEYRING_31:
case INVENTORY_KEYRING_32:
{
if(proto->BagFamily == ITEM_TYPE_KEYRING )
{
return 0;
}
else
{
return INV_ERR_ITEM_DOESNT_GO_INTO_BAG;
}
}
default:
return 0;
}
}
//-------------------------------------------------------------------//
//Description: Checks if player can receive the item
//-------------------------------------------------------------------//
int8 ItemInterface::CanReceiveItem(ItemPrototype * item, uint32 amount)
{
if(!item)
{
return (int8)NULL;
}
if(item->Unique)
{
uint32 count = GetItemCount(item->ItemId, true);
if(count == item->Unique || ((count + amount) > item->Unique))
{
return INV_ERR_CANT_CARRY_MORE_OF_THIS;
}
}
return (int8)NULL;
}
void ItemInterface::BuyItem(ItemPrototype *item, uint32 amount)
{
m_pOwner->ModUInt32Value(PLAYER_FIELD_COINAGE, -(GetBuyPriceForItem(item, amount, amount)));
ItemExtendedCostEntry *ex = ItemExtendedCostStore::getSingleton().LookupEntry(item->ItemExtendedCost);
if(ex)
{
for(int i = 0;i<5;i++)
{
if(ex->item[i])
{
m_pOwner->GetItemInterface()->RemoveItemAmt(ex->item[i],ex->count[i]);
}
}
//just make sure we do not loop the value, Though we should have checked it before
if(m_pOwner->GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY) >= ex->honor)
{
m_pOwner->ModUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, -int32(ex->honor));
m_pOwner->m_honorPoints -=int32(ex->honor);
}
if(m_pOwner->GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY ) >= ex->arena)
m_pOwner->ModUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, -int32(ex->arena));
}
else sLog.outDebug("Warning: item %u has extended cost but could not find the value in ItemExtendedCostStore",item->ItemId);
}
int8 ItemInterface::CanAffordItem(ItemPrototype *item,uint32 amount)
{
if(item->ItemExtendedCost)
{
ItemExtendedCostEntry *ex = ItemExtendedCostStore::getSingleton().LookupEntry(item->ItemExtendedCost);
if(ex)
{
for(int i = 0;i<5;i++)
{
if(ex->item[i])
{
if(m_pOwner->GetItemInterface()->GetItemCount(ex->item[i], false) < ex->count[i])
return INV_ERR_NOT_ENOUGH_MONEY;
}
}
if(m_pOwner->GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY) < ex->honor)
return INV_ERR_NOT_ENOUGH_MONEY;
if(m_pOwner->GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY ) < ex->arena)
return INV_ERR_NOT_ENOUGH_MONEY;
}
else sLog.outDebug("Warning: item %u has extended cost but could not find the value in ItemExtendedCostStore",item->ItemId);
}
if(item->BuyPrice)
{
int32 price = GetBuyPriceForItem(item, amount, amount);
if((int32)m_pOwner->GetUInt32Value(PLAYER_FIELD_COINAGE) < price)
{
return INV_ERR_NOT_ENOUGH_MONEY;
}
}
if(item->RequiredFaction)
{
FactionDBC *factdbc = sFactionStore.LookupEntry(item->RequiredFaction);
if(!factdbc || factdbc->RepListId < 0)
return (int8)NULL;
//if(this->m_pOwner->reputationByListId[factdbc->RepListId]->CalcRating() < item->RequiredFactionStanding)
if(m_pOwner->reputationByListId[factdbc->RepListId] == 0 || m_pOwner->reputationByListId[factdbc->RepListId]->CalcRating()
< (int32)item->RequiredFactionStanding)
{
return INV_ERR_ITEM_REPUTATION_NOT_ENOUGH;
}
}
return (int8)NULL;
}
//-------------------------------------------------------------------//
//Description: Gets the Item slot by item type
//-------------------------------------------------------------------//
int8 ItemInterface::GetItemSlotByType(uint32 type)
{
switch(type)
{
case INVTYPE_NON_EQUIP:
return ITEM_NO_SLOT_AVAILABLE;
case INVTYPE_HEAD:
{
return EQUIPMENT_SLOT_HEAD;
}
case INVTYPE_NECK:
{
return EQUIPMENT_SLOT_NECK;
}
case INVTYPE_SHOULDERS:
{
return EQUIPMENT_SLOT_SHOULDERS;
}
case INVTYPE_BODY:
{
return EQUIPMENT_SLOT_BODY;
}
case INVTYPE_CHEST:
{
return EQUIPMENT_SLOT_CHEST;
}
case INVTYPE_ROBE: // ???
{
return EQUIPMENT_SLOT_CHEST;
}
case INVTYPE_WAIST:
{
return EQUIPMENT_SLOT_WAIST;
}
case INVTYPE_LEGS:
{
return EQUIPMENT_SLOT_LEGS;
}
case INVTYPE_FEET:
{
return EQUIPMENT_SLOT_FEET;
}
case INVTYPE_WRISTS:
{
return EQUIPMENT_SLOT_WRISTS;
}
case INVTYPE_HANDS:
{
return EQUIPMENT_SLOT_HANDS;
}
case INVTYPE_FINGER:
{
if (!GetInventoryItem(EQUIPMENT_SLOT_FINGER1))
return EQUIPMENT_SLOT_FINGER1;
else if (!GetInventoryItem(EQUIPMENT_SLOT_FINGER2))
return EQUIPMENT_SLOT_FINGER2;
else
return EQUIPMENT_SLOT_FINGER1; //auto equips always in finger 1
}
case INVTYPE_TRINKET:
{
if (!GetInventoryItem(EQUIPMENT_SLOT_TRINKET1))
return EQUIPMENT_SLOT_TRINKET1;
else if (!GetInventoryItem(EQUIPMENT_SLOT_TRINKET2))
return EQUIPMENT_SLOT_TRINKET2;
else
return EQUIPMENT_SLOT_TRINKET1; //auto equips always on trinket 1
}
case INVTYPE_CLOAK:
{
return EQUIPMENT_SLOT_BACK;
}
case INVTYPE_WEAPON:
{
if (!GetInventoryItem(EQUIPMENT_SLOT_MAINHAND) )
return EQUIPMENT_SLOT_MAINHAND;
else if(!GetInventoryItem(EQUIPMENT_SLOT_OFFHAND))
return EQUIPMENT_SLOT_OFFHAND;
else
return EQUIPMENT_SLOT_MAINHAND;
}
case INVTYPE_SHIELD:
{
return EQUIPMENT_SLOT_OFFHAND;
}
case INVTYPE_RANGED:
{
return EQUIPMENT_SLOT_RANGED;
}
case INVTYPE_2HWEAPON:
{
return EQUIPMENT_SLOT_MAINHAND;
}
case INVTYPE_TABARD:
{
return EQUIPMENT_SLOT_TABARD;
}
case INVTYPE_WEAPONMAINHAND:
{
return EQUIPMENT_SLOT_MAINHAND;
}
case INVTYPE_WEAPONOFFHAND:
{
return EQUIPMENT_SLOT_OFFHAND;
}
case INVTYPE_HOLDABLE:
{
return EQUIPMENT_SLOT_OFFHAND;
}
case INVTYPE_THROWN:
return EQUIPMENT_SLOT_RANGED; // ?
case INVTYPE_RANGEDRIGHT:
return EQUIPMENT_SLOT_RANGED; // ?
case INVTYPE_RELIC:
return EQUIPMENT_SLOT_RANGED;
case INVTYPE_BAG:
{
for (int8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
if (!GetInventoryItem(i))
return i;
}
return ITEM_NO_SLOT_AVAILABLE; //bags are not suposed to be auto-equiped when slots are not free
}
default:
return ITEM_NO_SLOT_AVAILABLE;
}
}
//-------------------------------------------------------------------//
//Description: Gets a Item by guid
//-------------------------------------------------------------------//
Item* ItemInterface::GetItemByGUID(uint64 Guid)
{
uint32 i ;
//EQUIPMENT
for(i=EQUIPMENT_SLOT_START;iGetGUID() == Guid)
{
result.ContainerSlot = INVALID_BACKPACK_SLOT;//not a containerslot. In 1.8 client marked wrong slot like this
result.Slot = i;
return m_pItems[i];
}
}
}
//INVENTORY BAGS
for(i=INVENTORY_SLOT_BAG_START;iGetGUID()==Guid)
{
result.ContainerSlot = INVALID_BACKPACK_SLOT;
result.Slot = i;
return m_pItems[i];
}
for (uint32 j =0; j < m_pItems[i]->GetProto()->ContainerSlots;j++)
{
Item *item2 = ((Container*)m_pItems[i])->GetItem(j);
if (item2)
{
if (item2->GetGUID() == Guid)
{
result.ContainerSlot = i;
result.Slot = j;
return item2;
}
}
}
}
}
//INVENTORY
for(i=INVENTORY_SLOT_ITEM_START;iGetGUID() == Guid)
{
result.ContainerSlot = INVALID_BACKPACK_SLOT;
result.Slot = i;
return m_pItems[i];
}
}
}
//Keyring
for(i=INVENTORY_KEYRING_START;iGetGUID() == Guid)
{
result.ContainerSlot = INVALID_BACKPACK_SLOT;
result.Slot = i;
return m_pItems[i];
}
}
}
return NULL;
}
//-------------------------------------------------------------------//
//Description: Inventory Error report
//-------------------------------------------------------------------//
void ItemInterface::BuildInventoryChangeError(Item *SrcItem, Item *DstItem, uint8 Error)
{
WorldPacket data(22);
data.Initialize( SMSG_INVENTORY_CHANGE_FAILURE );
data << Error;
if(Error == 1)
{
if(SrcItem)
{
data << SrcItem->GetProto()->RequiredLevel;
}
}
data << (SrcItem ? SrcItem->GetGUID() : uint64(0));
data << (DstItem ? DstItem->GetGUID() : uint64(0));
data << uint8(0);
m_pOwner->GetSession()->SendPacket( &data );
}
void ItemInterface::EmptyBuyBack()
{
for (uint32 j = 0;j < 12;j++)
{
if (m_pBuyBack[j] != NULL)
{
m_pBuyBack[j]->DestroyForPlayer(m_pOwner);
m_pBuyBack[j]->DeleteFromDB();
if(m_pBuyBack[j]->IsContainer())
{
if (static_cast(m_pBuyBack[j])->IsInWorld())
static_cast(m_pBuyBack[j])->RemoveFromWorld();
delete static_cast(m_pBuyBack[j]);
}
else
{
if (m_pBuyBack[j]->IsInWorld())
m_pBuyBack[j]->RemoveFromWorld();
delete m_pBuyBack[j];
}
m_pOwner->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (2*j),0);
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + j,0);
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + j,0);
m_pBuyBack[j] = NULL;
}
else
break;
}
}
void ItemInterface::AddBuyBackItem(Item *it,uint32 price)
{
int i;
if ((m_pBuyBack[11] != NULL) && (m_pOwner->GetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + 22) != 0))
{
if(m_pBuyBack[0] != NULL)
{
m_pBuyBack[0]->DestroyForPlayer(m_pOwner);
m_pBuyBack[0]->DeleteFromDB();
if(m_pBuyBack[0]->IsContainer())
{
if (static_cast(m_pBuyBack[0])->IsInWorld())
static_cast(m_pBuyBack[0])->RemoveFromWorld();
delete static_cast(m_pBuyBack[0]);
}
else
{
if (m_pBuyBack[0]->IsInWorld())
m_pBuyBack[0]->RemoveFromWorld();
delete m_pBuyBack[0];
}
m_pBuyBack[0] = NULL;
}
for (int j = 0;j < 11;j++)
{
//SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (2*j),buyback[j+1]->GetGUID());
m_pOwner->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (2*j),m_pOwner->GetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + ((j+1)*2) ) );
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + j,m_pOwner->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + j+1));
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + j,m_pOwner->GetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + j+1));
m_pBuyBack[j] = m_pBuyBack[j+1];
}
m_pBuyBack[11] = it;
m_pOwner->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (2*(11)),m_pBuyBack[11]->GetGUID());
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + 11,price);
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + 11,time(NULL));
return;
}
for(i=0; i < 24;i+=2)
{
if((m_pOwner->GetUInt32Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + i) == 0) || (m_pBuyBack[i/2] == NULL))
{
sLog.outDetail("setting buybackslot %u\n",i/2);
m_pBuyBack[i/2] = it;
m_pOwner->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + i,m_pBuyBack[i/2]->GetGUID());
//SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + i,it->GetGUID());
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + (i/2),price);
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + (i/2),time(NULL));
return;
}
}
}
void ItemInterface::RemoveBuyBackItem(uint32 index)
{
int32 j = 0;
for (j = index;j < 11;j++)
{
if (m_pOwner->GetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (j*2)) != 0)
{
m_pOwner->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (2*j), m_pOwner->GetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + ((j+1)*2)));
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + j, m_pOwner->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + j+1));
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + j, m_pOwner->GetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + j+1));
if ((m_pBuyBack[j+1] != NULL) && (m_pOwner->GetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + ((j+1)*2)) != 0))
{
m_pBuyBack[j] = m_pBuyBack[j+1];
}
else
{
if(m_pBuyBack[j])
{
m_pBuyBack[j] = NULL;
}
sLog.outDetail("nulling %u\n",(j));
}
}
else
return;
}
j = 11;
m_pOwner->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (2*j), m_pOwner->GetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + ((j+1)*2)));
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + j, m_pOwner->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + j+1));
m_pOwner->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + j, m_pOwner->GetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + j+1));
if(m_pBuyBack[11])
{
m_pBuyBack[11] = NULL;
}
}
//-------------------------------------------------------------------//
//Description: swap inventory slots
//-------------------------------------------------------------------//
void ItemInterface::SwapItemSlots(int8 srcslot, int8 dstslot)
{
// srcslot and dstslot are int... NULL might not be an int depending on arch where it is compiled
ASSERT(srcslot < MAX_INVENTORY_SLOT && srcslot >= 0);
ASSERT(dstslot < MAX_INVENTORY_SLOT && dstslot >= 0);
Item *SrcItem = GetInventoryItem(srcslot);
Item *DstItem = GetInventoryItem(dstslot);
if(SrcItem && DstItem && SrcItem->GetEntry()==DstItem->GetEntry()&& SrcItem->GetProto()->MaxCount>1)
{
uint32 total=SrcItem->GetUInt32Value(ITEM_FIELD_STACK_COUNT)+DstItem->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
if(total<=DstItem->GetProto()->MaxCount)
{
DstItem->ModUInt32Value(ITEM_FIELD_STACK_COUNT, SrcItem->GetUInt32Value(ITEM_FIELD_STACK_COUNT));
SafeFullRemoveItemFromSlot(INVENTORY_SLOT_NOT_SET, srcslot);
return;
}
else
{
if(DstItem->GetUInt32Value(ITEM_FIELD_STACK_COUNT) == DstItem->GetProto()->MaxCount)
{
}
else
{
int32 delta=DstItem->GetProto()->MaxCount-DstItem->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
DstItem->SetUInt32Value(ITEM_FIELD_STACK_COUNT,DstItem->GetProto()->MaxCount);
SrcItem->ModUInt32Value(ITEM_FIELD_STACK_COUNT,-delta);
return;
}
}
}
m_pItems[(int)srcslot] = DstItem;
m_pItems[(int)dstslot] = SrcItem;
if(DstItem)
DstItem->m_isDirty = true;
if(SrcItem)
SrcItem->m_isDirty = true;
if(m_pItems[(int)dstslot])
{
m_pOwner->SetUInt64Value(PLAYER_FIELD_INV_SLOT_HEAD + (dstslot*2), m_pItems[(int)dstslot]->GetGUID() );
}
else
{
m_pOwner->SetUInt64Value(PLAYER_FIELD_INV_SLOT_HEAD + (dstslot*2), 0 );
}
if( m_pItems[(int)srcslot])
{
m_pOwner->SetUInt64Value(PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2), m_pItems[(int)srcslot]->GetGUID() );
}
else
{
m_pOwner->SetUInt64Value(PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2), 0 );
}
// bool noreapply=( srcslot < EQUIPMENT_SLOT_END && dstslot < EQUIPMENT_SLOT_END);//just move inside inv, no equip/unequip
if(srcslot < INVENTORY_SLOT_BAG_END) // source item is equiped
{
// remove mods from original item
// if(!noreapply)
{
if(m_pItems[(int)dstslot]) // Remove mods from the old item in this slot.
m_pOwner->ApplyItemMods(m_pItems[(int)dstslot], srcslot, false);
if(m_pItems[(int)srcslot]) // Apply mods from the new item into this slot
m_pOwner->ApplyItemMods(m_pItems[(int)srcslot], dstslot, true);
}
if(m_pItems[(int)srcslot]) // dstitem goes into here.
{
// Bags aren't considered "visible".
if(srcslot < EQUIPMENT_SLOT_END)
{
int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (srcslot * 16);
m_pOwner->SetUInt32Value(VisibleBase, m_pItems[(int)srcslot]->GetEntry());
m_pOwner->SetUInt32Value(VisibleBase + 1, m_pItems[(int)srcslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT));
m_pOwner->SetUInt32Value(VisibleBase + 2, m_pItems[(int)srcslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 3));
m_pOwner->SetUInt32Value(VisibleBase + 3, m_pItems[(int)srcslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 6));
m_pOwner->SetUInt32Value(VisibleBase + 4, m_pItems[(int)srcslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 9));
m_pOwner->SetUInt32Value(VisibleBase + 5, m_pItems[(int)srcslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 12));
m_pOwner->SetUInt32Value(VisibleBase + 6, m_pItems[(int)srcslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 15));
m_pOwner->SetUInt32Value(VisibleBase + 7, m_pItems[(int)srcslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 18));
m_pOwner->SetUInt32Value(VisibleBase + 8, m_pItems[(int)srcslot]->GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID));
}
// handle bind on equip
if(m_pItems[(int)srcslot]->GetProto()->Bonding == ITEM_BIND_ON_EQUIP)
m_pItems[(int)srcslot]->SoulBind();
}
else
{
// Bags aren't considered "visible".
if(srcslot < EQUIPMENT_SLOT_END)
{
int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (srcslot * 16);
m_pOwner->SetUInt32Value(VisibleBase, 0);
m_pOwner->SetUInt32Value(VisibleBase + 1, 0);
m_pOwner->SetUInt32Value(VisibleBase + 2, 0);
m_pOwner->SetUInt32Value(VisibleBase + 3, 0);
m_pOwner->SetUInt32Value(VisibleBase + 4, 0);
m_pOwner->SetUInt32Value(VisibleBase + 5, 0);
m_pOwner->SetUInt32Value(VisibleBase + 6, 0);
m_pOwner->SetUInt32Value(VisibleBase + 7, 0);
m_pOwner->SetUInt32Value(VisibleBase + 8, 0);
}
}
}
if(dstslot < INVENTORY_SLOT_BAG_END) // source item is inside inventory
{
// remove mods from original item
if(m_pItems[(int)srcslot]) // Remove mods from the old item in this slot.
m_pOwner->ApplyItemMods(m_pItems[(int)srcslot], srcslot, false);
if(m_pItems[(int)dstslot]) // srcitem goes into here.
{
// Apply mods from the new item into this slot
m_pOwner->ApplyItemMods(m_pItems[(int)dstslot], dstslot, true);
// Bags aren't considered "visible".
if(dstslot < EQUIPMENT_SLOT_END)
{
int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (dstslot * 16);
m_pOwner->SetUInt32Value(VisibleBase, m_pItems[(int)dstslot]->GetEntry());
m_pOwner->SetUInt32Value(VisibleBase + 1, m_pItems[(int)dstslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT));
m_pOwner->SetUInt32Value(VisibleBase + 2, m_pItems[(int)dstslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 3));
m_pOwner->SetUInt32Value(VisibleBase + 3, m_pItems[(int)dstslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 6));
m_pOwner->SetUInt32Value(VisibleBase + 4, m_pItems[(int)dstslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 9));
m_pOwner->SetUInt32Value(VisibleBase + 5, m_pItems[(int)dstslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 12));
m_pOwner->SetUInt32Value(VisibleBase + 6, m_pItems[(int)dstslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 15));
m_pOwner->SetUInt32Value(VisibleBase + 7, m_pItems[(int)dstslot]->GetUInt32Value(ITEM_FIELD_ENCHANTMENT + 18));
m_pOwner->SetUInt32Value(VisibleBase + 8, m_pItems[(int)dstslot]->GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID));
}
// handle bind on equip
if(m_pItems[(int)dstslot]->GetProto()->Bonding == ITEM_BIND_ON_EQUIP)
m_pItems[(int)dstslot]->SoulBind();
} else {
// bags aren't considered visible
if(dstslot < EQUIPMENT_SLOT_END)
{
int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (dstslot * 16);
m_pOwner->SetUInt32Value(VisibleBase, 0);
m_pOwner->SetUInt32Value(VisibleBase + 1, 0);
m_pOwner->SetUInt32Value(VisibleBase + 2, 0);
m_pOwner->SetUInt32Value(VisibleBase + 3, 0);
m_pOwner->SetUInt32Value(VisibleBase + 4, 0);
m_pOwner->SetUInt32Value(VisibleBase + 5, 0);
m_pOwner->SetUInt32Value(VisibleBase + 6, 0);
m_pOwner->SetUInt32Value(VisibleBase + 7, 0);
m_pOwner->SetUInt32Value(VisibleBase + 8, 0);
}
}
}
if(dstslot == EQUIPMENT_SLOT_OFFHAND || srcslot == EQUIPMENT_SLOT_OFFHAND)
{
if(m_pItems[EQUIPMENT_SLOT_OFFHAND] != 0 && m_pItems[EQUIPMENT_SLOT_OFFHAND]->GetProto()->Class == ITEM_CLASS_WEAPON)
m_pOwner->SetDuelWield(true);
else
m_pOwner->SetDuelWield(false);
}
}
//-------------------------------------------------------------------//
//Description: Item Loading
//-------------------------------------------------------------------//
void ItemInterface::mLoadItemsFromDatabase()
{
int8 containerslot, slot;
Item* item;
ItemPrototype *proto;
std::stringstream invq;
invq << "SELECT * FROM playeritems WHERE ownerguid=" << m_pOwner->GetGUIDLow() << " ORDER BY containerslot ASC";
QueryResult *result = CharacterDatabase.Query( invq.str().c_str() );
if(result)
{
do
{
Field *fields = result->Fetch();
containerslot = fields[10].GetInt8();
slot = fields[11].GetInt8();
proto = ItemPrototypeStorage.LookupEntry(fields[2].GetUInt32());
if(proto)
{
if(proto->InventoryType == INVTYPE_BAG)
{
item=new Container(HIGHGUID_CONTAINER,fields[1].GetUInt32());
((Container*)item)->LoadFromDB(fields);
}
else
{
item = new Item(HIGHGUID_ITEM,fields[1].GetUInt32());
item->LoadFromDB(fields, m_pOwner, false);
}
if(SafeAddItem(item, containerslot, slot))
item->m_isDirty = false;
}
}
while( result->NextRow() );
}
delete result;
}
//-------------------------------------------------------------------//
//Description: Item saving
//-------------------------------------------------------------------//
void ItemInterface::mSaveItemsToDatabase(bool first)
{
uint32 x;
for(x = EQUIPMENT_SLOT_START; x < INVENTORY_KEYRING_END; ++x)
{
if(GetInventoryItem(x) != NULL)
{
if(!( (GetInventoryItem(x)->GetProto()->Flags)&2 )) // skip conjured item on save
{
if(IsBagSlot(x) && GetInventoryItem(x)->IsContainer())
{
((Container*)GetInventoryItem(x))->SaveBagToDB(x, first);
}
else
{
GetInventoryItem(x)->SaveToDB(INVENTORY_SLOT_NOT_SET, x, first);
}
}
}
}
}
bool ItemInterface::AddItemToFreeBankSlot(Item *item)
{
//special items first
for(uint32 i=BANK_SLOT_BAG_START;iGetProto()->BagFamily == item->GetProto()->BagFamily)
{
if(m_pItems[i]->IsContainer())
{
bool result = static_cast(m_pItems[i])->AddItemToFreeSlot(item);
if(result) { return true; }
}
}
}
}
for(uint32 i= BANK_SLOT_ITEM_START;i< BANK_SLOT_ITEM_END;i++)
{
if(m_pItems[i] == NULL)
{
return SafeAddItem(item, INVENTORY_SLOT_NOT_SET, i);
}
}
for(uint32 i=BANK_SLOT_BAG_START;iGetProto()->BagFamily == 0) //special bags ignored
{
for (uint32 j =0; j < m_pItems[i]->GetProto()->ContainerSlots;j++)
{
Item *item2 = ((Container*)m_pItems[i])->GetItem(j);
if (item2 == NULL)
{
return SafeAddItem(item, i, j);
}
}
}
}
return false;
}
int8 ItemInterface::FindSpecialBag(Item *item)
{
for(uint32 i=INVENTORY_SLOT_BAG_START;iGetProto()->BagFamily == item->GetProto()->BagFamily)
{
return i;
}
}
}
return ITEM_NO_SLOT_AVAILABLE;
}
int8 ItemInterface::FindFreeKeyringSlot()
{
for(uint32 i=INVENTORY_KEYRING_START;iBagFamily)
{
if(proto->BagFamily == ITEM_TYPE_KEYRING)
{
for(uint32 i = INVENTORY_KEYRING_START; i < INVENTORY_KEYRING_END; i++)
{
if(m_pItems[i] == NULL)
{
result.ContainerSlot = ITEM_NO_SLOT_AVAILABLE;
result.Slot = i;
result.Result = true;
return result;
}
}
}
else
{
for(uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END;i++)
{
if(m_pItems[i] && m_pItems[i]->IsContainer())
{
if (m_pItems[i]->GetProto()->BagFamily == proto->BagFamily)
{
int32 slot = ((Container*)m_pItems[i])->FindFreeSlot();
if(slot != ITEM_NO_SLOT_AVAILABLE)
{
result.ContainerSlot = i;
result.Slot = slot;
result.Result = true;
return result;
}
}
}
}
}
}
}
//backpack
for(uint32 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if(!item)
{
result.ContainerSlot = ITEM_NO_SLOT_AVAILABLE;
result.Slot = i;
result.Result = true;
return result;
}
}
//bags
for(uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item)
{
if(item->IsContainer() && !item->GetProto()->BagFamily)
{
int32 slot = ((Container*)m_pItems[i])->FindFreeSlot();
if(slot != ITEM_NO_SLOT_AVAILABLE)
{
result.ContainerSlot = i;
result.Slot = slot;
result.Result = true;
return result;
}
}
}
}
result.ContainerSlot = ITEM_NO_SLOT_AVAILABLE;
result.Slot = ITEM_NO_SLOT_AVAILABLE;
result.Result = false;
return result;
}
SlotResult ItemInterface::FindFreeBankSlot(ItemPrototype *proto)
{
//special item
//special slots will be ignored of item is not set
if(proto)
{
if(proto->BagFamily)
{
for(uint32 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END;i++)
{
if(m_pItems[i] && m_pItems[i]->IsContainer())
{
if (m_pItems[i]->GetProto()->BagFamily == proto->BagFamily)
{
int32 slot = ((Container*)m_pItems[i])->FindFreeSlot();
if(slot != ITEM_NO_SLOT_AVAILABLE)
{
result.ContainerSlot = i;
result.Slot = slot;
result.Result = true;
return result;
}
}
}
}
}
}
//backpack
for(uint32 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++)
{
Item *item = GetInventoryItem(i);
if(!item)
{
result.ContainerSlot = ITEM_NO_SLOT_AVAILABLE;
result.Slot = i;
result.Result = true;
return result;
}
}
//bags
for(uint32 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
Item *item = GetInventoryItem(i);
if(item)
{
if(item->IsContainer() && !item->GetProto()->BagFamily)
{
int32 slot = ((Container*)m_pItems[i])->FindFreeSlot();
if(slot != ITEM_NO_SLOT_AVAILABLE)
{
result.ContainerSlot = i;
result.Slot = slot;
result.Result = true;
return result;
}
}
}
}
result.ContainerSlot = ITEM_NO_SLOT_AVAILABLE;
result.Slot = ITEM_NO_SLOT_AVAILABLE;
result.Result = false;
return result;
}
SlotResult ItemInterface::FindAmmoBag()
{
for(uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END;i++)
if(m_pItems[i] && m_pItems[i]->IsAmmoBag())
{
result.ContainerSlot = ITEM_NO_SLOT_AVAILABLE;
result.Slot = i;
result.Result = true;
return result;
}
result.ContainerSlot = ITEM_NO_SLOT_AVAILABLE;
result.Slot = ITEM_NO_SLOT_AVAILABLE;
result.Result = false;
return result;
}
void ItemInterface::ReduceItemDurability()
{
uint32 f = sRand.randInt(100);
if(f <= 10) //10% chance to loose 1 dur from a random valid item.
{
int32 slot = sRand.randInt(EQUIPMENT_SLOT_END);
Item *pItem = GetInventoryItem(INVENTORY_SLOT_NOT_SET, slot);
if(pItem)
{
if(pItem->GetUInt32Value(ITEM_FIELD_DURABILITY) && pItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
{
pItem->SetUInt32Value(ITEM_FIELD_DURABILITY, (pItem->GetUInt32Value(ITEM_FIELD_DURABILITY)-1));
pItem->m_isDirty = true;
//check final durabiity
if(!pItem->GetUInt32Value(ITEM_FIELD_DURABILITY)) //no dur left
{
this->GetOwner()->ApplyItemMods(pItem,slot,false,true);
}
}
}
}
}
bool ItemInterface::IsEquipped(uint32 itemid)
{
for(uint32 x = EQUIPMENT_SLOT_START; x < EQUIPMENT_SLOT_END; ++x)
{
if(m_pItems[x])
if(m_pItems[x]->GetProto()->ItemId == itemid)
return true;
}
return false;
}