67 uint8 foundDuplicates = 0;
68 for (std::vector<LootItem>::const_iterator itr =
_loot.
items.begin(); itr !=
_loot.
items.end(); ++itr)
69 if (itr->itemid == item->
itemid)
124 i->second->Verify(*
this, i->first);
131 LootTemplateMap::const_iterator tab;
137 QueryResult result =
WorldDatabase.PQuery(
"SELECT Entry, Item, Reference, Chance, QuestRequired, LootMode, GroupId, MinCount, MaxCount FROM {}",
GetName());
146 Field* fields = result->Fetch();
151 float chance = fields[3].
GetFloat();
152 bool needsquest = fields[4].
GetBool();
158 if (groupid >= 1 << 7)
160 TC_LOG_ERROR(
"sql.sql",
"Table '{}' Entry {} Item {}: GroupId ({}) must be less {} - skipped",
GetName(), entry, item, groupid, 1 << 7);
166 if (!storeitem->
IsValid(*
this, entry))
188 tab->second->AddEntry(storeitem);
191 while (result->NextRow());
205 return itr->second->HasQuestDrop();
212 if (tab->second->HasQuestDropForPlayer(player))
223 itr->second->CopyConditions(empty);
252 lootIdSet.insert(tab->first);
266 for (LootIdSet::const_iterator itr = lootIdSet.begin(); itr != lootIdSet.end(); ++itr)
272 TC_LOG_ERROR(
"sql.sql",
"Table '{}' Entry {} does not exist but it is used by {} {}",
GetName(), lootId, ownerType, ownerId);
310 TC_LOG_ERROR(
"sql.sql",
"Table '{}' Entry {} Item {}: item entry not listed in `item_template` - skipped", store.
GetName(), entry,
itemid);
316 TC_LOG_ERROR(
"sql.sql",
"Table '{}' Entry {} Item {}: equal-chanced grouped entry, but group not defined - skipped", store.
GetName(), entry,
itemid);
322 TC_LOG_ERROR(
"sql.sql",
"Table '{}' Entry {} Item {}: low chance ({}) - skipped",
339 TC_LOG_ERROR(
"sql.sql",
"Table '{}' Entry {} Item {}: zero chance is specified for a reference, skipped", store.
GetName(), entry,
itemid);
369 ExplicitlyChanced.push_back(item);
371 EqualChanced.push_back(item);
380 if (!possibleLoot.empty())
384 for (LootStoreItemList::const_iterator itr = possibleLoot.begin(); itr != possibleLoot.end(); ++itr)
387 if (item->
chance >= 100.0f)
396 possibleLoot = EqualChanced;
398 if (!possibleLoot.empty())
407 for (LootStoreItemList::const_iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
408 if ((*i)->needs_quest)
411 for (LootStoreItemList::const_iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
412 if ((*i)->needs_quest)
421 for (LootStoreItemList::const_iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
425 for (LootStoreItemList::const_iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
434 for (LootStoreItemList::iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
437 for (LootStoreItemList::iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
438 (*i)->conditions.clear();
453 for (LootStoreItemList::const_iterator i=ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
454 if (!(*i)->needs_quest)
455 result += (*i)->chance;
463 float result = RawTotalChance();
465 if (!EqualChanced.empty() && result < 100.0f)
473 float chance = RawTotalChance();
475 TC_LOG_ERROR(
"sql.sql",
"Table '{}' entry {} group {} has total chance > 100% ({})", lootstore.
GetName(),
id, group_id, chance);
477 if (chance >= 100.0f && !EqualChanced.empty())
478 TC_LOG_ERROR(
"sql.sql",
"Table '{}' entry {} group {} has items with chance=0% but group total chance >= 100% ({})", lootstore.
GetName(),
id, group_id, chance);
483 for (LootStoreItemList::const_iterator ieItr = ExplicitlyChanced.begin(); ieItr != ExplicitlyChanced.end(); ++ieItr)
495 for (LootStoreItemList::const_iterator ieItr = EqualChanced.begin(); ieItr != EqualChanced.end(); ++ieItr)
514 for (LootStoreItemList::iterator i =
Entries.begin(); i !=
Entries.end(); ++i)
517 for (
size_t i = 0; i <
Groups.size(); ++i)
539 for (LootStoreItemList::iterator i =
Entries.begin(); i !=
Entries.end(); ++i)
540 (*i)->conditions.clear();
542 for (LootGroups::iterator i =
Groups.begin(); i !=
Groups.end(); ++i)
544 group->CopyConditions(conditions);
550 for (LootStoreItemList::const_iterator _iter =
Entries.begin(); _iter !=
Entries.end(); ++_iter)
566 if (groupId >
Groups.size())
572 Groups[groupId - 1]->Process(loot, lootMode);
577 for (LootStoreItemList::const_iterator i =
Entries.begin(); i !=
Entries.end(); ++i)
583 if (!item->
Roll(rate))
593 for (
uint32 loop = 0; loop < maxcount; ++loop)
601 for (LootGroups::const_iterator i =
Groups.begin(); i !=
Groups.end(); ++i)
603 group->Process(loot, lootMode);
611 if (groupId >
Groups.size())
617 return Groups[groupId-1]->HasQuestDrop();
620 for (LootStoreItemList::const_iterator i =
Entries.begin(); i !=
Entries.end(); ++i)
636 for (LootGroups::const_iterator i =
Groups.begin(); i !=
Groups.end(); ++i)
638 if (group->HasQuestDrop())
649 if (groupId >
Groups.size())
659 for (LootStoreItemList::const_iterator i =
Entries.begin(); i !=
Entries.end(); ++i)
675 for (LootGroups::const_iterator i =
Groups.begin(); i !=
Groups.end(); ++i)
677 if (group->HasQuestDropForPlayer(player))
696 for (LootStoreItemList::const_iterator ieItr =
Entries.begin(); ieItr !=
Entries.end(); ++ieItr)
708 for (LootGroups::const_iterator grItr =
Groups.begin(); grItr !=
Groups.end(); ++grItr)
710 group->CheckLootRefs(store, ref_set);
717 TC_LOG_ERROR(
"loot",
"LootTemplate::addConditionItem: condition is null");
723 for (LootStoreItemList::iterator i =
Entries.begin(); i !=
Entries.end(); ++i)
727 (*i)->conditions.push_back(cond);
735 for (LootGroups::iterator groupItr =
Groups.begin(); groupItr !=
Groups.end(); ++groupItr)
742 if (!itemList->empty())
744 for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
748 (*i)->conditions.push_back(cond);
755 if (!itemList->empty())
757 for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
761 (*i)->conditions.push_back(cond);
773 for (LootStoreItemList::const_iterator ieItr =
Entries.begin(); ieItr !=
Entries.end(); ++ieItr)
774 if ((*ieItr)->itemid ==
id && (*ieItr)->reference > 0)
782 TC_LOG_INFO(
"server.loading",
"Loading creature loot templates...");
791 for (
auto const& creatureTemplatePair : ctc)
793 if (
uint32 lootid = creatureTemplatePair.second.lootid)
795 if (!lootIdSet.count(lootid))
798 lootIdSetUsed.insert(lootid);
802 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
803 lootIdSet.erase(*itr);
814 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature loot templates. DB table `creature_loot_template` is empty");
819 TC_LOG_INFO(
"server.loading",
"Loading disenchanting loot templates...");
827 for (
auto const& itemTemplatePair : its)
829 if (
uint32 lootid = itemTemplatePair.second.DisenchantID)
831 if (!lootIdSet.count(lootid))
834 lootIdSetUsed.insert(lootid);
838 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
839 lootIdSet.erase(*itr);
847 TC_LOG_INFO(
"server.loading",
">> Loaded 0 disenchanting loot templates. DB table `disenchant_loot_template` is empty");
852 TC_LOG_INFO(
"server.loading",
"Loading fishing loot templates...");
861 if (lootIdSet.find(areaTable->ID) != lootIdSet.end())
862 lootIdSet.erase(areaTable->ID);
870 TC_LOG_INFO(
"server.loading",
">> Loaded 0 fishing loot templates. DB table `fishing_loot_template` is empty");
875 TC_LOG_INFO(
"server.loading",
"Loading gameobject loot templates...");
884 for (
auto const& gameObjectTemplatePair : gotc)
886 if (
uint32 lootid = gameObjectTemplatePair.second.GetLootId())
888 if (!lootIdSet.count(lootid))
891 lootIdSetUsed.insert(lootid);
895 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
896 lootIdSet.erase(*itr);
904 TC_LOG_INFO(
"server.loading",
">> Loaded 0 gameobject loot templates. DB table `gameobject_loot_template` is empty");
909 TC_LOG_INFO(
"server.loading",
"Loading item loot templates...");
918 for (
auto const& itemTemplatePair : its)
919 if (lootIdSet.count(itemTemplatePair.first) > 0 && itemTemplatePair.second.HasFlag(
ITEM_FLAG_HAS_LOOT))
920 lootIdSet.erase(itemTemplatePair.first);
928 TC_LOG_INFO(
"server.loading",
">> Loaded 0 item loot templates. DB table `item_loot_template` is empty");
933 TC_LOG_INFO(
"server.loading",
"Loading milling loot templates...");
942 for (
auto const& itemTemplatePair : its)
947 if (lootIdSet.count(itemTemplatePair.first) > 0)
948 lootIdSet.erase(itemTemplatePair.first);
957 TC_LOG_INFO(
"server.loading",
">> Loaded 0 milling loot templates. DB table `milling_loot_template` is empty");
962 TC_LOG_INFO(
"server.loading",
"Loading pickpocketing loot templates...");
971 for (
auto const& creatureTemplatePair : ctc)
973 if (
uint32 lootid = creatureTemplatePair.second.pickpocketLootId)
975 if (!lootIdSet.count(lootid))
978 lootIdSetUsed.insert(lootid);
982 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
983 lootIdSet.erase(*itr);
991 TC_LOG_INFO(
"server.loading",
">> Loaded 0 pickpocketing loot templates. DB table `pickpocketing_loot_template` is empty");
996 TC_LOG_INFO(
"server.loading",
"Loading prospecting loot templates...");
1005 for (
auto const& itemTemplatePair : its)
1010 if (lootIdSet.count(itemTemplatePair.first) > 0)
1011 lootIdSet.erase(itemTemplatePair.first);
1020 TC_LOG_INFO(
"server.loading",
">> Loaded 0 prospecting loot templates. DB table `prospecting_loot_template` is empty");
1025 TC_LOG_INFO(
"server.loading",
"Loading mail loot templates...");
1035 if (lootIdSet.find(i) != lootIdSet.end())
1044 TC_LOG_INFO(
"server.loading",
">> Loaded 0 mail loot templates. DB table `mail_loot_template` is empty");
1049 TC_LOG_INFO(
"server.loading",
"Loading skinning loot templates...");
1058 for (
auto const& creatureTemplatePair : ctc)
1060 if (
uint32 lootid = creatureTemplatePair.second.SkinLootId)
1062 if (!lootIdSet.count(lootid))
1065 lootIdSetUsed.insert(lootid);
1069 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
1070 lootIdSet.erase(*itr);
1078 TC_LOG_INFO(
"server.loading",
">> Loaded 0 skinning loot templates. DB table `skinning_loot_template` is empty");
1083 TC_LOG_INFO(
"server.loading",
"Loading spell loot templates...");
1091 for (
uint32 spell_id = 1; spell_id <
sSpellMgr->GetSpellInfoStoreSize(); ++spell_id)
1101 if (lootIdSet.find(spell_id) == lootIdSet.end())
1109 lootIdSet.erase(spell_id);
1118 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spell loot templates. DB table `spell_loot_template` is empty");
1123 TC_LOG_INFO(
"server.loading",
"Loading reference loot templates...");
std::vector< Condition * > ConditionContainer
DBCStorage< MailTemplateEntry > sMailTemplateStore(MailTemplateEntryfmt)
DBCStorage< AreaTableEntry > sAreaTableStore(AreaTableEntryfmt)
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
@ ITEM_FLAG_IS_PROSPECTABLE
#define TC_LOG_ERROR(filterType__,...)
#define TC_LOG_INFO(filterType__,...)
LootStore LootTemplates_Spell("spell_loot_template", "spell id (random item creating)", false)
LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true)
LootStore LootTemplates_Gameobject("gameobject_loot_template", "gameobject entry", true)
LootStore LootTemplates_Item("item_loot_template", "item entry", true)
LootStore LootTemplates_Milling("milling_loot_template", "item entry (herb)", true)
LootStore LootTemplates_Reference("reference_loot_template", "reference id", false)
LootStore LootTemplates_Disenchant("disenchant_loot_template", "item disenchant id", true)
LootStore LootTemplates_Prospecting("prospecting_loot_template", "item entry (ore)", true)
static Rates const qualityToRate[MAX_ITEM_QUALITY]
LootStore LootTemplates_Creature("creature_loot_template", "creature entry", true)
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template", "creature pickpocket lootid", true)
LootStore LootTemplates_Mail("mail_loot_template", "mail template id", false)
LootStore LootTemplates_Fishing("fishing_loot_template", "area id", true)
TC_GAME_API void LoadLootTemplates_Skinning()
TC_GAME_API LootStore LootTemplates_Reference
TC_GAME_API void LoadLootTemplates_Creature()
TC_GAME_API void LoadLootTemplates_Milling()
TC_GAME_API void LoadLootTemplates_Disenchant()
TC_GAME_API LootStore LootTemplates_Gameobject
TC_GAME_API LootStore LootTemplates_Item
TC_GAME_API LootStore LootTemplates_Prospecting
TC_GAME_API void LoadLootTemplates_Gameobject()
TC_GAME_API LootStore LootTemplates_Skinning
TC_GAME_API void LoadLootTemplates_Pickpocketing()
TC_GAME_API LootStore LootTemplates_Fishing
TC_GAME_API void LoadLootTemplates_Prospecting()
TC_GAME_API LootStore LootTemplates_Disenchant
TC_GAME_API LootStore LootTemplates_Pickpocketing
TC_GAME_API LootStore LootTemplates_Spell
std::unordered_map< uint32, LootTemplate * > LootTemplateMap
TC_GAME_API void LoadLootTemplates_Mail()
TC_GAME_API LootStore LootTemplates_Creature
TC_GAME_API void LoadLootTables()
TC_GAME_API LootStore LootTemplates_Mail
std::set< uint32 > LootIdSet
std::list< LootStoreItem * > LootStoreItemList
TC_GAME_API void LoadLootTemplates_Item()
TC_GAME_API void LoadLootTemplates_Fishing()
TC_GAME_API void LoadLootTemplates_Reference()
TC_GAME_API LootStore LootTemplates_Milling
TC_GAME_API void LoadLootTemplates_Spell()
std::unordered_map< uint32, ItemTemplate > ItemTemplateContainer
std::unordered_map< uint32, GameObjectTemplate > GameObjectTemplateContainer
std::unordered_map< uint32, CreatureTemplate > CreatureTemplateContainer
bool roll_chance_f(float chance)
#define PLAYER_CORPSE_LOOT_ENTRY
@ SPELL_ATTR0_NOT_SHAPESHIFT
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Class used to access individual fields of database query result.
uint32 LoadAndCollectLootIds(LootIdSet &ids_set)
LootTemplate const * GetLootFor(uint32 loot_id) const
LootTemplateMap m_LootTemplates
void ReportNonExistingId(uint32 lootId, char const *ownerType, uint32 ownerId) const
void CheckLootRefs(LootIdSet *ref_set=nullptr) const
char const * GetEntryName() const
bool HaveQuestLootFor(uint32 loot_id) const
LootTemplate * GetLootForConditionFill(uint32 loot_id)
char const * GetName() const
bool HaveQuestLootForPlayer(uint32 loot_id, Player const *player) const
void ReportUnusedIds(LootIdSet const &ids_set) const
void CheckLootRefs(LootTemplateMap const &store, LootIdSet *ref_set) const
LootStoreItemList ExplicitlyChanced
LootStoreItemList * GetEqualChancedItemList()
LootGroup & operator=(LootGroup const &)=delete
void CopyConditions(ConditionContainer conditions)
LootStoreItemList EqualChanced
void Verify(LootStore const &lootstore, uint32 id, uint8 group_id) const
LootStoreItemList * GetExplicitlyChancedItemList()
float RawTotalChance() const
void AddEntry(LootStoreItem *item)
bool HasQuestDropForPlayer(Player const *player) const
void Process(Loot &loot, uint16 lootMode) const
LootGroup(LootGroup const &)=delete
float TotalChance() const
LootStoreItem const * Roll(Loot &loot, uint16 lootMode) const
bool HasQuestDrop() const
void Process(Loot &loot, bool rate, uint16 lootMode, uint8 groupId=0) const
bool HasQuestDropForPlayer(Player const *player, uint8 groupId=0) const
bool HasQuestDrop(uint8 groupId=0) const
void CheckLootRefs(LootTemplateMap const &store, LootIdSet *ref_set) const
bool isReference(uint32 id)
void AddEntry(LootStoreItem *item)
void Verify(LootStore const &store, uint32 Id) const
bool addConditionItem(Condition *cond)
void CopyConditions(ConditionContainer const &conditions)
bool HasQuestForItem(uint32 itemId, uint32 excludeQuestId=0, bool turnIn=false) const
bool IsLootCrafting() const
bool HasAttribute(SpellAttr0 attribute) const
@ RATE_DROP_ITEM_REFERENCED_AMOUNT
@ RATE_DROP_ITEM_LEGENDARY
@ RATE_DROP_ITEM_UNCOMMON
@ RATE_DROP_ITEM_REFERENCED
@ RATE_DROP_ITEM_ARTIFACT
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
bool operator()(LootStoreItem *item) const
LootGroupInvalidSelector(Loot const &loot, uint16 lootMode)
ConditionContainer conditions
bool Roll(bool rate) const
ConditionContainer conditions
bool IsValid(LootStore const &store, uint32 entry) const
void AddItem(LootStoreItem const &item)
std::vector< LootItem > items