diff options
Diffstat (limited to 'src/server/game/Loot/LootMgr.cpp')
-rw-r--r-- | src/server/game/Loot/LootMgr.cpp | 426 |
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 } |