fix(Core/Player): Loot Chest eligibility and re-send loot rolls (#26469)

This commit is contained in:
sogladev
2026-07-19 00:57:27 +02:00
committed by GitHub
parent 01b1fb6205
commit 37c723895b
3 changed files with 83 additions and 4 deletions

View File

@@ -7896,6 +7896,15 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
// get next RR player (for next loot)
if (groupRules && !go->loot.empty())
group->UpdateLooterGuid(go);
if (groupRules)
{
GuidUnorderedSet const& allowedLooters = go->GetAllowedLooters();
if (!allowedLooters.empty())
for (ObjectGuid const& allowedGuid : allowedLooters)
if (Player* allowedPlayer = ObjectAccessor::FindPlayer(allowedGuid))
loot->FillNotNormalLootFor(allowedPlayer);
}
}
if (GameObjectTemplateAddon const* addon = go->GetTemplateAddon())
loot->generateMoneyLoot(addon->mingold, addon->maxgold);
@@ -11761,6 +11770,13 @@ void Player::SendInitialPacketsAfterAddToMap()
}
else if (GetRaidDifficulty() != GetStoredRaidDifficulty())
SendRaidDifficulty(GetGroup() != nullptr);
// Re-send any pending group loot rolls to this player when they enter a dungeon/raid.
if (Map* map = GetMap())
if (map->IsDungeon() || map->IsRaid())
if (Group* group = GetGroup())
group->SendPendingRollsToPlayer(this, map);
}
void Player::SendUpdateToOutOfRangeGroupMembers()

View File

@@ -880,6 +880,50 @@ void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll& r)
}
}
void Group::SendPendingRollsToPlayer(Player* player, Map* map)
{
for (Roll* roll : RollId)
{
auto itr = roll->playerVote.find(player->GetGUID());
if (itr == roll->playerVote.end())
continue;
if (itr->second != NOT_EMITED_YET)
continue;
Loot* loot = roll->getLoot();
if (!loot)
continue;
// Get remaining time from the loot source object
uint32 remainingTime = 60000;
WorldObject* lootedObject = nullptr;
if (GameObject* go = loot->sourceGameObject)
{
remainingTime = go->m_groupLootTimer;
lootedObject = go;
}
else if (!loot->sourceWorldObjectGUID.IsEmpty())
{
if (Creature* creature = map->GetCreature(loot->sourceWorldObjectGUID))
{
remainingTime = creature->m_groupLootTimer;
lootedObject = creature;
}
}
bool canNeed = true;
if (GetLootMethod() == NEED_BEFORE_GREED)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(roll->itemid);
if (proto && lootedObject)
canNeed = (player->CanRollForItemInLFG(proto, lootedObject) == EQUIP_ERR_OK);
}
SendLootStartRollToPlayer(remainingTime, map->GetId(), player, canNeed, *roll);
}
}
void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, bool canNeed, Roll const& r)
{
if (!p)
@@ -1036,7 +1080,12 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
Player* member = itr->GetSource();
if (!member || !member->GetSession())
continue;
if (member->IsAtLootRewardDistance(pLootedObject))
bool canLoot = member->IsAtLootRewardDistance(pLootedObject);
if (!canLoot && !pLootedObject->GetAllowedLooters().empty())
canLoot = pLootedObject->HasAllowedLooter(member->GetGUID());
if (canLoot)
{
r->totalPlayersRolling++;
@@ -1122,7 +1171,11 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
if (!member || !member->GetSession())
continue;
if (member->IsAtLootRewardDistance(pLootedObject))
bool canLoot = member->IsAtLootRewardDistance(pLootedObject);
if (!canLoot && !pLootedObject->GetAllowedLooters().empty())
canLoot = pLootedObject->HasAllowedLooter(member->GetGUID());
if (canLoot)
{
r->totalPlayersRolling++;
@@ -1186,7 +1239,11 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
if (!playerToRoll || !playerToRoll->GetSession())
continue;
if (playerToRoll->IsAtGroupRewardDistance(lootedObject))
bool canLoot = playerToRoll->IsAtGroupRewardDistance(lootedObject);
if (!canLoot && !lootedObject->GetAllowedLooters().empty())
canLoot = lootedObject->HasAllowedLooter(playerToRoll->GetGUID());
if (canLoot)
{
r->totalPlayersRolling++;
@@ -1335,6 +1392,7 @@ void Group::MasterLoot(Loot* loot, WorldObject* pLootedObject)
}
std::vector<Player*> looters;
bool hasAllowedLooters = !pLootedObject->GetAllowedLooters().empty();
for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
{
Player* looter = itr->GetSource();
@@ -1343,7 +1401,11 @@ void Group::MasterLoot(Loot* loot, WorldObject* pLootedObject)
continue;
}
if (looter->IsAtLootRewardDistance(pLootedObject))
bool canLoot = looter->IsAtLootRewardDistance(pLootedObject);
if (!canLoot && hasAllowedLooters)
canLoot = pLootedObject->HasAllowedLooter(looter->GetGUID());
if (canLoot)
{
looters.push_back(looter);
}

View File

@@ -295,6 +295,7 @@ public:
bool isRollLootActive() const;
void SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll& r);
void SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, bool canNeed, Roll const& r);
void SendPendingRollsToPlayer(Player* player, Map* map);
void SendLootRoll(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, const Roll& r, bool autoPass = false);
void SendLootRollWon(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, const Roll& r);
void SendLootAllPassed(Roll const& roll);