From 61b2b3d2341456a8423ffc8a97466a33299232de Mon Sep 17 00:00:00 2001 From: ApoC Date: Sat, 25 Oct 2008 20:51:40 +0200 Subject: [PATCH] Prevent adding more than 5 people into RAID subgroup. Optimized free subgroup in raid finding. Optimized method calls, now using const uint64& instead of value passing. Signed-off-by: ApoC --- src/game/Group.cpp | 79 +++++++++++++++++++++++++++++---------- src/game/Group.h | 60 ++++++++++++++++++++++------- src/game/GroupHandler.cpp | 3 ++ 3 files changed, 109 insertions(+), 33 deletions(-) diff --git a/src/game/Group.cpp b/src/game/Group.cpp index eade6412d..d850fcfee 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -42,6 +42,7 @@ Group::Group() m_lootMethod = (LootMethod)0; m_looterGuid = 0; m_lootThreshold = ITEM_QUALITY_UNCOMMON; + m_subGroupsCounts = NULL; for(int i=0; isecond.save->RemoveGroup(this); + + // Sub group counters clean up + if (m_subGroupsCounts) + delete[] m_subGroupsCounts; } bool Group::Create(const uint64 &guid, const char * name) @@ -79,6 +84,10 @@ bool Group::Create(const uint64 &guid, const char * name) m_leaderName = name; m_groupType = isBGGroup() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL; + + if (m_groupType == GROUPTYPE_RAID) + _initRaidSubGroupsCounter(); + m_lootMethod = GROUP_LOOT; m_lootThreshold = ITEM_QUALITY_UNCOMMON; m_looterGuid = guid; @@ -134,6 +143,10 @@ bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool } m_groupType = (*result)[13].GetBool() ? GROUPTYPE_RAID : GROUPTYPE_NORMAL; + + if (m_groupType == GROUPTYPE_RAID) + _initRaidSubGroupsCounter(); + m_difficulty = (*result)[14].GetUInt8(); m_mainTank = (*result)[0].GetUInt64(); m_mainAssistant = (*result)[1].GetUInt64(); @@ -176,6 +189,9 @@ bool Group::LoadMemberFromDB(uint32 guidLow, uint8 subgroup, bool assistant) member.group = subgroup; member.assistant = assistant; m_memberSlots.push_back(member); + + SubGroupCounterIncrease(subgroup); + return true; } @@ -384,7 +400,7 @@ void Group::SendLootStartRoll(uint32 CountDown, const Roll &r) } } -void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +void Group::SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) { WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1)); data << uint64(SourceGuid); // guid of the item rolled @@ -408,7 +424,7 @@ void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, } } -void Group::SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +void Group::SendLootRollWon(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) { WorldPacket data(SMSG_LOOT_ROLL_WON, (8+4+4+4+4+8+1+1)); data << uint64(SourceGuid); // guid of the item rolled @@ -451,7 +467,7 @@ void Group::SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r) } } -void Group::GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature) +void Group::GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature) { std::vector::iterator i; ItemPrototype const *item; @@ -507,7 +523,7 @@ void Group::GroupLoot(uint64 playerGUID, Loot *loot, Creature *creature) } } -void Group::NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature) +void Group::NeedBeforeGreed(const uint64& playerGUID, Loot *loot, Creature *creature) { ItemPrototype const *item; Player *player = objmgr.GetPlayer(playerGUID); @@ -561,7 +577,7 @@ void Group::NeedBeforeGreed(uint64 playerGUID, Loot *loot, Creature *creature) } } -void Group::MasterLoot(uint64 playerGUID, Loot* /*loot*/, Creature *creature) +void Group::MasterLoot(const uint64& playerGUID, Loot* /*loot*/, Creature *creature) { Player *player = objmgr.GetPlayer(playerGUID); if(!player) @@ -597,7 +613,7 @@ void Group::MasterLoot(uint64 playerGUID, Loot* /*loot*/, Creature *creature) } } -void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise) +void Group::CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 NumberOfPlayers, uint8 Choise) { Rolls::iterator rollI = GetRoll(Guid); if (rollI == RollId.end()) @@ -929,13 +945,20 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant) { // get first not-full group uint8 groupid = 0; - std::vector temp(MAXRAIDSIZE/MAXGROUPSIZE); - for(member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) + if (m_subGroupsCounts) { - if (itr->group >= temp.size()) continue; - ++temp[itr->group]; - if(temp[groupid] >= MAXGROUPSIZE) - ++groupid; + bool groupFound = false; + for (; groupid < MAXRAIDSIZE/MAXGROUPSIZE; ++groupid) + { + if (m_subGroupsCounts[groupid] < MAXGROUPSIZE) + { + groupFound = true; + break; + } + } + // We are raid group and no one slot is free + if (!groupFound) + return false; } return _addMember(guid, name, isAssistant, groupid); @@ -958,6 +981,8 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant, u member.assistant = isAssistant; m_memberSlots.push_back(member); + SubGroupCounterIncrease(group); + if(player) { player->SetGroupInvite(NULL); @@ -995,7 +1020,11 @@ bool Group::_removeMember(const uint64 &guid) member_witerator slot = _getMemberWSlot(guid); if (slot != m_memberSlots.end()) + { + SubGroupCounterDecrease(slot->group); + m_memberSlots.erase(slot); + } if(!isBGGroup()) CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid='%u'", GUID_LOPART(guid)); @@ -1088,13 +1117,6 @@ void Group::_removeRolls(const uint64 &guid) } } -void Group::_convertToRaid() -{ - m_groupType = GROUPTYPE_RAID; - - if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); -} - bool Group::_setMembersGroup(const uint64 &guid, const uint8 &group) { member_witerator slot = _getMemberWSlot(guid); @@ -1102,7 +1124,11 @@ bool Group::_setMembersGroup(const uint64 &guid, const uint8 &group) return false; slot->group = group; + + SubGroupCounterIncrease(group); + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'", group, GUID_LOPART(guid)); + return true; } @@ -1156,12 +1182,20 @@ void Group::ChangeMembersGroup(const uint64 &guid, const uint8 &group) if(!isRaidGroup()) return; Player *player = objmgr.GetPlayer(guid); + if (!player) { + uint8 prevSubGroup; + prevSubGroup = GetMemberGroup(guid); + + SubGroupCounterDecrease(prevSubGroup); + if(_setMembersGroup(guid, group)) SendUpdate(); } - else ChangeMembersGroup(player, group); + else + // This methods handles itself groupcounter decrease + ChangeMembersGroup(player, group); } // only for online members @@ -1171,6 +1205,11 @@ void Group::ChangeMembersGroup(Player *player, const uint8 &group) return; if(_setMembersGroup(player->GetGUID(), group)) { + uint8 prevSubGroup; + prevSubGroup = player->GetSubGroup(); + + SubGroupCounterDecrease(prevSubGroup); + player->GetGroupRef().setSubGroup(group); SendUpdate(); } diff --git a/src/game/Group.h b/src/game/Group.h index 0dc7135e7..c3e7585a0 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -181,8 +181,8 @@ class MANGOS_DLL_SPEC Group ItemQualities GetLootThreshold() const { return m_lootThreshold; } // member manipulation methods - bool IsMember(uint64 guid) const { return _getMemberCSlot(guid) != m_memberSlots.end(); } - bool IsLeader(uint64 guid) const { return (GetLeaderGUID() == guid); } + bool IsMember(const uint64& guid) const { return _getMemberCSlot(guid) != m_memberSlots.end(); } + bool IsLeader(const uint64& guid) const { return (GetLeaderGUID() == guid); } bool IsAssistant(uint64 guid) const { member_citerator mslot = _getMemberCSlot(guid); @@ -192,7 +192,7 @@ class MANGOS_DLL_SPEC Group return mslot->assistant; } - bool SameSubGroup(uint64 guid1, uint64 guid2) const + bool SameSubGroup(uint64 guid1,const uint64& guid2) const { member_citerator mslot2 = _getMemberCSlot(guid2); if(mslot2==m_memberSlots.end()) @@ -210,6 +210,11 @@ class MANGOS_DLL_SPEC Group return (mslot1->group==slot2->group); } + bool HasFreeSlotSubGroup(uint8 subgroup) const + { + return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAXGROUPSIZE); + } + bool SameSubGroup(Player const* member1, Player const* member2) const; MemberSlotList const& GetMemberSlots() const { return m_memberSlots; } @@ -228,7 +233,11 @@ class MANGOS_DLL_SPEC Group // some additional raid methods void ConvertToRaid() { - _convertToRaid(); + m_groupType = GROUPTYPE_RAID; + + _initRaidSubGroupsCounter(); + + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); SendUpdate(); } void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } @@ -236,14 +245,14 @@ class MANGOS_DLL_SPEC Group void ChangeMembersGroup(const uint64 &guid, const uint8 &group); void ChangeMembersGroup(Player *player, const uint8 &group); - void SetAssistant(const uint64 &guid, const bool &state) + void SetAssistant(uint64 guid, const bool &state) { if(!isRaidGroup()) return; if(_setAssistantFlag(guid, state)) SendUpdate(); } - void SetMainTank(const uint64 &guid) + void SetMainTank(uint64 guid) { if(!isRaidGroup()) return; @@ -251,7 +260,7 @@ class MANGOS_DLL_SPEC Group if(_setMainTank(guid)) SendUpdate(); } - void SetMainAssistant(const uint64 &guid) + void SetMainAssistant(uint64 guid) { if(!isRaidGroup()) return; @@ -282,12 +291,12 @@ class MANGOS_DLL_SPEC Group /*********************************************************/ void SendLootStartRoll(uint32 CountDown, const Roll &r); - void SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); - void SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); + void SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); + void SendLootRollWon(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); void SendLootAllPassed(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); + void GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature); + void NeedBeforeGreed(const uint64& playerGUID, Loot *loot, Creature *creature); + void MasterLoot(const uint64& playerGUID, Loot *loot, Creature *creature); Rolls::iterator GetRoll(uint64 Guid) { Rolls::iterator iter; @@ -301,7 +310,7 @@ class MANGOS_DLL_SPEC Group return RollId.end(); } void CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers); - void CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise); + void CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 NumberOfPlayers, uint8 Choise); void EndRoll(); void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); } @@ -328,6 +337,18 @@ class MANGOS_DLL_SPEC Group void _homebindIfInstance(Player *player); + void _initRaidSubGroupsCounter() + { + // Sub group counters initialization + if (!m_subGroupsCounts) + m_subGroupsCounts = new uint8[MAXRAIDSIZE / MAXGROUPSIZE]; + + memset((void*)m_subGroupsCounts, 0, (MAXRAIDSIZE / MAXGROUPSIZE)*sizeof(uint8)); + + for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) + ++m_subGroupsCounts[itr->group]; + } + member_citerator _getMemberCSlot(uint64 Guid) const { for(member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr) @@ -348,6 +369,18 @@ class MANGOS_DLL_SPEC Group return m_memberSlots.end(); } + void SubGroupCounterIncrease(uint8 subgroup) + { + if (m_subGroupsCounts) + ++m_subGroupsCounts[subgroup]; + } + + void SubGroupCounterDecrease(uint8 subgroup) + { + if (m_subGroupsCounts) + --m_subGroupsCounts[subgroup]; + } + MemberSlotList m_memberSlots; GroupRefManager m_memberMgr; InvitesList m_invitees; @@ -364,5 +397,6 @@ class MANGOS_DLL_SPEC Group uint64 m_looterGuid; Rolls RollId; BoundInstancesMap m_boundInstances[TOTAL_DIFFICULTIES]; + uint8* m_subGroupsCounts; }; #endif diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 5695f1290..780198c02 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -543,6 +543,9 @@ void WorldSession::HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data ) /** error handling **/ if(!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) return; + + if (!group->HasFreeSlotSubGroup(groupNr)) + return; /********************/ // everything's fine, do it