aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp17
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/Handlers/LootHandler.cpp21
-rw-r--r--src/server/game/Loot/Loot.cpp26
-rw-r--r--src/server/game/Loot/Loot.h7
-rw-r--r--src/server/game/Loot/LootItemStorage.cpp2
6 files changed, 56 insertions, 18 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8983ebf69c4..c201032cf77 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -17888,7 +17888,7 @@ bool Player::isAllowedToLoot(const Creature* creature) const
Loot const* loot = creature->GetLootForPlayer(this);
if (!loot || loot->isLooted()) // nothing to loot or everything looted.
return false;
- if (!loot->hasItemForAll() && !loot->hasItemFor(this)) // no loot in creature for this player
+ if (!loot->HasAllowedLooter(GetGUID()) || (!loot->hasItemForAll() && !loot->hasItemFor(this))) // no loot in creature for this player
return false;
if (loot->loot_type == LOOT_SKINNING)
@@ -20660,6 +20660,19 @@ void Player::SendResetInstanceFailed(ResetFailedReason reason, uint32 mapID) con
SendDirectMessage(data.Write());
}
+bool Player::IsLockedToDungeonEncounter(uint32 dungeonEncounterId) const
+{
+ DungeonEncounterEntry const* dungeonEncounter = sDungeonEncounterStore.LookupEntry(dungeonEncounterId);
+ if (!dungeonEncounter)
+ return false;
+
+ InstanceLock const* instanceLock = sInstanceLockMgr.FindActiveInstanceLock(GetGUID(), { GetMap()->GetEntry(), GetMap()->GetMapDifficulty() });
+ if (!instanceLock)
+ return false;
+
+ return (instanceLock->GetData()->CompletedEncountersMask & (1u << dungeonEncounter->Bit)) != 0;
+}
+
/*********************************************************/
/*** Update timers ***/
/*********************************************************/
@@ -25434,7 +25447,7 @@ void Player::StoreLootItem(ObjectGuid lootWorldObjectGuid, uint8 lootSlot, Loot*
return;
}
- if (!item->AllowedForPlayer(this))
+ if (!item->HasAllowedLooter(GetGUID()))
{
SendLootReleaseAll();
return;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index c23b658998e..160529696fe 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2091,6 +2091,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SendResetInstanceSuccess(uint32 MapId) const;
void SendResetInstanceFailed(ResetFailedReason reason, uint32 mapID) const;
void SendResetFailedNotify(uint32 mapid) const;
+ bool IsLockedToDungeonEncounter(uint32 dungeonEncounterId) const;
bool UpdatePosition(float x, float y, float z, float orientation, bool teleport = false) override;
bool UpdatePosition(Position const& pos, bool teleport = false) override { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); }
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index eb27319992e..ed1ed76be36 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -159,6 +159,9 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
if (!member)
continue;
+ if (!loot->HasAllowedLooter(member->GetGUID()))
+ continue;
+
if (player->IsAtGroupRewardDistance(member))
playersNear.push_back(member);
}
@@ -404,15 +407,21 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPackets::Loot::MasterLootItem
{
Loot* loot = Trinity::Containers::MapGetValuePtr(_player->GetAELootView(), req.Object);
+ if (!loot || loot->GetLootMethod() != MASTER_LOOT)
+ return;
+
if (!_player->IsInRaidWith(target) || !_player->IsInMap(target))
{
- _player->SendLootError(req.Object, ObjectGuid::Empty, LOOT_ERROR_MASTER_OTHER);
+ _player->SendLootError(req.Object, loot->GetOwnerGUID(), LOOT_ERROR_MASTER_OTHER);
TC_LOG_INFO("entities.player.cheat", "MasterLootItem: Player %s tried to give an item to ineligible player %s !", GetPlayer()->GetName().c_str(), target->GetName().c_str());
return;
}
- if (!loot || loot->GetLootMethod() != MASTER_LOOT)
+ if (!loot->HasAllowedLooter(masterLootItem.Target))
+ {
+ _player->SendLootError(req.Object, loot->GetOwnerGUID(), LOOT_ERROR_MASTER_OTHER);
return;
+ }
if (req.LootListID >= loot->items.size())
{
@@ -425,16 +434,16 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPackets::Loot::MasterLootItem
ItemPosCountVec dest;
InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count);
- if (!item.AllowedForPlayer(target, true))
+ if (!item.HasAllowedLooter(target->GetGUID()))
msg = EQUIP_ERR_CANT_EQUIP_EVER;
if (msg != EQUIP_ERR_OK)
{
if (msg == EQUIP_ERR_ITEM_MAX_COUNT)
- _player->SendLootError(req.Object, ObjectGuid::Empty, LOOT_ERROR_MASTER_UNIQUE_ITEM);
+ _player->SendLootError(req.Object, loot->GetOwnerGUID(), LOOT_ERROR_MASTER_UNIQUE_ITEM);
else if (msg == EQUIP_ERR_INV_FULL)
- _player->SendLootError(req.Object, ObjectGuid::Empty, LOOT_ERROR_MASTER_INV_FULL);
+ _player->SendLootError(req.Object, loot->GetOwnerGUID(), LOOT_ERROR_MASTER_INV_FULL);
else
- _player->SendLootError(req.Object, ObjectGuid::Empty, LOOT_ERROR_MASTER_OTHER);
+ _player->SendLootError(req.Object, loot->GetOwnerGUID(), LOOT_ERROR_MASTER_OTHER);
return;
}
diff --git a/src/server/game/Loot/Loot.cpp b/src/server/game/Loot/Loot.cpp
index 91eac407aaa..d67f9ea55d9 100644
--- a/src/server/game/Loot/Loot.cpp
+++ b/src/server/game/Loot/Loot.cpp
@@ -68,7 +68,7 @@ LootItem& LootItem::operator=(LootItem&&) noexcept = default;
LootItem::~LootItem() = default;
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
-bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter) const
+bool LootItem::AllowedForPlayer(Player const* player, Loot const& loot) const
{
// DB conditions check
if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(player), conditions))
@@ -86,10 +86,8 @@ bool LootItem::AllowedForPlayer(Player const* player, bool isGivenByMasterLooter
return false;
// Master looter can see all items even if the character can't loot them
- if (!isGivenByMasterLooter && player->GetGroup() && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID())
- {
+ if (loot.GetLootMethod() == MASTER_LOOT && follow_loot_rules && player->GetGroup() && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID())
return true;
- }
// Don't allow loot for players without profession or those who already know the recipe
if (pProto->HasFlag(ITEM_FLAG_HIDE_UNUSABLE_RECIPE))
@@ -132,6 +130,11 @@ void LootItem::AddAllowedLooter(const Player* player)
allowedGUIDs.insert(player->GetGUID());
}
+bool LootItem::HasAllowedLooter(ObjectGuid const& looter) const
+{
+ return allowedGUIDs.find(looter) != allowedGUIDs.end();
+}
+
Optional<LootSlotType> LootItem::GetUiTypeForPlayer(Player const* player, Loot const& loot) const
{
if (is_looted)
@@ -405,7 +408,7 @@ bool LootRoll::TryToStart(Map* map, Loot& loot, uint32 lootListId, uint16 enchan
for (ObjectGuid allowedLooter : m_lootItem->GetAllowedLooters())
{
Player* plr = ObjectAccessor::GetPlayer(m_map, allowedLooter);
- if (!plr || !m_lootItem->AllowedForPlayer(plr)) // check if player meet the condition to be able to roll this item
+ if (!plr || !m_lootItem->HasAllowedLooter(plr->GetGUID())) // check if player meet the condition to be able to roll this item
{
m_rollVoteMap[allowedLooter].Vote = RollVote::NotValid;
continue;
@@ -739,6 +742,11 @@ void Loot::OnLootOpened(Map* map, ObjectGuid looter)
}
}
+bool Loot::HasAllowedLooter(ObjectGuid const& looter) const
+{
+ return _allowedLooters.find(looter) != _allowedLooters.end();
+}
+
void Loot::generateMoneyLoot(uint32 minAmount, uint32 maxAmount)
{
if (maxAmount > 0)
@@ -858,7 +866,7 @@ bool Loot::AutoStore(Player* player, uint8 bag, uint8 slot, bool broadcast, bool
if (!lootItem || lootItem->is_looted)
continue;
- if (!lootItem->AllowedForPlayer(player))
+ if (!lootItem->HasAllowedLooter(player->GetGUID()))
continue;
if (lootItem->is_blocked)
@@ -1012,6 +1020,10 @@ void Loot::Update()
void Loot::FillNotNormalLootFor(Player const* player)
{
+ if (_dungeonEncounterId)
+ if (player->IsLockedToDungeonEncounter(_dungeonEncounterId))
+ return;
+
ObjectGuid plguid = player->GetGUID();
_allowedLooters.insert(plguid);
@@ -1019,7 +1031,7 @@ void Loot::FillNotNormalLootFor(Player const* player)
for (LootItem& item : items)
{
- if (!item.AllowedForPlayer(player))
+ if (!item.AllowedForPlayer(player, *this))
continue;
item.AddAllowedLooter(player);
diff --git a/src/server/game/Loot/Loot.h b/src/server/game/Loot/Loot.h
index fda1cb0e9c7..12f3d559f05 100644
--- a/src/server/game/Loot/Loot.h
+++ b/src/server/game/Loot/Loot.h
@@ -192,10 +192,11 @@ struct TC_GAME_API LootItem
LootItem& operator=(LootItem&&) noexcept;
~LootItem();
- // Basic checks for player/item compatibility - if false no chance to see the item in the loot
- bool AllowedForPlayer(Player const* player, bool isGivenByMasterLooter = false) const;
+ // Basic checks for player/item compatibility - if false no chance to see the item in the loot - used only for loot generation
+ bool AllowedForPlayer(Player const* player, Loot const& loot) const;
void AddAllowedLooter(Player const* player);
GuidSet const& GetAllowedLooters() const { return allowedGUIDs; }
+ bool HasAllowedLooter(ObjectGuid const& looter) const;
Optional<LootSlotType> GetUiTypeForPlayer(Player const* player, Loot const& loot) const;
};
@@ -299,6 +300,8 @@ struct TC_GAME_API Loot
void AddLooter(ObjectGuid GUID) { PlayersLooting.insert(GUID); }
void RemoveLooter(ObjectGuid GUID) { PlayersLooting.erase(GUID); }
+ bool HasAllowedLooter(ObjectGuid const& looter) const;
+
void generateMoneyLoot(uint32 minAmount, uint32 maxAmount);
bool FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bool personal, bool noEmptyError = false, uint16 lootMode = LOOT_MODE_DEFAULT, ItemContext context = ItemContext::NONE);
diff --git a/src/server/game/Loot/LootItemStorage.cpp b/src/server/game/Loot/LootItemStorage.cpp
index 5edb9f7e9fd..c464b6ee914 100644
--- a/src/server/game/Loot/LootItemStorage.cpp
+++ b/src/server/game/Loot/LootItemStorage.cpp
@@ -272,7 +272,7 @@ void LootItemStorage::AddNewStoredLoot(uint64 containerId, Loot* loot, Player* p
// saved to the DB that the player never should have gotten. This check prevents that, so that only
// items that the player should get in loot are in the DB.
// IE: Horde items are not saved to the DB for Ally players.
- if (!li.AllowedForPlayer(player))
+ if (!li.AllowedForPlayer(player, *loot))
continue;
// Don't save currency tokens