diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 17 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Handlers/LootHandler.cpp | 21 | ||||
-rw-r--r-- | src/server/game/Loot/Loot.cpp | 26 | ||||
-rw-r--r-- | src/server/game/Loot/Loot.h | 7 | ||||
-rw-r--r-- | src/server/game/Loot/LootItemStorage.cpp | 2 |
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 |