mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-14 17:49:10 +00:00
fix(Core/Loot): Items below group threshold should not be blocked by master looter. (#5041)
This commit is contained in:
@@ -25705,9 +25705,9 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
|
||||
return;
|
||||
}
|
||||
|
||||
// Xinef: exploit protection, dont allow to loot normal items if player is not master loot
|
||||
// Xinef: exploit protection, dont allow to loot normal items if player is not master loot and not below loot threshold
|
||||
// Xinef: only quest, ffa and conditioned items
|
||||
if (!IS_ITEM_GUID(GetLootGUID()) && GetGroup() && GetGroup()->GetLootMethod() == MASTER_LOOT && GetGUID() != GetGroup()->GetMasterLooterGuid())
|
||||
if (!item->is_underthreshold && !IS_ITEM_GUID(GetLootGUID()) && GetGroup() && GetGroup()->GetLootMethod() == MASTER_LOOT && GetGUID() != GetGroup()->GetMasterLooterGuid())
|
||||
if (qitem == nullptr && ffaitem == nullptr && conditem == nullptr)
|
||||
{
|
||||
SendLootRelease(GetLootGUID());
|
||||
|
||||
@@ -474,7 +474,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
|
||||
|
||||
ItemPosCountVec dest;
|
||||
InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count);
|
||||
if (item.follow_loot_rules && !item.AllowedForPlayer(target))
|
||||
if (!item.AllowedForPlayer(target, true))
|
||||
msg = EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||
if (msg != EQUIP_ERR_OK)
|
||||
{
|
||||
@@ -485,7 +485,6 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
|
||||
else
|
||||
_player->SendLootError(lootguid, LOOT_ERROR_MASTER_OTHER);
|
||||
|
||||
target->SendEquipError(msg, nullptr, nullptr, item.itemid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -387,19 +387,28 @@ LootItem::LootItem(LootStoreItem const& li)
|
||||
}
|
||||
|
||||
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
|
||||
bool LootItem::AllowedForPlayer(Player const* player) const
|
||||
bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter /*= false*/, bool allowQuestLoot /*= true*/) const
|
||||
{
|
||||
// DB conditions check
|
||||
if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(player), conditions))
|
||||
return false;
|
||||
|
||||
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
|
||||
if (!pProto)
|
||||
return false;
|
||||
|
||||
// not show loot for players without profession or those who already know the recipe
|
||||
if ((pProto->Flags & ITEM_FLAG_HIDE_UNUSABLE_RECIPE) && (!player->HasSkill(pProto->RequiredSkill) || player->HasSpell(pProto->Spells[1].SpellId)))
|
||||
bool isMasterLooter = player->GetGroup() && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID();
|
||||
|
||||
// DB conditions check
|
||||
if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(player), conditions))
|
||||
{
|
||||
// Master Looter can see conditioned recipes
|
||||
if (!isGivenByMasterLooter && isMasterLooter)
|
||||
{
|
||||
if ((pProto->Flags & ITEM_FLAG_HIDE_UNUSABLE_RECIPE) || (pProto->Class == ITEM_CLASS_RECIPE && pProto->Bonding == BIND_WHEN_PICKED_UP && pProto->Spells[1].SpellId != 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// not show loot for not own team
|
||||
if ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && player->GetTeamId(true) != TEAM_HORDE)
|
||||
@@ -408,6 +417,26 @@ bool LootItem::AllowedForPlayer(Player const* player) const
|
||||
if ((pProto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && player->GetTeamId(true) != TEAM_ALLIANCE)
|
||||
return false;
|
||||
|
||||
// Master looter can see certain items even if the character can't loot them
|
||||
if (!isGivenByMasterLooter && isMasterLooter && allowQuestLoot)
|
||||
{
|
||||
// check quest requirements (exclude items not under threshold)
|
||||
if (!(pProto->FlagsCu & ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && (needs_quest || pProto->StartQuest))
|
||||
{
|
||||
return !is_underthreshold;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't allow loot for players without profession or those who already know the recipe
|
||||
if ((pProto->Flags & ITEM_FLAG_HIDE_UNUSABLE_RECIPE) && (!player->HasSkill(pProto->RequiredSkill) || player->HasSpell(pProto->Spells[1].SpellId)))
|
||||
return false;
|
||||
|
||||
// Don't allow to loot soulbound recipes that the player has already learned
|
||||
if (pProto->Class == ITEM_CLASS_RECIPE && pProto->Bonding == BIND_WHEN_PICKED_UP && pProto->Spells[1].SpellId != 0 && player->HasSpell(pProto->Spells[1].SpellId))
|
||||
return false;
|
||||
|
||||
// check quest requirements
|
||||
if (!(pProto->FlagsCu & ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && ((needs_quest || (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE)) && !player->HasQuestForItem(itemid)))
|
||||
return false;
|
||||
@@ -571,7 +600,7 @@ QuestItemList* Loot::FillQuestLoot(Player* player)
|
||||
{
|
||||
LootItem& item = quest_items[i];
|
||||
|
||||
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 ))))
|
||||
if (!item.is_looted && (item.AllowedForPlayer(player, false, false) || (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));
|
||||
|
||||
@@ -887,11 +916,13 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
|
||||
case MASTER_PERMISSION:
|
||||
case RESTRICTED_PERMISSION:
|
||||
{
|
||||
bool isMasterLooter = lv.viewer->GetGroup() && lv.viewer->GetGroup()->GetMasterLooterGuid() == lv.viewer->GetGUID();
|
||||
|
||||
// if you are not the round-robin group looter, you can only see
|
||||
// blocked rolled items and quest items, and !ffa items
|
||||
for (uint8 i = 0; i < l.items.size(); ++i)
|
||||
{
|
||||
if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer))
|
||||
if (!l.items[i].is_looted && !l.items[i].freeforall && (l.items[i].conditions.empty() || isMasterLooter) && l.items[i].AllowedForPlayer(lv.viewer))
|
||||
{
|
||||
uint8 slot_type = 0;
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ struct LootItem
|
||||
LootItem() = default;
|
||||
|
||||
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
|
||||
bool AllowedForPlayer(Player const* player) const;
|
||||
bool AllowedForPlayer(Player const* player, bool isGivenByMasterLooter = false, bool allowQuestLoot = true) const;
|
||||
|
||||
void AddAllowedLooter(Player const* player);
|
||||
[[nodiscard]] const AllowedLooterSet& GetAllowedLooters() const { return allowedGUIDs; }
|
||||
|
||||
Reference in New Issue
Block a user