diff options
Diffstat (limited to 'src/game/Item.cpp')
| -rw-r--r-- | src/game/Item.cpp | 159 | 
1 files changed, 130 insertions, 29 deletions
diff --git a/src/game/Item.cpp b/src/game/Item.cpp index 766bd81d640..bffd3c0d335 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(int 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; +    } +}  | 
