mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-18 11:25:42 +00:00
fix(Core/Loot): implement automatic pass in group loot for items that… (#19272)
* fix(Core/Loot): implement automatic pass in group loot for items that cannot be looted
* cherry-pick commit (00fdf6e99a)
* closes https://github.com/chromiecraft/chromiecraft/issues/4523
Co-Authored-By: Wyrserth <43747507+Wyrserth@users.noreply.github.com>
* whoopise
---------
Co-authored-by: Wyrserth <43747507+Wyrserth@users.noreply.github.com>
This commit is contained in:
@@ -898,7 +898,7 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p,
|
||||
p->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Group::SendLootRoll(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 rollNumber, uint8 rollType, Roll const& roll)
|
||||
void Group::SendLootRoll(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 rollNumber, uint8 rollType, Roll const& roll, bool autoPass)
|
||||
{
|
||||
WorldPacket data(SMSG_LOOT_ROLL, (8 + 4 + 8 + 4 + 4 + 4 + 1 + 1 + 1));
|
||||
data << sourceGuid; // guid of the item rolled
|
||||
@@ -909,7 +909,7 @@ void Group::SendLootRoll(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 rol
|
||||
data << uint32(roll.itemRandomPropId); // Item random property ID
|
||||
data << uint8(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number
|
||||
data << uint8(rollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll
|
||||
data << uint8(0); // 1: "You automatically passed on: %s because you cannot loot that item." - Possibly used in need befor greed
|
||||
data << uint8(autoPass); // 1: "You automatically passed on: %s because you cannot loot that item."
|
||||
|
||||
for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr)
|
||||
{
|
||||
@@ -986,6 +986,23 @@ void Group::SendLooter(Creature* creature, Player* groupLooter)
|
||||
BroadcastPacket(&data, false);
|
||||
}
|
||||
|
||||
bool CanRollOnItem(LootItem const& item, Player const* player, Loot* loot)
|
||||
{
|
||||
// Players can't roll on unique items if they already reached the maximum quantity of that item
|
||||
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item.itemid);
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
uint32 itemCount = player->GetItemCount(item.itemid);
|
||||
if ((proto->MaxCount > 0 && static_cast<int32>(itemCount) >= proto->MaxCount) || (player->CanEquipUniqueItem(proto) != EQUIP_ERR_OK))
|
||||
return false;
|
||||
|
||||
if (!item.AllowedForPlayer(player, loot->sourceWorldObjectGUID))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
|
||||
{
|
||||
std::vector<LootItem>::iterator i;
|
||||
@@ -1013,23 +1030,20 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
|
||||
for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* member = itr->GetSource();
|
||||
if (!member)
|
||||
if (!member || !member->GetSession())
|
||||
continue;
|
||||
if (member->IsAtLootRewardDistance(pLootedObject))
|
||||
{
|
||||
if (i->AllowedForPlayer(member, loot->sourceWorldObjectGUID))
|
||||
{
|
||||
r->totalPlayersRolling++;
|
||||
r->totalPlayersRolling++;
|
||||
|
||||
if (member->GetPassOnGroupLoot())
|
||||
{
|
||||
r->playerVote[member->GetGUID()] = PASS;
|
||||
r->totalPass++;
|
||||
// can't broadcast the pass now. need to wait until all rolling players are known.
|
||||
}
|
||||
else
|
||||
r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
|
||||
RollVote vote = member->GetPassOnGroupLoot() ? PASS : NOT_EMITED_YET;
|
||||
if (!CanRollOnItem(*i, member, loot))
|
||||
{
|
||||
vote = PASS;
|
||||
++r->totalPass;
|
||||
}
|
||||
|
||||
r->playerVote[member->GetGUID()] = vote;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1052,23 +1066,28 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
|
||||
continue;
|
||||
|
||||
if (itr->second == PASS)
|
||||
SendLootRoll(newitemGUID, p->GetGUID(), 128, ROLL_PASS, *r);
|
||||
SendLootRoll(newitemGUID, p->GetGUID(), 128, ROLL_PASS, *r, true);
|
||||
}
|
||||
}
|
||||
|
||||
SendLootStartRoll(60000, pLootedObject->GetMapId(), *r);
|
||||
|
||||
RollId.push_back(r);
|
||||
|
||||
if (Creature* creature = pLootedObject->ToCreature())
|
||||
if (r->totalPass == r->totalPlayersRolling)
|
||||
delete r;
|
||||
else
|
||||
{
|
||||
creature->m_groupLootTimer = 60000;
|
||||
creature->lootingGroupLowGUID = GetGUID().GetCounter();
|
||||
}
|
||||
else if (GameObject* go = pLootedObject->ToGameObject())
|
||||
{
|
||||
go->m_groupLootTimer = 60000;
|
||||
go->lootingGroupLowGUID = GetGUID().GetCounter();
|
||||
SendLootStartRoll(60000, pLootedObject->GetMapId(), *r);
|
||||
|
||||
RollId.push_back(r);
|
||||
|
||||
if (Creature* creature = pLootedObject->ToCreature())
|
||||
{
|
||||
creature->m_groupLootTimer = 60000;
|
||||
creature->lootingGroupLowGUID = GetGUID().GetCounter();
|
||||
}
|
||||
else if (GameObject* go = pLootedObject->ToGameObject())
|
||||
{
|
||||
go->m_groupLootTimer = 60000;
|
||||
go->lootingGroupLowGUID = GetGUID().GetCounter();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1096,16 +1115,18 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
|
||||
for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* member = itr->GetSource();
|
||||
if (!member)
|
||||
if (!member || !member->GetSession())
|
||||
continue;
|
||||
|
||||
if (member->IsAtLootRewardDistance(pLootedObject))
|
||||
{
|
||||
if (i->AllowedForPlayer(member, loot->sourceWorldObjectGUID))
|
||||
RollVote vote = NOT_EMITED_YET;
|
||||
if (!CanRollOnItem(*i, member, loot))
|
||||
{
|
||||
r->totalPlayersRolling++;
|
||||
r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
|
||||
vote = PASS;
|
||||
++r->totalPass;
|
||||
}
|
||||
r->playerVote[member->GetGUID()] = vote;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1156,20 +1177,21 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
|
||||
for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* playerToRoll = itr->GetSource();
|
||||
if (!playerToRoll)
|
||||
if (!playerToRoll || !playerToRoll->GetSession())
|
||||
continue;
|
||||
|
||||
if (i->AllowedForPlayer(playerToRoll, loot->sourceWorldObjectGUID) && playerToRoll->IsAtLootRewardDistance(lootedObject))
|
||||
if (playerToRoll->IsAtGroupRewardDistance(lootedObject))
|
||||
{
|
||||
r->totalPlayersRolling++;
|
||||
if (playerToRoll->GetPassOnGroupLoot())
|
||||
|
||||
RollVote vote = playerToRoll->GetPassOnGroupLoot() ? PASS : NOT_EMITED_YET;
|
||||
if (!CanRollOnItem(*i, playerToRoll, loot))
|
||||
{
|
||||
r->playerVote[playerToRoll->GetGUID()] = PASS;
|
||||
r->totalPass++;
|
||||
// can't broadcast the pass now. need to wait until all rolling players are known.
|
||||
vote = PASS;
|
||||
r->totalPass++; // Can't broadcast the pass now. need to wait until all rolling players are known
|
||||
}
|
||||
else
|
||||
r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
|
||||
|
||||
r->playerVote[playerToRoll->GetGUID()] = vote;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1230,13 +1252,21 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
|
||||
for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* playerToRoll = itr->GetSource();
|
||||
if (!playerToRoll)
|
||||
if (!playerToRoll || !playerToRoll->GetSession())
|
||||
continue;
|
||||
|
||||
if (i->AllowedForPlayer(playerToRoll, loot->sourceWorldObjectGUID) && playerToRoll->IsAtLootRewardDistance(lootedObject))
|
||||
if (playerToRoll->IsAtGroupRewardDistance(lootedObject))
|
||||
{
|
||||
r->totalPlayersRolling++;
|
||||
r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
|
||||
|
||||
RollVote vote = playerToRoll->GetPassOnGroupLoot() ? PASS : NOT_EMITED_YET;
|
||||
if (!CanRollOnItem(*i, playerToRoll, loot))
|
||||
{
|
||||
vote = PASS;
|
||||
r->totalPass++; // Can't broadcast the pass now. need to wait until all rolling players are known
|
||||
}
|
||||
|
||||
r->playerVote[playerToRoll->GetGUID()] = vote;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user