rendered paste bodyIndex: 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; }