All pastes #966003 Raw Edit

master loot v2

public text v1 · immutable
·published 2008-04-01 12:16 UTC
rendered paste body
Index: 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);