/*
* 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"
Container::Container(uint32 high,uint32 low) : Item()
{
m_objectTypeId = TYPEID_CONTAINER;
m_valuesCount = CONTAINER_END;
m_uint32Values = __fields;
memset(m_uint32Values, 0,(CONTAINER_END)*sizeof(uint32));
m_updateMask.SetCount(CONTAINER_END);
SetUInt32Value( OBJECT_FIELD_TYPE,TYPE_CONTAINER|TYPE_ITEM|TYPE_OBJECT);
SetUInt32Value( OBJECT_FIELD_GUID,low);
SetUInt32Value( OBJECT_FIELD_GUID+1,high);
m_wowGuid.Init(GetGUID());
SetFloatValue( OBJECT_FIELD_SCALE_X, 1 );//always 1
m_Slot = NULL;
}
Container::~Container( )
{
for(uint32 i = 0; i < m_itemProto->ContainerSlots; i++)
{
if(m_Slot[i])
{
if(m_Slot[i]->IsContainer())
delete ((Container*)m_Slot[i]);
else
delete m_Slot[i];
}
}
delete [] m_Slot;
}
void Container::LoadFromDB( Field*fields )
{
uint32 itemid=fields[2].GetUInt32();
m_itemProto = ItemPrototypeStorage.LookupEntry( itemid );
ASSERT(m_itemProto);
SetUInt32Value( OBJECT_FIELD_ENTRY, itemid );
SetUInt32Value( ITEM_FIELD_CREATOR, fields[3].GetUInt32() );
SetUInt32Value( ITEM_FIELD_STACK_COUNT, 1);
SetUInt32Value( ITEM_FIELD_FLAGS, fields[6].GetUInt32());
SetUInt32Value( ITEM_FIELD_RANDOM_PROPERTIES_ID, fields[7].GetUInt32());
SetUInt32Value( ITEM_FIELD_MAXDURABILITY, m_itemProto->MaxDurability);
SetUInt32Value( ITEM_FIELD_DURABILITY, fields[9].GetUInt32());
SetUInt32Value( CONTAINER_FIELD_NUM_SLOTS, m_itemProto->ContainerSlots);
m_Slot = new Item*[m_itemProto->ContainerSlots];
memset(m_Slot, 0, sizeof(Item*)*(m_itemProto->ContainerSlots));
}
void Container::Create( uint32 itemid, Player *owner )
{
m_itemProto = ItemPrototypeStorage.LookupEntry( itemid );
ASSERT(m_itemProto);
SetUInt32Value( OBJECT_FIELD_ENTRY, itemid );
SetUInt64Value( ITEM_FIELD_OWNER, owner->GetGUID() );
SetUInt64Value( ITEM_FIELD_CONTAINED, owner->GetGUID() );
SetUInt32Value( ITEM_FIELD_STACK_COUNT, 1 );
SetUInt32Value( CONTAINER_FIELD_NUM_SLOTS, m_itemProto->ContainerSlots);
m_Slot = new Item*[m_itemProto->ContainerSlots];
memset(m_Slot, 0, sizeof(Item*)*(m_itemProto->ContainerSlots));
m_owner = owner;
}
int8 Container::FindFreeSlot()
{
int8 TotalSlots = GetUInt32Value( CONTAINER_FIELD_NUM_SLOTS );
for (int8 i=0; i < TotalSlots; i++)
{
if(!m_Slot[i])
{
return i;
}
}
return ITEM_NO_SLOT_AVAILABLE;
}
bool Container::HasItems()
{
int8 TotalSlots = GetUInt32Value( CONTAINER_FIELD_NUM_SLOTS );
for (int8 i=0; i < TotalSlots; i++)
{
if(m_Slot[i])
{
return true;
}
}
return false;
}
bool Container::AddItem(int8 slot, Item *item)
{
if((uint32)slot > m_itemProto->ContainerSlots)
return false;
//ASSERT(m_Slot[slot] == NULL);
if(m_Slot[slot] != NULL)
{
//sLog.outString("Bad container item %u slot %d", item->GetGUID(), slot);
return false;
}
if (!m_owner)
return false;
m_Slot[slot] = item;
item->m_isDirty = true;
item->SetUInt64Value(ITEM_FIELD_CONTAINED, GetGUID());
item->SetOwner(m_owner);
if (item->GetProto()->Bonding == ITEM_BIND_ON_PICKUP)
item->SoulBind();
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (slot*2), item->GetGUID());
//new version to fix bag issues
if(m_owner->IsInWorld() && !item->IsInWorld())
{
//item->AddToWorld();
item->PushToWorld(m_owner->GetMapMgr());
ByteBuffer buf(2500);
uint32 count = item->BuildCreateUpdateBlockForPlayer(&buf, m_owner);
m_owner->PushCreationData(&buf, count);
}
return true;
}
void Container::SwapItems(int8 SrcSlot, int8 DstSlot)
{
Item *temp;
if(m_Slot[DstSlot] && m_Slot[SrcSlot]&&m_Slot[DstSlot]->GetEntry()==m_Slot[SrcSlot]->GetEntry() && m_Slot[DstSlot]->GetProto()->MaxCount>1)
{
uint32 total=m_Slot[SrcSlot]->GetUInt32Value(ITEM_FIELD_STACK_COUNT)+m_Slot[DstSlot]->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
m_Slot[DstSlot]->m_isDirty = m_Slot[SrcSlot]->m_isDirty = true;
if(total<=m_Slot[DstSlot]->GetProto()->MaxCount)
{
m_Slot[DstSlot]->ModUInt32Value(ITEM_FIELD_STACK_COUNT,m_Slot[SrcSlot]->GetUInt32Value(ITEM_FIELD_STACK_COUNT));
SafeFullRemoveItemFromSlot(SrcSlot);
return;
}
else
{
if(m_Slot[DstSlot]->GetUInt32Value(ITEM_FIELD_STACK_COUNT) == m_Slot[DstSlot]->GetProto()->MaxCount)
{
}
else
{
int32 delta=m_Slot[DstSlot]->GetProto()->MaxCount-m_Slot[DstSlot]->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
m_Slot[DstSlot]->SetUInt32Value(ITEM_FIELD_STACK_COUNT,m_Slot[DstSlot]->GetProto()->MaxCount);
m_Slot[SrcSlot]->ModUInt32Value(ITEM_FIELD_STACK_COUNT,-delta);
return;
}
}
}
temp = m_Slot[SrcSlot];
m_Slot[SrcSlot] = m_Slot[DstSlot];
m_Slot[DstSlot] = temp;
if( m_Slot[DstSlot])
{
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (DstSlot*2), m_Slot[DstSlot]->GetGUID() );
m_Slot[DstSlot]->m_isDirty = true;
}
else
{
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (DstSlot*2), 0 );
}
if( m_Slot[SrcSlot])
{
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (SrcSlot*2), m_Slot[SrcSlot]->GetGUID() );
m_Slot[SrcSlot]->m_isDirty = true;
}
else
{
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (SrcSlot*2), 0 );
}
}
Item *Container::SafeRemoveAndRetreiveItemFromSlot(int8 slot, bool destroy)
{
ASSERT((uint32)slot < GetProto()->ContainerSlots);
Item *pItem = m_Slot[slot];
if (pItem == NULL || pItem==this) return NULL;
m_Slot[slot] = NULL;
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + slot*2, 0 );
pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, 0);
if(destroy)
{
if(pItem->IsInWorld())
{
pItem->RemoveFromWorld();
}
pItem->DeleteFromDB();
}
return pItem;
}
bool Container::SafeFullRemoveItemFromSlot(int8 slot)
{
ASSERT((uint32)slot < GetProto()->ContainerSlots);
Item *pItem = m_Slot[slot];
if (pItem == NULL ||pItem==this) return false;
m_Slot[slot] = NULL;
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + slot*2, 0 );
pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, 0);
if(pItem->IsInWorld())
{
pItem->RemoveFromWorld();
}
pItem->DeleteFromDB();
delete pItem;
return true;
}
bool Container::AddItemToFreeSlot(Item *pItem)
{
uint32 slot;
for(slot = 0; slot < GetProto()->ContainerSlots; slot++)
{
if(!m_Slot[slot])
{
m_Slot[slot] = pItem;
pItem->m_isDirty = true;
pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, GetGUID());
pItem->SetOwner(m_owner);
SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (slot*2), pItem->GetGUID());
if(m_owner->IsInWorld() && !pItem->IsInWorld())
{
pItem->PushToWorld(m_owner->GetMapMgr());
ByteBuffer buf(2500);
uint32 count = pItem->BuildCreateUpdateBlockForPlayer( &buf, m_owner );
m_owner->PushCreationData(&buf, count);
}
return true;
}
}
return false;
}
void Container::SaveBagToDB(int8 slot, bool first)
{
((Item*)this)->SaveToDB(INVENTORY_SLOT_NOT_SET, slot);
for(uint32 i = 0; i < m_itemProto->ContainerSlots; i++)
{
if (m_Slot[i])
{
m_Slot[i]->SaveToDB(slot, i, first);
}
}
}