OregonCore  revision fb2a440-git
Your Favourite TBC server
Item.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "Item.h"
20 #include "ObjectMgr.h"
21 #include "WorldPacket.h"
22 #include "Database/DatabaseEnv.h"
23 #include "ItemEnchantmentMgr.h"
24 
25 void AddItemsSetItem(Player* player, Item* item)
26 {
27  ItemTemplate const* proto = item->GetProto();
28  uint32 setid = proto->ItemSet;
29 
30  ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
31 
32  if (!set)
33  {
34  sLog.outErrorDb("Item set %u for item (id %u) not found, mods not applied.", setid, proto->ItemId);
35  return;
36  }
37 
38  if (set->required_skill_id && player->GetSkillValue(set->required_skill_id) < set->required_skill_value)
39  return;
40 
41  ItemSetEffect* eff = NULL;
42 
43  for (size_t x = 0; x < player->ItemSetEff.size(); ++x)
44  {
45  if (player->ItemSetEff[x] && player->ItemSetEff[x]->setid == setid)
46  {
47  eff = player->ItemSetEff[x];
48  break;
49  }
50  }
51 
52  if (!eff)
53  {
54  eff = new ItemSetEffect;
55  memset(eff, 0, sizeof(ItemSetEffect));
56  eff->setid = setid;
57 
58  size_t x = 0;
59  for (; x < player->ItemSetEff.size(); x++)
60  if (!player->ItemSetEff[x])
61  break;
62 
63  if (x < player->ItemSetEff.size())
64  player->ItemSetEff[x] = eff;
65  else
66  player->ItemSetEff.push_back(eff);
67  }
68 
69  ++eff->item_count;
70 
71  for (uint32 x = 0; x < 8; x++)
72  {
73  if (!set->spells [x])
74  continue;
75  //not enough for spell
76  if (set->items_to_triggerspell[x] > eff->item_count)
77  continue;
78 
79  uint32 z = 0;
80  for (; z < 8; z++)
81  if (eff->spells[z] && eff->spells[z]->Id == set->spells[x])
82  break;
83 
84  if (z < 8)
85  continue;
86 
87  //new spell
88  for (uint32 y = 0; y < 8; y++)
89  {
90  if (!eff->spells[y]) // free slot
91  {
92  SpellEntry const* spellInfo = sSpellStore.LookupEntry(set->spells[x]);
93  if (!spellInfo)
94  {
95  sLog.outError("WORLD: unknown spell id %u in items set %u effects", set->spells[x], setid);
96  break;
97  }
98 
99  // spell casted only if fit form requirement, in other case will casted at form change
100  player->ApplyEquipSpell(spellInfo, NULL, true);
101  eff->spells[y] = spellInfo;
102  break;
103  }
104  }
105  }
106 }
107 
108 void RemoveItemsSetItem(Player* player, ItemTemplate const* proto)
109 {
110  uint32 setid = proto->ItemSet;
111 
112  ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
113 
114  if (!set)
115  {
116  sLog.outErrorDb("Item set #%u for item #%u not found, mods not removed.", setid, proto->ItemId);
117  return;
118  }
119 
120  ItemSetEffect* eff = NULL;
121  size_t setindex = 0;
122  for (; setindex < player->ItemSetEff.size(); setindex++)
123  {
124  if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->setid == setid)
125  {
126  eff = player->ItemSetEff[setindex];
127  break;
128  }
129  }
130 
131  // can be in case now enough skill requirement for set appling but set has been appliend when skill requirement not enough
132  if (!eff)
133  return;
134 
135  --eff->item_count;
136 
137  for (uint32 x = 0; x < 8; x++)
138  {
139  if (!set->spells[x])
140  continue;
141 
142  // enough for spell
143  if (set->items_to_triggerspell[x] <= eff->item_count)
144  continue;
145 
146  for (uint32 z = 0; z < 8; z++)
147  {
148  if (eff->spells[z] && eff->spells[z]->Id == set->spells[x])
149  {
150  // spell can be not active if not fit form requirement
151  player->ApplyEquipSpell(eff->spells[z], NULL, false);
152  eff->spells[z] = NULL;
153  break;
154  }
155  }
156  }
157 
158  if (!eff->item_count) //all items of a set were removed
159  {
160  ASSERT(eff == player->ItemSetEff[setindex]);
161  delete eff;
162  player->ItemSetEff[setindex] = NULL;
163  }
164 }
165 
166 bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
167 {
168  if (!pProto || !pBagProto)
169  return false;
170 
171  switch (pBagProto->Class)
172  {
174  switch (pBagProto->SubClass)
175  {
177  return true;
179  if (!(pProto->BagFamily & BAG_FAMILY_MASK_SOUL_SHARDS))
180  return false;
181  return true;
183  if (!(pProto->BagFamily & BAG_FAMILY_MASK_HERBS))
184  return false;
185  return true;
188  return false;
189  return true;
191  if (!(pProto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
192  return false;
193  return true;
196  return false;
197  return true;
199  if (!(pProto->BagFamily & BAG_FAMILY_MASK_GEMS))
200  return false;
201  return true;
204  return false;
205  return true;
206  default:
207  return false;
208  }
209  case ITEM_CLASS_QUIVER:
210  switch (pBagProto->SubClass)
211  {
213  if (!(pProto->BagFamily & BAG_FAMILY_MASK_ARROWS))
214  return false;
215  return true;
217  if (!(pProto->BagFamily & BAG_FAMILY_MASK_BULLETS))
218  return false;
219  return true;
220  default:
221  return false;
222  }
223  }
224  return false;
225 }
226 
228 {
231  // 2.3.2 - 0x18
233 
235  m_slot = 0;
236  uState = ITEM_NEW;
237  uQueuePos = -1;
238  m_container = NULL;
239  m_lootGenerated = false;
240  mb_in_trade = false;
241 }
242 
243 bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner)
244 {
245  Object::_Create(guidlow, 0, HIGHGUID_ITEM);
246 
247  SetEntry(itemid);
248  SetObjectScale(1.0f);
249 
250  SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0);
251  SetUInt64Value(ITEM_FIELD_CONTAINED, owner ? owner->GetGUID() : 0);
252 
253  ItemTemplate const* itemProto = sObjectMgr.GetItemTemplate(itemid);
254  if (!itemProto)
255  return false;
256 
258  SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability);
259  SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability);
260 
261  for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
262  SetSpellCharges(i, itemProto->Spells[i].SpellCharges);
263 
264  SetUInt32Value(ITEM_FIELD_DURATION, abs(itemProto->Duration));
265 
266  return true;
267 }
268 
270 {
272  return;
273 
274  sLog.outDebug("Item::UpdateDuration Item (Entry: %u Duration %u Diff %u)", GetEntry(), GetUInt32Value(ITEM_FIELD_DURATION), diff);
275 
276  if (GetUInt32Value(ITEM_FIELD_DURATION) <= diff)
277  {
278  owner->DestroyItem(GetBagSlot(), GetSlot(), true);
279  return;
280  }
281 
283  SetState(ITEM_CHANGED, owner); // save new time in database
284 }
285 
287 {
288  uint32 guid = GetGUIDLow();
289  switch (uState)
290  {
291  case ITEM_NEW:
292  {
293  std::ostringstream ss;
294  ss << "REPLACE INTO item_instance (guid,owner_guid,itemEntry,creatorGuid,giftCreatorGuid,count,duration,charges,flags,enchantments,randomPropertyId,durability,itemTextId) VALUES (";
295  ss << guid << ",";
296  ss << GUID_LOPART(GetOwnerGUID()) << ",";
297  ss << GetEntry() << ",";
300  ss << GetCount() << ",";
301  ss << GetUInt32Value(ITEM_FIELD_DURATION) << ",'";
302  for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
303  ss << GetSpellCharges(i) << " ";
304 
305  ss << "'," << GetUInt32Value(ITEM_FIELD_FLAGS) << ",'";
306  for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
307  {
308  ss << GetEnchantmentId(EnchantmentSlot(i)) << " ";
309  ss << GetEnchantmentDuration(EnchantmentSlot(i)) << " ";
310  ss << GetEnchantmentCharges(EnchantmentSlot(i)) << " ";
311  }
312 
313  ss << "'," << GetItemRandomPropertyId() << ",";
316 
317  CharacterDatabase.Execute(ss.str().c_str());
318  }
319  break;
320  case ITEM_CHANGED:
321  {
322  std::ostringstream ss;
323  ss << "UPDATE item_instance SET owner_guid = " << GUID_LOPART(GetOwnerGUID());
324  ss << ", itemEntry = " << GetEntry();
325  ss << ", creatorGuid = " << GUID_LOPART(GetUInt64Value(ITEM_FIELD_CREATOR));
326  ss << ", giftCreatorGuid = " << GUID_LOPART(GetUInt64Value(ITEM_FIELD_GIFTCREATOR));
327  ss << ", count = " << GetCount();
328  ss << ", duration = " << GetUInt32Value(ITEM_FIELD_DURATION);
329  ss << ", charges = '";
330  for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
331  ss << GetSpellCharges(i) << " ";
332 
333  ss << "', flags = " << GetUInt32Value(ITEM_FIELD_FLAGS);
334  ss << ", enchantments = '";
335  for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
336  {
337  ss << GetEnchantmentId(EnchantmentSlot(i)) << " ";
338  ss << GetEnchantmentDuration(EnchantmentSlot(i)) << " ";
339  ss << GetEnchantmentCharges(EnchantmentSlot(i)) << " ";
340  }
341 
342  ss << "', randomPropertyId = " << GetItemRandomPropertyId();
343  ss << ", durability = " << GetUInt32Value(ITEM_FIELD_DURABILITY);
344  ss << ", itemTextId = " << GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID);
345  ss << " WHERE guid = " << guid;
346 
347  CharacterDatabase.Execute(ss.str().c_str());
348 
350  CharacterDatabase.PExecute("UPDATE character_gifts SET guid = '%u' WHERE item_guid = '%u'", GUID_LOPART(GetOwnerGUID()), GetGUIDLow());
351  }
352  break;
353  case ITEM_REMOVED:
354  {
356  CharacterDatabase.PExecute("DELETE FROM item_text WHERE id = '%u'", GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID));
357  CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", guid);
359  CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", GetGUIDLow());
360  delete this;
361  return;
362  }
363  case ITEM_UNCHANGED:
364  break;
365  }
367 }
368 
369 bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields)
370 {
371  // 0 1 2 3 4 5 6 7 8 9 10
372  //result = CharacterDatabase.PQuery("SELECT itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, itemTextId FROM item_instance WHERE guid = '%u'", guid);
373 
374  // create item before any checks for store correct guid
375  // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB
376  Object::_Create(guid, 0, HIGHGUID_ITEM);
377 
378  // Set entry, MUST be before proto check
379  SetEntry(fields[0].GetUInt32());
380  SetObjectScale(1.0f);
381 
382  ItemTemplate const* proto = GetProto();
383  if (!proto)
384  return false;
385 
386  // set owner (not if item is only loaded for gbank/auction/mail)
387  if (owner_guid)
388  SetOwnerGUID(owner_guid);
389 
390  bool need_save = false; // need explicit save data at load fixes
391  SetUInt64Value(ITEM_FIELD_CREATOR, MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER));
393  SetCount(fields[3].GetUInt32());
394 
395  uint32 duration = fields[4].GetUInt32();
397  // update duration if need, and remove if not need
398  if ((proto->Duration == 0) != (duration == 0))
399  {
400  SetUInt32Value(ITEM_FIELD_DURATION, abs(proto->Duration)); //why is abs needed here?
401  need_save = true;
402  }
403 
404  Tokens tokens = StrSplit(fields[5].GetCppString(), " ");
405  if (tokens.size() == MAX_ITEM_PROTO_SPELLS)
406  for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
407  SetSpellCharges(i, atoi(tokens[i].c_str()));
408 
409  SetUInt32Value(ITEM_FIELD_FLAGS, fields[6].GetUInt32());
410  // Remove bind flag for items vs NO_BIND set
411  if (IsSoulBound() && proto->Bonding == NO_BIND)
412  {
414  need_save = true;
415  }
416 
418  SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, fields[8].GetInt16());
419 
420  // recalculate suffix factor
421  if (GetItemRandomPropertyId() < 0)
423 
424  uint32 durability = fields[9].GetUInt16();
426  // update max durability (and durability) if need
428  if (durability > proto->MaxDurability)
429  {
431  need_save = true;
432  }
433 
434  SetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID, fields[10].GetUInt32());
435 
436  if (need_save) // normal item changed state set not work at loading
437  {
438  std::ostringstream ss;
439  ss << "UPDATE item_instance SET duration = " << GetUInt32Value(ITEM_FIELD_DURATION)
440  << ", flags = " << GetUInt32Value(ITEM_FIELD_FLAGS)
441  << ", durability = " << GetUInt32Value(ITEM_FIELD_DURABILITY)
442  << " WHERE guid = " << guid;
443 
444  CharacterDatabase.Execute(ss.str().c_str());
445  }
446 
447  return true;
448 }
449 
451 {
452  CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", GetGUIDLow());
453 }
454 
456 {
457  CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", GetGUIDLow());
458 }
459 
461 {
462  return sObjectMgr.GetItemTemplate(GetEntry());
463 }
464 
466 {
467  return sObjectMgr.GetPlayer(GetOwnerGUID());
468 }
469 
471 {
472  const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] =
473  {
479  };
480 
481  const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] =
482  {
484  };
485 
486  ItemTemplate const* proto = GetProto();
487 
488  switch (proto->Class)
489  {
490  case ITEM_CLASS_WEAPON:
491  if (proto->SubClass >= MAX_ITEM_SUBCLASS_WEAPON)
492  return 0;
493  else
494  return item_weapon_skills[proto->SubClass];
495 
496  case ITEM_CLASS_ARMOR:
497  if (proto->SubClass >= MAX_ITEM_SUBCLASS_ARMOR)
498  return 0;
499  else
500  return item_armor_skills[proto->SubClass];
501 
502  default:
503  return 0;
504  }
505 }
506 
508 {
509  ItemTemplate const* proto = GetProto();
510 
511  switch (proto->Class)
512  {
513  case ITEM_CLASS_WEAPON:
514  switch (proto->SubClass)
515  {
517  return 196;
519  return 197;
521  return 264;
523  return 266;
525  return 198;
527  return 199;
529  return 200;
531  return 201;
533  return 202;
535  return 227;
537  return 1180;
539  return 2567;
541  return 3386;
543  return 5011;
545  return 5009;
546  default:
547  return 0;
548  }
549  case ITEM_CLASS_ARMOR:
550  switch (proto->SubClass)
551  {
553  return 9078;
555  return 9077;
557  return 8737;
559  return 750;
561  return 9116;
562  default:
563  return 0;
564  }
565  }
566  return 0;
567 }
568 
570 {
571  ItemTemplate const* itemProto = sItemStorage.LookupEntry<ItemTemplate>(item_id);
572 
573  if (!itemProto)
574  return 0;
575 
576  // item must have one from this field values not null if it can have random enchantments
577  if ((!itemProto->RandomProperty) && (!itemProto->RandomSuffix))
578  return 0;
579 
580  // item can have not null only one from field values
581  if ((itemProto->RandomProperty) && (itemProto->RandomSuffix))
582  {
583  sLog.outErrorDb("Item template %u has RandomProperty == %u and RandomSuffix == %u, but must have one from field =0", itemProto->ItemId, itemProto->RandomProperty, itemProto->RandomSuffix);
584  return 0;
585  }
586 
587  // RandomProperty case
588  if (itemProto->RandomProperty)
589  {
590  uint32 randomPropId = GetItemEnchantMod(itemProto->RandomProperty);
591  ItemRandomPropertiesEntry const* random_id = sItemRandomPropertiesStore.LookupEntry(randomPropId);
592  if (!random_id)
593  {
594  sLog.outErrorDb("Enchantment id #%u used but it doesn't have a record in 'ItemRandomProperties.dbc'", randomPropId);
595  return 0;
596  }
597 
598  return random_id->ID;
599  }
600  // RandomSuffix case
601  else
602  {
603  uint32 randomPropId = GetItemEnchantMod(itemProto->RandomSuffix);
604  ItemRandomSuffixEntry const* random_id = sItemRandomSuffixStore.LookupEntry(randomPropId);
605  if (!random_id)
606  {
607  sLog.outErrorDb("Enchantment id #%u used but it doesn't have a record in sItemRandomSuffixStore.", randomPropId);
608  return 0;
609  }
610 
611  return -int32(random_id->ID);
612  }
613 }
614 
616 {
617  if (!randomPropId)
618  return;
619 
620  if (randomPropId > 0)
621  {
622  ItemRandomPropertiesEntry const* item_rand = sItemRandomPropertiesStore.LookupEntry(randomPropId);
623  if (item_rand)
624  {
626  {
629  }
631  SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_2], 0, 0);
632  }
633  }
634  else
635  {
636  ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(-randomPropId);
637  if (item_rand)
638  {
639  if (GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID) != -int32(item_rand->ID) ||
641  {
645  }
646 
648  SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_0], 0, 0);
649  }
650  }
651 }
652 
654 {
655  uint32 suffixFactor = GenerateEnchSuffixFactor(GetEntry());
656  if (GetItemSuffixFactor() == suffixFactor)
657  return;
659 }
660 
661 void Item::SetState(ItemUpdateState state, Player* forplayer)
662 {
663  if (uState == ITEM_NEW && state == ITEM_REMOVED)
664  {
665  // pretend the item never existed
666  if (forplayer)
667  RemoveFromUpdateQueueOf(forplayer);
668  delete this;
669  return;
670  }
671  if (state != ITEM_UNCHANGED)
672  {
673  // new items must stay in new state until saved
674  if (uState != ITEM_NEW)
675  uState = state;
676  if (forplayer)
677  AddToUpdateQueueOf(forplayer);
678  }
679  else
680  {
681  // unset in queue
682  // the item must be removed from the queue manually
683  uQueuePos = -1;
685  }
686 }
687 
689 {
690  if (IsInUpdateQueue())
691  return;
692 
693  ASSERT(player != NULL);
694 
695  if (player->GetGUID() != GetOwnerGUID())
696  {
697  sLog.outDebug("Item::AddToUpdateQueueOf - Owner's guid (%u) and player's guid (%u) don't match!", GUID_LOPART(GetOwnerGUID()), player->GetGUIDLow());
698  return;
699  }
700 
701  if (player->m_itemUpdateQueueBlocked)
702  return;
703 
704  player->m_itemUpdateQueue.push_back(this);
705  uQueuePos = player->m_itemUpdateQueue.size() - 1;
706 }
707 
709 {
710  if (!IsInUpdateQueue())
711  return;
712 
713  ASSERT(player != NULL)
714 
715  if (player->GetGUID() != GetOwnerGUID())
716  {
717  sLog.outDebug("Item::RemoveFromUpdateQueueOf - Owner's guid (%u) and player's guid (%u) don't match!", GUID_LOPART(GetOwnerGUID()), player->GetGUIDLow());
718  return;
719  }
720 
721  if (player->m_itemUpdateQueueBlocked)
722  return;
723 
724  player->m_itemUpdateQueue[uQueuePos] = NULL;
725  uQueuePos = -1;
726 }
727 
729 {
731 }
732 
733 bool Item::IsEquipped() const
734 {
735  return !IsInBag() && m_slot < EQUIPMENT_SLOT_END;
736 }
737 
738 bool Item::CanBeTraded() const
739 {
740  if (m_lootGenerated)
741  return false;
742 
743  if (IsSoulBound())
744  return false;
745 
746  if (IsBag() && (Player::IsBagPos(GetPos()) || !((Bag const*)this)->IsEmpty()))
747  return false;
748 
749  if (Player* owner = GetOwner())
750  {
751  if (owner->CanUnequipItem(GetPos(), false) != EQUIP_ERR_OK)
752  return false;
753  if (owner->GetLootGUID() == GetGUID())
754  return false;
755  }
756 
757  if (IsBoundByEnchant())
758  return false;
759 
760  return true;
761 }
762 
764 {
765  // Check all enchants for soulbound
766  for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
767  if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
768  if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
769  if (enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND)
770  return true;
771  return false;
772 }
773 
775 {
776  // not allow merge looting currently items
777  if (m_lootGenerated)
779 
780  // check item type
781  if (GetEntry() != proto->ItemId)
783 
784  // check free space (full stacks can't be target of merge
785  if (GetCount() >= proto->Stackable)
787 
788  return EQUIP_ERR_OK;
789 }
790 
791 bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
792 {
793  ItemTemplate const* proto = GetProto();
794 
795  if (spellInfo->EquippedItemClass != -1) // -1 == any item class
796  {
797  if (spellInfo->EquippedItemClass != int32(proto->Class))
798  return false; // wrong item class
799 
800  if (spellInfo->EquippedItemSubClassMask != 0) // 0 == any subclass
801  {
802  if ((spellInfo->EquippedItemSubClassMask & (1 << proto->SubClass)) == 0)
803  return false; // subclass not present in mask
804  }
805  }
806 
807  if (spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type
808  {
809  if ((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->InventoryType)) == 0)
810  return false; // inventory type not present in mask
811  }
812 
813  return true;
814 }
815 
816 void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges)
817 {
818  // Better lost small time at check in comparison lost time at item save to DB.
819  if ((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
820  return;
821 
826 }
827 
829 {
830  if (GetEnchantmentDuration(slot) == duration)
831  return;
832 
834  SetState(ITEM_CHANGED, owner);
835  // Cannot use GetOwner() here, has to be passed as an argument to avoid freeze due to hashtable locking
836 }
837 
839 {
840  if (GetEnchantmentCharges(slot) == charges)
841  return;
842 
845 }
846 
848 {
849  if (!GetEnchantmentId(slot))
850  return;
851 
852  for (uint8 x = 0; x < 3; ++x)
855 }
856 
858 {
859  bool fits = true;
860  for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + 3; ++enchant_slot)
861  {
863 
864  uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
865  if (!enchant_id)
866  {
867  if (SocketColor) fits &= false;
868  continue;
869  }
870 
871  SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
872  if (!enchantEntry)
873  {
874  if (SocketColor) fits &= false;
875  continue;
876  }
877 
878  uint8 GemColor = 0;
879 
880  uint32 gemid = enchantEntry->GemID;
881  if (gemid)
882  {
883  ItemTemplate const* gemProto = sItemStorage.LookupEntry<ItemTemplate>(gemid);
884  if (gemProto)
885  {
886  GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GemProperties);
887  if (gemProperty)
888  GemColor = gemProperty->color;
889  }
890  }
891 
892  fits &= (GemColor & SocketColor) ? true : false;
893  }
894  return fits;
895 }
896 
898 {
899  uint8 count = 0;
900  for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + 3; ++enchant_slot)
901  {
902  uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
903  if (!enchant_id)
904  continue;
905 
906  SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
907  if (!enchantEntry)
908  continue;
909 
910  if (GemID == enchantEntry->GemID)
911  ++count;
912  }
913  return count;
914 }
915 
916 bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
917 {
918  ItemTemplate const* proto = GetProto();
919  return proto && ((proto->Map && proto->Map != cur_mapId) || (proto->Area && proto->Area != cur_zoneId));
920 }
921 
922 // Though the client has the information in the item's data field,
923 // we have to send SMSG_ITEM_TIME_UPDATE to display the remaining
924 // time.
926 {
928  return;
929 
930  WorldPacket data(SMSG_ITEM_TIME_UPDATE, (8 + 4));
931  data << (uint64)GetGUID();
933  owner->GetSession()->SendPacket(&data);
934 }
935 
936 Item* Item::CreateItem(uint32 item, uint32 count, Player const* player)
937 {
938  if (count < 1)
939  return NULL; //don't create item at zero count
940 
941  ItemTemplate const* pProto = sObjectMgr.GetItemTemplate(item);
942  if (pProto)
943  {
944  if (count > pProto->Stackable)
945  count = pProto->Stackable;
946 
947  ASSERT(count != 0 && "pProto->Stackable == 0 but checked at loading already");
948 
949  Item* pItem = NewItemOrBag(pProto);
950  if (pItem->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_ITEM), item, player))
951  {
952  pItem->SetCount(count);
953  return pItem;
954  }
955  else
956  delete pItem;
957  }
958  else
959  ASSERT(false);
960  return NULL;
961 }
962 
963 Item* Item::CloneItem(uint32 count, Player const* player) const
964 {
965  Item* newItem = CreateItem(GetEntry(), count, player);
966  if (!newItem)
967  return NULL;
968 
974  return newItem;
975 }
976 
977 bool Item::IsBindedNotWith(Player const* player) const
978 {
979  // not binded item
980  if (!IsSoulBound())
981  return false;
982 
983  // own item
984  if (GetOwnerGUID() == player->GetGUID())
985  return false;
986 
987  return true;
988 }
989 
991 {
992  if (Player* owner = GetOwner())
993  BuildFieldsUpdate(owner, data_map);
994  ClearUpdateMask(false);
995 }
996 
uint32 GetItemEnchantMod(uint32 entry)
bool IsBindedNotWith(Player const *player) const
Definition: Item.cpp:977
uint32 GetCount() const
Definition: Item.h:251
ItemTemplate const * GetProto() const
Definition: Item.cpp:460
void SetState(ItemUpdateState state, Player *forplayer=NULL)
Definition: Item.cpp:661
uint32 InventoryType
const uint32 & GetUInt32Value(uint16 index) const
Definition: Object.h:234
int32 GetSpellCharges(uint8 index=0) const
Definition: Item.h:330
void ClearUpdateMask(bool remove)
Definition: Object.cpp:678
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
bool mb_in_trade
Definition: Item.h:380
uint32 GetSkill()
Definition: Item.cpp:470
DBCStorage< ItemSetEntry > sItemSetStore(ItemSetEntryfmt)
std::vector< std::string > Tokens
Definition: Util.h:26
SocketColor
_Socket Socket[3]
uint32 GetItemSuffixFactor() const
Definition: Item.h:302
bool IsSoulBound() const
Definition: Item.h:219
virtual void DeleteFromDB()
Definition: Item.cpp:450
uint32 GetSpell()
Definition: Item.cpp:507
Item * CloneItem(uint32 count, Player const *player=NULL) const
Definition: Item.cpp:963
void BuildFieldsUpdate(Player *, UpdateDataMapType &) const
Definition: Object.cpp:690
void SetInt32Value(uint16 index, int32 value)
Definition: Object.cpp:760
Definition: Field.h:24
void SetObjectScale(float scale)
Definition: Object.h:205
virtual void SaveToDB()
Definition: Item.cpp:286
bool Execute(const char *sql)
Definition: Database.cpp:420
bool IsEquipped() const
Definition: Item.cpp:733
DBCStorage< ItemRandomSuffixEntry > sItemRandomSuffixStore(ItemRandomSuffixfmt)
const uint64 & GetUInt64Value(uint16 index) const
Definition: Object.h:240
void AddToUpdateQueueOf(Player *player)
Definition: Item.cpp:688
bool m_lootGenerated
Definition: Item.h:340
#define MAX_ITEM_SUBCLASS_ARMOR
void _LoadIntoDataField(const char *data, uint32 startOffset, uint32 count)
Definition: Object.cpp:721
bool IsFitToSpellRequirements(SpellEntry const *spellInfo) const
Definition: Item.cpp:791
#define sLog
Log class singleton.
Definition: Log.h:187
uint16 GetPos() const
Definition: Item.h:279
Item()
Definition: Item.cpp:227
Tokens StrSplit(const std::string &src, const std::string &sep)
Definition: Util.cpp:58
void SetUInt32Value(uint16 index, uint32 value)
Definition: Object.cpp:779
void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
Definition: Item.cpp:838
ACE_INT32 int32
Definition: Define.h:67
int32 EquippedItemClass
Definition: DBCStructure.h:721
void UpdateDuration(Player *owner, uint32 diff)
Definition: Item.cpp:269
bool GemsFitSockets() const
Definition: Item.cpp:857
void SetCount(uint32 value)
Definition: Item.h:255
uint32 GetGUIDLow() const
Definition: Object.h:166
void SetEntry(uint32 entry)
Definition: Object.h:196
void SetOwnerGUID(uint64 guid)
Definition: Item.h:212
Bag * m_container
Definition: Item.h:377
bool IsBag() const
Definition: Item.h:229
void SetItemRandomProperties(int32 randomPropId)
Definition: Item.cpp:615
int32 GetItemRandomPropertyId() const
Definition: Item.h:298
uint16 m_objectType
Definition: Object.h:424
#define sObjectMgr
Definition: ObjectMgr.h:1285
void SendPacket(WorldPacket const *packet)
void RemoveItemsSetItem(Player *player, ItemTemplate const *proto)
Definition: Item.cpp:108
DBCStorage< SpellEntry > sSpellStore(SpellEntryfmt)
uint32 Color
void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges)
Definition: Item.cpp:816
void UpdateItemSuffixFactor()
Definition: Item.cpp:653
uint32 RandomSuffix
uint32 GetEnchantmentDuration(EnchantmentSlot slot) const
Definition: Item.h:317
void DestroyItem(uint8 bag, uint8 slot, bool update)
Definition: Player.cpp:10668
uint32 setid
Definition: Item.h:33
ItemUpdateState uState
Definition: Item.h:378
uint8 m_objectTypeId
Definition: Object.h:426
bool IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
Definition: Item.cpp:916
int32 EquippedItemSubClassMask
Definition: DBCStructure.h:722
void _Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
Definition: Object.cpp:125
DBCStorage< ItemRandomPropertiesEntry > sItemRandomPropertiesStore(ItemRandomPropertiesfmt)
SpellEntry const * spells[8]
Definition: Item.h:35
void SendTimeUpdate(Player *owner)
Definition: Item.cpp:925
Definition: Bag.h:27
ACE_UINT8 uint8
Definition: Define.h:73
Item * NewItemOrBag(ItemTemplate const *proto)
Definition: Bag.h:70
static int32 GenerateItemRandomPropertyId(uint32 item_id)
Definition: Item.cpp:569
virtual bool Create(uint32 guidlow, uint32 itemid, Player const *owner)
Definition: Item.cpp:243
Player * GetOwner() const
Definition: Item.cpp:465
uint8 GetGemCountWithID(uint32 GemID) const
Definition: Item.cpp:897
uint8 m_updateFlag
Definition: Object.h:427
void BuildUpdate(UpdateDataMapType &) override
Definition: Item.cpp:990
#define MAKE_NEW_GUID(l, e, h)
Definition: ObjectGuid.h:80
Definition: Item.h:196
#define MAX_ENCHANTMENT_OFFSET
Definition: Item.h:174
static Item * CreateItem(uint32 item, uint32 count, Player const *player=NULL)
Definition: Item.cpp:936
void ClearEnchantment(EnchantmentSlot slot)
Definition: Item.cpp:847
uint16 GetSkillValue(uint32 skill) const
Definition: Player.cpp:5487
DBCStorage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore(SpellItemEnchantmentfmt)
void RemoveFromUpdateQueueOf(Player *player)
Definition: Item.cpp:708
void AddItemsSetItem(Player *player, Item *item)
Definition: Item.cpp:25
UNORDERED_MAP< Player *, UpdateData > UpdateDataMapType
Definition: Object.h:126
bool PExecute(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:441
uint8 CanBeMergedPartlyWith(ItemTemplate const *proto) const
Definition: Item.cpp:774
SQLStorage sItemStorage
std::vector< Item * > m_itemUpdateQueue
Definition: Player.h:2784
#define MAX_ITEM_PROTO_SPELLS
void SetUInt64Value(uint16 index, const uint64 &value)
Definition: Object.cpp:798
uint8 m_slot
Definition: Item.h:376
int16 uQueuePos
Definition: Item.h:379
uint8 GetSlot() const
Definition: Item.h:266
bool IsBoundByEnchant() const
Definition: Item.cpp:763
uint32 MaxDurability
virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, Field *fields)
Definition: Item.cpp:369
void SetSpellCharges(uint8 index, int32 value)
Definition: Item.h:334
ACE_UINT64 uint64
Definition: Define.h:70
void ApplyModFlag(uint16 index, uint32 flag, bool apply)
Definition: Object.h:329
T const * LookupEntry(uint32 id) const
Definition: SQLStorage.h:52
ItemUpdateState
Definition: Item.h:184
uint32 GetEnchantmentCharges(EnchantmentSlot slot) const
Definition: Item.h:321
int32 EquippedItemInventoryTypeMask
Definition: DBCStructure.h:723
DBCStorage< GemPropertiesEntry > sGemPropertiesStore(GemPropertiesEntryfmt)
uint16 m_valuesCount
Definition: Object.h:438
EnchantmentSlot
Definition: Item.h:147
uint32 Stackable
#define ASSERT
Definition: Errors.h:29
const int32 & GetInt32Value(uint16 index) const
Definition: Object.h:228
bool CanBeTraded() const
Definition: Item.cpp:738
uint32 GetEntry() const
Definition: Object.h:192
WorldSession * GetSession() const
Definition: Player.h:1944
void ApplyEquipSpell(SpellEntry const *spellInfo, Item *item, bool apply, bool form_change=false)
Definition: Player.cpp:6862
Definition: Item.h:188
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
bool IsInBag() const
Definition: Item.h:288
uint32 GenerateEnchSuffixFactor(uint32 item_id)
bool HasFlag(uint16 index, uint32 flag) const
Definition: Object.h:305
bool IsInUpdateQueue() const
Definition: Item.h:350
ACE_UINT32 uint32
Definition: Define.h:71
static bool IsBagPos(uint16 pos)
Definition: Player.cpp:8667
uint32 item_count
Definition: Item.h:34
uint8 GetBagSlot() const
Definition: Item.cpp:728
void DeleteFromInventoryDB()
Definition: Item.cpp:455
bool ItemCanGoIntoBag(ItemTemplate const *pProto, ItemTemplate const *pBagProto)
Definition: Item.cpp:166
uint32 RandomProperty
Definition: Player.h:922
uint64 const & GetOwnerGUID() const
Definition: Item.h:208
uint32 BagFamily
std::vector< ItemSetEffect * > ItemSetEff
Definition: Player.h:2183
bool m_itemUpdateQueueBlocked
Definition: Player.h:2785
uint32 GemProperties
#define MAX_ITEM_SUBCLASS_WEAPON
const uint64 & GetGUID() const
Definition: Object.h:162
void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player *owner)
Definition: Item.cpp:828
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition: Item.h:313