Index: src/game/Group.cpp =================================================================== --- src/game/Group.cpp (revision 5515) +++ src/game/Group.cpp (working copy) @@ -37,6 +37,7 @@ m_lootMethod = (LootMethod)0; m_looterGuid = 0; m_lootThreshold = ITEM_QUALITY_UNCOMMON; + m_looterMasterGuid = 0; for(int i=0; iGetName()); + + WorldPacket data(SMSG_LOOT_MASTER_LIST, 330); + uint32 real_count = 0; + 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; + } + } + *(uint8*)&data.contents()[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 5515) +++ src/game/Group.h (working copy) @@ -148,6 +148,7 @@ void SetLootMethod(LootMethod method) { m_lootMethod = method; } void SetLooterGuid(const uint64 &guid) { m_looterGuid = guid; } void SetLootThreshold(ItemQualities threshold) { m_lootThreshold = threshold; } + void SetLooterMasterGuid(const uint64 &guid) { m_looterMasterGuid = guid; } void Disband(bool hideDestroy=false); // properties accessories @@ -158,6 +159,7 @@ LootMethod GetLootMethod() const { return m_lootMethod; } const uint64& GetLooterGuid() const { return m_looterGuid; } ItemQualities GetLootThreshold() const { return m_lootThreshold; } + const uint64& GetLooterMasterGuid() const { return m_looterMasterGuid; } // member manipulation methods bool IsMember(uint64 guid) const { return _getMemberCSlot(guid) != m_memberSlots.end(); } @@ -260,6 +262,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, Creature *creature); Rolls::iterator GetRoll(uint64 Guid) { Rolls::iterator iter; @@ -326,6 +329,7 @@ LootMethod m_lootMethod; ItemQualities m_lootThreshold; uint64 m_looterGuid; + uint64 m_looterMasterGuid; Rolls RollId; }; #endif Index: src/game/GroupHandler.cpp =================================================================== --- src/game/GroupHandler.cpp (revision 5515) +++ src/game/GroupHandler.cpp (working copy) @@ -363,6 +363,7 @@ group->SetLootMethod((LootMethod)lootMethod); group->SetLooterGuid(lootMaster); group->SetLootThreshold((ItemQualities)lootThreshold); + group->SetLooterMasterGuid(lootMaster); group->SendUpdate(); } Index: src/game/LootHandler.cpp =================================================================== --- src/game/LootHandler.cpp (revision 5515) +++ src/game/LootHandler.cpp (working copy) @@ -28,6 +28,7 @@ #include "Object.h" #include "Group.h" #include "World.h" +#include "ObjectMgr.h" void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) { @@ -424,3 +425,66 @@ //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 ) +{ + if(!_player->IsInWorld()) return; + + Creature *pCreature = NULL; + Loot *pLoot = NULL; + uint64 creatureguid, target_playerguid; + uint8 slotid; + recv_data >> creatureguid >> slotid >> target_playerguid; + + if(_player->GetGroup() == NULL || _player->GetGroup()->GetLooterMasterGuid() != _player->GetGUID()) + return; + + Player *target = objmgr.GetPlayer((uint32)target_playerguid); + if(!target) + return; + + sLog.outDebug("WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = [%s].", target->GetName()); + + if(_player->GetLootGUID() != creatureguid) + return; + + if(IS_CREATURE_GUID(GetPlayer()->GetLootGUID())) + { + pCreature = ObjectAccessor::GetCreature(*GetPlayer(), creatureguid); + if (!pCreature)return; + pLoot=&pCreature->loot; + } + + if(!pLoot) return; + if (_player->GetGUID() != _player->GetGroup()->GetLooterMasterGuid()) + { + _player->SendLootRelease(GetPlayer()->GetLootGUID()); + 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.at(slotid).count; + uint32 itemid = pLoot->items.at(slotid).itemid; + ItemPosCountVec dest; + + uint8 msg = target->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemid, amount ); + if ( msg == EQUIP_ERR_OK ) + { + Item * newitem = target->StoreNewItem( dest, itemid, amount ); + pLoot->items.at(slotid).count=0; + pLoot->items.at(slotid).is_looted=true; + target->SendNewItem(newitem, uint32(amount), false, false, true ); + pLoot->NotifyItemRemoved(slotid); + --pLoot->unlootedCount; + } + else + { + target->SendEquipError( msg, NULL, NULL ); + return; + } +} Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (revision 5515) +++ src/game/Player.cpp (working copy) @@ -6898,6 +6898,9 @@ case NEED_BEFORE_GREED: group->NeedBeforeGreed(recipient->GetGUID(), loot, creature); break; + case MASTER_LOOT: + group->MasterLoot(recipient->GetGUID(), creature); + break; default: break; } @@ -6967,14 +6970,78 @@ 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()->GetLooterMasterGuid())->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::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()->GetLooterMasterGuid() ) data << uint8(1); + else data << slottype; + count++; + } + for(std::vector::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 5515) +++ 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 5515) +++ 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);