fix(Core/LFG): prevent RDF anti-kick exploit via loot rolls (#25112)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
82eaf7506b
commit
3f0c60c1dd
4 changed files with 38 additions and 30 deletions
|
|
@ -13040,7 +13040,7 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid targetPlayerGUID) const
|
|||
if (state == lfg::LFG_STATE_FINISHED_DUNGEON)
|
||||
return ERR_PARTY_LFG_BOOT_DUNGEON_COMPLETE;
|
||||
|
||||
if (grp->isRollLootActive())
|
||||
if (grp->isRollLootActive() && ObjectAccessor::FindConnectedPlayer(targetPlayerGUID))
|
||||
return ERR_PARTY_LFG_BOOT_LOOT_ROLLS;
|
||||
|
||||
/// @todo: Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer.
|
||||
|
|
|
|||
|
|
@ -600,35 +600,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
|
|||
}
|
||||
|
||||
// Remove player from loot rolls
|
||||
for (Rolls::iterator it = RollId.begin(); it != RollId.end();)
|
||||
{
|
||||
Roll* roll = *it;
|
||||
Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);
|
||||
if (itr2 == roll->playerVote.end())
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itr2->second == GREED || itr2->second == DISENCHANT)
|
||||
--roll->totalGreed;
|
||||
else if (itr2->second == NEED)
|
||||
--roll->totalNeed;
|
||||
else if (itr2->second == PASS)
|
||||
--roll->totalPass;
|
||||
|
||||
if (itr2->second != NOT_VALID)
|
||||
--roll->totalPlayersRolling;
|
||||
|
||||
roll->playerVote.erase(itr2);
|
||||
|
||||
// Xinef: itr can be erased inside
|
||||
// Xinef: player is removed from all vote lists so it will not pass above playerVote == playerVote.end statement during second iteration
|
||||
if (CountRollVote(guid, roll->itemGUID, MAX_ROLL_TYPE))
|
||||
it = RollId.begin();
|
||||
else
|
||||
++it;
|
||||
}
|
||||
RemovePlayerFromRolls(guid);
|
||||
|
||||
// Update subgroups
|
||||
member_witerator slot = _getMemberWSlot(guid);
|
||||
|
|
@ -1422,6 +1394,37 @@ void Group::EndRoll(Loot* pLoot, Map* allowedMap)
|
|||
}
|
||||
}
|
||||
|
||||
void Group::RemovePlayerFromRolls(ObjectGuid guid)
|
||||
{
|
||||
for (Rolls::iterator it = RollId.begin(); it != RollId.end();)
|
||||
{
|
||||
Roll* roll = *it;
|
||||
Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);
|
||||
if (itr2 == roll->playerVote.end())
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itr2->second == GREED || itr2->second == DISENCHANT)
|
||||
--roll->totalGreed;
|
||||
else if (itr2->second == NEED)
|
||||
--roll->totalNeed;
|
||||
else if (itr2->second == PASS)
|
||||
--roll->totalPass;
|
||||
|
||||
if (itr2->second != NOT_VALID)
|
||||
--roll->totalPlayersRolling;
|
||||
|
||||
roll->playerVote.erase(itr2);
|
||||
|
||||
if (CountRollVote(guid, roll->itemGUID, MAX_ROLL_TYPE))
|
||||
it = RollId.begin();
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
|
||||
{
|
||||
Roll* roll = *rollI;
|
||||
|
|
|
|||
|
|
@ -299,6 +299,7 @@ public:
|
|||
void CountTheRoll(Rolls::iterator roll, Map* allowedMap);
|
||||
bool CountRollVote(ObjectGuid playerGUID, ObjectGuid Guid, uint8 Choise);
|
||||
void EndRoll(Loot* loot, Map* allowedMap);
|
||||
void RemovePlayerFromRolls(ObjectGuid guid);
|
||||
|
||||
// related to disenchant rolls
|
||||
void ResetMaxEnchantingLevel();
|
||||
|
|
|
|||
|
|
@ -702,6 +702,10 @@ void WorldSession::LogoutPlayer(bool save)
|
|||
// a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) d) LeaveGroupOnLogout is enabled
|
||||
if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && !_player->GetGroup()->isLFGGroup() && m_Socket && sWorld->getBoolConfig(CONFIG_LEAVE_GROUP_ON_LOGOUT))
|
||||
_player->RemoveFromGroup();
|
||||
// Remove player from active loot rolls in LFG groups (player stays in group but should not block rolls)
|
||||
else if (Group* group = _player->GetGroup())
|
||||
if (group->isLFGGroup())
|
||||
group->RemovePlayerFromRolls(_player->GetGUID());
|
||||
|
||||
// pussywizard: checked second time after being removed from a group
|
||||
if (!_player->IsBeingTeleportedFar() && !_player->m_InstanceValid && !_player->IsGameMaster())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue