rendered paste bodyIndex: src/game/Group.cpp
===================================================================
--- src/game/Group.cpp (revision 5523)
+++ src/game/Group.cpp (working copy)
@@ -69,6 +69,7 @@
m_groupType = GROUPTYPE_NORMAL;
m_lootMethod = GROUP_LOOT;
m_lootThreshold = ITEM_QUALITY_UNCOMMON;
+ m_looterGuid = guid;
if(!AddMember(guid, name))
return false;
@@ -445,13 +446,12 @@
void Group::NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature)
{
- std::vector<LootItem>::iterator i;
ItemPrototype const *item;
- uint8 itemSlot = 0;
Player *player = objmgr.GetPlayer(playerGUID);
Group *group = player->GetGroup();
- for (i=loot->items.begin(); i != loot->items.end(); ++i, ++itemSlot)
+ uint8 itemSlot = 0;
+ for(std::vector<LootItem>::iterator i=loot->items.begin(); i != loot->items.end(); ++i, ++itemSlot)
{
item = objmgr.GetItemPrototype(i->itemid);
@@ -502,6 +502,50 @@
}
}
+void Group::MasterLoot(uint64 playerGUID, Loot *loot, Creature *creature)
+{
+ Player *player = objmgr.GetPlayer(playerGUID);
+ if(!player)
+ return;
+
+ sLog.outDebug("Group::MasterLoot (SMSG_LOOT_MASTER_LIST, 330) player = [%s].", player->GetName());
+
+ //mark threshold items amnd free for all items
+ for(std::vector<LootItem>::iterator i=loot->items.begin(); i != loot->items.end(); ++i)
+ {
+ ItemPrototype const* item = objmgr.GetItemPrototype(i->itemid);
+ if(item && (item->Quality < uint32(m_lootThreshold) || i->freeforall))
+ i->is_underthreshold=1;
+ }
+
+ uint32 real_count = 0;
+
+ WorldPacket data(SMSG_LOOT_MASTER_LIST, 330);
+ data << (uint8)GetMembersCount();
+
+ for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player *looter = itr->getSource();
+ if (!looter->IsInWorld())
+ continue;
+
+ if (looter->GetDistance2dSq(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ {
+ data << looter->GetGUID();
+ ++real_count;
+ }
+ }
+
+ data.put<uint8>(0,real_count);
+
+ for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player *looter = itr->getSource();
+ if (looter->GetDistance2dSq(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ looter->GetSession()->SendPacket(&data);
+ }
+}
+
void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise)
{
Rolls::iterator rollI = GetRoll(Guid);
Index: src/game/Group.h
===================================================================
--- src/game/Group.h (revision 5523)
+++ src/game/Group.h (working copy)
@@ -260,6 +260,7 @@
void SendLootAllPassed(uint64 Guid, uint32 NumberOfPlayers, const Roll &r);
void GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature);
void NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature);
+ void MasterLoot(uint64 playerGUID, Loot *loot, Creature *creature);
Rolls::iterator GetRoll(uint64 Guid)
{
Rolls::iterator iter;
Index: src/game/LootHandler.cpp
===================================================================
--- src/game/LootHandler.cpp (revision 5523)
+++ src/game/LootHandler.cpp (working copy)
@@ -424,3 +424,78 @@
//Player is not looking at loot list, he doesn't need to see updates on the loot list
loot->RemoveLooter(player->GetGUID());
}
+
+void WorldSession::HandleLootMasterGiveOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8+1+8);
+
+ uint8 slotid;
+ uint64 lootguid, target_playerguid;
+
+ recv_data >> lootguid >> slotid >> target_playerguid;
+
+ if(!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetGUID())
+ {
+ _player->SendLootRelease(GetPlayer()->GetLootGUID());
+ return;
+ }
+
+ Player *target = ObjectAccessor::FindPlayer(MAKE_GUID(target_playerguid,HIGHGUID_PLAYER));
+ if(!target)
+ return;
+
+ sLog.outDebug("WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = [%s].", target->GetName());
+
+ if(_player->GetLootGUID() != lootguid)
+ return;
+
+ Loot *pLoot = NULL;
+
+ if(IS_CREATURE_GUID(GetPlayer()->GetLootGUID()))
+ {
+ Creature *pCreature = ObjectAccessor::GetCreature(*GetPlayer(), lootguid);
+ if(!pCreature)
+ return;
+
+ pLoot = &pCreature->loot;
+ }
+ else if(IS_GAMEOBJECT_GUID(GetPlayer()->GetLootGUID()))
+ {
+ GameObject *pGO = ObjectAccessor::GetGameObject(*GetPlayer(), lootguid);
+ if(!pGO)
+ return;
+
+ pLoot = &pGO->loot;
+ }
+
+ if(!pLoot)
+ return;
+
+ if (slotid > pLoot->items.size())
+ {
+ sLog.outDebug("AutoLootItem: Player %s might be using a hack! (slot %d, size %d)",GetPlayer()->GetName(), slotid, pLoot->items.size());
+ return;
+ }
+
+ uint32 amount = pLoot->items[slotid].count;
+ uint32 itemid = pLoot->items[slotid].itemid;
+
+ ItemPosCountVec dest;
+ uint8 msg = target->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemid, amount );
+ if ( msg != EQUIP_ERR_OK )
+ {
+ target->SendEquipError( msg, NULL, NULL );
+ _player->SendEquipError( msg, NULL, NULL ); // send duplicate of error massage to master looter
+ return;
+ }
+
+ // not move item from loot to target inventory
+ Item * newitem = target->StoreNewItem( dest, itemid, true );
+
+ pLoot->items[slotid].count=0;
+ pLoot->items[slotid].is_looted=true;
+
+ target->SendNewItem(newitem, uint32(amount), false, false, true );
+ pLoot->NotifyItemRemoved(slotid);
+ --pLoot->unlootedCount;
+}
Index: src/game/Player.cpp
===================================================================
--- src/game/Player.cpp (revision 5523)
+++ src/game/Player.cpp (working copy)
@@ -6880,17 +6880,28 @@
if (recipient->GetGroup())
{
- // round robin style looting applies for all low
- // quality items in each loot method except free for all
GroupReference &group = recipient->GetGroupRef();
- // next by circle
- uint64 next_guid = 0;
- if (group.next()) next_guid = group.next()->getSource()->GetGUID();
- else if(group->GetFirstMember() && group->GetFirstMember()->isValid())
- next_guid = group->GetFirstMember()->getSource()->GetGUID();
- group->SetLooterGuid(next_guid);
+ switch (group->GetLootMethod())
+ {
+ case MASTER_LOOT:
+ case FREE_FOR_ALL:
+ break;
+ default:
+ {
+ // round robin style looting applies for all low
+ // quality items in each loot method except free for all and master loot
+ // next by circle
+ uint64 next_guid = 0;
+ if (group.next()) next_guid = group.next()->getSource()->GetGUID();
+ else if(group->GetFirstMember() && group->GetFirstMember()->isValid())
+ next_guid = group->GetFirstMember()->getSource()->GetGUID();
+ group->SetLooterGuid(next_guid);
+ break;
+ }
+ }
+
switch (group->GetLootMethod())
{
case GROUP_LOOT:
@@ -6900,6 +6911,9 @@
case NEED_BEFORE_GREED:
group->NeedBeforeGreed(recipient->GetGUID(), loot, creature);
break;
+ case MASTER_LOOT:
+ group->MasterLoot(recipient->GetGUID(), loot, creature);
+ break;
default:
break;
}
@@ -6969,14 +6983,80 @@
if(loot_type == LOOT_PICKPOCKETING || loot_type == LOOT_DISENCHANTING || loot_type == LOOT_PROSPECTING || loot_type == LOOT_INSIGNIA)
loot_type = LOOT_SKINNING;
- WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size
- data << uint64(guid);
- data << uint8(loot_type);
- data << LootView(*loot, q_list, ffa_list, conditional_list, this, permission);
- SendDirectMessage(&data);
+
+ uint8 slottype = 0; // <-- SlotType is the type of the slot (0 = FFA/1 = GL/2 = ML)
+ if( GetGroup() )
+ {
+ if( GetGroup()->GetLootMethod() == MASTER_LOOT ) slottype = 2;
+ }
+
+ if( slottype == 2 && IS_CREATURE_GUID(guid) ) // <-- Only for Creature's Corpse (Offylike is also Object as Chest)
+ {
+ sLog.outDebug("Player::SendLoot Looter = [%s], LooterMaster = [%s]", GetName(), objmgr.GetPlayer(GetGroup()->GetLooterGuid())->GetName());
+ WorldPacket data;
+ data.SetOpcode (SMSG_LOOT_RESPONSE);
+ data << uint64(guid);
+ data << uint8(loot_type);
+ data << loot->gold;
+ data << (uint8) 0;
+
+ uint32 count = 0;
+ uint8 x = 0;
+ for(std::vector<LootItem>::iterator itr=loot->items.begin(); itr!=loot->items.end(); itr++,x++)
+ {
+ ItemPrototype const *itemProto = objmgr.GetItemPrototype(itr->itemid);
+ if (!itemProto) continue;
+ if (itr->is_looted) continue;
+
+ data << uint8(x);
+ data << uint32(itr->itemid);
+ data << uint32(itr->count);
+ data << uint32(itr->displayid);
+ data << uint32(itr->randomSuffix);
+ data << uint32(itr->randomPropertyId);
+
+ if( itemProto->Quality < GetGroup()->GetLootThreshold() || itr->freeforall )
+ {
+ data << uint8(0);
+ itr->is_underthreshold = true;
+ }
+ else if( GetGUID() != GetGroup()->GetLooterGuid() )
+ data << uint8(1);
+ else
+ data << slottype;
+ count++;
+ }
+ for(std::vector<LootItem>::iterator itq=loot->quest_items.begin(); itq!=loot->quest_items.end(); itq++,x++)
+ {
+ if(!HasQuestForItem(itq->itemid)) continue;
+
+ data << uint8(x);
+ data << uint32(itq->itemid);
+ data << uint32(itq->count);
+ data << uint32(itq->displayid);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ count++;
+ }
+ data.wpos (13) ;
+ data << (uint8)count;
+ GetSession ()->SendPacket(&data);
+ }
+ else // <-- Normal loot in case Master Loot Not Set!
+ {
+ WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size
+
+ data << uint64(guid);
+ data << uint8(loot_type);
+ data << LootView(*loot, q_list, ffa_list, conditional_list, this, permission);
+
+ SendDirectMessage(&data);
+ }
+
// add 'this' player as one of the players that are looting 'loot'
if (permission != NONE_PERMISSION)
loot->AddLooter(GetGUID());
Index: src/game/WorldSession.cpp
===================================================================
--- src/game/WorldSession.cpp (revision 5523)
+++ src/game/WorldSession.cpp (working copy)
@@ -87,6 +87,7 @@
objmgr.opcodeTable[ CMSG_LOOT_MONEY ] = OpcodeHandler( STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode );
objmgr.opcodeTable[ CMSG_LOOT ] = OpcodeHandler( STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode );
objmgr.opcodeTable[ CMSG_LOOT_RELEASE ] = OpcodeHandler( STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode );
+ objmgr.opcodeTable[ CMSG_LOOT_MASTER_GIVE ] = OpcodeHandler( STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode );
objmgr.opcodeTable[ CMSG_WHO ] = OpcodeHandler( STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode );
objmgr.opcodeTable[ CMSG_LOGOUT_REQUEST ] = OpcodeHandler( STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode );
objmgr.opcodeTable[ CMSG_PLAYER_LOGOUT ] = OpcodeHandler( STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode );
Index: src/game/WorldSession.h
===================================================================
--- src/game/WorldSession.h (revision 5523)
+++ src/game/WorldSession.h (working copy)
@@ -241,6 +241,7 @@
void HandleLootMoneyOpcode(WorldPacket& recvPacket);
void HandleLootOpcode(WorldPacket& recvPacket);
void HandleLootReleaseOpcode(WorldPacket& recvPacket);
+ void HandleLootMasterGiveOpcode(WorldPacket& recvPacket);
void HandleWhoOpcode(WorldPacket& recvPacket);
void HandleLogoutRequestOpcode(WorldPacket& recvPacket);
void HandlePlayerLogoutOpcode(WorldPacket& recvPacket);