[9327] Replace leader based indexing groups by group ids.

* This must repolve problem with loot.
  Before if some mob killed by group member and then leader changed
  then group members can't loot this mob body.
* Possible resolve crashes at loot. Now group storage content not dependent from leader changes.
This commit is contained in:
VladimirMangos 2010-02-08 08:19:35 +03:00
parent 5a7eb09bd2
commit 8e0069f364
8 changed files with 66 additions and 42 deletions

View file

@ -113,7 +113,7 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
Creature::Creature(CreatureSubtype subtype) : Creature::Creature(CreatureSubtype subtype) :
Unit(), i_AI(NULL), Unit(), i_AI(NULL),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0), lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), m_groupLootId(0),
m_lootMoney(0), m_lootRecipient(0), m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f), m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0),
@ -395,7 +395,7 @@ void Creature::Update(uint32 diff)
else else
{ {
m_deathTimer -= diff; m_deathTimer -= diff;
if (m_groupLootTimer && lootingGroupLeaderGUID) if (m_groupLootTimer && m_groupLootId)
{ {
if(diff <= m_groupLootTimer) if(diff <= m_groupLootTimer)
{ {
@ -403,10 +403,10 @@ void Creature::Update(uint32 diff)
} }
else else
{ {
if (Group* group = sObjectMgr.GetGroupByLeaderLowGUID(GUID_LOPART(lootingGroupLeaderGUID))) if (Group* group = sObjectMgr.GetGroupById(m_groupLootId))
group->EndRoll(); group->EndRoll();
m_groupLootTimer = 0; m_groupLootTimer = 0;
lootingGroupLeaderGUID = 0; m_groupLootId = 0;
} }
} }
} }

View file

@ -583,7 +583,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
void SetRespawnRadius(float dist) { m_respawnradius = dist; } void SetRespawnRadius(float dist) { m_respawnradius = dist; }
uint32 m_groupLootTimer; // (msecs)timer used for group loot uint32 m_groupLootTimer; // (msecs)timer used for group loot
uint64 lootingGroupLeaderGUID; // used to find group which is looting corpse uint32 m_groupLootId; // used to find group which is looting corpse
void SendZoneUnderAttackMessage(Player* attacker); void SendZoneUnderAttackMessage(Player* attacker);

View file

@ -33,18 +33,11 @@
#include "MapInstanced.h" #include "MapInstanced.h"
#include "Util.h" #include "Util.h"
Group::Group() Group::Group() : m_Id(0), m_leaderGuid(0), m_mainTank(0), m_mainAssistant(0), m_groupType(GROUPTYPE_NORMAL),
m_dungeonDifficulty(REGULAR_DIFFICULTY), m_raidDifficulty(REGULAR_DIFFICULTY),
m_bgGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_looterGuid(0), m_lootThreshold(ITEM_QUALITY_UNCOMMON),
m_subGroupsCounts(NULL)
{ {
m_leaderGuid = 0;
m_mainTank = 0;
m_mainAssistant = 0;
m_groupType = (GroupType)0;
m_bgGroup = NULL;
m_lootMethod = (LootMethod)0;
m_looterGuid = 0;
m_lootThreshold = ITEM_QUALITY_UNCOMMON;
m_subGroupsCounts = NULL;
for (int i = 0; i < TARGETICONCOUNT; ++i) for (int i = 0; i < TARGETICONCOUNT; ++i)
m_targetIcons[i] = 0; m_targetIcons[i] = 0;
} }
@ -123,7 +116,10 @@ bool Group::Create(const uint64 &guid, const char * name)
return false; return false;
if(!isBGGroup()) if(!isBGGroup())
{
CharacterDatabase.CommitTransaction(); CharacterDatabase.CommitTransaction();
m_Id = sObjectMgr.GenerateGroupId();
}
return true; return true;
} }
@ -194,6 +190,7 @@ bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool
return false; return false;
} }
m_Id = sObjectMgr.GenerateGroupId();
return true; return true;
} }
@ -616,7 +613,7 @@ void Group::GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature)
loot->items[itemSlot].is_blocked = true; loot->items[itemSlot].is_blocked = true;
creature->m_groupLootTimer = 60000; creature->m_groupLootTimer = 60000;
creature->lootingGroupLeaderGUID = GetLeaderGUID(); creature->m_groupLootId = GetId();
RollId.push_back(r); RollId.push_back(r);
} }
@ -1256,11 +1253,6 @@ void Group::_setLeader(const uint64 &guid)
m_leaderGuid = slot->guid; m_leaderGuid = slot->guid;
m_leaderName = slot->name; m_leaderName = slot->name;
// Non-BG groups stored in sObjectMgr with leader low-guids as keys
if (IsCreated() && !isBGGroup())
sObjectMgr.UpdateGroup(old_guidlow,this);
} }
void Group::_removeRolls(const uint64 &guid) void Group::_removeRolls(const uint64 &guid)

View file

@ -180,6 +180,7 @@ class MANGOS_DLL_SPEC Group
void Disband(bool hideDestroy=false); void Disband(bool hideDestroy=false);
// properties accessories // properties accessories
uint32 GetId() const { return m_Id; }
bool IsFull() const { return (m_groupType==GROUPTYPE_NORMAL) ? (m_memberSlots.size()>=MAXGROUPSIZE) : (m_memberSlots.size()>=MAXRAIDSIZE); } bool IsFull() const { return (m_groupType==GROUPTYPE_NORMAL) ? (m_memberSlots.size()>=MAXGROUPSIZE) : (m_memberSlots.size()>=MAXRAIDSIZE); }
bool isRaidGroup() const { return m_groupType==GROUPTYPE_RAID; } bool isRaidGroup() const { return m_groupType==GROUPTYPE_RAID; }
bool isBGGroup() const { return m_bgGroup != NULL; } bool isBGGroup() const { return m_bgGroup != NULL; }
@ -402,6 +403,7 @@ class MANGOS_DLL_SPEC Group
--m_subGroupsCounts[subgroup]; --m_subGroupsCounts[subgroup];
} }
uint32 m_Id; // 0 for not created or BG groups
MemberSlotList m_memberSlots; MemberSlotList m_memberSlots;
GroupRefManager m_memberMgr; GroupRefManager m_memberMgr;
InvitesList m_invitees; InvitesList m_invitees;

View file

@ -189,10 +189,12 @@ void WorldSession::HandleGroupAcceptOpcode( WorldPacket & recv_data )
// forming a new group, create it // forming a new group, create it
if(!group->IsCreated()) if(!group->IsCreated())
{ {
if( leader ) if (leader)
group->RemoveInvite(leader); group->RemoveInvite(leader);
group->Create(group->GetLeaderGUID(), group->GetLeaderName()); if (group->Create(group->GetLeaderGUID(), group->GetLeaderName()))
sObjectMgr.AddGroup(group); sObjectMgr.AddGroup(group);
else
return;
} }
// everything's fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!! // everything's fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!

View file

@ -142,6 +142,7 @@ ObjectMgr::ObjectMgr()
m_guildId = 1; m_guildId = 1;
m_arenaTeamId = 1; m_arenaTeamId = 1;
m_auctionid = 1; m_auctionid = 1;
m_groupId = 1;
// Only zero condition left, others will be added while loading DB tables // Only zero condition left, others will be added while loading DB tables
mConditions.resize(1); mConditions.resize(1);
@ -180,16 +181,26 @@ ObjectMgr::~ObjectMgr()
itr->second.Clear(); itr->second.Clear();
} }
Group * ObjectMgr::GetGroupByLeaderLowGUID(uint32 guid) const Group* ObjectMgr::GetGroupById(uint32 id) const
{ {
GroupMap::const_iterator itr = mGroupMap.find(guid); GroupMap::const_iterator itr = mGroupMap.find(id);
if (itr != mGroupMap.end()) if (itr != mGroupMap.end())
return itr->second; return itr->second;
return NULL; return NULL;
} }
Guild * ObjectMgr::GetGuildById(uint32 GuildId) const Group* ObjectMgr::GetGroupByLeaderLowGUID(uint32 guid) const
{
for(GroupMap::const_iterator itr = mGroupMap.begin(); itr != mGroupMap.end(); ++itr)
if (GUID_LOPART(itr->second->GetLeaderGUID())==guid)
return itr->second;
return NULL;
}
Guild* ObjectMgr::GetGuildById(uint32 GuildId) const
{ {
GuildMap::const_iterator itr = mGuildMap.find(GuildId); GuildMap::const_iterator itr = mGuildMap.find(GuildId);
if (itr != mGuildMap.end()) if (itr != mGuildMap.end())
@ -3124,6 +3135,8 @@ void ObjectMgr::LoadGroups()
return; return;
} }
std::map<uint32,uint32> leader2groupMap;
barGoLink bar( result->GetRowCount() ); barGoLink bar( result->GetRowCount() );
do do
@ -3140,6 +3153,7 @@ void ObjectMgr::LoadGroups()
continue; continue;
} }
AddGroup(group); AddGroup(group);
leader2groupMap[GUID_LOPART(leaderGuid)] = group->GetId();
}while( result->NextRow() ); }while( result->NextRow() );
delete result; delete result;
@ -3173,7 +3187,11 @@ void ObjectMgr::LoadGroups()
uint32 leaderGuidLow = fields[3].GetUInt32(); uint32 leaderGuidLow = fields[3].GetUInt32();
if(!group || GUID_LOPART(group->GetLeaderGUID()) != leaderGuidLow) if(!group || GUID_LOPART(group->GetLeaderGUID()) != leaderGuidLow)
{ {
group = GetGroupByLeaderLowGUID(leaderGuidLow); // find group id in map by leader low guid
std::map<uint32,uint32>::const_iterator l2g_itr = leader2groupMap.find(leaderGuidLow);
if (l2g_itr != leader2groupMap.end())
group = GetGroupById(l2g_itr->second);
if(!group) if(!group)
{ {
sLog.outErrorDb("Incorrect entry in group_member table : no group with leader %d for member %d!", leaderGuidLow, memberGuidlow); sLog.outErrorDb("Incorrect entry in group_member table : no group with leader %d for member %d!", leaderGuidLow, memberGuidlow);
@ -3237,7 +3255,11 @@ void ObjectMgr::LoadGroups()
if(!group || GUID_LOPART(group->GetLeaderGUID()) != leaderGuidLow) if(!group || GUID_LOPART(group->GetLeaderGUID()) != leaderGuidLow)
{ {
group = GetGroupByLeaderLowGUID(leaderGuidLow); // find group id in map by leader low guid
std::map<uint32,uint32>::const_iterator l2g_itr = leader2groupMap.find(leaderGuidLow);
if (l2g_itr != leader2groupMap.end())
group = GetGroupById(l2g_itr->second);
if(!group) if(!group)
{ {
sLog.outErrorDb("Incorrect entry in group_instance table : no group with leader %d", leaderGuidLow); sLog.outErrorDb("Incorrect entry in group_instance table : no group with leader %d", leaderGuidLow);
@ -5706,6 +5728,16 @@ uint32 ObjectMgr::GenerateGuildId()
return m_guildId++; return m_guildId++;
} }
uint32 ObjectMgr::GenerateGroupId()
{
if(m_groupId>=0xFFFFFFFE)
{
sLog.outError("Group ids overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
return m_groupId++;
}
uint32 ObjectMgr::GenerateMailID() uint32 ObjectMgr::GenerateMailID()
{ {
if(m_mailid>=0xFFFFFFFE) if(m_mailid>=0xFFFFFFFE)
@ -8426,18 +8458,12 @@ void ObjectMgr::RemoveGuild( uint32 Id )
void ObjectMgr::AddGroup( Group* group ) void ObjectMgr::AddGroup( Group* group )
{ {
mGroupMap[GUID_LOPART(group->GetLeaderGUID())] = group ; mGroupMap[group->GetId()] = group ;
} }
void ObjectMgr::RemoveGroup( Group* group ) void ObjectMgr::RemoveGroup( Group* group )
{ {
mGroupMap.erase(GUID_LOPART(group->GetLeaderGUID())); mGroupMap.erase(group->GetId());
}
void ObjectMgr::UpdateGroup( uint32 old_guidlow, Group* group )
{
mGroupMap.erase(old_guidlow);
AddGroup(group);
} }
void ObjectMgr::AddArenaTeam( ArenaTeam* arenaTeam ) void ObjectMgr::AddArenaTeam( ArenaTeam* arenaTeam )

View file

@ -408,10 +408,10 @@ class ObjectMgr
void LoadGameobjectInfo(); void LoadGameobjectInfo();
void AddGameobjectInfo(GameObjectInfo *goinfo); void AddGameobjectInfo(GameObjectInfo *goinfo);
Group * GetGroupByLeaderLowGUID(uint32 lowguid) const; Group* GetGroupById(uint32 id) const;
Group* GetGroupByLeaderLowGUID(uint32 guid) const; // slow way by leader guid
void AddGroup(Group* group); void AddGroup(Group* group);
void RemoveGroup(Group* group); void RemoveGroup(Group* group);
void UpdateGroup(uint32 old_guidlow, Group* group); // when need update leader guid as group key
Guild* GetGuildByLeader(uint64 const&guid) const; Guild* GetGuildByLeader(uint64 const&guid) const;
Guild* GetGuildById(uint32 GuildId) const; Guild* GetGuildById(uint32 GuildId) const;
@ -656,6 +656,7 @@ class ObjectMgr
uint32 GenerateAuctionID(); uint32 GenerateAuctionID();
uint64 GenerateEquipmentSetGuid(); uint64 GenerateEquipmentSetGuid();
uint32 GenerateGuildId(); uint32 GenerateGuildId();
uint32 GenerateGroupId();
uint32 GenerateItemTextID(); uint32 GenerateItemTextID();
uint32 GenerateMailID(); uint32 GenerateMailID();
uint32 GeneratePetNumber(); uint32 GeneratePetNumber();
@ -894,8 +895,9 @@ class ObjectMgr
uint32 m_ItemTextId; uint32 m_ItemTextId;
uint32 m_mailid; uint32 m_mailid;
uint32 m_hiPetNumber; uint32 m_hiPetNumber;
uint32 m_groupId;
// first free low guid for seelcted guid type // first free low guid for selected guid type
uint32 m_hiCharGuid; uint32 m_hiCharGuid;
uint32 m_hiCreatureGuid; uint32 m_hiCreatureGuid;
uint32 m_hiItemGuid; uint32 m_hiItemGuid;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9326" #define REVISION_NR "9327"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__