aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Loot/LootMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Loot/LootMgr.cpp')
-rw-r--r--src/server/game/Loot/LootMgr.cpp426
1 files changed, 211 insertions, 215 deletions
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 0a66c781c8f..94aea40f511 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -26,6 +26,7 @@
#include "SpellInfo.h"
#include "Group.h"
#include "Player.h"
+#include "Containers.h"
static Rates const qualityToRate[MAX_ITEM_QUALITY] =
{
@@ -51,10 +52,26 @@ LootStore LootTemplates_Reference("reference_loot_template", "reference
LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true);
LootStore LootTemplates_Spell("spell_loot_template", "spell id (random item creating)", false);
+struct NotMatchingLootMode : public std::unary_function<LootStoreItem*, bool>
+{
+ explicit NotMatchingLootMode(uint16 lootMode) : _lootMode(lootMode) { }
+
+ bool operator()(LootStoreItem* item) const
+ {
+ return !(item->lootmode & _lootMode);
+ }
+
+private:
+ uint16 _lootMode;
+};
+
class LootTemplate::LootGroup // A set of loot definitions for items (refs are not allowed)
{
public:
- void AddEntry(LootStoreItem& item); // Adds an entry to the group (at loading stage)
+ LootGroup() { }
+ ~LootGroup();
+
+ void AddEntry(LootStoreItem* item); // Adds an entry to the group (at loading stage)
bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry
bool HasQuestDropForPlayer(Player const* player) const;
// The same for active quests of the player
@@ -72,7 +89,11 @@ class LootTemplate::LootGroup // A set of loot def
LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB
LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance
- LootStoreItem const* Roll() const; // Rolls an item from the group, returns NULL if all miss their chances
+ LootStoreItem const* Roll(uint16 lootMode) const; // Rolls an item from the group, returns NULL if all miss their chances
+
+ // This class must never be copied - storing pointers
+ LootGroup(LootGroup const&);
+ LootGroup& operator=(LootGroup const&);
};
//Remove all data and free all memory
@@ -126,10 +147,13 @@ uint32 LootStore::LoadLootTable()
continue; // error already printed to log/console.
}
- LootStoreItem storeitem = LootStoreItem(item, chanceOrQuestChance, lootmode, group, mincountOrRef, maxcount);
+ LootStoreItem* storeitem = new LootStoreItem(item, chanceOrQuestChance, lootmode, group, mincountOrRef, maxcount);
- if (!storeitem.IsValid(*this, entry)) // Validity checks
+ if (!storeitem->IsValid(*this, entry)) // Validity checks
+ {
+ delete storeitem;
continue;
+ }
// Looking for the template of the entry
// often entries are put together
@@ -139,7 +163,7 @@ uint32 LootStore::LoadLootTable()
tab = m_LootTemplates.find(entry);
if (tab == m_LootTemplates.end())
{
- std::pair< LootTemplateMap::iterator, bool > pr = m_LootTemplates.insert(LootTemplateMap::value_type(entry, new LootTemplate));
+ std::pair< LootTemplateMap::iterator, bool > pr = m_LootTemplates.insert(LootTemplateMap::value_type(entry, new LootTemplate()));
tab = pr.first;
}
}
@@ -182,7 +206,7 @@ void LootStore::ResetConditions()
for (LootTemplateMap::iterator itr = m_LootTemplates.begin(); itr != m_LootTemplates.end(); ++itr)
{
ConditionList empty;
- (*itr).second->CopyConditions(empty);
+ itr->second->CopyConditions(empty);
}
}
@@ -327,7 +351,6 @@ LootItem::LootItem(LootStoreItem const& li)
needs_quest = li.needs_quest;
- count = urand(li.mincountOrRef, li.maxcount); // constructor called for mincountOrRef > 0 only
randomSuffix = GenerateEnchSuffixFactor(itemid);
randomPropertyId = Item::GenerateItemRandomPropertyId(itemid);
is_looted = 0;
@@ -376,26 +399,30 @@ void LootItem::AddAllowedLooter(const Player* player)
//
// Inserts the item into the loot (called by LootTemplate processors)
-void Loot::AddItem(LootStoreItem const & item)
+void Loot::AddItem(LootStoreItem const& item)
{
- if (item.needs_quest) // Quest drop
- {
- if (quest_items.size() < MAX_NR_QUEST_ITEMS)
- quest_items.push_back(LootItem(item));
- }
- else if (items.size() < MAX_NR_LOOT_ITEMS) // Non-quest drop
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item.itemid);
+ if (!proto)
+ return;
+
+ uint32 count = urand(item.mincountOrRef, item.maxcount);
+ uint32 stacks = count / proto->GetMaxStackSize() + (count % proto->GetMaxStackSize() ? 1 : 0);
+
+ std::vector<LootItem>& lootItems = item.needs_quest ? quest_items : items;
+ uint32 limit = item.needs_quest ? MAX_NR_QUEST_ITEMS : MAX_NR_LOOT_ITEMS;
+
+ for (uint32 i = 0; i < stacks && lootItems.size() < limit; ++i)
{
- items.push_back(LootItem(item));
+ LootItem generatedLoot(item);
+ generatedLoot.count = std::min(count, proto->GetMaxStackSize());
+ lootItems.push_back(generatedLoot);
+ count -= proto->GetMaxStackSize();
// non-conditional one-player only items are counted here,
// free for all items are counted in FillFFALoot(),
// non-ffa conditionals are counted in FillNonQuestNonFFAConditionalLoot()
- if (item.conditions.empty())
- {
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item.itemid);
- if (!proto || (proto->Flags & ITEM_PROTO_FLAG_PARTY_LOOT) == 0)
- ++unlootedCount;
- }
+ if (!item.needs_quest && item.conditions.empty() && !(proto->Flags & ITEM_PROTO_FLAG_PARTY_LOOT))
+ ++unlootedCount;
}
}
@@ -1028,34 +1055,56 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
// --------- LootTemplate::LootGroup ---------
//
+LootTemplate::LootGroup::~LootGroup()
+{
+ while (!ExplicitlyChanced.empty())
+ {
+ delete ExplicitlyChanced.back();
+ ExplicitlyChanced.pop_back();
+ }
+
+ while (!EqualChanced.empty())
+ {
+ delete EqualChanced.back();
+ EqualChanced.pop_back();
+ }
+}
+
// Adds an entry to the group (at loading stage)
-void LootTemplate::LootGroup::AddEntry(LootStoreItem& item)
+void LootTemplate::LootGroup::AddEntry(LootStoreItem* item)
{
- if (item.chance != 0)
+ if (item->chance != 0)
ExplicitlyChanced.push_back(item);
else
EqualChanced.push_back(item);
}
// Rolls an item from the group, returns NULL if all miss their chances
-LootStoreItem const* LootTemplate::LootGroup::Roll() const
+LootStoreItem const* LootTemplate::LootGroup::Roll(uint16 lootMode) const
{
- if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked
+ LootStoreItemList possibleLoot = ExplicitlyChanced;
+ possibleLoot.remove_if(NotMatchingLootMode(lootMode));
+
+ if (!possibleLoot.empty()) // First explicitly chanced entries are checked
{
- float Roll = (float)rand_chance();
+ float roll = (float)rand_chance();
- for (uint32 i = 0; i < ExplicitlyChanced.size(); ++i) // check each explicitly chanced entry in the template and modify its chance based on quality.
+ 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.
{
- if (ExplicitlyChanced[i].chance >= 100.0f)
- return &ExplicitlyChanced[i];
+ LootStoreItem* item = *itr;
+ if (item->chance >= 100.0f)
+ return item;
- Roll -= ExplicitlyChanced[i].chance;
- if (Roll < 0)
- return &ExplicitlyChanced[i];
+ roll -= item->chance;
+ if (roll < 0)
+ return item;
}
}
- if (!EqualChanced.empty()) // If nothing selected yet - an item is taken from equal-chanced part
- return &EqualChanced[irand(0, EqualChanced.size()-1)];
+
+ possibleLoot = EqualChanced;
+ possibleLoot.remove_if(NotMatchingLootMode(lootMode));
+ if (!possibleLoot.empty()) // If nothing selected yet - an item is taken from equal-chanced part
+ return Trinity::Containers::SelectRandomContainerElement(possibleLoot);
return NULL; // Empty drop from the group
}
@@ -1063,12 +1112,14 @@ LootStoreItem const* LootTemplate::LootGroup::Roll() const
// True if group includes at least 1 quest drop entry
bool LootTemplate::LootGroup::HasQuestDrop() const
{
- for (LootStoreItemList::const_iterator i=ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
- if (i->needs_quest)
+ for (LootStoreItemList::const_iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
+ if ((*i)->needs_quest)
return true;
- for (LootStoreItemList::const_iterator i=EqualChanced.begin(); i != EqualChanced.end(); ++i)
- if (i->needs_quest)
+
+ for (LootStoreItemList::const_iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
+ if ((*i)->needs_quest)
return true;
+
return false;
}
@@ -1076,111 +1127,30 @@ bool LootTemplate::LootGroup::HasQuestDrop() const
bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const* player) const
{
for (LootStoreItemList::const_iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
- if (player->HasQuestForItem(i->itemid))
+ if (player->HasQuestForItem((*i)->itemid))
return true;
+
for (LootStoreItemList::const_iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
- if (player->HasQuestForItem(i->itemid))
+ if (player->HasQuestForItem((*i)->itemid))
return true;
+
return false;
}
void LootTemplate::LootGroup::CopyConditions(ConditionList /*conditions*/)
{
for (LootStoreItemList::iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
- {
- i->conditions.clear();
- }
+ (*i)->conditions.clear();
+
for (LootStoreItemList::iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
- {
- i->conditions.clear();
- }
+ (*i)->conditions.clear();
}
// Rolls an item from the group (if any takes its chance) and adds the item to the loot
void LootTemplate::LootGroup::Process(Loot& loot, uint16 lootMode) const
{
- // build up list of possible drops
- LootStoreItemList EqualPossibleDrops = EqualChanced;
- LootStoreItemList ExplicitPossibleDrops = ExplicitlyChanced;
-
- uint8 uiAttemptCount = 0;
- const uint8 uiMaxAttempts = ExplicitlyChanced.size() + EqualChanced.size();
-
- while (!ExplicitPossibleDrops.empty() || !EqualPossibleDrops.empty())
- {
- if (uiAttemptCount == uiMaxAttempts) // already tried rolling too many times, just abort
- return;
-
- LootStoreItem* item = NULL;
-
- // begin rolling (normally called via Roll())
- LootStoreItemList::iterator itr;
- uint8 itemSource = 0;
- if (!ExplicitPossibleDrops.empty()) // First explicitly chanced entries are checked
- {
- itemSource = 1;
- float Roll = (float)rand_chance();
- // check each explicitly chanced entry in the template and modify its chance based on quality
- for (itr = ExplicitPossibleDrops.begin(); itr != ExplicitPossibleDrops.end(); itr = ExplicitPossibleDrops.erase(itr))
- {
- if (itr->chance >= 100.0f)
- {
- item = &*itr;
- break;
- }
-
- Roll -= itr->chance;
- if (Roll < 0)
- {
- item = &*itr;
- break;
- }
- }
- }
- if (item == NULL && !EqualPossibleDrops.empty()) // If nothing selected yet - an item is taken from equal-chanced part
- {
- itemSource = 2;
- itr = EqualPossibleDrops.begin();
- std::advance(itr, irand(0, EqualPossibleDrops.size()-1));
- item = &*itr;
- }
- // finish rolling
-
- ++uiAttemptCount;
-
- if (item != NULL && item->lootmode & lootMode) // only add this item if roll succeeds and the mode matches
- {
- bool duplicate = false;
- if (ItemTemplate const* _proto = sObjectMgr->GetItemTemplate(item->itemid))
- {
- uint8 _item_counter = 0;
- for (LootItemList::const_iterator _item = loot.items.begin(); _item != loot.items.end(); ++_item)
- if (_item->itemid == item->itemid) // search through the items that have already dropped
- {
- ++_item_counter;
- if (_proto->InventoryType == 0 && _item_counter == 3) // Non-equippable items are limited to 3 drops
- duplicate = true;
- else if (_proto->InventoryType != 0 && _item_counter == 1) // Equippable item are limited to 1 drop
- duplicate = true;
- }
- }
- if (duplicate) // if item->itemid is a duplicate, remove it
- switch (itemSource)
- {
- case 1: // item came from ExplicitPossibleDrops
- ExplicitPossibleDrops.erase(itr);
- break;
- case 2: // item came from EqualPossibleDrops
- EqualPossibleDrops.erase(itr);
- break;
- }
- else // otherwise, add the item and exit the function
- {
- loot.AddItem(*item);
- return;
- }
- }
- }
+ if (LootStoreItem const* item = Roll(lootMode))
+ loot.AddItem(*item);
}
// Overall chance for the group without equal chanced items
@@ -1189,8 +1159,8 @@ float LootTemplate::LootGroup::RawTotalChance() const
float result = 0;
for (LootStoreItemList::const_iterator i=ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
- if (!i->needs_quest)
- result += i->chance;
+ if (!(*i)->needs_quest)
+ result += (*i)->chance;
return result;
}
@@ -1210,37 +1180,35 @@ void LootTemplate::LootGroup::Verify(LootStore const& lootstore, uint32 id, uint
{
float chance = RawTotalChance();
if (chance > 101.0f) // TODO: replace with 100% when DBs will be ready
- {
sLog->outError(LOG_FILTER_SQL, "Table '%s' entry %u group %d has total chance > 100%% (%f)", lootstore.GetName(), id, group_id, chance);
- }
if (chance >= 100.0f && !EqualChanced.empty())
- {
sLog->outError(LOG_FILTER_SQL, "Table '%s' entry %u group %d has items with chance=0%% but group total chance >= 100%% (%f)", lootstore.GetName(), id, group_id, chance);
- }
}
void LootTemplate::LootGroup::CheckLootRefs(LootTemplateMap const& /*store*/, LootIdSet* ref_set) const
{
- for (LootStoreItemList::const_iterator ieItr=ExplicitlyChanced.begin(); ieItr != ExplicitlyChanced.end(); ++ieItr)
+ for (LootStoreItemList::const_iterator ieItr = ExplicitlyChanced.begin(); ieItr != ExplicitlyChanced.end(); ++ieItr)
{
- if (ieItr->mincountOrRef < 0)
+ LootStoreItem* item = *ieItr;
+ if (item->mincountOrRef < 0)
{
- if (!LootTemplates_Reference.GetLootFor(-ieItr->mincountOrRef))
- LootTemplates_Reference.ReportNotExistedId(-ieItr->mincountOrRef);
+ if (!LootTemplates_Reference.GetLootFor(-item->mincountOrRef))
+ LootTemplates_Reference.ReportNotExistedId(-item->mincountOrRef);
else if (ref_set)
- ref_set->erase(-ieItr->mincountOrRef);
+ ref_set->erase(-item->mincountOrRef);
}
}
- for (LootStoreItemList::const_iterator ieItr=EqualChanced.begin(); ieItr != EqualChanced.end(); ++ieItr)
+ for (LootStoreItemList::const_iterator ieItr = EqualChanced.begin(); ieItr != EqualChanced.end(); ++ieItr)
{
- if (ieItr->mincountOrRef < 0)
+ LootStoreItem* item = *ieItr;
+ if (item->mincountOrRef < 0)
{
- if (!LootTemplates_Reference.GetLootFor(-ieItr->mincountOrRef))
- LootTemplates_Reference.ReportNotExistedId(-ieItr->mincountOrRef);
+ if (!LootTemplates_Reference.GetLootFor(-item->mincountOrRef))
+ LootTemplates_Reference.ReportNotExistedId(-item->mincountOrRef);
else if (ref_set)
- ref_set->erase(-ieItr->mincountOrRef);
+ ref_set->erase(-item->mincountOrRef);
}
}
}
@@ -1249,14 +1217,30 @@ void LootTemplate::LootGroup::CheckLootRefs(LootTemplateMap const& /*store*/, Lo
// --------- LootTemplate ---------
//
+LootTemplate::~LootTemplate()
+{
+ while (!Entries.empty())
+ {
+ delete Entries.back();
+ Entries.pop_back();
+ }
+
+ for (size_t i = 0; i < Groups.size(); ++i)
+ delete Groups[i];
+ Groups.clear();
+}
+
// Adds an entry to the group (at loading stage)
-void LootTemplate::AddEntry(LootStoreItem& item)
+void LootTemplate::AddEntry(LootStoreItem* item)
{
- if (item.group > 0 && item.mincountOrRef > 0) // Group
+ if (item->group > 0 && item->mincountOrRef > 0) // Group
{
- if (item.group >= Groups.size())
- Groups.resize(item.group); // Adds new group the the loot template if needed
- Groups[item.group-1].AddEntry(item); // Adds new entry to the group
+ if (item->group >= Groups.size())
+ Groups.resize(item->group, NULL); // Adds new group the the loot template if needed
+ if (!Groups[item->group - 1])
+ Groups[item->group - 1] = new LootGroup();
+
+ Groups[item->group-1]->AddEntry(item); // Adds new entry to the group
}
else // Non-grouped entries and references are stored together
Entries.push_back(item);
@@ -1265,10 +1249,11 @@ void LootTemplate::AddEntry(LootStoreItem& item)
void LootTemplate::CopyConditions(ConditionList conditions)
{
for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
- i->conditions.clear();
+ (*i)->conditions.clear();
for (LootGroups::iterator i = Groups.begin(); i != Groups.end(); ++i)
- i->CopyConditions(conditions);
+ if (LootGroup* group = *i)
+ group->CopyConditions(conditions);
}
void LootTemplate::CopyConditions(LootItem* li) const
@@ -1276,10 +1261,11 @@ void LootTemplate::CopyConditions(LootItem* li) const
// Copies the conditions list from a template item to a LootItem
for (LootStoreItemList::const_iterator _iter = Entries.begin(); _iter != Entries.end(); ++_iter)
{
- if (_iter->itemid != li->itemid)
+ LootStoreItem* item = *_iter;
+ if (item->itemid != li->itemid)
continue;
- li->conditions = _iter->conditions;
+ li->conditions = item->conditions;
break;
}
}
@@ -1292,54 +1278,42 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId
if (groupId > Groups.size())
return; // Error message already printed at loading stage
- Groups[groupId-1].Process(loot, lootMode);
+ if (!Groups[groupId - 1])
+ return;
+
+ Groups[groupId-1]->Process(loot, lootMode);
return;
}
// Rolling non-grouped items
for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i)
{
- if (i->lootmode &~ lootMode) // Do not add if mode mismatch
+ LootStoreItem* item = *i;
+ if (item->lootmode &~ lootMode) // Do not add if mode mismatch
continue;
- if (!i->Roll(rate))
- continue; // Bad luck for the entry
+ if (!item->Roll(rate))
+ continue; // Bad luck for the entry
- if (ItemTemplate const* _proto = sObjectMgr->GetItemTemplate(i->itemid))
+ if (item->mincountOrRef < 0) // References processing
{
- uint8 _item_counter = 0;
- LootItemList::const_iterator _item = loot.items.begin();
- for (; _item != loot.items.end(); ++_item)
- if (_item->itemid == i->itemid) // search through the items that have already dropped
- {
- ++_item_counter;
- if (_proto->InventoryType == 0 && _item_counter == 3) // Non-equippable items are limited to 3 drops
- continue;
- else if (_proto->InventoryType != 0 && _item_counter == 1) // Equippable item are limited to 1 drop
- continue;
- }
- if (_item != loot.items.end())
- continue;
- }
-
- if (i->mincountOrRef < 0) // References processing
- {
- LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(-i->mincountOrRef);
+ LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(-item->mincountOrRef);
if (!Referenced)
- continue; // Error message already printed at loading stage
+ continue; // Error message already printed at loading stage
- uint32 maxcount = uint32(float(i->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT));
- for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator
- Referenced->Process(loot, rate, lootMode, i->group);
+ uint32 maxcount = uint32(float(item->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT));
+ for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator
+ Referenced->Process(loot, rate, lootMode, item->group);
}
- else // Plain entries (not a reference, not grouped)
- loot.AddItem(*i); // Chance is already checked, just add
+ else // Plain entries (not a reference, not grouped)
+ loot.AddItem(*item); // Chance is already checked, just add
}
// Now processing groups
for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
- i->Process(loot, lootMode);
+ if (LootGroup* group = *i)
+ group->Process(loot, lootMode);
}
// True if template includes at least 1 quest drop entry
@@ -1349,27 +1323,33 @@ bool LootTemplate::HasQuestDrop(LootTemplateMap const& store, uint8 groupId) con
{
if (groupId > Groups.size())
return false; // Error message [should be] already printed at loading stage
- return Groups[groupId-1].HasQuestDrop();
+
+ if (!Groups[groupId - 1])
+ return false;
+
+ return Groups[groupId-1]->HasQuestDrop();
}
for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i)
{
- if (i->mincountOrRef < 0) // References
+ LootStoreItem* item = *i;
+ if (item->mincountOrRef < 0) // References
{
- LootTemplateMap::const_iterator Referenced = store.find(-i->mincountOrRef);
+ LootTemplateMap::const_iterator Referenced = store.find(-item->mincountOrRef);
if (Referenced == store.end())
continue; // Error message [should be] already printed at loading stage
- if (Referenced->second->HasQuestDrop(store, i->group))
+ if (Referenced->second->HasQuestDrop(store, item->group))
return true;
}
- else if (i->needs_quest)
+ else if (item->needs_quest)
return true; // quest drop found
}
// Now processing groups
for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
- if (i->HasQuestDrop())
- return true;
+ if (LootGroup* group = *i)
+ if (group->HasQuestDrop())
+ return true;
return false;
}
@@ -1381,28 +1361,34 @@ bool LootTemplate::HasQuestDropForPlayer(LootTemplateMap const& store, Player co
{
if (groupId > Groups.size())
return false; // Error message already printed at loading stage
- return Groups[groupId-1].HasQuestDropForPlayer(player);
+
+ if (!Groups[groupId - 1])
+ return false;
+
+ return Groups[groupId-1]->HasQuestDropForPlayer(player);
}
// Checking non-grouped entries
for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i)
{
- if (i->mincountOrRef < 0) // References processing
+ LootStoreItem* item = *i;
+ if (item->mincountOrRef < 0) // References processing
{
- LootTemplateMap::const_iterator Referenced = store.find(-i->mincountOrRef);
+ LootTemplateMap::const_iterator Referenced = store.find(-item->mincountOrRef);
if (Referenced == store.end())
continue; // Error message already printed at loading stage
- if (Referenced->second->HasQuestDropForPlayer(store, player, i->group))
+ if (Referenced->second->HasQuestDropForPlayer(store, player, item->group))
return true;
}
- else if (player->HasQuestForItem(i->itemid))
+ else if (player->HasQuestForItem(item->itemid))
return true; // active quest drop found
}
// Now checking groups
for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
- if (i->HasQuestDropForPlayer(player))
- return true;
+ if (LootGroup* group = *i)
+ if (group->HasQuestDropForPlayer(player))
+ return true;
return false;
}
@@ -1411,8 +1397,9 @@ bool LootTemplate::HasQuestDropForPlayer(LootTemplateMap const& store, Player co
void LootTemplate::Verify(LootStore const& lootstore, uint32 id) const
{
// Checking group chances
- for (uint32 i=0; i < Groups.size(); ++i)
- Groups[i].Verify(lootstore, id, i+1);
+ for (uint32 i = 0; i < Groups.size(); ++i)
+ if (Groups[i])
+ Groups[i]->Verify(lootstore, id, i + 1);
// TODO: References validity checks
}
@@ -1421,18 +1408,21 @@ void LootTemplate::CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_se
{
for (LootStoreItemList::const_iterator ieItr = Entries.begin(); ieItr != Entries.end(); ++ieItr)
{
- if (ieItr->mincountOrRef < 0)
+ LootStoreItem* item = *ieItr;
+ if (item->mincountOrRef < 0)
{
- if (!LootTemplates_Reference.GetLootFor(-ieItr->mincountOrRef))
- LootTemplates_Reference.ReportNotExistedId(-ieItr->mincountOrRef);
+ if (!LootTemplates_Reference.GetLootFor(-item->mincountOrRef))
+ LootTemplates_Reference.ReportNotExistedId(-item->mincountOrRef);
else if (ref_set)
- ref_set->erase(-ieItr->mincountOrRef);
+ ref_set->erase(-item->mincountOrRef);
}
}
for (LootGroups::const_iterator grItr = Groups.begin(); grItr != Groups.end(); ++grItr)
- grItr->CheckLootRefs(store, ref_set);
+ if (LootGroup* group = *grItr)
+ group->CheckLootRefs(store, ref_set);
}
+
bool LootTemplate::addConditionItem(Condition* cond)
{
if (!cond || !cond->isLoaded())//should never happen, checked at loading
@@ -1440,41 +1430,48 @@ bool LootTemplate::addConditionItem(Condition* cond)
sLog->outError(LOG_FILTER_LOOT, "LootTemplate::addConditionItem: condition is null");
return false;
}
+
if (!Entries.empty())
{
for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
{
- if (i->itemid == uint32(cond->SourceEntry))
+ if ((*i)->itemid == uint32(cond->SourceEntry))
{
- i->conditions.push_back(cond);
+ (*i)->conditions.push_back(cond);
return true;
}
}
}
+
if (!Groups.empty())
{
for (LootGroups::iterator groupItr = Groups.begin(); groupItr != Groups.end(); ++groupItr)
{
- LootStoreItemList* itemList = (*groupItr).GetExplicitlyChancedItemList();
+ LootGroup* group = *groupItr;
+ if (!group)
+ continue;
+
+ LootStoreItemList* itemList = group->GetExplicitlyChancedItemList();
if (!itemList->empty())
{
for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
{
- if ((*i).itemid == uint32(cond->SourceEntry))
+ if ((*i)->itemid == uint32(cond->SourceEntry))
{
- (*i).conditions.push_back(cond);
+ (*i)->conditions.push_back(cond);
return true;
}
}
}
- itemList = (*groupItr).GetEqualChancedItemList();
+
+ itemList = group->GetEqualChancedItemList();
if (!itemList->empty())
{
for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
{
- if ((*i).itemid == uint32(cond->SourceEntry))
+ if ((*i)->itemid == uint32(cond->SourceEntry))
{
- (*i).conditions.push_back(cond);
+ (*i)->conditions.push_back(cond);
return true;
}
}
@@ -1487,10 +1484,9 @@ bool LootTemplate::addConditionItem(Condition* cond)
bool LootTemplate::isReference(uint32 id)
{
for (LootStoreItemList::const_iterator ieItr = Entries.begin(); ieItr != Entries.end(); ++ieItr)
- {
- if (ieItr->itemid == id && ieItr->mincountOrRef < 0)
+ if ((*ieItr)->itemid == id && (*ieItr)->mincountOrRef < 0)
return true;
- }
+
return false;//not found or not reference
}