2 * Copyright (C) 2005,2006,2007 MaNGOS <http://www.mangosproject.org/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "ObjectMgr.h"
22 #include "Database/DatabaseEnv.h"
23 #include "ItemEnchantmentMgr.h"
25 void AddItemsSetItem(Player
*player
,Item
*item
)
27 ItemPrototype
const *proto
= item
->GetProto();
28 uint32 setid
= proto
->ItemSet
;
30 ItemSetEntry
const *set
= sItemSetStore
.LookupEntry(setid
);
34 sLog
.outErrorDb("Item set %u for item (id %u) not found, mods not applied.",setid
,proto
->ItemId
);
38 if(set
->required_skill_id
)
39 if(player
->GetSkillValue(set
->required_skill_id
) < set
->required_skill_value
) return;
41 ItemSetEffect
*eff
=NULL
;
43 for(size_t x
= 0; x
< player
->ItemSetEff
.size(); x
++)
44 if(player
->ItemSetEff
[x
] && player
->ItemSetEff
[x
]->setid
== setid
)
46 eff
= player
->ItemSetEff
[x
];
52 eff
= new ItemSetEffect
;
53 memset(eff
,0,sizeof(ItemSetEffect
));
57 for(; x
< player
->ItemSetEff
.size(); x
++)
58 if(!player
->ItemSetEff
[x
])
61 if(x
< player
->ItemSetEff
.size())
62 player
->ItemSetEff
[x
]=eff
;
64 player
->ItemSetEff
.push_back(eff
);
69 for(uint32 x
=0;x
<8;x
++)
72 if(set
->items_to_triggerspell
[x
] <= eff
->item_count
)
77 if(eff
->spells
[z
]->Id
==set
->spells
[x
])break;
80 for(uint32 y
=0;y
<8;y
++)
83 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(set
->spells
[x
]);
86 sLog
.outError("WORLD: unknown spell id %u in items set %u effects", set
->spells
[x
],setid
);
90 player
->CastSpell(player
,set
->spells
[x
],true,item
);
91 eff
->spells
[y
] = spellInfo
;
98 void RemoveItemsSetItem(Player
*player
,ItemPrototype
const *proto
)
100 uint32 setid
= proto
->ItemSet
;
102 ItemSetEntry
const *set
= sItemSetStore
.LookupEntry(setid
);
106 sLog
.outErrorDb("Item set #%u for item #%u not found, mods not removed.",setid
,proto
->ItemId
);
110 ItemSetEffect
*eff
= NULL
;
112 for(;setindex
< player
->ItemSetEff
.size(); setindex
++)
113 if(player
->ItemSetEff
[setindex
] && player
->ItemSetEff
[setindex
]->setid
== setid
)
115 eff
= player
->ItemSetEff
[setindex
];
119 // can be in case now enough skill requirement for set appling but set has been appliend when skill requirement not enough
125 for(uint32 x
=0;x
<8;x
++)
127 //not enough for spell
128 if(set
->items_to_triggerspell
[x
] > eff
->item_count
)
130 for(uint32 z
=0;z
<8;z
++)
132 if(eff
->spells
[z
]->Id
==set
->spells
[x
])
134 player
->RemoveAurasDueToSpell(set
->spells
[x
]);
140 if(!eff
->item_count
) //all items of a set were removed
142 assert(eff
== player
->ItemSetEff
[setindex
]);
144 player
->ItemSetEff
[setindex
] = NULL
;
150 m_objectType
|= TYPE_ITEM
;
151 m_objectTypeId
= TYPEID_ITEM
;
152 m_updateFlag
= (UPDATEFLAG_HIGHGUID
| UPDATEFLAG_ALL
); // 2.1.2 - 0x18
154 m_valuesCount
= ITEM_END
;
159 m_lootGenerated
= false;
163 bool Item::Create( uint32 guidlow
, uint32 itemid
, Player
* owner
)
165 Object::_Create( guidlow
, HIGHGUID_ITEM
);
167 SetUInt32Value(OBJECT_FIELD_ENTRY
, itemid
);
168 SetFloatValue(OBJECT_FIELD_SCALE_X
, 1.0f
);
170 SetUInt64Value(ITEM_FIELD_OWNER
, owner
->GetGUID());
171 SetUInt64Value(ITEM_FIELD_CONTAINED
, owner
->GetGUID());
173 ItemPrototype
const *itemProto
= objmgr
.GetItemPrototype(itemid
);
177 SetUInt32Value(ITEM_FIELD_STACK_COUNT
, 1);
178 SetUInt32Value(ITEM_FIELD_MAXDURABILITY
, itemProto
->MaxDurability
);
179 SetUInt32Value(ITEM_FIELD_DURABILITY
, itemProto
->MaxDurability
);
181 for(int i
= 0; i
< 5; ++i
)
182 SetSpellCharges(i
,itemProto
->Spells
[i
].SpellCharges
);
184 SetUInt32Value(ITEM_FIELD_FLAGS
, itemProto
->Flags
);
185 //SetUInt32Value(ITEM_FIELD_DURATION, itemProto->Delay); ITEM_FIELD_DURATION is time until item expires, not speed
190 void Item::SaveToDB()
192 uint32 guid
= GetGUIDLow();
199 // it's better than rebuilding indexes multiple times
200 QueryResult
*result
= sDatabase
.PQuery("select count(*) as r from `item_instance` where `guid` = '%u'", guid
);
203 Rows
= result
->Fetch()[0].GetUInt32();
207 // guess - instance exists ?
210 // no - we must insert new rec
211 std::ostringstream ss
;
212 ss
<< "INSERT INTO `item_instance` (`guid`,`owner_guid`,`data`) VALUES (" << guid
<< "," << GUID_LOPART(GetOwnerGUID()) << ",'";
213 for(uint16 i
= 0; i
< m_valuesCount
; i
++ )
214 ss
<< GetUInt32Value(i
) << " ";
217 sDatabase
.Execute( ss
.str().c_str() );
220 std::ostringstream ss
;
221 ss
<< "UPDATE `item_instance` SET `data` = '";
222 for(uint16 i
= 0; i
< m_valuesCount
; i
++ )
223 ss
<< GetUInt32Value(i
) << " ";
224 ss
<< "' WHERE `guid` = '" << guid
<< "'";
225 sDatabase
.Execute( ss
.str().c_str() );
230 std::ostringstream ss
;
231 ss
<< "UPDATE `item_instance` SET `data` = '";
232 for(uint16 i
= 0; i
< m_valuesCount
; i
++ )
233 ss
<< GetUInt32Value(i
) << " ";
234 ss
<< "', `owner_guid` = '" << GUID_LOPART(GetOwnerGUID()) << "' WHERE `guid` = '" << guid
<< "'";
236 sDatabase
.Execute( ss
.str().c_str() );
238 if(HasFlag(ITEM_FIELD_FLAGS
, ITEM_FLAGS_WRAPPED
))
239 sDatabase
.PExecute("UPDATE `character_gifts` SET `guid` = '%u' WHERE `item_guid` = '%u'", GUID_LOPART(GetOwnerGUID()),GetGUIDLow());
243 if (GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID
) > 0 )
244 sDatabase
.PExecute("DELETE FROM `item_text` WHERE `id` = '%u'", GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID
));
245 sDatabase
.PExecute("DELETE FROM `item_instance` WHERE `guid` = '%u'", guid
);
246 if(HasFlag(ITEM_FIELD_FLAGS
, ITEM_FLAGS_WRAPPED
))
247 sDatabase
.PExecute("DELETE FROM `character_gifts` WHERE `item_guid` = '%u'", GetGUIDLow());
254 SetState(ITEM_UNCHANGED
);
257 bool Item::LoadFromDB(uint32 guid
, uint64 owner_guid
, QueryResult
*result
)
259 bool delete_result
= false;
262 result
= sDatabase
.PQuery("SELECT `data` FROM `item_instance` WHERE `guid` = '%u'", guid
);
263 delete_result
= true;
268 sLog
.outError("ERROR: Item (GUID: %u owner: %u) not found in table `item_instance`, can't load. ",guid
,owner_guid
);
272 Field
*fields
= result
->Fetch();
274 _Create(guid
, HIGHGUID_ITEM
);
276 if(!LoadValues(fields
[0].GetString()))
278 sLog
.outError("ERROR: Item #%d have broken data in `data` field. Can't be loaded.",guid
);
279 if (delete_result
) delete result
;
283 if (delete_result
) delete result
;
285 if(owner_guid
!= 0 && GetOwnerGUID()!=owner_guid
)
287 sLog
.outError("Item::LoadFromDB: item: %u have in DB owner guid: %u. Updated to correct: %u",GetGUIDLow(),GUID_LOPART(GetOwnerGUID()), GUID_LOPART(owner_guid
));
288 SetOwnerGUID(owner_guid
);
294 void Item::DeleteFromDB()
296 sDatabase
.PExecute("DELETE FROM `item_instance` WHERE `guid` = '%u'",GetGUIDLow());
299 void Item::DeleteFromInventoryDB()
301 sDatabase
.PExecute("DELETE FROM `character_inventory` WHERE `item` = '%u'",GetGUIDLow());
304 ItemPrototype
const *Item::GetProto() const
306 return objmgr
.GetItemPrototype(GetUInt32Value(OBJECT_FIELD_ENTRY
));
309 Player
* Item::GetOwner()const
311 return objmgr
.GetPlayer(GetOwnerGUID());
314 uint32
Item::GetSkill()
316 const static uint32 item_weapon_skills
[MAX_ITEM__SUBCLASS_WEAPON
] =
318 SKILL_AXES
, SKILL_2H_AXES
, SKILL_BOWS
, SKILL_GUNS
, SKILL_MACES
,
319 SKILL_2H_MACES
, SKILL_POLEARMS
, SKILL_SWORDS
, SKILL_2H_SWORDS
, 0,
320 SKILL_STAVES
, 0, 0, SKILL_UNARMED
, 0,
321 SKILL_DAGGERS
, SKILL_THROWN
, SKILL_ASSASSINATION
, SKILL_CROSSBOWS
, SKILL_WANDS
,
325 const static uint32 item_armor_skills
[MAX_ITEM_SUBCLASS_ARMOR
] =
327 0,SKILL_CLOTH
,SKILL_LEATHER
,SKILL_MAIL
,SKILL_PLATE_MAIL
,0,SKILL_SHIELD
,0,0,0
330 switch (GetProto()->Class
)
332 case ITEM_CLASS_WEAPON
:
333 if( GetProto()->SubClass
>= MAX_ITEM__SUBCLASS_WEAPON
)
336 return item_weapon_skills
[GetProto()->SubClass
];
338 case ITEM_CLASS_ARMOR
:
339 if( GetProto()->SubClass
>= MAX_ITEM_SUBCLASS_ARMOR
)
342 return item_armor_skills
[GetProto()->SubClass
];
349 uint32
Item::GetSpell()
351 switch (GetProto()->Class
)
353 case ITEM_CLASS_WEAPON
:
354 switch (GetProto()->SubClass
)
356 case ITEM_SUBCLASS_WEAPON_AXE
: return 196;
357 case ITEM_SUBCLASS_WEAPON_AXE2
: return 197;
358 case ITEM_SUBCLASS_WEAPON_BOW
: return 264;
359 case ITEM_SUBCLASS_WEAPON_GUN
: return 266;
360 case ITEM_SUBCLASS_WEAPON_MACE
: return 198;
361 case ITEM_SUBCLASS_WEAPON_MACE2
: return 199;
362 case ITEM_SUBCLASS_WEAPON_POLEARM
: return 200;
363 case ITEM_SUBCLASS_WEAPON_SWORD
: return 201;
364 case ITEM_SUBCLASS_WEAPON_SWORD2
: return 202;
365 case ITEM_SUBCLASS_WEAPON_STAFF
: return 227;
366 case ITEM_SUBCLASS_WEAPON_DAGGER
: return 1180;
367 case ITEM_SUBCLASS_WEAPON_THROWN
: return 2567;
368 case ITEM_SUBCLASS_WEAPON_SPEAR
: return 3386;
369 case ITEM_SUBCLASS_WEAPON_CROSSBOW
:return 5011;
370 case ITEM_SUBCLASS_WEAPON_WAND
: return 5009;
373 case ITEM_CLASS_ARMOR
:
374 switch(GetProto()->SubClass
)
376 case ITEM_SUBCLASS_ARMOR_CLOTH
: return 9078;
377 case ITEM_SUBCLASS_ARMOR_LEATHER
: return 9077;
378 case ITEM_SUBCLASS_ARMOR_MAIL
: return 8737;
379 case ITEM_SUBCLASS_ARMOR_PLATE
: return 750;
380 case ITEM_SUBCLASS_ARMOR_SHIELD
: return 9116;
387 int32
Item::GenerateItemRandomPropertyId(uint32 item_id
)
389 ItemPrototype
const *itemProto
= sItemStorage
.LookupEntry
<ItemPrototype
>(item_id
);
394 // item must have one from this field values not null if it can have random enchantments
395 if((!itemProto
->RandomProperty
) && (!itemProto
->RandomSuffix
))
398 // item can have not null only one from field values
399 if((itemProto
->RandomProperty
) && (itemProto
->RandomSuffix
))
401 sLog
.outErrorDb("Item template %u have `RandomProperty`==%u and `RandomSuffix`==%u, but must have one from field =0",itemProto
->ItemId
,itemProto
->RandomProperty
,itemProto
->RandomSuffix
);
405 // RandomProperty case
406 if(itemProto
->RandomProperty
)
408 uint32 randomPropId
= GetItemEnchantMod(itemProto
->RandomProperty
);
409 ItemRandomPropertiesEntry
const *random_id
= sItemRandomPropertiesStore
.LookupEntry(randomPropId
);
412 sLog
.outErrorDb("Enchantment id #%u used but it doesn't have records in 'ItemRandomProperties.dbc'",randomPropId
);
416 return random_id
->ID
;
421 uint32 randomPropId
= GetItemEnchantMod(itemProto
->RandomSuffix
);
422 ItemRandomSuffixEntry
const *random_id
= sItemRandomSuffixStore
.LookupEntry(randomPropId
);
425 sLog
.outErrorDb("Enchantment id #%u used but it doesn't have records in sItemRandomSuffixStore.",randomPropId
);
429 return -int32(random_id
->ID
);
434 void Item::SetItemRandomProperties(int32 randomPropId
)
441 ItemRandomPropertiesEntry
const *item_rand
= sItemRandomPropertiesStore
.LookupEntry(randomPropId
);
444 if(GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID
) != item_rand
->ID
)
446 SetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID
,item_rand
->ID
);
447 SetState(ITEM_CHANGED
);
449 for(uint32 i
= PROP_ENCHANTMENT_SLOT_2
; i
< PROP_ENCHANTMENT_SLOT_2
+ 3; ++i
)
450 SetEnchantment(EnchantmentSlot(i
),item_rand
->enchant_id
[i
- PROP_ENCHANTMENT_SLOT_2
],0,0);
455 ItemRandomSuffixEntry
const *item_rand
= sItemRandomSuffixStore
.LookupEntry(-randomPropId
);
458 if( GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID
)!=(uint32
)(-int32(item_rand
->ID
)) ||
459 !GetUInt32Value(ITEM_FIELD_SUFFIX_FACTOR
))
461 SetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID
,(uint32
)(-int32(item_rand
->ID
)));
462 SetUInt32Value(ITEM_FIELD_SUFFIX_FACTOR
,GenerateEnchSuffixFactor(GetEntry()));
463 SetState(ITEM_CHANGED
);
466 for(uint32 i
= PROP_ENCHANTMENT_SLOT_0
; i
< PROP_ENCHANTMENT_SLOT_0
+ 3; ++i
)
467 SetEnchantment(EnchantmentSlot(i
),item_rand
->enchant_id
[i
- PROP_ENCHANTMENT_SLOT_0
],0,0);
472 void Item::SetState(ItemUpdateState state
, Player
*forplayer
)
474 if (uState
== ITEM_NEW
&& state
== ITEM_REMOVED
)
476 // pretend the item never existed
477 RemoveFromUpdateQueueOf(forplayer
);
482 if (state
!= ITEM_UNCHANGED
)
484 // new items must stay in new state until saved
485 if (uState
!= ITEM_NEW
) uState
= state
;
486 AddToUpdateQueueOf(forplayer
);
491 // the item must be removed from the queue manually
493 uState
= ITEM_UNCHANGED
;
497 void Item::AddToUpdateQueueOf(Player
*player
)
499 if (IsInUpdateQueue()) return;
506 sLog
.outError("Item::AddToUpdateQueueOf - GetPlayer didn't find a player matching owner's guid (%u)!", GUID_LOPART(GetOwnerGUID()));
511 if (player
->GetGUID() != GetOwnerGUID())
513 sLog
.outError("Item::AddToUpdateQueueOf - Owner's guid (%u) and player's guid (%u) don't match!", GUID_LOPART(GetOwnerGUID()), player
->GetGUIDLow());
517 if (player
->m_itemUpdateQueueBlocked
) return;
519 player
->m_itemUpdateQueue
.push_back(this);
520 uQueuePos
= player
->m_itemUpdateQueue
.size()-1;
523 void Item::RemoveFromUpdateQueueOf(Player
*player
)
525 if (!IsInUpdateQueue()) return;
532 sLog
.outError("Item::RemoveFromUpdateQueueOf - GetPlayer didn't find a player matching owner's guid (%u)!", GUID_LOPART(GetOwnerGUID()));
537 if (player
->GetGUID() != GetOwnerGUID())
539 sLog
.outError("Item::RemoveFromUpdateQueueOf - Owner's guid (%u) and player's guid (%u) don't match!", GUID_LOPART(GetOwnerGUID()), player
->GetGUIDLow());
543 if (player
->m_itemUpdateQueueBlocked
) return;
545 player
->m_itemUpdateQueue
[uQueuePos
] = NULL
;
549 uint8
Item::GetBagSlot() const
551 return m_container
? m_container
->GetSlot() : INVENTORY_SLOT_BAG_0
;
554 bool Item::IsEquipped() const
556 return !IsInBag() && m_slot
< EQUIPMENT_SLOT_END
;
559 bool Item::CanBeTraded() const
561 if(HasFlag(ITEM_FIELD_FLAGS
, ITEM_FLAGS_BINDED
) || GetProto()->Class
== ITEM_CLASS_QUEST
)
563 if(IsBag() && !((Bag
*)this)->IsEmpty())
566 if(Player
* owner
= GetOwner())
568 if(owner
->CanUnequipItem(uint16(GetBagSlot()) << 8 | GetSlot(),false) != EQUIP_ERR_OK
)
570 if(owner
->GetLootGUID()==GetGUID())
577 bool Item::CanGoIntoBag(ItemPrototype
const *pBagProto
)
579 ItemPrototype
const *pProto
= GetProto();
581 if(!pProto
|| !pBagProto
)
584 switch(pBagProto
->Class
)
586 case ITEM_CLASS_CONTAINER
:
587 switch(pBagProto
->SubClass
)
589 case ITEM_SUBCLASS_CONTAINER
:
591 case ITEM_SUBCLASS_SOUL_CONTAINER
:
592 if(pProto
->BagFamily
!= BAG_FAMILY_SOUL_SHARDS
)
595 case ITEM_SUBCLASS_HERB_CONTAINER
:
596 if(pProto
->BagFamily
!= BAG_FAMILY_HERBS
)
599 case ITEM_SUBCLASS_ENCHANTING_CONTAINER
:
600 if(pProto
->BagFamily
!= BAG_FAMILY_ENCHANTING_SUPP
)
603 case ITEM_SUBCLASS_MINING_CONTAINER
:
604 if(pProto
->BagFamily
!= BAG_FAMILY_MINING_SUPP
)
607 case ITEM_SUBCLASS_ENGINEERING_CONTAINER
:
608 if(pProto
->BagFamily
!= BAG_FAMILY_ENGINEERING_SUPP
)
611 case ITEM_SUBCLASS_GEM_CONTAINER
:
612 if(pProto
->BagFamily
!= BAG_FAMILY_GEMS
)
618 case ITEM_CLASS_QUIVER
:
619 switch(pBagProto
->SubClass
)
621 case ITEM_SUBCLASS_QUIVER
:
622 if(pProto
->BagFamily
!= BAG_FAMILY_ARROWS
)
625 case ITEM_SUBCLASS_AMMO_POUCH
:
626 if(pProto
->BagFamily
!= BAG_FAMILY_BULLETS
)
636 bool Item::IsFitToSpellRequirements(SpellEntry
const* spellInfo
) const
638 ItemPrototype
const* proto
= GetProto();
640 if (spellInfo
->EquippedItemClass
!= -1) // -1 == any item class
642 if(spellInfo
->EquippedItemClass
!= int32(proto
->Class
))
643 return false; // wrong item class
645 if(spellInfo
->EquippedItemSubClassMask
!= 0) // 0 == any subclass
647 if((spellInfo
->EquippedItemSubClassMask
& (1 << proto
->SubClass
)) == 0)
648 return false; // subclass not present in mask
652 if(spellInfo
->EquippedItemInventoryTypeMask
!= 0) // 0 == any inventory type
654 if((spellInfo
->EquippedItemInventoryTypeMask
& (1 << proto
->InventoryType
)) == 0)
655 return false; // inventory type not present in mask
661 void Item::SetEnchantment(EnchantmentSlot slot
, uint32 id
, uint32 duration
, uint32 charges
)
663 // Better lost small time at check in comparison lost time at item save to DB.
664 if( GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_ID_OFFSET
)==id
&&
665 GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_DURATION_OFFSET
)==duration
&&
666 GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_CHARGES_OFFSET
)==charges
)
669 SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_ID_OFFSET
,id
);
670 SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_DURATION_OFFSET
,duration
);
671 SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_CHARGES_OFFSET
,charges
);
672 SetState(ITEM_CHANGED
);
675 void Item::SetEnchantmentDuration(EnchantmentSlot slot
, uint32 duration
)
677 if(GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_DURATION_OFFSET
)==duration
)
680 SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_DURATION_OFFSET
,duration
);
681 SetState(ITEM_CHANGED
);
684 void Item::SetEnchantmentCharges(EnchantmentSlot slot
, uint32 charges
)
686 SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_CHARGES_OFFSET
,charges
);
687 SetState(ITEM_CHANGED
);
690 void Item::ClearEnchantment(EnchantmentSlot slot
)
692 if(!GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+ENCHANTMENT_ID_OFFSET
))
696 SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+slot
*3+x
,0);
697 SetState(ITEM_CHANGED
);
700 bool Item::GemsFitSockets() const
703 for(uint32 enchant_slot
= SOCK_ENCHANTMENT_SLOT
; enchant_slot
< SOCK_ENCHANTMENT_SLOT
+3; ++enchant_slot
)
705 uint8 SocketColor
= GetProto()->Socket
[enchant_slot
-SOCK_ENCHANTMENT_SLOT
].Color
;
707 uint32 enchant_id
= GetEnchantmentId(EnchantmentSlot(enchant_slot
));
710 if(SocketColor
) fits
&= false;
714 SpellItemEnchantmentEntry
const* enchantEntry
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
717 if(SocketColor
) fits
&= false;
723 uint32 gemid
= enchantEntry
->GemID
;
726 ItemPrototype
const* gemProto
= sItemStorage
.LookupEntry
<ItemPrototype
>(gemid
);
729 GemPropertiesEntry
const* gemProperty
= sGemPropertiesStore
.LookupEntry(gemProto
->GemProperties
);
731 GemColor
= gemProperty
->color
;
735 fits
&= (GemColor
& SocketColor
) ? true : false;
740 uint8
Item::GetGemCountWithID(uint32 GemID
) const
743 for(uint32 enchant_slot
= SOCK_ENCHANTMENT_SLOT
; enchant_slot
< SOCK_ENCHANTMENT_SLOT
+3; ++enchant_slot
)
745 uint32 enchant_id
= GetEnchantmentId(EnchantmentSlot(enchant_slot
));
749 SpellItemEnchantmentEntry
const* enchantEntry
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
753 if(GemID
== enchantEntry
->GemID
)