aboutsummaryrefslogtreecommitdiff
path: root/src/game/Item.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/Item.cpp')
-rw-r--r--src/game/Item.cpp159
1 files changed, 130 insertions, 29 deletions
diff --git a/src/game/Item.cpp b/src/game/Item.cpp
index 766bd81d640..bc1c1eeeaab 100644
--- a/src/game/Item.cpp
+++ b/src/game/Item.cpp
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
- * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
*
* 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
@@ -24,6 +24,7 @@
#include "WorldPacket.h"
#include "Database/DatabaseEnv.h"
#include "ItemEnchantmentMgr.h"
+#include "SpellMgr.h"
void AddItemsSetItem(Player*player,Item *item)
{
@@ -206,6 +207,10 @@ bool ItemCanGoIntoBag(ItemPrototype const *pProto, ItemPrototype const *pBagProt
if(!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP))
return false;
return true;
+ case ITEM_SUBCLASS_INSCRIPTION_CONTAINER:
+ if(!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP))
+ return false;
+ return true;
default:
return false;
}
@@ -231,8 +236,8 @@ Item::Item( )
{
m_objectType |= TYPEMASK_ITEM;
m_objectTypeId = TYPEID_ITEM;
- // 2.3.2 - 0x18
- m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID);
+
+ m_updateFlag = UPDATEFLAG_HIGHGUID;
m_valuesCount = ITEM_END;
m_slot = 0;
@@ -261,7 +266,7 @@ bool Item::Create( uint32 guidlow, uint32 itemid, Player const* owner)
SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability);
SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability);
- for(int i = 0; i < 5; ++i)
+ for(uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
SetSpellCharges(i,itemProto->Spells[i].SpellCharges);
SetUInt32Value(ITEM_FIELD_FLAGS, itemProto->Flags);
@@ -284,7 +289,7 @@ void Item::UpdateDuration(Player* owner, uint32 diff)
}
SetUInt32Value(ITEM_FIELD_DURATION, GetUInt32Value(ITEM_FIELD_DURATION) - diff);
- SetState(ITEM_CHANGED); // save new time in database
+ SetState(ITEM_CHANGED, owner); // save new time in database
}
void Item::SaveToDB()
@@ -297,7 +302,7 @@ void Item::SaveToDB()
CharacterDatabase.PExecute( "DELETE FROM item_instance WHERE guid = '%u'", guid );
std::ostringstream ss;
ss << "INSERT INTO item_instance (guid,owner_guid,data) VALUES (" << guid << "," << GUID_LOPART(GetOwnerGUID()) << ",'";
- for(uint16 i = 0; i < m_valuesCount; i++ )
+ for(uint16 i = 0; i < m_valuesCount; ++i )
ss << GetUInt32Value(i) << " ";
ss << "' )";
CharacterDatabase.Execute( ss.str().c_str() );
@@ -306,7 +311,7 @@ void Item::SaveToDB()
{
std::ostringstream ss;
ss << "UPDATE item_instance SET data = '";
- for(uint16 i = 0; i < m_valuesCount; i++ )
+ for(uint16 i = 0; i < m_valuesCount; ++i )
ss << GetUInt32Value(i) << " ";
ss << "', owner_guid = '" << GUID_LOPART(GetOwnerGUID()) << "' WHERE guid = '" << guid << "'";
@@ -346,7 +351,7 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result)
if (!result)
{
- sLog.outError("ERROR: Item (GUID: %u owner: %u) not found in table `item_instance`, can't load. ",guid,GUID_LOPART(owner_guid));
+ sLog.outError("Item (GUID: %u owner: %u) not found in table `item_instance`, can't load. ",guid,GUID_LOPART(owner_guid));
return false;
}
@@ -354,7 +359,7 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result)
if(!LoadValues(fields[0].GetString()))
{
- sLog.outError("ERROR: Item #%d have broken data in `data` field. Can't be loaded.",guid);
+ sLog.outError("Item #%d have broken data in `data` field. Can't be loaded.",guid);
if (delete_result) delete result;
return false;
}
@@ -407,7 +412,7 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result)
{
std::ostringstream ss;
ss << "UPDATE item_instance SET data = '";
- for(uint16 i = 0; i < m_valuesCount; i++ )
+ for(uint16 i = 0; i < m_valuesCount; ++i )
ss << GetUInt32Value(i) << " ";
ss << "', owner_guid = '" << GUID_LOPART(GetOwnerGUID()) << "' WHERE guid = '" << guid << "'";
@@ -450,7 +455,7 @@ uint32 Item::GetSkill()
const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] =
{
- 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0
+ 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0,0
};
ItemPrototype const* proto = GetProto();
@@ -694,18 +699,19 @@ bool Item::IsEquipped() const
return !IsInBag() && m_slot < EQUIPMENT_SLOT_END;
}
-bool Item::CanBeTraded() const
+bool Item::CanBeTraded(bool mail) const
{
- if(IsSoulBound())
+ if ((!mail || !IsBoundAccountWide()) && IsSoulBound())
return false;
- if(IsBag() && (Player::IsBagPos(GetPos()) || !((Bag const*)this)->IsEmpty()) )
+
+ if (IsBag() && (Player::IsBagPos(GetPos()) || !((Bag const*)this)->IsEmpty()) )
return false;
- if(Player* owner = GetOwner())
+ if (Player* owner = GetOwner())
{
- if(owner->CanUnequipItem(GetPos(),false) != EQUIP_ERR_OK )
+ if (owner->CanUnequipItem(GetPos(),false) != EQUIP_ERR_OK )
return false;
- if(owner->GetLootGUID()==GetGUID())
+ if (owner->GetLootGUID()==GetGUID())
return false;
}
@@ -740,6 +746,12 @@ bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
if (spellInfo->EquippedItemClass != -1) // -1 == any item class
{
+ // Special case - accept vellum for armor/weapon requirements
+ if( (spellInfo->EquippedItemClass==ITEM_CLASS_ARMOR && proto->IsArmorVellum())
+ ||( spellInfo->EquippedItemClass==ITEM_CLASS_WEAPON && proto->IsWeaponVellum()))
+ if (spellmgr.IsSkillTypeSpell(spellInfo->Id, SKILL_ENCHANTING)) // only for enchanting spells
+ return true;
+
if(spellInfo->EquippedItemClass != int32(proto->Class))
return false; // wrong item class
@@ -752,22 +764,44 @@ bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
if(spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type
{
- if((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->InventoryType)) == 0)
+ // Special case - accept weapon type for main and offhand requirements
+ if(proto->InventoryType == INVTYPE_WEAPON &&
+ (spellInfo->EquippedItemInventoryTypeMask & (1 << INVTYPE_WEAPONMAINHAND) ||
+ spellInfo->EquippedItemInventoryTypeMask & (1 << INVTYPE_WEAPONOFFHAND)))
+ return true;
+ else if ((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->InventoryType)) == 0)
return false; // inventory type not present in mask
}
return true;
}
+bool Item::IsTargetValidForItemUse(Unit* pUnitTarget)
+{
+ ItemRequiredTargetMapBounds bounds = objmgr.GetItemRequiredTargetMapBounds(GetProto()->ItemId);
+
+ if (bounds.first == bounds.second)
+ return true;
+
+ if (!pUnitTarget)
+ return false;
+
+ for(ItemRequiredTargetMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
+ if(itr->second.IsFitToRequirements(pUnitTarget))
+ return true;
+
+ return false;
+}
+
void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges)
{
// Better lost small time at check in comparison lost time at item save to DB.
if((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
return;
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id);
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
SetState(ITEM_CHANGED);
}
@@ -776,7 +810,7 @@ void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration)
if(GetEnchantmentDuration(slot) == duration)
return;
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
SetState(ITEM_CHANGED);
}
@@ -785,7 +819,7 @@ void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
if(GetEnchantmentCharges(slot) == charges)
return;
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
SetState(ITEM_CHANGED);
}
@@ -795,14 +829,14 @@ void Item::ClearEnchantment(EnchantmentSlot slot)
return;
for(uint8 x = 0; x < 3; ++x)
- SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + x, 0);
+ SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + x, 0);
SetState(ITEM_CHANGED);
}
bool Item::GemsFitSockets() const
{
bool fits = true;
- for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
+ for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
{
uint8 SocketColor = GetProto()->Socket[enchant_slot-SOCK_ENCHANTMENT_SLOT].Color;
@@ -842,7 +876,7 @@ bool Item::GemsFitSockets() const
uint8 Item::GetGemCountWithID(uint32 GemID) const
{
uint8 count = 0;
- for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
+ for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
{
uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
if(!enchant_id)
@@ -858,6 +892,29 @@ uint8 Item::GetGemCountWithID(uint32 GemID) const
return count;
}
+uint8 Item::GetGemCountWithLimitCategory(uint32 limitCategory) const
+{
+ uint8 count = 0;
+ for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
+ {
+ uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
+ if(!enchant_id)
+ continue;
+
+ SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
+ if(!enchantEntry)
+ continue;
+
+ ItemPrototype const* gemProto = ObjectMgr::GetItemPrototype(enchantEntry->GemID);
+ if(!gemProto)
+ continue;
+
+ if(gemProto->ItemLimitCategory==limitCategory)
+ ++count;
+ }
+ return count;
+}
+
bool Item::IsLimitedToAnotherMapOrZone( uint32 cur_mapId, uint32 cur_zoneId) const
{
ItemPrototype const* proto = GetProto();
@@ -886,8 +943,8 @@ Item* Item::CreateItem( uint32 item, uint32 count, Player const* player )
ItemPrototype const *pProto = objmgr.GetItemPrototype( item );
if( pProto )
{
- if ( count > pProto->Stackable )
- count = pProto->Stackable;
+ if ( count > pProto->GetMaxStackSize())
+ count = pProto->GetMaxStackSize();
assert(count !=0 && "pProto->Stackable==0 but checked at loading already");
@@ -917,3 +974,47 @@ Item* Item::CloneItem( uint32 count, Player const* player ) const
return newItem;
}
+bool Item::IsBindedNotWith( Player const* player ) const
+{
+ // not binded item
+ if(!IsSoulBound())
+ return false;
+
+ // own item
+ if(GetOwnerGUID()== player->GetGUID())
+ return false;
+
+ // not BOA item case
+ if(!IsBoundAccountWide())
+ return true;
+
+ // online
+ if(Player* owner = objmgr.GetPlayer(GetOwnerGUID()))
+ {
+ return owner->GetSession()->GetAccountId() != player->GetSession()->GetAccountId();
+ }
+ // offline slow case
+ else
+ {
+ return objmgr.GetPlayerAccountIdByGUID(GetOwnerGUID()) != player->GetSession()->GetAccountId();
+ }
+}
+
+bool ItemRequiredTarget::IsFitToRequirements( Unit* pUnitTarget ) const
+{
+ if(pUnitTarget->GetTypeId() != TYPEID_UNIT)
+ return false;
+
+ if(pUnitTarget->GetEntry() != m_uiTargetEntry)
+ return false;
+
+ switch(m_uiType)
+ {
+ case ITEM_TARGET_TYPE_CREATURE:
+ return pUnitTarget->isAlive();
+ case ITEM_TARGET_TYPE_DEAD:
+ return !pUnitTarget->isAlive();
+ default:
+ return false;
+ }
+}