[3.3.5] Core/Loot: Fix conditional Master Loot (#17943)

* Core/Loot: Fix master looting of conditional items

follow_loot_rules was a flag intended to force certain quest items to be
master looted. It should not be used for the
NonQuestNonFFAConditionalLoot.

The flag was originally introduced in 869ea349
"Core/Loot: fix the way quest items are handled. so far ive only found 3
quest items that should be able to be masterlooted. added a new flag to
item_template.flagsCustom to allow for making a quest item always follow
loot rules. a bonus may be the fix of the handlelootmasteropcode crash!"

* Core/Loot: Rename QuestItem to NotNormalItem

QuestItem struct was being used for quest items, ffa items, and
conditional items. Renaming it to avoid confusion when working with ffa
and conditional items

* Core/Loot: Use existing AddAllowedLooter rather than reaching into allowedGUIDs directly

* Core/Loot: Rename NotNormalItem to NotNormalLootItem

(cherry picked from commit f5d3343f27f68c7837152fc592310397a686a83e)

# Conflicts:
#	src/server/game/Entities/Item/Item.cpp
#	src/server/game/Loot/LootMgr.cpp
#	src/server/game/Loot/LootMgr.h
This commit is contained in:
Richard
2017-12-10 17:59:58 +01:00
committed by joschiwald
parent 1b7fb624d3
commit 6c54fbbb03
4 changed files with 86 additions and 91 deletions
+1 -1
View File
@@ -2112,7 +2112,7 @@ bool Item::ItemContainerLoadLootFromDB()
// If container item is in a bag, add that player as an allowed looter
if (GetBagSlot())
loot_item.allowedGUIDs.insert(GetOwner()->GetGUID());
loot_item.AddAllowedLooter(GetOwner());
// Finally add the LootItem to the container
loot.items.push_back(loot_item);
+3 -3
View File
@@ -25578,9 +25578,9 @@ void Player::AutoStoreLoot(uint8 bag, uint8 slot, uint32 loot_id, LootStore cons
void Player::StoreLootItem(uint8 lootSlot, Loot* loot, AELootResult* aeResult/* = nullptr*/)
{
QuestItem* qitem = nullptr;
QuestItem* ffaitem = nullptr;
QuestItem* conditem = nullptr;
NotNormalLootItem* qitem = nullptr;
NotNormalLootItem* ffaitem = nullptr;
NotNormalLootItem* conditem = nullptr;
LootItem* item = loot->LootItemInSlot(lootSlot, this, &qitem, &ffaitem, &conditem);
+66 -71
View File
@@ -134,15 +134,15 @@ void Loot::DeleteLootMoneyFromContainerItemDB()
void Loot::clear()
{
for (QuestItemMap::const_iterator itr = PlayerQuestItems.begin(); itr != PlayerQuestItems.end(); ++itr)
for (NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.begin(); itr != PlayerQuestItems.end(); ++itr)
delete itr->second;
PlayerQuestItems.clear();
for (QuestItemMap::const_iterator itr = PlayerFFAItems.begin(); itr != PlayerFFAItems.end(); ++itr)
for (NotNormalLootItemMap::const_iterator itr = PlayerFFAItems.begin(); itr != PlayerFFAItems.end(); ++itr)
delete itr->second;
PlayerFFAItems.clear();
for (QuestItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.begin(); itr != PlayerNonQuestNonFFAConditionalItems.end(); ++itr)
for (NotNormalLootItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.begin(); itr != PlayerNonQuestNonFFAConditionalItems.end(); ++itr)
delete itr->second;
PlayerNonQuestNonFFAConditionalItems.clear();
@@ -187,11 +187,11 @@ void Loot::NotifyQuestItemRemoved(uint8 questIndex)
++i_next;
if (Player* player = ObjectAccessor::FindPlayer(*i))
{
QuestItemMap::const_iterator pq = PlayerQuestItems.find(player->GetGUID());
NotNormalLootItemMap::const_iterator pq = PlayerQuestItems.find(player->GetGUID());
if (pq != PlayerQuestItems.end() && pq->second)
{
// find where/if the player has the given item in it's vector
QuestItemList& pql = *pq->second;
NotNormalLootItemList& pql = *pq->second;
uint8 j;
for (j = 0; j < pql.size(); ++j)
@@ -329,17 +329,17 @@ LootItem const* Loot::GetItemInSlot(uint32 lootSlot) const
return nullptr;
}
LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qitem, QuestItem* *ffaitem, QuestItem* *conditem)
LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, NotNormalLootItem* *qitem, NotNormalLootItem* *ffaitem, NotNormalLootItem* *conditem)
{
LootItem* item = NULL;
bool is_looted = true;
if (lootSlot >= items.size())
{
uint32 questSlot = lootSlot - items.size();
QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID());
NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID());
if (itr != PlayerQuestItems.end() && questSlot < itr->second->size())
{
QuestItem* qitem2 = &(*itr->second)[questSlot];
NotNormalLootItem* qitem2 = &(*itr->second)[questSlot];
if (qitem)
*qitem = qitem2;
item = &quest_items[qitem2->index];
@@ -352,13 +352,13 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
is_looted = item->is_looted;
if (item->freeforall)
{
QuestItemMap::const_iterator itr = PlayerFFAItems.find(player->GetGUID());
NotNormalLootItemMap::const_iterator itr = PlayerFFAItems.find(player->GetGUID());
if (itr != PlayerFFAItems.end())
{
for (QuestItemList::const_iterator iter = itr->second->begin(); iter != itr->second->end(); ++iter)
for (NotNormalLootItemList::const_iterator iter = itr->second->begin(); iter != itr->second->end(); ++iter)
if (iter->index == lootSlot)
{
QuestItem* ffaitem2 = (QuestItem*)&(*iter);
NotNormalLootItem* ffaitem2 = (NotNormalLootItem*)&(*iter);
if (ffaitem)
*ffaitem = ffaitem2;
is_looted = ffaitem2->is_looted;
@@ -368,14 +368,14 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
}
else if (!item->conditions.empty())
{
QuestItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUID());
NotNormalLootItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUID());
if (itr != PlayerNonQuestNonFFAConditionalItems.end())
{
for (QuestItemList::const_iterator iter = itr->second->begin(); iter != itr->second->end(); ++iter)
for (NotNormalLootItemList::const_iterator iter = itr->second->begin(); iter != itr->second->end(); ++iter)
{
if (iter->index == lootSlot)
{
QuestItem* conditem2 = (QuestItem*)&(*iter);
NotNormalLootItem* conditem2 = (NotNormalLootItem*)&(*iter);
if (conditem)
*conditem = conditem2;
is_looted = conditem2->is_looted;
@@ -394,7 +394,7 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem* *qite
uint32 Loot::GetMaxSlotInLootFor(Player* player) const
{
QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID());
NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUID());
return items.size() + (itr != PlayerQuestItems.end() ? itr->second->size() : 0);
}
@@ -414,12 +414,12 @@ bool Loot::hasItemForAll() const
// return true if there is any FFA, quest or conditional item for the player.
bool Loot::hasItemFor(Player* player) const
{
QuestItemMap const& lootPlayerQuestItems = GetPlayerQuestItems();
QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(player->GetGUID());
NotNormalLootItemMap const& lootPlayerQuestItems = GetPlayerQuestItems();
NotNormalLootItemMap::const_iterator q_itr = lootPlayerQuestItems.find(player->GetGUID());
if (q_itr != lootPlayerQuestItems.end())
{
QuestItemList* q_list = q_itr->second;
for (QuestItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi)
NotNormalLootItemList* q_list = q_itr->second;
for (NotNormalLootItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi)
{
const LootItem &item = quest_items[qi->index];
if (!qi->is_looted && !item.is_looted)
@@ -427,12 +427,12 @@ bool Loot::hasItemFor(Player* player) const
}
}
QuestItemMap const& lootPlayerFFAItems = GetPlayerFFAItems();
QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(player->GetGUID());
NotNormalLootItemMap const& lootPlayerFFAItems = GetPlayerFFAItems();
NotNormalLootItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(player->GetGUID());
if (ffa_itr != lootPlayerFFAItems.end())
{
QuestItemList* ffa_list = ffa_itr->second;
for (QuestItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
NotNormalLootItemList* ffa_list = ffa_itr->second;
for (NotNormalLootItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
{
const LootItem &item = items[fi->index];
if (!fi->is_looted && !item.is_looted)
@@ -440,12 +440,12 @@ bool Loot::hasItemFor(Player* player) const
}
}
QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems();
QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(player->GetGUID());
NotNormalLootItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems();
NotNormalLootItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(player->GetGUID());
if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
{
QuestItemList* conditional_list = nn_itr->second;
for (QuestItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
NotNormalLootItemList* conditional_list = nn_itr->second;
for (NotNormalLootItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
{
const LootItem &item = items[ci->index];
if (!ci->is_looted && !item.is_looted)
@@ -554,14 +554,14 @@ void Loot::BuildLootResponse(WorldPackets::Loot::LootResponse& packet, Player* v
}
LootSlotType slotType = permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT;
QuestItemMap const& lootPlayerQuestItems = GetPlayerQuestItems();
QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(viewer->GetGUID());
NotNormalLootItemMap const& lootPlayerQuestItems = GetPlayerQuestItems();
NotNormalLootItemMap::const_iterator q_itr = lootPlayerQuestItems.find(viewer->GetGUID());
if (q_itr != lootPlayerQuestItems.end())
{
QuestItemList const& q_list = *q_itr->second;
NotNormalLootItemList const& q_list = *q_itr->second;
for (std::size_t i = 0; i < q_list.size(); ++i)
{
QuestItem const& qi = q_list[i];
NotNormalLootItem const& qi = q_list[i];
LootItem const& item = quest_items[qi.index];
if (!qi.is_looted && !item.is_looted)
{
@@ -599,12 +599,12 @@ void Loot::BuildLootResponse(WorldPackets::Loot::LootResponse& packet, Player* v
}
}
QuestItemMap const& lootPlayerFFAItems = GetPlayerFFAItems();
QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(viewer->GetGUID());
NotNormalLootItemMap const& lootPlayerFFAItems = GetPlayerFFAItems();
NotNormalLootItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(viewer->GetGUID());
if (ffa_itr != lootPlayerFFAItems.end())
{
QuestItemList* ffa_list = ffa_itr->second;
for (QuestItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
NotNormalLootItemList* ffa_list = ffa_itr->second;
for (NotNormalLootItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi)
{
LootItem const& item = items[fi->index];
if (!fi->is_looted && !item.is_looted)
@@ -619,12 +619,12 @@ void Loot::BuildLootResponse(WorldPackets::Loot::LootResponse& packet, Player* v
}
}
QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems();
QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(viewer->GetGUID());
NotNormalLootItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems();
NotNormalLootItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(viewer->GetGUID());
if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end())
{
QuestItemList* conditional_list = nn_itr->second;
for (QuestItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
NotNormalLootItemList* conditional_list = nn_itr->second;
for (NotNormalLootItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci)
{
LootItem const& item = items[ci->index];
if (!ci->is_looted && !item.is_looted)
@@ -634,29 +634,24 @@ void Loot::BuildLootResponse(WorldPackets::Loot::LootResponse& packet, Player* v
lootItem.Quantity = item.count;
lootItem.Loot.Initialize(item);
if (item.follow_loot_rules)
switch (permission)
{
switch (permission)
{
case MASTER_PERMISSION:
lootItem.UIType = LOOT_SLOT_TYPE_MASTER;
break;
case RESTRICTED_PERMISSION:
lootItem.UIType = item.is_blocked ? LOOT_SLOT_TYPE_LOCKED : LOOT_SLOT_TYPE_ALLOW_LOOT;
break;
case GROUP_PERMISSION:
if (!item.is_blocked)
lootItem.UIType = LOOT_SLOT_TYPE_ALLOW_LOOT;
else
lootItem.UIType = LOOT_SLOT_TYPE_ROLL_ONGOING;
break;
default:
lootItem.UIType = slotType;
break;
}
case MASTER_PERMISSION:
lootItem.UIType = LOOT_SLOT_TYPE_MASTER;
break;
case RESTRICTED_PERMISSION:
lootItem.UIType = item.is_blocked ? LOOT_SLOT_TYPE_LOCKED : LOOT_SLOT_TYPE_ALLOW_LOOT;
break;
case GROUP_PERMISSION:
if (!item.is_blocked)
lootItem.UIType = LOOT_SLOT_TYPE_ALLOW_LOOT;
else
lootItem.UIType = LOOT_SLOT_TYPE_ROLL_ONGOING;
break;
default:
lootItem.UIType = slotType;
break;
}
else
lootItem.UIType = slotType;
packet.Items.push_back(lootItem);
}
@@ -668,7 +663,7 @@ void Loot::FillNotNormalLootFor(Player* player, bool presentAtLooting)
{
ObjectGuid plguid = player->GetGUID();
QuestItemMap::const_iterator qmapitr = PlayerQuestItems.find(plguid);
NotNormalLootItemMap::const_iterator qmapitr = PlayerQuestItems.find(plguid);
if (qmapitr == PlayerQuestItems.end())
FillQuestLoot(player);
@@ -702,16 +697,16 @@ void Loot::FillNotNormalLootFor(Player* player, bool presentAtLooting)
}
}
QuestItemList* Loot::FillFFALoot(Player* player)
NotNormalLootItemList* Loot::FillFFALoot(Player* player)
{
QuestItemList* ql = new QuestItemList();
NotNormalLootItemList* ql = new NotNormalLootItemList();
for (uint8 i = 0; i < items.size(); ++i)
{
LootItem &item = items[i];
if (!item.is_looted && item.freeforall && item.AllowedForPlayer(player))
{
ql->push_back(QuestItem(i));
ql->push_back(NotNormalLootItem(i));
++unlootedCount;
}
}
@@ -725,12 +720,12 @@ QuestItemList* Loot::FillFFALoot(Player* player)
return ql;
}
QuestItemList* Loot::FillQuestLoot(Player* player)
NotNormalLootItemList* Loot::FillQuestLoot(Player* player)
{
if (items.size() == MAX_NR_LOOT_ITEMS)
return NULL;
QuestItemList* ql = new QuestItemList();
NotNormalLootItemList* ql = new NotNormalLootItemList();
for (uint8 i = 0; i < quest_items.size(); ++i)
{
@@ -738,7 +733,7 @@ QuestItemList* Loot::FillQuestLoot(Player* player)
if (!item.is_looted && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT))))
{
ql->push_back(QuestItem(i));
ql->push_back(NotNormalLootItem(i));
// quest items get blocked when they first appear in a
// player's quest vector
@@ -763,20 +758,20 @@ QuestItemList* Loot::FillQuestLoot(Player* player)
return ql;
}
QuestItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting)
NotNormalLootItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting)
{
QuestItemList* ql = new QuestItemList();
NotNormalLootItemList* ql = new NotNormalLootItemList();
for (uint8 i = 0; i < items.size(); ++i)
{
LootItem &item = items[i];
if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT))))
if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player)))
{
if (presentAtLooting)
item.AddAllowedLooter(player);
if (!item.conditions.empty())
{
ql->push_back(QuestItem(i));
ql->push_back(NotNormalLootItem(i));
if (!item.is_counted)
{
++unlootedCount;
+16 -16
View File
@@ -165,21 +165,21 @@ struct TC_GAME_API LootItem
GuidSet const& GetAllowedLooters() const { return allowedGUIDs; }
};
struct QuestItem
struct NotNormalLootItem
{
uint8 index; // position in quest_items;
uint8 index; // position in quest_items or items;
bool is_looted;
QuestItem()
NotNormalLootItem()
: index(0), is_looted(false) { }
QuestItem(uint8 _index, bool _islooted = false)
NotNormalLootItem(uint8 _index, bool _islooted = false)
: index(_index), is_looted(_islooted) { }
};
typedef std::vector<QuestItem> QuestItemList;
typedef std::vector<NotNormalLootItem> NotNormalLootItemList;
typedef std::vector<LootItem> LootItemList;
typedef std::unordered_map<ObjectGuid, QuestItemList*> QuestItemMap;
typedef std::unordered_map<ObjectGuid, NotNormalLootItemList*> NotNormalLootItemMap;
//=====================================================
@@ -208,9 +208,9 @@ public:
struct TC_GAME_API Loot
{
QuestItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; }
QuestItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; }
QuestItemMap const& GetPlayerNonQuestNonFFAConditionalItems() const { return PlayerNonQuestNonFFAConditionalItems; }
NotNormalLootItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; }
NotNormalLootItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; }
NotNormalLootItemMap const& GetPlayerNonQuestNonFFAConditionalItems() const { return PlayerNonQuestNonFFAConditionalItems; }
std::vector<LootItem> items;
std::vector<LootItem> quest_items;
@@ -258,7 +258,7 @@ struct TC_GAME_API Loot
void AddItem(LootStoreItem const & item);
LootItem const* GetItemInSlot(uint32 lootSlot) const;
LootItem* LootItemInSlot(uint32 lootslot, Player* player, QuestItem** qitem = NULL, QuestItem** ffaitem = NULL, QuestItem** conditem = NULL);
LootItem* LootItemInSlot(uint32 lootslot, Player* player, NotNormalLootItem** qitem = NULL, NotNormalLootItem** ffaitem = NULL, NotNormalLootItem** conditem = NULL);
uint32 GetMaxSlotInLootFor(Player* player) const;
bool hasItemForAll() const;
bool hasItemFor(Player* player) const;
@@ -270,14 +270,14 @@ struct TC_GAME_API Loot
private:
void FillNotNormalLootFor(Player* player, bool presentAtLooting);
QuestItemList* FillFFALoot(Player* player);
QuestItemList* FillQuestLoot(Player* player);
QuestItemList* FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting);
NotNormalLootItemList* FillFFALoot(Player* player);
NotNormalLootItemList* FillQuestLoot(Player* player);
NotNormalLootItemList* FillNonQuestNonFFAConditionalLoot(Player* player, bool presentAtLooting);
GuidSet PlayersLooting;
QuestItemMap PlayerQuestItems;
QuestItemMap PlayerFFAItems;
QuestItemMap PlayerNonQuestNonFFAConditionalItems;
NotNormalLootItemMap PlayerQuestItems;
NotNormalLootItemMap PlayerFFAItems;
NotNormalLootItemMap PlayerNonQuestNonFFAConditionalItems;
// All rolls are registered here. They need to know, when the loot is not valid anymore
LootValidatorRefManager i_LootValidatorRefManager;