TrinityCore
Loading...
Searching...
No Matches
LootMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore 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 "LootMgr.h"
19#include "Containers.h"
20#include "DatabaseEnv.h"
21#include "DBCStores.h"
22#include "Group.h"
23#include "Log.h"
24#include "Loot.h"
25#include "ObjectMgr.h"
26#include "Player.h"
27#include "SharedDefines.h"
28#include "SpellInfo.h"
29#include "SpellMgr.h"
30#include "Util.h"
31#include "World.h"
32
34{
35 RATE_DROP_ITEM_POOR, // ITEM_QUALITY_POOR
36 RATE_DROP_ITEM_NORMAL, // ITEM_QUALITY_NORMAL
37 RATE_DROP_ITEM_UNCOMMON, // ITEM_QUALITY_UNCOMMON
38 RATE_DROP_ITEM_RARE, // ITEM_QUALITY_RARE
39 RATE_DROP_ITEM_EPIC, // ITEM_QUALITY_EPIC
40 RATE_DROP_ITEM_LEGENDARY, // ITEM_QUALITY_LEGENDARY
41 RATE_DROP_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT
42};
43
44LootStore LootTemplates_Creature("creature_loot_template", "creature entry", true);
45LootStore LootTemplates_Disenchant("disenchant_loot_template", "item disenchant id", true);
46LootStore LootTemplates_Fishing("fishing_loot_template", "area id", true);
47LootStore LootTemplates_Gameobject("gameobject_loot_template", "gameobject entry", true);
48LootStore LootTemplates_Item("item_loot_template", "item entry", true);
49LootStore LootTemplates_Mail("mail_loot_template", "mail template id", false);
50LootStore LootTemplates_Milling("milling_loot_template", "item entry (herb)", true);
51LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template", "creature pickpocket lootid", true);
52LootStore LootTemplates_Prospecting("prospecting_loot_template", "item entry (ore)", true);
53LootStore LootTemplates_Reference("reference_loot_template", "reference id", false);
54LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true);
55LootStore LootTemplates_Spell("spell_loot_template", "spell id (random item creating)", false);
56
57// Selects invalid loot items to be removed from group possible entries (before rolling)
59{
60 explicit LootGroupInvalidSelector(Loot const& loot, uint16 lootMode) : _loot(loot), _lootMode(lootMode) { }
61
62 bool operator()(LootStoreItem* item) const
63 {
64 if (!(item->lootmode & _lootMode))
65 return true;
66
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)
70 if (++foundDuplicates == _loot.maxDuplicates)
71 return true;
72
73 return false;
74 }
75
76private:
77 Loot const& _loot;
79};
80
81class LootTemplate::LootGroup // A set of loot definitions for items (refs are not allowed)
82{
83 public:
85 ~LootGroup();
86
87 void AddEntry(LootStoreItem* item); // Adds an entry to the group (at loading stage)
88 bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry
89 bool HasQuestDropForPlayer(Player const* player) const;
90 // The same for active quests of the player
91 void Process(Loot& loot, uint16 lootMode) const; // Rolls an item from the group (if any) and adds the item to the loot
92 float RawTotalChance() const; // Overall chance for the group (without equal chanced items)
93 float TotalChance() const; // Overall chance for the group
94
95 void Verify(LootStore const& lootstore, uint32 id, uint8 group_id) const;
96 void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const;
99 void CopyConditions(ConditionContainer conditions);
100 private:
101 LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB
102 LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance
103
104 LootStoreItem const* Roll(Loot& loot, uint16 lootMode) const; // Rolls an item from the group, returns NULL if all miss their chances
105
106 // This class must never be copied - storing pointers
107 LootGroup(LootGroup const&) = delete;
108 LootGroup& operator=(LootGroup const&) = delete;
109};
110
111//Remove all data and free all memory
113{
114 for (LootTemplateMap::const_iterator itr = m_LootTemplates.begin(); itr != m_LootTemplates.end(); ++itr)
115 delete itr->second;
116 m_LootTemplates.clear();
117}
118
119// Checks validity of the loot store
120// Actual checks are done within LootTemplate::Verify() which is called for every template
122{
123 for (LootTemplateMap::const_iterator i = m_LootTemplates.begin(); i != m_LootTemplates.end(); ++i)
124 i->second->Verify(*this, i->first);
125}
126
127// Loads a *_loot_template DB table into loot store
128// All checks of the loaded template are called from here, no error reports at loot generation required
130{
131 LootTemplateMap::const_iterator tab;
132
133 // Clearing store (for reloading case)
134 Clear();
135
136 // 0 1 2 3 4 5 6
137 QueryResult result = WorldDatabase.PQuery("SELECT Entry, Item, Reference, Chance, QuestRequired, LootMode, GroupId, MinCount, MaxCount FROM {}", GetName());
138
139 if (!result)
140 return 0;
141
142 uint32 count = 0;
143
144 do
145 {
146 Field* fields = result->Fetch();
147
148 uint32 entry = fields[0].GetUInt32();
149 uint32 item = fields[1].GetUInt32();
150 uint32 reference = fields[2].GetUInt32();
151 float chance = fields[3].GetFloat();
152 bool needsquest = fields[4].GetBool();
153 uint16 lootmode = fields[5].GetUInt16();
154 uint8 groupid = fields[6].GetUInt8();
155 uint8 mincount = fields[7].GetUInt8();
156 uint8 maxcount = fields[8].GetUInt8();
157
158 if (groupid >= 1 << 7) // it stored in 7 bit field
159 {
160 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} Item {}: GroupId ({}) must be less {} - skipped", GetName(), entry, item, groupid, 1 << 7);
161 return 0;
162 }
163
164 LootStoreItem* storeitem = new LootStoreItem(item, reference, chance, needsquest, lootmode, groupid, mincount, maxcount);
165
166 if (!storeitem->IsValid(*this, entry)) // Validity checks
167 {
168 delete storeitem;
169 continue;
170 }
171
172 // Looking for the template of the entry
173 // often entries are put together
174 if (m_LootTemplates.empty() || tab->first != entry)
175 {
176 // Searching the template (in case template Id changed)
177 tab = m_LootTemplates.find(entry);
178 if (tab == m_LootTemplates.end())
179 {
180 std::pair< LootTemplateMap::iterator, bool > pr = m_LootTemplates.insert(LootTemplateMap::value_type(entry, new LootTemplate()));
181 tab = pr.first;
182 }
183 }
184 // else is empty - template Id and iter are the same
185 // finally iter refers to already existed or just created <entry, LootTemplate>
186
187 // Adds current row to the template
188 tab->second->AddEntry(storeitem);
189 ++count;
190 }
191 while (result->NextRow());
192
193 Verify(); // Checks validity of the loot store
194
195 return count;
196}
197
199{
200 LootTemplateMap::const_iterator itr = m_LootTemplates.find(loot_id);
201 if (itr == m_LootTemplates.end())
202 return false;
203
204 // scan loot for quest items
205 return itr->second->HasQuestDrop();
206}
207
208bool LootStore::HaveQuestLootForPlayer(uint32 loot_id, Player const* player) const
209{
210 LootTemplateMap::const_iterator tab = m_LootTemplates.find(loot_id);
211 if (tab != m_LootTemplates.end())
212 if (tab->second->HasQuestDropForPlayer(player))
213 return true;
214
215 return false;
216}
217
219{
220 for (LootTemplateMap::iterator itr = m_LootTemplates.begin(); itr != m_LootTemplates.end(); ++itr)
221 {
222 ConditionContainer empty;
223 itr->second->CopyConditions(empty);
224 }
225}
226
228{
229 LootTemplateMap::const_iterator tab = m_LootTemplates.find(loot_id);
230
231 if (tab == m_LootTemplates.end())
232 return nullptr;
233
234 return tab->second;
235}
236
238{
239 LootTemplateMap::iterator tab = m_LootTemplates.find(loot_id);
240
241 if (tab == m_LootTemplates.end())
242 return nullptr;
243
244 return tab->second;
245}
246
248{
249 uint32 count = LoadLootTable();
250
251 for (LootTemplateMap::const_iterator tab = m_LootTemplates.begin(); tab != m_LootTemplates.end(); ++tab)
252 lootIdSet.insert(tab->first);
253
254 return count;
255}
256
258{
259 for (LootTemplateMap::const_iterator ltItr = m_LootTemplates.begin(); ltItr != m_LootTemplates.end(); ++ltItr)
260 ltItr->second->CheckLootRefs(m_LootTemplates, ref_set);
261}
262
263void LootStore::ReportUnusedIds(LootIdSet const& lootIdSet) const
264{
265 // all still listed ids isn't referenced
266 for (LootIdSet::const_iterator itr = lootIdSet.begin(); itr != lootIdSet.end(); ++itr)
267 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} isn't {} and not referenced from loot, and thus useless.", GetName(), *itr, GetEntryName());
268}
269
270void LootStore::ReportNonExistingId(uint32 lootId, char const* ownerType, uint32 ownerId) const
271{
272 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} does not exist but it is used by {} {}", GetName(), lootId, ownerType, ownerId);
273}
274
275//
276// --------- LootStoreItem ---------
277//
278
279// Checks if the entry (quest, non-quest, reference) takes it's chance (at loot generation)
280// RATE_DROP_ITEMS is no longer used for all types of entries
281bool LootStoreItem::Roll(bool rate) const
282{
283 if (chance >= 100.0f)
284 return true;
285
286 if (reference > 0) // reference case
287 return roll_chance_f(chance* (rate ? sWorld->getRate(RATE_DROP_ITEM_REFERENCED) : 1.0f));
288
289 ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
290
291 float qualityModifier = pProto && rate ? sWorld->getRate(qualityToRate[pProto->Quality]) : 1.0f;
292
293 return roll_chance_f(chance*qualityModifier);
294}
295
296// Checks correctness of values
297bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const
298{
299 if (mincount == 0)
300 {
301 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} Item {}: wrong MinCount ({}) - skipped", store.GetName(), entry, itemid, mincount);
302 return false;
303 }
304
305 if (reference == 0) // item (quest or non-quest) entry, maybe grouped
306 {
307 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemid);
308 if (!proto)
309 {
310 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} Item {}: item entry not listed in `item_template` - skipped", store.GetName(), entry, itemid);
311 return false;
312 }
313
314 if (chance == 0 && groupid == 0) // Zero chance is allowed for grouped entries only
315 {
316 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} Item {}: equal-chanced grouped entry, but group not defined - skipped", store.GetName(), entry, itemid);
317 return false;
318 }
319
320 if (chance != 0 && chance < 0.000001f) // loot with low chance
321 {
322 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} Item {}: low chance ({}) - skipped",
323 store.GetName(), entry, itemid, chance);
324 return false;
325 }
326
327 if (maxcount < mincount) // wrong max count
328 {
329 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} Item {}: MaxCount ({}) less that MinCount ({}) - skipped", store.GetName(), entry, itemid, int32(maxcount), mincount);
330 return false;
331 }
332 }
333 else // if reference loot
334 {
335 if (needs_quest)
336 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} Item {}: quest required will be ignored", store.GetName(), entry, itemid);
337 else if (chance == 0) // no chance for the reference
338 {
339 TC_LOG_ERROR("sql.sql", "Table '{}' Entry {} Item {}: zero chance is specified for a reference, skipped", store.GetName(), entry, itemid);
340 return false;
341 }
342 }
343 return true; // Referenced template existence is checked at whole store level
344}
345
346//
347// --------- LootTemplate::LootGroup ---------
348//
349
351{
352 while (!ExplicitlyChanced.empty())
353 {
354 delete ExplicitlyChanced.back();
355 ExplicitlyChanced.pop_back();
356 }
357
358 while (!EqualChanced.empty())
359 {
360 delete EqualChanced.back();
361 EqualChanced.pop_back();
362 }
363}
364
365// Adds an entry to the group (at loading stage)
367{
368 if (item->chance != 0)
369 ExplicitlyChanced.push_back(item);
370 else
371 EqualChanced.push_back(item);
372}
373
374// Rolls an item from the group, returns NULL if all miss their chances
376{
377 LootStoreItemList possibleLoot = ExplicitlyChanced;
378 possibleLoot.remove_if(LootGroupInvalidSelector(loot, lootMode));
379
380 if (!possibleLoot.empty()) // First explicitly chanced entries are checked
381 {
382 float roll = (float)rand_chance();
383
384 for (LootStoreItemList::const_iterator itr = possibleLoot.begin(); itr != possibleLoot.end(); ++itr) // check each explicitly chanced entry in the template and modify its chance based on quality.
385 {
386 LootStoreItem* item = *itr;
387 if (item->chance >= 100.0f)
388 return item;
389
390 roll -= item->chance;
391 if (roll < 0)
392 return item;
393 }
394 }
395
396 possibleLoot = EqualChanced;
397 possibleLoot.remove_if(LootGroupInvalidSelector(loot, lootMode));
398 if (!possibleLoot.empty()) // If nothing selected yet - an item is taken from equal-chanced part
400
401 return nullptr; // Empty drop from the group
402}
403
404// True if group includes at least 1 quest drop entry
406{
407 for (LootStoreItemList::const_iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
408 if ((*i)->needs_quest)
409 return true;
410
411 for (LootStoreItemList::const_iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
412 if ((*i)->needs_quest)
413 return true;
414
415 return false;
416}
417
418// True if group includes at least 1 quest drop entry for active quests of the player
420{
421 for (LootStoreItemList::const_iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
422 if (player->HasQuestForItem((*i)->itemid))
423 return true;
424
425 for (LootStoreItemList::const_iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
426 if (player->HasQuestForItem((*i)->itemid))
427 return true;
428
429 return false;
430}
431
433{
434 for (LootStoreItemList::iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
435 (*i)->conditions.clear();
436
437 for (LootStoreItemList::iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
438 (*i)->conditions.clear();
439}
440
441// Rolls an item from the group (if any takes its chance) and adds the item to the loot
443{
444 if (LootStoreItem const* item = Roll(loot, lootMode))
445 loot.AddItem(*item);
446}
447
448// Overall chance for the group without equal chanced items
450{
451 float result = 0;
452
453 for (LootStoreItemList::const_iterator i=ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
454 if (!(*i)->needs_quest)
455 result += (*i)->chance;
456
457 return result;
458}
459
460// Overall chance for the group
462{
463 float result = RawTotalChance();
464
465 if (!EqualChanced.empty() && result < 100.0f)
466 return 100.0f;
467
468 return result;
469}
470
471void LootTemplate::LootGroup::Verify(LootStore const& lootstore, uint32 id, uint8 group_id) const
472{
473 float chance = RawTotalChance();
474 if (chance > 101.0f)
475 TC_LOG_ERROR("sql.sql", "Table '{}' entry {} group {} has total chance > 100% ({})", lootstore.GetName(), id, group_id, chance);
476
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);
479}
480
482{
483 for (LootStoreItemList::const_iterator ieItr = ExplicitlyChanced.begin(); ieItr != ExplicitlyChanced.end(); ++ieItr)
484 {
485 LootStoreItem* item = *ieItr;
486 if (item->reference > 0)
487 {
490 else if (ref_set)
491 ref_set->erase(item->reference);
492 }
493 }
494
495 for (LootStoreItemList::const_iterator ieItr = EqualChanced.begin(); ieItr != EqualChanced.end(); ++ieItr)
496 {
497 LootStoreItem* item = *ieItr;
498 if (item->reference > 0)
499 {
502 else if (ref_set)
503 ref_set->erase(item->reference);
504 }
505 }
506}
507
508//
509// --------- LootTemplate ---------
510//
511
513{
514 for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
515 delete *i;
516
517 for (size_t i = 0; i < Groups.size(); ++i)
518 delete Groups[i];
519}
520
521// Adds an entry to the group (at loading stage)
523{
524 if (item->groupid > 0 && item->reference == 0) // Group
525 {
526 if (item->groupid >= Groups.size())
527 Groups.resize(item->groupid, nullptr); // Adds new group the the loot template if needed
528 if (!Groups[item->groupid - 1])
529 Groups[item->groupid - 1] = new LootGroup();
530
531 Groups[item->groupid - 1]->AddEntry(item); // Adds new entry to the group
532 }
533 else // Non-grouped entries and references are stored together
534 Entries.push_back(item);
535}
536
538{
539 for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
540 (*i)->conditions.clear();
541
542 for (LootGroups::iterator i = Groups.begin(); i != Groups.end(); ++i)
543 if (LootGroup* group = *i)
544 group->CopyConditions(conditions);
545}
546
548{
549 // Copies the conditions list from a template item to a LootItem
550 for (LootStoreItemList::const_iterator _iter = Entries.begin(); _iter != Entries.end(); ++_iter)
551 {
552 LootStoreItem* item = *_iter;
553 if (item->itemid != li->itemid)
554 continue;
555
556 li->conditions = item->conditions;
557 break;
558 }
559}
560
561// Rolls for every item in the template and adds the rolled items the the loot
562void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId) const
563{
564 if (groupId) // Group reference uses own processing of the group
565 {
566 if (groupId > Groups.size())
567 return; // Error message already printed at loading stage
568
569 if (!Groups[groupId - 1])
570 return;
571
572 Groups[groupId - 1]->Process(loot, lootMode);
573 return;
574 }
575
576 // Rolling non-grouped items
577 for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i)
578 {
579 LootStoreItem* item = *i;
580 if (!(item->lootmode & lootMode)) // Do not add if mode mismatch
581 continue;
582
583 if (!item->Roll(rate))
584 continue; // Bad luck for the entry
585
586 if (item->reference > 0) // References processing
587 {
588 LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(item->reference);
589 if (!Referenced)
590 continue; // Error message already printed at loading stage
591
592 uint32 maxcount = uint32(float(item->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT));
593 for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator
594 Referenced->Process(loot, rate, lootMode, item->groupid);
595 }
596 else // Plain entries (not a reference, not grouped)
597 loot.AddItem(*item); // Chance is already checked, just add
598 }
599
600 // Now processing groups
601 for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
602 if (LootGroup* group = *i)
603 group->Process(loot, lootMode);
604}
605
606// True if template includes at least 1 quest drop entry
608{
609 if (groupId) // Group reference
610 {
611 if (groupId > Groups.size())
612 return false; // Error message [should be] already printed at loading stage
613
614 if (!Groups[groupId - 1])
615 return false;
616
617 return Groups[groupId-1]->HasQuestDrop();
618 }
619
620 for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i)
621 {
622 LootStoreItem* item = *i;
623 if (item->reference > 0) // References
624 {
625 LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(item->reference);
626 if (!Referenced)
627 continue; // Error message [should be] already printed at loading stage
628 if (Referenced->HasQuestDrop(item->groupid))
629 return true;
630 }
631 else if (item->needs_quest)
632 return true; // quest drop found
633 }
634
635 // Now processing groups
636 for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
637 if (LootGroup* group = *i)
638 if (group->HasQuestDrop())
639 return true;
640
641 return false;
642}
643
644// True if template includes at least 1 quest drop for an active quest of the player
645bool LootTemplate::HasQuestDropForPlayer(Player const* player, uint8 groupId) const
646{
647 if (groupId) // Group reference
648 {
649 if (groupId > Groups.size())
650 return false; // Error message already printed at loading stage
651
652 if (!Groups[groupId - 1])
653 return false;
654
655 return Groups[groupId - 1]->HasQuestDropForPlayer(player);
656 }
657
658 // Checking non-grouped entries
659 for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i)
660 {
661 LootStoreItem* item = *i;
662 if (item->reference > 0) // References processing
663 {
664 LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(item->reference);
665 if (!Referenced)
666 continue; // Error message already printed at loading stage
667 if (Referenced->HasQuestDropForPlayer(player, item->groupid))
668 return true;
669 }
670 else if (player->HasQuestForItem(item->itemid))
671 return true; // active quest drop found
672 }
673
674 // Now checking groups
675 for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
676 if (LootGroup* group = *i)
677 if (group->HasQuestDropForPlayer(player))
678 return true;
679
680 return false;
681}
682
683// Checks integrity of the template
684void LootTemplate::Verify(LootStore const& lootstore, uint32 id) const
685{
686 // Checking group chances
687 for (uint32 i = 0; i < Groups.size(); ++i)
688 if (Groups[i])
689 Groups[i]->Verify(lootstore, id, i + 1);
690
692}
693
694void LootTemplate::CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const
695{
696 for (LootStoreItemList::const_iterator ieItr = Entries.begin(); ieItr != Entries.end(); ++ieItr)
697 {
698 LootStoreItem* item = *ieItr;
699 if (item->reference > 0)
700 {
703 else if (ref_set)
704 ref_set->erase(item->reference);
705 }
706 }
707
708 for (LootGroups::const_iterator grItr = Groups.begin(); grItr != Groups.end(); ++grItr)
709 if (LootGroup* group = *grItr)
710 group->CheckLootRefs(store, ref_set);
711}
712
714{
715 if (!cond || !cond->isLoaded())//should never happen, checked at loading
716 {
717 TC_LOG_ERROR("loot", "LootTemplate::addConditionItem: condition is null");
718 return false;
719 }
720
721 if (!Entries.empty())
722 {
723 for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
724 {
725 if ((*i)->itemid == uint32(cond->SourceEntry))
726 {
727 (*i)->conditions.push_back(cond);
728 return true;
729 }
730 }
731 }
732
733 if (!Groups.empty())
734 {
735 for (LootGroups::iterator groupItr = Groups.begin(); groupItr != Groups.end(); ++groupItr)
736 {
737 LootGroup* group = *groupItr;
738 if (!group)
739 continue;
740
742 if (!itemList->empty())
743 {
744 for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
745 {
746 if ((*i)->itemid == uint32(cond->SourceEntry))
747 {
748 (*i)->conditions.push_back(cond);
749 return true;
750 }
751 }
752 }
753
754 itemList = group->GetEqualChancedItemList();
755 if (!itemList->empty())
756 {
757 for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
758 {
759 if ((*i)->itemid == uint32(cond->SourceEntry))
760 {
761 (*i)->conditions.push_back(cond);
762 return true;
763 }
764 }
765 }
766 }
767 }
768 return false;
769}
770
772{
773 for (LootStoreItemList::const_iterator ieItr = Entries.begin(); ieItr != Entries.end(); ++ieItr)
774 if ((*ieItr)->itemid == id && (*ieItr)->reference > 0)
775 return true;
776
777 return false;//not found or not reference
778}
779
781{
782 TC_LOG_INFO("server.loading", "Loading creature loot templates...");
783
784 uint32 oldMSTime = getMSTime();
785
786 LootIdSet lootIdSet, lootIdSetUsed;
788
789 // Remove real entries and check loot existence
790 CreatureTemplateContainer const& ctc = sObjectMgr->GetCreatureTemplates();
791 for (auto const& creatureTemplatePair : ctc)
792 {
793 if (uint32 lootid = creatureTemplatePair.second.lootid)
794 {
795 if (!lootIdSet.count(lootid))
796 LootTemplates_Creature.ReportNonExistingId(lootid, "Creature", creatureTemplatePair.first);
797 else
798 lootIdSetUsed.insert(lootid);
799 }
800 }
801
802 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
803 lootIdSet.erase(*itr);
804
805 // 1 means loot for player corpse
806 lootIdSet.erase(PLAYER_CORPSE_LOOT_ENTRY);
807
808 // output error for any still listed (not referenced from appropriate table) ids
810
811 if (count)
812 TC_LOG_INFO("server.loading", ">> Loaded {} creature loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
813 else
814 TC_LOG_INFO("server.loading", ">> Loaded 0 creature loot templates. DB table `creature_loot_template` is empty");
815}
816
818{
819 TC_LOG_INFO("server.loading", "Loading disenchanting loot templates...");
820
821 uint32 oldMSTime = getMSTime();
822
823 LootIdSet lootIdSet, lootIdSetUsed;
825
826 ItemTemplateContainer const& its = sObjectMgr->GetItemTemplateStore();
827 for (auto const& itemTemplatePair : its)
828 {
829 if (uint32 lootid = itemTemplatePair.second.DisenchantID)
830 {
831 if (!lootIdSet.count(lootid))
832 LootTemplates_Disenchant.ReportNonExistingId(lootid, "Item", itemTemplatePair.first);
833 else
834 lootIdSetUsed.insert(lootid);
835 }
836 }
837
838 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
839 lootIdSet.erase(*itr);
840
841 // output error for any still listed (not referenced from appropriate table) ids
843
844 if (count)
845 TC_LOG_INFO("server.loading", ">> Loaded {} disenchanting loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
846 else
847 TC_LOG_INFO("server.loading", ">> Loaded 0 disenchanting loot templates. DB table `disenchant_loot_template` is empty");
848}
849
851{
852 TC_LOG_INFO("server.loading", "Loading fishing loot templates...");
853
854 uint32 oldMSTime = getMSTime();
855
856 LootIdSet lootIdSet;
858
859 // remove real entries and check existence loot
860 for (AreaTableEntry const* areaTable : sAreaTableStore)
861 if (lootIdSet.find(areaTable->ID) != lootIdSet.end())
862 lootIdSet.erase(areaTable->ID);
863
864 // output error for any still listed (not referenced from appropriate table) ids
866
867 if (count)
868 TC_LOG_INFO("server.loading", ">> Loaded {} fishing loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
869 else
870 TC_LOG_INFO("server.loading", ">> Loaded 0 fishing loot templates. DB table `fishing_loot_template` is empty");
871}
872
874{
875 TC_LOG_INFO("server.loading", "Loading gameobject loot templates...");
876
877 uint32 oldMSTime = getMSTime();
878
879 LootIdSet lootIdSet, lootIdSetUsed;
881
882 // remove real entries and check existence loot
883 GameObjectTemplateContainer const& gotc = sObjectMgr->GetGameObjectTemplates();
884 for (auto const& gameObjectTemplatePair : gotc)
885 {
886 if (uint32 lootid = gameObjectTemplatePair.second.GetLootId())
887 {
888 if (!lootIdSet.count(lootid))
889 LootTemplates_Gameobject.ReportNonExistingId(lootid, "Gameobject", gameObjectTemplatePair.first);
890 else
891 lootIdSetUsed.insert(lootid);
892 }
893 }
894
895 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
896 lootIdSet.erase(*itr);
897
898 // output error for any still listed (not referenced from appropriate table) ids
900
901 if (count)
902 TC_LOG_INFO("server.loading", ">> Loaded {} gameobject loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
903 else
904 TC_LOG_INFO("server.loading", ">> Loaded 0 gameobject loot templates. DB table `gameobject_loot_template` is empty");
905}
906
908{
909 TC_LOG_INFO("server.loading", "Loading item loot templates...");
910
911 uint32 oldMSTime = getMSTime();
912
913 LootIdSet lootIdSet;
915
916 // remove real entries and check existence loot
917 ItemTemplateContainer const& its = sObjectMgr->GetItemTemplateStore();
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);
921
922 // output error for any still listed (not referenced from appropriate table) ids
924
925 if (count)
926 TC_LOG_INFO("server.loading", ">> Loaded {} item loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
927 else
928 TC_LOG_INFO("server.loading", ">> Loaded 0 item loot templates. DB table `item_loot_template` is empty");
929}
930
932{
933 TC_LOG_INFO("server.loading", "Loading milling loot templates...");
934
935 uint32 oldMSTime = getMSTime();
936
937 LootIdSet lootIdSet;
939
940 // remove real entries and check existence loot
941 ItemTemplateContainer const& its = sObjectMgr->GetItemTemplateStore();
942 for (auto const& itemTemplatePair : its)
943 {
944 if (!itemTemplatePair.second.HasFlag(ITEM_FLAG_IS_MILLABLE))
945 continue;
946
947 if (lootIdSet.count(itemTemplatePair.first) > 0)
948 lootIdSet.erase(itemTemplatePair.first);
949 }
950
951 // output error for any still listed (not referenced from appropriate table) ids
953
954 if (count)
955 TC_LOG_INFO("server.loading", ">> Loaded {} milling loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
956 else
957 TC_LOG_INFO("server.loading", ">> Loaded 0 milling loot templates. DB table `milling_loot_template` is empty");
958}
959
961{
962 TC_LOG_INFO("server.loading", "Loading pickpocketing loot templates...");
963
964 uint32 oldMSTime = getMSTime();
965
966 LootIdSet lootIdSet, lootIdSetUsed;
968
969 // Remove real entries and check loot existence
970 CreatureTemplateContainer const& ctc = sObjectMgr->GetCreatureTemplates();
971 for (auto const& creatureTemplatePair : ctc)
972 {
973 if (uint32 lootid = creatureTemplatePair.second.pickpocketLootId)
974 {
975 if (!lootIdSet.count(lootid))
976 LootTemplates_Pickpocketing.ReportNonExistingId(lootid, "Creature", creatureTemplatePair.first);
977 else
978 lootIdSetUsed.insert(lootid);
979 }
980 }
981
982 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
983 lootIdSet.erase(*itr);
984
985 // output error for any still listed (not referenced from appropriate table) ids
987
988 if (count)
989 TC_LOG_INFO("server.loading", ">> Loaded {} pickpocketing loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
990 else
991 TC_LOG_INFO("server.loading", ">> Loaded 0 pickpocketing loot templates. DB table `pickpocketing_loot_template` is empty");
992}
993
995{
996 TC_LOG_INFO("server.loading", "Loading prospecting loot templates...");
997
998 uint32 oldMSTime = getMSTime();
999
1000 LootIdSet lootIdSet;
1002
1003 // remove real entries and check existence loot
1004 ItemTemplateContainer const& its = sObjectMgr->GetItemTemplateStore();
1005 for (auto const& itemTemplatePair : its)
1006 {
1007 if (!itemTemplatePair.second.HasFlag(ITEM_FLAG_IS_PROSPECTABLE))
1008 continue;
1009
1010 if (lootIdSet.count(itemTemplatePair.first) > 0)
1011 lootIdSet.erase(itemTemplatePair.first);
1012 }
1013
1014 // output error for any still listed (not referenced from appropriate table) ids
1016
1017 if (count)
1018 TC_LOG_INFO("server.loading", ">> Loaded {} prospecting loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
1019 else
1020 TC_LOG_INFO("server.loading", ">> Loaded 0 prospecting loot templates. DB table `prospecting_loot_template` is empty");
1021}
1022
1024{
1025 TC_LOG_INFO("server.loading", "Loading mail loot templates...");
1026
1027 uint32 oldMSTime = getMSTime();
1028
1029 LootIdSet lootIdSet;
1031
1032 // remove real entries and check existence loot
1033 for (uint32 i = 1; i < sMailTemplateStore.GetNumRows(); ++i)
1034 if (sMailTemplateStore.LookupEntry(i))
1035 if (lootIdSet.find(i) != lootIdSet.end())
1036 lootIdSet.erase(i);
1037
1038 // output error for any still listed (not referenced from appropriate table) ids
1040
1041 if (count)
1042 TC_LOG_INFO("server.loading", ">> Loaded {} mail loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
1043 else
1044 TC_LOG_INFO("server.loading", ">> Loaded 0 mail loot templates. DB table `mail_loot_template` is empty");
1045}
1046
1048{
1049 TC_LOG_INFO("server.loading", "Loading skinning loot templates...");
1050
1051 uint32 oldMSTime = getMSTime();
1052
1053 LootIdSet lootIdSet, lootIdSetUsed;
1055
1056 // remove real entries and check existence loot
1057 CreatureTemplateContainer const& ctc = sObjectMgr->GetCreatureTemplates();
1058 for (auto const& creatureTemplatePair : ctc)
1059 {
1060 if (uint32 lootid = creatureTemplatePair.second.SkinLootId)
1061 {
1062 if (!lootIdSet.count(lootid))
1063 LootTemplates_Skinning.ReportNonExistingId(lootid, "Creature", creatureTemplatePair.first);
1064 else
1065 lootIdSetUsed.insert(lootid);
1066 }
1067 }
1068
1069 for (LootIdSet::const_iterator itr = lootIdSetUsed.begin(); itr != lootIdSetUsed.end(); ++itr)
1070 lootIdSet.erase(*itr);
1071
1072 // output error for any still listed (not referenced from appropriate table) ids
1074
1075 if (count)
1076 TC_LOG_INFO("server.loading", ">> Loaded {} skinning loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
1077 else
1078 TC_LOG_INFO("server.loading", ">> Loaded 0 skinning loot templates. DB table `skinning_loot_template` is empty");
1079}
1080
1082{
1083 TC_LOG_INFO("server.loading", "Loading spell loot templates...");
1084
1085 uint32 oldMSTime = getMSTime();
1086
1087 LootIdSet lootIdSet;
1089
1090 // remove real entries and check existence loot
1091 for (uint32 spell_id = 1; spell_id < sSpellMgr->GetSpellInfoStoreSize(); ++spell_id)
1092 {
1093 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
1094 if (!spellInfo)
1095 continue;
1096
1097 // possible cases
1098 if (!spellInfo->IsLootCrafting())
1099 continue;
1100
1101 if (lootIdSet.find(spell_id) == lootIdSet.end())
1102 {
1103 // not report about not trainable spells (optionally supported by DB)
1104 // ignore 61756 (Northrend Inscription Research (FAST QA VERSION) for example
1106 LootTemplates_Spell.ReportNonExistingId(spell_id, "Spell", spellInfo->Id);
1107 }
1108 else
1109 lootIdSet.erase(spell_id);
1110 }
1111
1112 // output error for any still listed (not referenced from appropriate table) ids
1114
1115 if (count)
1116 TC_LOG_INFO("server.loading", ">> Loaded {} spell loot templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
1117 else
1118 TC_LOG_INFO("server.loading", ">> Loaded 0 spell loot templates. DB table `spell_loot_template` is empty");
1119}
1120
1122{
1123 TC_LOG_INFO("server.loading", "Loading reference loot templates...");
1124
1125 uint32 oldMSTime = getMSTime();
1126
1127 LootIdSet lootIdSet;
1129
1130 // check references and remove used
1142
1143 // output error for any still listed ids (not referenced from any loot table)
1145
1146 TC_LOG_INFO("server.loading", ">> Loaded reference loot templates in {} ms", GetMSTimeDiffToNow(oldMSTime));
1147}
1148
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.
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
@ ITEM_FLAG_IS_MILLABLE
@ ITEM_FLAG_IS_PROSPECTABLE
@ ITEM_FLAG_HAS_LOOT
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition Log.h:159
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]
Definition LootMgr.cpp:33
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()
Definition LootMgr.cpp:1047
TC_GAME_API LootStore LootTemplates_Reference
TC_GAME_API void LoadLootTemplates_Creature()
Definition LootMgr.cpp:780
TC_GAME_API void LoadLootTemplates_Milling()
Definition LootMgr.cpp:931
TC_GAME_API void LoadLootTemplates_Disenchant()
Definition LootMgr.cpp:817
TC_GAME_API LootStore LootTemplates_Gameobject
TC_GAME_API LootStore LootTemplates_Item
TC_GAME_API LootStore LootTemplates_Prospecting
TC_GAME_API void LoadLootTemplates_Gameobject()
Definition LootMgr.cpp:873
TC_GAME_API LootStore LootTemplates_Skinning
TC_GAME_API void LoadLootTemplates_Pickpocketing()
Definition LootMgr.cpp:960
TC_GAME_API LootStore LootTemplates_Fishing
TC_GAME_API void LoadLootTemplates_Prospecting()
Definition LootMgr.cpp:994
TC_GAME_API LootStore LootTemplates_Disenchant
TC_GAME_API LootStore LootTemplates_Pickpocketing
TC_GAME_API LootStore LootTemplates_Spell
std::unordered_map< uint32, LootTemplate * > LootTemplateMap
Definition LootMgr.h:59
TC_GAME_API void LoadLootTemplates_Mail()
Definition LootMgr.cpp:1023
TC_GAME_API LootStore LootTemplates_Creature
TC_GAME_API void LoadLootTables()
Definition LootMgr.cpp:1149
TC_GAME_API LootStore LootTemplates_Mail
std::set< uint32 > LootIdSet
Definition LootMgr.h:61
std::list< LootStoreItem * > LootStoreItemList
Definition LootMgr.h:58
TC_GAME_API void LoadLootTemplates_Item()
Definition LootMgr.cpp:907
TC_GAME_API void LoadLootTemplates_Fishing()
Definition LootMgr.cpp:850
TC_GAME_API void LoadLootTemplates_Reference()
Definition LootMgr.cpp:1121
TC_GAME_API LootStore LootTemplates_Milling
TC_GAME_API void LoadLootTemplates_Spell()
Definition LootMgr.cpp:1081
std::unordered_map< uint32, ItemTemplate > ItemTemplateContainer
Definition ObjectMgr.h:556
std::unordered_map< uint32, GameObjectTemplate > GameObjectTemplateContainer
Definition ObjectMgr.h:544
#define sObjectMgr
Definition ObjectMgr.h:1721
std::unordered_map< uint32, CreatureTemplate > CreatureTemplateContainer
Definition ObjectMgr.h:535
double rand_chance()
Definition Random.cpp:81
bool roll_chance_f(float chance)
Definition Random.h:53
#define PLAYER_CORPSE_LOOT_ENTRY
@ MAX_ITEM_QUALITY
@ SPELL_ATTR0_TRADESPELL
@ SPELL_ATTR0_NOT_SHAPESHIFT
#define sSpellMgr
Definition SpellMgr.h:738
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
Class used to access individual fields of database query result.
Definition Field.h:92
uint8 GetUInt8() const
Definition Field.cpp:29
uint16 GetUInt16() const
Definition Field.cpp:45
float GetFloat() const
Definition Field.cpp:93
bool GetBool() const
Definition Field.h:100
uint32 GetUInt32() const
Definition Field.cpp:61
uint32 LoadLootTable()
Definition LootMgr.cpp:129
uint32 LoadAndCollectLootIds(LootIdSet &ids_set)
Definition LootMgr.cpp:247
void ResetConditions()
Definition LootMgr.cpp:218
LootTemplate const * GetLootFor(uint32 loot_id) const
Definition LootMgr.cpp:227
LootTemplateMap m_LootTemplates
Definition LootMgr.h:93
void ReportNonExistingId(uint32 lootId, char const *ownerType, uint32 ownerId) const
Definition LootMgr.cpp:270
void CheckLootRefs(LootIdSet *ref_set=nullptr) const
Definition LootMgr.cpp:257
char const * GetEntryName() const
Definition LootMgr.h:87
bool HaveQuestLootFor(uint32 loot_id) const
Definition LootMgr.cpp:198
LootTemplate * GetLootForConditionFill(uint32 loot_id)
Definition LootMgr.cpp:237
void Clear()
Definition LootMgr.cpp:112
char const * GetName() const
Definition LootMgr.h:86
bool HaveQuestLootForPlayer(uint32 loot_id, Player const *player) const
Definition LootMgr.cpp:208
void ReportUnusedIds(LootIdSet const &ids_set) const
Definition LootMgr.cpp:263
void Verify() const
Definition LootMgr.cpp:121
void CheckLootRefs(LootTemplateMap const &store, LootIdSet *ref_set) const
Definition LootMgr.cpp:481
LootStoreItemList ExplicitlyChanced
Definition LootMgr.cpp:101
LootStoreItemList * GetEqualChancedItemList()
Definition LootMgr.cpp:98
LootGroup & operator=(LootGroup const &)=delete
void CopyConditions(ConditionContainer conditions)
Definition LootMgr.cpp:432
LootStoreItemList EqualChanced
Definition LootMgr.cpp:102
void Verify(LootStore const &lootstore, uint32 id, uint8 group_id) const
Definition LootMgr.cpp:471
LootStoreItemList * GetExplicitlyChancedItemList()
Definition LootMgr.cpp:97
float RawTotalChance() const
Definition LootMgr.cpp:449
void AddEntry(LootStoreItem *item)
Definition LootMgr.cpp:366
bool HasQuestDropForPlayer(Player const *player) const
Definition LootMgr.cpp:419
void Process(Loot &loot, uint16 lootMode) const
Definition LootMgr.cpp:442
LootGroup(LootGroup const &)=delete
float TotalChance() const
Definition LootMgr.cpp:461
LootStoreItem const * Roll(Loot &loot, uint16 lootMode) const
Definition LootMgr.cpp:375
bool HasQuestDrop() const
Definition LootMgr.cpp:405
void Process(Loot &loot, bool rate, uint16 lootMode, uint8 groupId=0) const
Definition LootMgr.cpp:562
bool HasQuestDropForPlayer(Player const *player, uint8 groupId=0) const
Definition LootMgr.cpp:645
bool HasQuestDrop(uint8 groupId=0) const
Definition LootMgr.cpp:607
void CheckLootRefs(LootTemplateMap const &store, LootIdSet *ref_set) const
Definition LootMgr.cpp:694
bool isReference(uint32 id)
Definition LootMgr.cpp:771
void AddEntry(LootStoreItem *item)
Definition LootMgr.cpp:522
void Verify(LootStore const &store, uint32 Id) const
Definition LootMgr.cpp:684
LootGroups Groups
Definition LootMgr.h:128
bool addConditionItem(Condition *cond)
Definition LootMgr.cpp:713
void CopyConditions(ConditionContainer const &conditions)
Definition LootMgr.cpp:537
bool HasQuestForItem(uint32 itemId, uint32 excludeQuestId=0, bool turnIn=false) const
Definition Player.cpp:16449
Definition Group.h:130
uint32 Id
Definition SpellInfo.h:289
bool IsLootCrafting() const
bool HasAttribute(SpellAttr0 attribute) const
Definition SpellInfo.h:375
#define sWorld
Definition World.h:900
Rates
Server rates.
Definition World.h:409
@ RATE_DROP_ITEM_REFERENCED_AMOUNT
Definition World.h:427
@ RATE_DROP_ITEM_RARE
Definition World.h:422
@ RATE_DROP_ITEM_LEGENDARY
Definition World.h:424
@ RATE_DROP_ITEM_POOR
Definition World.h:419
@ RATE_DROP_ITEM_UNCOMMON
Definition World.h:421
@ RATE_DROP_ITEM_REFERENCED
Definition World.h:426
@ RATE_DROP_ITEM_EPIC
Definition World.h:423
@ RATE_DROP_ITEM_ARTIFACT
Definition World.h:425
@ RATE_DROP_ITEM_NORMAL
Definition World.h:420
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:108
bool isLoaded() const
int32 SourceEntry
bool operator()(LootStoreItem *item) const
Definition LootMgr.cpp:62
LootGroupInvalidSelector(Loot const &loot, uint16 lootMode)
Definition LootMgr.cpp:60
uint32 itemid
Definition Loot.h:127
ConditionContainer conditions
Definition Loot.h:131
float chance
Definition LootMgr.h:38
bool Roll(bool rate) const
Definition LootMgr.cpp:281
ConditionContainer conditions
Definition LootMgr.h:44
bool needs_quest
Definition LootMgr.h:40
uint32 itemid
Definition LootMgr.h:36
uint32 reference
Definition LootMgr.h:37
uint8 maxcount
Definition LootMgr.h:43
uint16 lootmode
Definition LootMgr.h:39
uint8 groupid
Definition LootMgr.h:41
uint8 mincount
Definition LootMgr.h:42
bool IsValid(LootStore const &store, uint32 entry) const
Definition LootMgr.cpp:297
Definition Loot.h:207
void AddItem(LootStoreItem const &item)
Definition Loot.cpp:173
uint8 maxDuplicates
Definition Loot.h:221
std::vector< LootItem > items
Definition Loot.h:214