All pastes #828397 Raw Edit

Zeug

public text v1 · immutable
#828397 ·published 2007-12-22 12:48 UTC
rendered paste body
Index: game/Group.cpp
===================================================================
--- game/Group.cpp	(revision 4889)
+++ game/Group.cpp	(working copy)
@@ -51,6 +51,14 @@
         else if(m_bgGroup->GetBgRaid(HORDE) == this) m_bgGroup->SetBgRaid(HORDE, NULL);
         else sLog.outError("Group::~Group: battleground group is not linked to the correct battleground.");
     }
+    Rolls::iterator itr;
+    while(!RollId.empty())
+    {
+        itr = RollId.begin();
+        Roll *r = *itr;
+        RollId.erase(itr);
+        delete(r);
+    }
 }
 
 bool Group::Create(const uint64 &guid, const char * name)
@@ -392,12 +400,12 @@
         //roll for over-threshold item if it's one-player loot
         if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)
         {
-            Roll r;
+            Roll* r=new Roll();
             uint32 newitemGUID = objmgr.GenerateLowGuid(HIGHGUID_ITEM);
-            r.itemGUID = newitemGUID;
-            r.itemid = i->itemid;
-            r.itemRandomPropId = i->randomPropertyId;
-            r.itemRandomSuffix = i->randomSuffix;
+            r->itemGUID = newitemGUID;
+            r->itemid = i->itemid;
+            r->itemRandomPropId = i->randomPropertyId;
+            r->itemRandomSuffix = i->randomSuffix;
 
             //a vector is filled with only near party members
             for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
@@ -409,16 +417,16 @@
                 {
                     if (member->GetDistance2dSq(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
                     {
-                        r.playerVote[member->GetGUID()] = NOT_EMITED_YET;
-                        r.totalPlayersRolling++;
+                        r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
+                        r->totalPlayersRolling++;
                     }
                 }
             }
 
-            r.loot = loot;
-            r.itemSlot = itemSlot;
+            r->setLoot(loot);
+            r->itemSlot = itemSlot;
 
-            group->SendLootStartRoll(newitemGUID, 60000, r);
+            group->SendLootStartRoll(newitemGUID, 60000, *r);
 
             loot->items[itemSlot].is_blocked = true;
             creature->m_groupLootTimer = 60000;
@@ -447,12 +455,12 @@
         //only roll for one-player items, not for ones everyone can get
         if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)
         {
-            Roll r;
+            Roll* r=new Roll();
             uint32 newitemGUID = objmgr.GenerateLowGuid(HIGHGUID_ITEM);
-            r.itemGUID = newitemGUID;
-            r.itemid = i->itemid;
-            r.itemRandomPropId = i->randomPropertyId;
-            r.itemRandomSuffix = i->randomSuffix;
+            r->itemGUID = newitemGUID;
+            r->itemid = i->itemid;
+            r->itemRandomPropId = i->randomPropertyId;
+            r->itemRandomSuffix = i->randomSuffix;
 
             for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
             {
@@ -464,23 +472,27 @@
                 {
                     if (playerToRoll->GetDistance2dSq(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
                     {
-                        r.playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
-                        r.totalPlayersRolling++;
+                        r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
+                        r->totalPlayersRolling++;
                     }
                 }
             }
 
-            if (r.totalPlayersRolling > 0)
+            if (r->totalPlayersRolling > 0)
             {
-                r.loot = loot;
-                r.itemSlot = itemSlot;
+                r->setLoot(loot);
+                r->itemSlot = itemSlot;
 
-                group->SendLootStartRoll(newitemGUID, 60000, r);
+                group->SendLootStartRoll(newitemGUID, 60000, *r);
 
                 loot->items[itemSlot].is_blocked = true;
 
                 RollId.push_back(r);
             }
+            else
+            {
+                delete r;
+            }
         }
         else
             i->is_underthreshold=1;
@@ -489,8 +501,9 @@
 
 void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise)
 {
-    Rolls::iterator roll = GetRoll(Guid);
-    if (roll == RollId.end())
+    Rolls::iterator rollI = GetRoll(Guid);
+    Roll* roll = *rollI;
+    if (rollI == RollId.end())
         return;
 
     Roll::PlayerVote::iterator itr = roll->playerVote.find(playerGUID);
@@ -498,8 +511,8 @@
     if (itr == roll->playerVote.end())
         return;
 
-    if (roll->loot)
-        if (roll->loot->items.empty())
+    if (roll->getLoot())
+        if (roll->getLoot()->items.empty())
             return;
 
     switch (Choise)
@@ -528,7 +541,7 @@
     }
     if (roll->totalPass + roll->totalGreed + roll->totalNeed >= roll->totalPlayersRolling)
     {
-        CountTheRoll(roll, NumberOfPlayers);
+        CountTheRoll(rollI, NumberOfPlayers);
     }
 }
 
@@ -544,8 +557,15 @@
     }
 }
 
-void Group::CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers)
+void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
 {
+    Roll* roll = *rollI;
+    if(!roll->isValid()) // is loot already deleted ?
+    {
+        RollId.erase(rollI);
+        delete roll;
+        return;
+    }
     //end of the roll
     if (roll->totalNeed > 0)
     {
@@ -574,13 +594,13 @@
             if(player && player->GetSession())
             {
                 uint16 dest;
-                LootItem *item = &(roll->loot->items[roll->itemSlot]);
+                LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);
                 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count, false );
                 if ( msg == EQUIP_ERR_OK )
                 {
                     item->is_looted = true;
-                    roll->loot->NotifyItemRemoved(roll->itemSlot);
-                    roll->loot->unlootedCount--;
+                    roll->getLoot()->NotifyItemRemoved(roll->itemSlot);
+                    roll->getLoot()->unlootedCount--;
                     player->StoreNewItem( dest, roll->itemid, item->count, true, item->randomPropertyId);
                 }
                 else
@@ -619,13 +639,13 @@
             if(player && player->GetSession())
             {
                 uint16 dest;
-                LootItem *item = &(roll->loot->items[roll->itemSlot]);
+                LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);
                 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count, false );
                 if ( msg == EQUIP_ERR_OK )
                 {
                     item->is_looted = true;
-                    roll->loot->NotifyItemRemoved(roll->itemSlot);
-                    roll->loot->unlootedCount--;
+                    roll->getLoot()->NotifyItemRemoved(roll->itemSlot);
+                    roll->getLoot()->unlootedCount--;
                     player->StoreNewItem( dest, roll->itemid, item->count, true, item->randomPropertyId);
                 }
                 else
@@ -639,10 +659,11 @@
     else
     {
         SendLootAllPassed(roll->itemGUID, NumberOfPlayers, *roll);
-        LootItem *item = &(roll->loot->items[roll->itemSlot]);
+        LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);
         if(item) item->is_blocked = false;
     }
-    RollId.erase(roll);
+    RollId.erase(rollI);
+    delete roll;
 }
 
 void Group::SetTargetIcon(uint8 id, uint64 guid)
@@ -995,18 +1016,19 @@
 {
     for (Rolls::iterator it = RollId.begin(); it < RollId.end(); it++)
     {
-        Roll::PlayerVote::iterator itr2 = it->playerVote.find(guid);
-        if(itr2 == it->playerVote.end())
+        Roll* roll = *it;
+        Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);
+        if(itr2 == roll->playerVote.end())
             continue;
 
-        if (itr2->second == GREED) it->totalGreed--;
-        if (itr2->second == NEED) it->totalNeed--;
-        if (itr2->second == PASS) it->totalPass--;
-        if (itr2->second != NOT_VALID) it->totalPlayersRolling--;
+        if (itr2->second == GREED) roll->totalGreed--;
+        if (itr2->second == NEED) roll->totalNeed--;
+        if (itr2->second == PASS) roll->totalPass--;
+        if (itr2->second != NOT_VALID) roll->totalPlayersRolling--;
 
-        it->playerVote.erase(itr2);
+        roll->playerVote.erase(itr2);
 
-        CountRollVote(guid, it->itemGUID, GetMembersCount()-1, 3);
+        CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, 3);
     }
 }
 
@@ -1095,3 +1117,13 @@
         SendUpdate();
     }
 }
+
+//===================================================
+//============== Roll ===============================
+//===================================================
+
+void Roll::targetObjectBuildLink()
+{
+    // called from link()
+    this->getTarget()->addLootInvalidListener(this);
+}
Index: game/Group.h
===================================================================
--- game/Group.h	(revision 4889)
+++ game/Group.h	(working copy)
@@ -21,6 +21,7 @@
 
 #include "GroupReference.h"
 #include "GroupRefManager.h"
+#include "LootMgr.h"
 
 #include <map>
 #include <vector>
@@ -100,6 +101,28 @@
                                                             //0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 static const uint8 GroupUpdateLength[GROUP_UPDATE_FLAGS_COUNT] = { 0, 1, 2, 2, 1, 2, 2, 2, 2, 4};
 
+class Roll : public LootInvalidListener
+{
+public:
+    Roll(): itemGUID(0), itemid(0), itemRandomPropId(0), totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), itemSlot(0) {}
+    ~Roll() { }
+    void setLoot(Loot *pLoot) { link(pLoot, this); }
+    Loot *getLoot() { return getTarget(); }
+    void targetObjectBuildLink();
+
+    uint64 itemGUID;
+    uint32 itemid;
+    uint32 itemRandomSuffix;
+    int32  itemRandomPropId;
+    typedef std::map<uint64, RollVote> PlayerVote;
+    PlayerVote playerVote;                          //vote position correspond with player position (in group)
+    uint8 totalPlayersRolling;
+    uint8 totalNeed;
+    uint8 totalGreed;
+    uint8 totalPass;
+    uint8 itemSlot;
+};
+
 /** request member stats checken **/
 /** todo: uninvite people that not accepted invite **/
 class MANGOS_DLL_SPEC Group
@@ -118,26 +141,8 @@
         typedef MemberSlotList::iterator member_witerator;
         typedef std::set<uint64> InvitesList;
 
-        struct Roll
-        {
-            Roll(): itemGUID(0), itemid(0), itemRandomPropId(0), totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), loot(NULL), itemSlot(0) {}
+        typedef std::vector<Roll*> Rolls;
 
-            uint64 itemGUID;
-            uint32 itemid;
-            uint32 itemRandomSuffix;
-            int32  itemRandomPropId;
-            typedef std::map<uint64, RollVote> PlayerVote;
-            PlayerVote playerVote;                          //vote position correspond with player position (in group)
-            uint8 totalPlayersRolling;
-            uint8 totalNeed;
-            uint8 totalGreed;
-            uint8 totalPass;
-            Loot *loot;
-            uint8 itemSlot;
-        };
-
-        typedef std::vector<Roll> Rolls;
-
     public:
         Group();
         ~Group();
@@ -271,7 +276,7 @@
             Rolls::iterator iter;
             for (iter=RollId.begin(); iter != RollId.end(); ++iter)
             {
-                if (iter->itemGUID == Guid)
+                if ((*iter)->itemGUID == Guid)
                 {
                     return iter;
                 }
Index: game/LootMgr.cpp
===================================================================
--- game/LootMgr.cpp	(revision 4889)
+++ game/LootMgr.cpp	(working copy)
@@ -556,6 +556,8 @@
     return ql;
 }
 
+//===================================================
+
 void Loot::NotifyItemRemoved(uint8 lootIndex)
 {
     // notify all players that are looting this that the item was removed
Index: game/LootMgr.h
===================================================================
--- game/LootMgr.h	(revision 4889)
+++ game/LootMgr.h	(working copy)
@@ -25,6 +25,7 @@
 #include "ItemEnchantmentMgr.h"
 #include "ByteBuffer.h"
 #include "Util.h"
+#include "Utilities/LinkedReference/RefManager.h"
 
 #include <map>
 #include <vector>
@@ -141,11 +142,41 @@
         : index(_index), is_looted(_islooted) {}
 };
 
+
 typedef std::vector<QuestItem> QuestItemList;
 typedef std::map<uint32, QuestItemList *> QuestItemMap;
 typedef std::vector<LootStoreItem> LootStoreItemList;
 typedef HM_NAMESPACE::hash_map<uint32, LootStoreItemList > LootStore;
 
+//=====================================================
+
+struct Loot;
+class LootInvalidListener :  public Reference<Loot, LootInvalidListener>
+{
+public:
+    LootInvalidListener() {}
+    void targetObjectDestroyLink() {}
+    void sourceObjectDestroyLink() {}
+};
+
+//=====================================================
+
+class LootInvalidRefManager : public RefManager<Loot, LootInvalidListener>
+{
+    public:
+        typedef LinkedListHead::Iterator< LootInvalidListener > iterator;
+
+        LootInvalidListener* getFirst() { return (LootInvalidListener*)RefManager<Loot, LootInvalidListener>::getFirst(); }
+        LootInvalidListener* getLast() { return (LootInvalidListener*)RefManager<Loot, LootInvalidListener>::getLast(); }
+
+        iterator begin() { return iterator(getFirst()); }
+        iterator end() { return iterator(NULL); }
+        iterator rbegin() { return iterator(getLast()); }
+        iterator rend() { return iterator(NULL); }
+};
+
+//=====================================================
+
 struct Loot
 {
     std::set<uint64> PlayersLooting;
@@ -154,6 +185,8 @@
     QuestItemMap PlayerNonQuestNonFFAConditionalItems;
     std::vector<LootItem> items;
     std::vector<LootItem> quest_items;
+    // All rolls are registered here. They need to know, when the loot is not valid anymore
+    LootInvalidRefManager i_LootInvalidRefManager;
     uint32 gold;
     uint8 unlootedCount;
     bool released;
@@ -161,6 +194,13 @@
     Loot(uint32 _gold = 0) : gold(_gold), unlootedCount(0), released(false) {}
     ~Loot() { clear(); }
 
+    // if loot becomes invalid this reference is used to inform the listener
+    void addLootInvalidListener(LootInvalidListener* pLootInvalidListener)
+    { 
+        i_LootInvalidRefManager.insertFirst(pLootInvalidListener);
+    }
+
+   // void clear();
     void clear()
     {
         items.clear(); gold = 0; PlayersLooting.clear();
@@ -179,6 +219,7 @@
         quest_items.clear();
         gold = 0;
         unlootedCount = 0;
+        i_LootInvalidRefManager.clearReferences();
     }
 
     bool empty() const { return items.empty() && gold == 0; }