aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Groups/Group.cpp99
-rw-r--r--src/server/game/Groups/Group.h2
2 files changed, 66 insertions, 35 deletions
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 74fc5cbdfb7..24bc91aad16 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -926,7 +926,7 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p,
p->SendDirectMessage(&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 << uint64(sourceGuid); // guid of the item rolled
@@ -937,7 +937,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)
{
@@ -1014,6 +1014,23 @@ void Group::SendLooter(Creature* creature, Player* groupLooter)
BroadcastPacket(&data, false);
}
+bool CanRollOnItem(const LootItem& item, Player const* player)
+{
+ // 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))
+ return false;
+
+ return true;
+}
+
void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
{
std::vector<LootItem>::iterator i;
@@ -1045,18 +1062,16 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
Player* member = itr->GetSource();
if (!member || !member->GetSession())
continue;
- if (member->IsAtGroupRewardDistance(pLootedObject) && i->AllowedForPlayer(member))
+ if (member->IsAtGroupRewardDistance(pLootedObject))
{
r->totalPlayersRolling++;
-
- if (member->GetPassOnGroupLoot())
+ RollVote vote = member->GetPassOnGroupLoot() ? PASS : NOT_EMITED_YET;
+ if (!CanRollOnItem(*i, member))
{
- r->playerVote[member->GetGUID()] = PASS;
- r->totalPass++;
- // can't broadcast the pass now. need to wait until all rolling players are known.
+ vote = PASS;
+ ++r->totalPass;
}
- else
- r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
+ r->playerVote[member->GetGUID()] = vote;
}
}
@@ -1069,7 +1084,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
loot->items[itemSlot].is_blocked = true;
- // If there is any "auto pass", broadcast the pass now.
+ // If there are any "auto pass", broadcast them now
if (r->totalPass)
{
for (Roll::PlayerVote::const_iterator itr=r->playerVote.begin(); itr != r->playerVote.end(); ++itr)
@@ -1079,23 +1094,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);
+ if (r->totalPass == r->totalPlayersRolling)
+ delete r;
+ else
+ {
+ SendLootStartRoll(60000, pLootedObject->GetMapId(), *r);
- RollId.push_back(r);
+ RollId.push_back(r);
- if (Creature* creature = pLootedObject->ToCreature())
- {
- creature->m_groupLootTimer = 60000;
- creature->lootingGroupLowGUID = GetLowGUID();
- }
- else if (GameObject* go = pLootedObject->ToGameObject())
- {
- go->m_groupLootTimer = 60000;
- go->lootingGroupLowGUID = GetLowGUID();
+ if (Creature* creature = pLootedObject->ToCreature())
+ {
+ creature->m_groupLootTimer = 60000;
+ creature->lootingGroupLowGUID = GetLowGUID();
+ }
+ else if (GameObject* go = pLootedObject->ToGameObject())
+ {
+ go->m_groupLootTimer = 60000;
+ go->lootingGroupLowGUID = GetLowGUID();
+ }
}
}
else
@@ -1128,10 +1148,16 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject)
if (!member || !member->GetSession())
continue;
- if (member->IsAtGroupRewardDistance(pLootedObject) && i->AllowedForPlayer(member))
+ if (member->IsAtGroupRewardDistance(pLootedObject))
{
r->totalPlayersRolling++;
- r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
+ RollVote vote = NOT_EMITED_YET;
+ if (!CanRollOnItem(*i, member))
+ {
+ vote = PASS;
+ ++r->totalPass;
+ }
+ r->playerVote[member->GetGUID()] = vote;
}
}
@@ -1186,17 +1212,16 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
if (!playerToRoll || !playerToRoll->GetSession())
continue;
- if (playerToRoll->IsAtGroupRewardDistance(lootedObject) && i->AllowedForPlayer(playerToRoll))
+ if (playerToRoll->IsAtGroupRewardDistance(lootedObject))
{
r->totalPlayersRolling++;
- if (playerToRoll->GetPassOnGroupLoot())
+ RollVote vote = playerToRoll->GetPassOnGroupLoot() ? PASS : NOT_EMITED_YET;
+ if (!CanRollOnItem(*i, playerToRoll))
{
- 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;
}
}
@@ -1261,10 +1286,16 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
if (!playerToRoll || !playerToRoll->GetSession())
continue;
- if (playerToRoll->IsAtGroupRewardDistance(lootedObject) && i->AllowedForPlayer(playerToRoll))
+ if (playerToRoll->IsAtGroupRewardDistance(lootedObject))
{
r->totalPlayersRolling++;
- r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
+ RollVote vote = NOT_EMITED_YET;
+ if (!CanRollOnItem(*i, playerToRoll))
+ {
+ vote = PASS;
+ ++r->totalPass;
+ }
+ r->playerVote[playerToRoll->GetGUID()] = vote;
}
}
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index a7a962f5758..6ac1b9a9b9c 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -304,7 +304,7 @@ class TC_GAME_API Group
bool isRollLootActive() const;
void SendLootStartRoll(uint32 CountDown, uint32 mapid, Roll const& r);
void SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, bool canNeed, Roll const& r);
- void SendLootRoll(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, Roll const& r);
+ void SendLootRoll(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, Roll const& r, bool autoPass = false);
void SendLootRollWon(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, Roll const& r);
void SendLootAllPassed(Roll const& roll);
void SendLooter(Creature* creature, Player* pLooter);