2010-10-07 15:35:36 +02:00
/*
2011-01-01 15:01:13 +01:00
* Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "Common.h"
#include "Opcodes.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Player.h"
#include "World.h"
#include "ObjectMgr.h"
2011-05-05 10:23:00 +02:00
#include "GroupMgr.h"
2008-10-11 14:16:25 -05:00
#include "Group.h"
2008-10-26 11:50:07 -05:00
#include "Formulas.h"
2008-10-11 14:16:25 -05:00
#include "ObjectAccessor.h"
2010-08-08 04:37:24 +02:00
#include "Battleground.h"
#include "BattlegroundMgr.h"
2008-10-11 14:16:25 -05:00
#include "MapManager.h"
#include "InstanceSaveMgr.h"
2011-10-08 13:36:27 +02:00
#include "MapInstanced.h"
2008-10-11 14:16:25 -05:00
#include "Util.h"
2010-12-16 10:53:21 +01:00
#include "LFGMgr.h"
2009-10-17 15:51:44 -07:00
2010-12-13 22:37:56 +01:00
Roll :: Roll ( uint64 _guid , LootItem const & li ) : itemGUID ( _guid ), itemid ( li . itemid ),
2010-11-29 07:50:31 +01:00
itemRandomPropId ( li . randomPropertyId ), itemRandomSuffix ( li . randomSuffix ), itemCount ( li . count ),
2010-12-13 22:37:56 +01:00
totalPlayersRolling ( 0 ), totalNeed ( 0 ), totalGreed ( 0 ), totalPass ( 0 ), itemSlot ( 0 ),
2010-11-29 07:50:31 +01:00
rollVoteMask ( ROLL_ALL_TYPE_NO_DISENCHANT )
{
}
Roll ::~ Roll ()
{
}
2011-09-15 14:08:17 +02:00
void Roll :: setLoot ( Loot * pLoot )
2010-11-29 07:50:31 +01:00
{
link ( pLoot , this );
}
Loot * Roll :: getLoot ()
{
return getTarget ();
}
2011-01-26 01:03:35 +01:00
Group :: Group () : m_leaderGuid ( 0 ), m_leaderName ( "" ), m_groupType ( GROUPTYPE_NORMAL ),
2010-12-15 10:44:06 +01:00
m_dungeonDifficulty ( DUNGEON_DIFFICULTY_NORMAL ), m_raidDifficulty ( RAID_DIFFICULTY_10MAN_NORMAL ),
2011-01-26 01:03:35 +01:00
m_bgGroup ( NULL ), m_lootMethod ( FREE_FOR_ALL ), m_lootThreshold ( ITEM_QUALITY_UNCOMMON ), m_looterGuid ( 0 ),
2011-05-05 10:23:00 +02:00
m_subGroupsCounts ( NULL ), m_guid ( 0 ), m_counter ( 0 ), m_maxEnchantingLevel ( 0 ), m_dbStoreId ( 0 )
2010-12-05 17:50:26 +01:00
{
2010-05-08 01:58:47 +02:00
for ( uint8 i = 0 ; i < TARGETICONCOUNT ; ++ i )
2008-10-11 14:16:25 -05:00
m_targetIcons [ i ] = 0 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Group ::~ Group ()
{
2010-04-07 19:14:10 +02:00
if ( m_bgGroup )
2008-10-11 14:16:25 -05:00
{
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_BATTLEGROUND , "Group::~Group: battleground group being deleted." );
2010-04-07 19:14:10 +02:00
if ( m_bgGroup -> GetBgRaid ( ALLIANCE ) == this ) m_bgGroup -> SetBgRaid ( ALLIANCE , NULL );
else if ( m_bgGroup -> GetBgRaid ( HORDE ) == this ) m_bgGroup -> SetBgRaid ( HORDE , NULL );
2010-12-23 23:25:44 +01:00
else sLog -> outError ( "Group::~Group: battleground group is not linked to the correct battleground." );
2008-10-11 14:16:25 -05:00
}
Rolls :: iterator itr ;
2010-04-07 19:13:19 +02:00
while ( ! RollId . empty ())
2008-10-11 14:16:25 -05:00
{
itr = RollId . begin ();
Roll * r = * itr ;
RollId . erase ( itr );
delete ( r );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// it is undefined whether objectmgr (which stores the groups) or instancesavemgr
// will be unloaded first so we must be prepared for both cases
// this may unload some instance saves
2009-12-17 11:11:54 +01:00
for ( uint8 i = 0 ; i < MAX_DIFFICULTY ; ++ i )
2009-10-17 16:20:24 -07:00
for ( BoundInstancesMap :: iterator itr2 = m_boundInstances [ i ]. begin (); itr2 != m_boundInstances [ i ]. end (); ++ itr2 )
2009-04-27 18:42:35 -05:00
itr2 -> second . save -> RemoveGroup ( this );
2009-10-17 15:51:44 -07:00
2009-02-01 16:38:53 -06:00
// Sub group counters clean up
2010-06-21 23:20:58 +02:00
delete [] m_subGroupsCounts ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
bool Group :: Create ( Player * leader )
2008-10-11 14:16:25 -05:00
{
2011-02-18 18:35:52 +01:00
uint64 leaderGuid = leader -> GetGUID ();
2011-05-05 10:23:00 +02:00
uint32 lowguid = sGroupMgr -> GenerateGroupId ();
2011-02-26 19:49:56 +01:00
2010-05-08 01:58:47 +02:00
m_guid = MAKE_NEW_GUID ( lowguid , 0 , HIGHGUID_GROUP );
2011-02-18 18:35:52 +01:00
m_leaderGuid = leaderGuid ;
m_leaderName = leader -> GetName ();
2009-10-17 15:51:44 -07:00
2010-04-11 11:22:29 +04:00
m_groupType = isBGGroup () ? GROUPTYPE_BGRAID : GROUPTYPE_NORMAL ;
2009-10-17 15:51:44 -07:00
2010-04-11 11:22:29 +04:00
if ( m_groupType & GROUPTYPE_RAID )
2009-02-01 16:38:53 -06:00
_initRaidSubGroupsCounter ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_lootMethod = GROUP_LOOT ;
m_lootThreshold = ITEM_QUALITY_UNCOMMON ;
2011-02-18 18:35:52 +01:00
m_looterGuid = leaderGuid ;
2009-10-17 15:51:44 -07:00
2009-12-17 11:11:54 +01:00
m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL ;
m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL ;
2011-02-18 18:35:52 +01:00
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2008-10-11 14:16:25 -05:00
{
2011-02-18 18:35:52 +01:00
m_dungeonDifficulty = leader -> GetDungeonDifficulty ();
m_raidDifficulty = leader -> GetRaidDifficulty ();
2010-08-21 03:19:25 +02:00
2011-05-05 10:23:00 +02:00
m_dbStoreId = sGroupMgr -> GenerateNewGroupDbStoreId ();
2011-02-26 19:49:56 +01:00
2011-05-05 10:23:00 +02:00
sGroupMgr -> RegisterGroupDbStoreId ( m_dbStoreId , this );
2011-02-26 19:49:56 +01:00
2008-10-11 14:16:25 -05:00
// store group in database
2011-04-29 20:47:02 +02:00
CharacterDatabase . PExecute ( "INSERT INTO groups (guid, leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty) "
"VALUES ('%u', '%u', '%u', '%u', '%u', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '%u', '%u', '%u')" ,
2011-05-05 10:23:00 +02:00
m_dbStoreId , GUID_LOPART ( m_leaderGuid ), uint32 ( m_lootMethod ),
2011-02-18 18:35:52 +01:00
GUID_LOPART ( m_looterGuid ), uint32 ( m_lootThreshold ), m_targetIcons [ 0 ], m_targetIcons [ 1 ], m_targetIcons [ 2 ], m_targetIcons [ 3 ], m_targetIcons [ 4 ], m_targetIcons [ 5 ], m_targetIcons [ 6 ],
m_targetIcons [ 7 ], uint8 ( m_groupType ), uint32 ( m_dungeonDifficulty ), m_raidDifficulty );
ASSERT ( AddMember ( leader )); // If the leader can't be added to a new group because it appears full, something is clearly wrong.
Player :: ConvertInstancesToGroup ( leader , this , false );
2008-10-11 14:16:25 -05:00
}
2011-02-18 18:35:52 +01:00
else if ( ! AddMember ( leader ))
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Group :: LoadGroupFromDB ( Field * fields )
2008-10-11 14:16:25 -05:00
{
2011-05-05 10:23:00 +02:00
m_dbStoreId = fields [ 15 ]. GetUInt32 ();
m_guid = MAKE_NEW_GUID ( sGroupMgr -> GenerateGroupId (), 0 , HIGHGUID_GROUP );
2010-05-08 01:58:47 +02:00
m_leaderGuid = MAKE_NEW_GUID ( fields [ 0 ]. GetUInt32 (), 0 , HIGHGUID_PLAYER );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// group leader not exist
2010-12-22 21:25:23 +01:00
if ( ! sObjectMgr -> GetPlayerNameByGUID ( fields [ 0 ]. GetUInt32 (), m_leaderName ))
2011-02-26 19:49:56 +01:00
return ;
2009-10-17 15:51:44 -07:00
2010-08-02 17:28:47 +02:00
m_lootMethod = LootMethod ( fields [ 1 ]. GetUInt8 ());
2010-05-08 01:58:47 +02:00
m_looterGuid = MAKE_NEW_GUID ( fields [ 2 ]. GetUInt32 (), 0 , HIGHGUID_PLAYER );
2010-08-02 17:28:47 +02:00
m_lootThreshold = ItemQualities ( fields [ 3 ]. GetUInt16 ());
2010-05-08 01:58:47 +02:00
for ( uint8 i = 0 ; i < TARGETICONCOUNT ; ++ i )
2011-01-20 03:06:51 +01:00
m_targetIcons [ i ] = fields [ 4 + i ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2010-05-08 01:58:47 +02:00
m_groupType = GroupType ( fields [ 12 ]. GetUInt8 ());
2010-04-11 11:22:29 +04:00
if ( m_groupType & GROUPTYPE_RAID )
2009-02-01 16:38:53 -06:00
_initRaidSubGroupsCounter ();
2009-10-17 15:51:44 -07:00
2010-05-08 01:58:47 +02:00
uint32 diff = fields [ 13 ]. GetUInt8 ();
2009-12-17 11:11:54 +01:00
if ( diff >= MAX_DUNGEON_DIFFICULTY )
2010-09-10 13:37:33 +02:00
m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL ;
else
m_dungeonDifficulty = Difficulty ( diff );
2009-12-17 11:11:54 +01:00
2010-05-08 01:58:47 +02:00
uint32 r_diff = fields [ 14 ]. GetUInt8 ();
2009-12-17 11:11:54 +01:00
if ( r_diff >= MAX_RAID_DIFFICULTY )
2010-09-10 13:37:33 +02:00
m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL ;
else
m_raidDifficulty = Difficulty ( r_diff );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-02-26 19:49:56 +01:00
void Group :: LoadMemberFromDB ( uint32 guidLow , uint8 memberFlags , uint8 subgroup , uint8 roles )
2008-10-11 14:16:25 -05:00
{
MemberSlot member ;
2010-05-08 01:58:47 +02:00
member . guid = MAKE_NEW_GUID ( guidLow , 0 , HIGHGUID_PLAYER );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// skip non-existed member
2010-12-22 21:25:23 +01:00
if ( ! sObjectMgr -> GetPlayerNameByGUID ( member . guid , member . name ))
2010-05-08 01:58:47 +02:00
{
CharacterDatabase . PQuery ( "DELETE FROM group_member WHERE memberGuid=%u" , guidLow );
2011-02-26 19:49:56 +01:00
return ;
2010-05-08 01:58:47 +02:00
}
2009-10-17 15:51:44 -07:00
2010-03-09 20:33:59 +01:00
member . group = subgroup ;
member . flags = memberFlags ;
2010-09-10 13:40:20 +02:00
member . roles = roles ;
2009-12-22 19:39:02 +01:00
2008-10-11 14:16:25 -05:00
m_memberSlots . push_back ( member );
2009-10-17 15:51:44 -07:00
2009-02-01 16:38:53 -06:00
SubGroupCounterIncrease ( subgroup );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-11 15:20:20 +02:00
void Group :: ConvertToLFG ()
{
m_groupType = GroupType ( m_groupType | GROUPTYPE_LFG | GROUPTYPE_UNK1 );
m_lootMethod = NEED_BEFORE_GREED ;
if ( ! isBGGroup ())
2011-05-05 10:23:00 +02:00
CharacterDatabase . PExecute ( "UPDATE groups SET groupType='%u' WHERE guid='%u'" , uint8 ( m_groupType ), m_dbStoreId );
2010-08-11 15:20:20 +02:00
SendUpdate ();
}
2008-10-29 17:09:32 -05:00
void Group :: ConvertToRaid ()
{
2010-04-11 11:22:29 +04:00
m_groupType = GroupType ( m_groupType | GROUPTYPE_RAID );
2009-10-17 15:51:44 -07:00
2009-02-01 16:38:53 -06:00
_initRaidSubGroupsCounter ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2011-05-05 10:23:00 +02:00
CharacterDatabase . PExecute ( "UPDATE groups SET groupType='%u' WHERE guid='%u'" , uint8 ( m_groupType ), m_dbStoreId );
2009-02-01 16:38:53 -06:00
SendUpdate ();
2009-10-17 15:51:44 -07:00
2009-02-01 16:38:53 -06:00
// update quest related GO states (quest activity dependent from raid membership)
2009-10-17 16:20:24 -07:00
for ( member_citerator citr = m_memberSlots . begin (); citr != m_memberSlots . end (); ++ citr )
2011-07-27 12:14:27 +02:00
if ( Player * player = ObjectAccessor :: FindPlayer ( citr -> guid ))
2009-05-05 16:56:15 -05:00
player -> UpdateForQuestWorldObjects ();
2008-10-29 17:09:32 -05:00
}
2009-10-17 15:51:44 -07:00
2011-06-12 01:47:45 +02:00
bool Group :: AddInvite ( Player * player )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( ! player || player -> GetGroupInvite ())
2009-03-14 20:00:02 -06:00
return false ;
Group * group = player -> GetGroup ();
2010-04-07 22:59:46 +02:00
if ( group && group -> isBGGroup ())
2009-03-14 20:00:02 -06:00
group = player -> GetOriginalGroup ();
2010-04-07 22:59:46 +02:00
if ( group )
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
RemoveInvite ( player );
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
m_invitees . insert ( player );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
player -> SetGroupInvite ( this );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnGroupInviteMember ( this , player -> GetGUID ());
2010-09-14 16:37:54 +02:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2011-06-12 01:47:45 +02:00
bool Group :: AddLeaderInvite ( Player * player )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! AddInvite ( player ))
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_leaderGuid = player -> GetGUID ();
m_leaderName = player -> GetName ();
return true ;
}
2009-10-17 15:51:44 -07:00
2011-06-12 01:47:45 +02:00
void Group :: RemoveInvite ( Player * player )
2008-10-11 14:16:25 -05:00
{
2010-10-29 14:09:25 +02:00
if ( player )
{
m_invitees . erase ( player );
player -> SetGroupInvite ( NULL );
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Group :: RemoveAllInvites ()
{
2010-04-08 08:20:08 +02:00
for ( InvitesList :: iterator itr = m_invitees . begin (); itr != m_invitees . end (); ++ itr )
2010-10-29 14:09:25 +02:00
if ( * itr )
( * itr ) -> SetGroupInvite ( NULL );
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
m_invitees . clear ();
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
Player * Group :: GetInvited ( uint64 guid ) const
2008-12-12 11:21:28 -06:00
{
2009-10-17 16:20:24 -07:00
for ( InvitesList :: const_iterator itr = m_invitees . begin (); itr != m_invitees . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2010-10-29 14:09:25 +02:00
if (( * itr ) && ( * itr ) -> GetGUID () == guid )
2008-12-12 11:21:28 -06:00
return ( * itr );
2008-10-11 14:16:25 -05:00
}
2008-12-12 11:21:28 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
Player * Group :: GetInvited ( const std :: string & name ) const
{
2009-10-17 16:20:24 -07:00
for ( InvitesList :: const_iterator itr = m_invitees . begin (); itr != m_invitees . end (); ++ itr )
2008-12-12 11:21:28 -06:00
{
2010-10-29 14:09:25 +02:00
if (( * itr ) && ( * itr ) -> GetName () == name )
2008-12-12 11:21:28 -06:00
return ( * itr );
}
return NULL ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-06-12 01:47:45 +02:00
bool Group :: AddMember ( Player * player )
2008-10-11 14:16:25 -05:00
{
2011-02-18 18:35:52 +01:00
// Get first not-full group
uint8 subGroup = 0 ;
if ( m_subGroupsCounts )
{
bool groupFound = false ;
for (; subGroup < MAX_RAID_SUBGROUPS ; ++ subGroup )
{
if ( m_subGroupsCounts [ subGroup ] < MAXGROUPSIZE )
{
groupFound = true ;
break ;
}
}
// We are raid group and no one slot is free
if ( ! groupFound )
return false ;
}
MemberSlot member ;
member . guid = player -> GetGUID ();
member . name = player -> GetName ();
member . group = subGroup ;
member . flags = 0 ;
member . roles = 0 ;
m_memberSlots . push_back ( member );
SubGroupCounterIncrease ( subGroup );
if ( player )
{
player -> SetGroupInvite ( NULL );
if ( player -> GetGroup () && isBGGroup ()) //if player is in group and he is being added to BG raid group, then call SetBattlegroundRaid()
player -> SetBattlegroundRaid ( this , subGroup );
else if ( player -> GetGroup ()) //if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
player -> SetOriginalGroup ( this , subGroup );
else //if player is not in group, then call set group
player -> SetGroup ( this , subGroup );
// if the same group invites the player back, cancel the homebind timer
2011-09-15 14:08:17 +02:00
InstanceGroupBind * bind = GetBoundInstance ( player );
2011-02-18 18:35:52 +01:00
if ( bind && bind -> save -> GetInstanceId () == player -> GetInstanceId ())
player -> m_InstanceValid = true ;
}
if ( ! isRaidGroup ()) // reset targetIcons for non-raid-groups
{
for ( uint8 i = 0 ; i < TARGETICONCOUNT ; ++ i )
m_targetIcons [ i ] = 0 ;
}
// insert into the table if we're not a battleground group
if ( ! isBGGroup ())
CharacterDatabase . PExecute ( "INSERT INTO group_member (guid, memberGuid, memberFlags, subgroup, roles) VALUES(%u, %u, %u, %u, %u)" ,
2011-05-05 10:23:00 +02:00
m_dbStoreId , GUID_LOPART ( member . guid ), member . flags , member . group , member . roles );
2010-08-11 15:20:20 +02:00
2008-10-11 14:16:25 -05:00
SendUpdate ();
2011-02-18 18:35:52 +01:00
sScriptMgr -> OnGroupAddMember ( this , player -> GetGUID ());
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( player )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! IsLeader ( player -> GetGUID ()) && ! isBGGroup ())
2008-10-11 14:16:25 -05:00
{
// reset the new member's instances, unless he is currently in one of them
// including raid/heroic instances that they are not permanently bound to!
2011-04-29 20:47:02 +02:00
player -> ResetInstances ( INSTANCE_RESET_GROUP_JOIN , false );
player -> ResetInstances ( INSTANCE_RESET_GROUP_JOIN , true );
2009-10-17 15:51:44 -07:00
2009-12-17 11:11:54 +01:00
if ( player -> getLevel () >= LEVELREQUIREMENT_HEROIC )
2008-10-11 14:16:25 -05:00
{
2009-12-17 11:11:54 +01:00
if ( player -> GetDungeonDifficulty () != GetDungeonDifficulty ())
{
player -> SetDungeonDifficulty ( GetDungeonDifficulty ());
player -> SendDungeonDifficulty ( true );
}
if ( player -> GetRaidDifficulty () != GetRaidDifficulty ())
{
player -> SetRaidDifficulty ( GetRaidDifficulty ());
player -> SendRaidDifficulty ( true );
}
2008-10-11 14:16:25 -05:00
}
}
player -> SetGroupUpdateFlag ( GROUP_UPDATE_FULL );
UpdatePlayerOutOfRange ( player );
2009-10-17 15:51:44 -07:00
2010-09-10 13:37:33 +02:00
// quest related GO state dependent from raid membership
2010-04-07 19:14:10 +02:00
if ( isRaidGroup ())
2009-05-05 16:56:15 -05:00
player -> UpdateForQuestWorldObjects ();
2010-05-21 22:45:47 +02:00
if ( m_maxEnchantingLevel < player -> GetSkillValue ( SKILL_ENCHANTING ))
m_maxEnchantingLevel = player -> GetSkillValue ( SKILL_ENCHANTING );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
bool Group :: RemoveMember ( uint64 guid , const RemoveMethod & method /*= GROUP_REMOVEMETHOD_DEFAULT*/ , uint64 kicker /*= 0*/ , const char * reason /*= NULL*/ )
2008-10-11 14:16:25 -05:00
{
2009-01-15 21:29:32 -05:00
BroadcastGroupUpdate ();
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnGroupRemoveMember ( this , guid , method , kicker , reason );
2010-09-14 16:37:54 +02:00
2011-02-18 18:35:52 +01:00
// LFG group vote kick handled in scripts
2010-11-23 20:49:57 +01:00
if ( isLFGGroup () && method == GROUP_REMOVEMETHOD_KICK )
return m_memberSlots . size ();
2010-10-25 07:36:26 +02:00
// remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG allow 1 member group)
if ( GetMembersCount () > ( isBGGroup () ? 1u : 2u ))
2008-10-11 14:16:25 -05:00
{
2011-07-27 12:14:27 +02:00
Player * player = ObjectAccessor :: FindPlayer ( guid );
2011-02-18 18:35:52 +01:00
if ( player )
2008-10-11 14:16:25 -05:00
{
2011-02-18 18:35:52 +01:00
// Battleground group handling
if ( isBGGroup ())
player -> RemoveFromBattlegroundRaid ();
else
// Regular group
{
if ( player -> GetOriginalGroup () == this )
player -> SetOriginalGroup ( NULL );
else
player -> SetGroup ( NULL );
// quest related GO state dependent from raid membership
2009-05-05 16:56:15 -05:00
player -> UpdateForQuestWorldObjects ();
2011-02-18 18:35:52 +01:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ;
2009-10-17 15:51:44 -07:00
2010-09-10 13:37:55 +02:00
if ( method == GROUP_REMOVEMETHOD_KICK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
data . Initialize ( SMSG_GROUP_UNINVITE , 0 );
player -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-02-18 18:35:52 +01:00
// Do we really need to send this opcode?
data . Initialize ( SMSG_GROUP_LIST , 1 + 1 + 1 + 1 + 8 + 4 + 4 + 8 );
data << uint8 ( 0x10 ) << uint8 ( 0 ) << uint8 ( 0 ) << uint8 ( 0 );
data << uint64 ( m_guid ) << uint32 ( m_counter ) << uint32 ( 0 ) << uint64 ( 0 );
player -> GetSession () -> SendPacket ( & data );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_homebindIfInstance ( player );
}
2009-10-17 15:51:44 -07:00
2011-02-18 18:35:52 +01:00
// Remove player from group in DB
CharacterDatabase . PExecute ( "DELETE FROM group_member WHERE memberGuid=%u" , GUID_LOPART ( guid ));
// Reevaluate group enchanter if the leaving player had enchanting skill or the player is offline
2011-05-09 03:37:31 +02:00
if (( player && player -> GetSkillValue ( SKILL_ENCHANTING )) || ! player )
2011-02-18 18:35:52 +01:00
ResetMaxEnchantingLevel ();
// Remove player from loot rolls
for ( Rolls :: iterator it = RollId . begin (); it != RollId . end (); ++ it )
{
Roll * roll = * it ;
Roll :: PlayerVote :: iterator itr2 = roll -> playerVote . find ( guid );
if ( itr2 == roll -> playerVote . end ())
continue ;
if ( itr2 -> second == GREED || itr2 -> second == DISENCHANT )
-- roll -> totalGreed ;
else if ( itr2 -> second == NEED )
-- roll -> totalNeed ;
else if ( itr2 -> second == PASS )
-- roll -> totalPass ;
if ( itr2 -> second != NOT_VALID )
-- roll -> totalPlayersRolling ;
roll -> playerVote . erase ( itr2 );
CountRollVote ( guid , roll -> itemGUID , GetMembersCount () - 1 , MAX_ROLL_TYPE );
}
// Update subgroups
member_witerator slot = _getMemberWSlot ( guid );
if ( slot != m_memberSlots . end ())
2008-10-11 14:16:25 -05:00
{
2011-02-18 18:35:52 +01:00
SubGroupCounterDecrease ( slot -> group );
m_memberSlots . erase ( slot );
}
// Pick new leader if necessary
if ( m_leaderGuid == guid )
{
for ( member_witerator itr = m_memberSlots . begin (); itr != m_memberSlots . end (); ++ itr )
{
2011-07-27 12:14:27 +02:00
if ( ObjectAccessor :: FindPlayer ( itr -> guid ))
2011-02-18 18:35:52 +01:00
{
ChangeLeader ( itr -> guid );
break ;
}
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SendUpdate ();
2011-02-22 16:52:38 +01:00
return true ;
2008-10-11 14:16:25 -05:00
}
2011-02-18 18:35:52 +01:00
// If group size before player removal <= 2 then disband it
2008-10-11 14:16:25 -05:00
else
2011-02-22 16:52:38 +01:00
{
2010-05-20 23:35:27 +02:00
Disband ();
2011-02-22 16:52:38 +01:00
return false ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
void Group :: ChangeLeader ( uint64 guid )
2008-10-11 14:16:25 -05:00
{
2011-02-18 18:35:52 +01:00
member_witerator slot = _getMemberWSlot ( guid );
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
if ( slot == m_memberSlots . end ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-07-27 12:14:27 +02:00
Player * player = ObjectAccessor :: FindPlayer ( slot -> guid );
2009-10-17 15:51:44 -07:00
2011-02-18 18:35:52 +01:00
// Don't allow switching leader to offline players
if ( ! player )
return ;
sScriptMgr -> OnGroupChangeLeader ( this , m_leaderGuid , guid );
if ( ! isBGGroup ())
{
// Remove the groups permanent instance bindings
for ( uint8 i = 0 ; i < MAX_DIFFICULTY ; ++ i )
{
for ( BoundInstancesMap :: iterator itr = m_boundInstances [ i ]. begin (); itr != m_boundInstances [ i ]. end ();)
{
if ( itr -> second . perm )
{
itr -> second . save -> RemoveGroup ( this );
m_boundInstances [ i ]. erase ( itr ++ );
}
else
++ itr ;
}
}
// Same in the database
CharacterDatabase . PExecute ( "DELETE FROM group_instance WHERE guid=%u AND (permanent = 1 OR instance IN (SELECT instance FROM character_instance WHERE guid = '%u'))" ,
2011-05-05 10:23:00 +02:00
m_dbStoreId , player -> GetGUIDLow ());
2011-02-18 18:35:52 +01:00
// Copy the permanent binds from the new leader to the group
Player :: ConvertInstancesToGroup ( player , this , true );
// update the group leader
2011-05-05 10:23:00 +02:00
CharacterDatabase . PExecute ( "UPDATE groups SET leaderGuid='%u' WHERE guid='%u'" , player -> GetGUIDLow (), m_dbStoreId );
2011-02-18 18:35:52 +01:00
}
m_leaderGuid = player -> GetGUID ();
m_leaderName = player -> GetName ();
ToggleGroupMemberFlag ( slot , MEMBER_FLAG_ASSISTANT , false );
WorldPacket data ( SMSG_GROUP_SET_LEADER , m_leaderName . size () + 1 );
2008-10-11 14:16:25 -05:00
data << slot -> name ;
2009-03-14 20:00:02 -06:00
BroadcastPacket ( & data , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-09-10 13:37:33 +02:00
void Group :: Disband ( bool hideDestroy /* = false */ )
2008-10-11 14:16:25 -05:00
{
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnGroupDisband ( this );
2009-10-17 15:51:44 -07:00
2011-06-12 01:47:45 +02:00
Player * player ;
2009-10-17 16:20:24 -07:00
for ( member_citerator citr = m_memberSlots . begin (); citr != m_memberSlots . end (); ++ citr )
2008-10-11 14:16:25 -05:00
{
2011-07-27 12:14:27 +02:00
player = ObjectAccessor :: FindPlayer ( citr -> guid );
2010-04-07 19:14:10 +02:00
if ( ! player )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-03-14 20:00:02 -06:00
//we cannot call _removeMember because it would invalidate member iterator
2009-03-14 20:06:00 -06:00
//if we are removing player from battleground raid
2010-04-07 22:59:46 +02:00
if ( isBGGroup ())
2010-08-08 04:37:24 +02:00
player -> RemoveFromBattlegroundRaid ();
2009-03-14 20:06:00 -06:00
else
2009-03-14 20:00:02 -06:00
{
2009-03-14 20:06:00 -06:00
//we can remove player who is in battleground from his original group
2010-04-07 22:59:46 +02:00
if ( player -> GetOriginalGroup () == this )
2009-03-14 20:06:00 -06:00
player -> SetOriginalGroup ( NULL );
2009-03-14 20:00:02 -06:00
else
2009-03-14 20:06:00 -06:00
player -> SetGroup ( NULL );
2009-03-14 20:00:02 -06:00
}
2009-10-17 15:51:44 -07:00
2009-02-01 16:38:53 -06:00
// quest related GO state dependent from raid membership
2010-04-07 19:14:10 +02:00
if ( isRaidGroup ())
2009-05-05 16:56:15 -05:00
player -> UpdateForQuestWorldObjects ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! player -> GetSession ())
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ;
2010-04-07 19:14:10 +02:00
if ( ! hideDestroy )
2008-10-11 14:16:25 -05:00
{
data . Initialize ( SMSG_GROUP_DESTROYED , 0 );
player -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2009-03-14 20:00:02 -06:00
//we already removed player from group and in player->GetGroup() is his original group, send update
2010-04-07 22:59:46 +02:00
if ( Group * group = player -> GetGroup ())
2009-03-14 20:00:02 -06:00
{
group -> SendUpdate ();
}
else
{
2010-02-14 19:13:14 -07:00
data . Initialize ( SMSG_GROUP_LIST , 1 + 1 + 1 + 1 + 8 + 4 + 4 + 8 );
data << uint8 ( 0x10 ) << uint8 ( 0 ) << uint8 ( 0 ) << uint8 ( 0 );
2010-05-21 14:19:47 +02:00
data << uint64 ( m_guid ) << uint32 ( m_counter ) << uint32 ( 0 ) << uint64 ( 0 );
2009-03-14 20:00:02 -06:00
player -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_homebindIfInstance ( player );
}
RollId . clear ();
m_memberSlots . clear ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
RemoveAllInvites ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2008-10-11 14:16:25 -05:00
{
2010-08-21 03:19:25 +02:00
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
2011-05-05 10:23:00 +02:00
trans -> PAppend ( "DELETE FROM groups WHERE guid = %u" , m_dbStoreId );
trans -> PAppend ( "DELETE FROM group_member WHERE guid = %u" , m_dbStoreId );
2010-08-21 03:19:25 +02:00
CharacterDatabase . CommitTransaction ( trans );
2009-12-17 11:11:54 +01:00
ResetInstances ( INSTANCE_RESET_GROUP_DISBAND , false , NULL );
ResetInstances ( INSTANCE_RESET_GROUP_DISBAND , true , NULL );
2011-02-22 23:47:32 +01:00
2011-05-05 10:23:00 +02:00
sGroupMgr -> FreeGroupDbStoreId ( this );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-05-05 10:23:00 +02:00
sGroupMgr -> RemoveGroup ( this );
2011-02-22 16:52:38 +01:00
delete this ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
/*********************************************************/
/*** LOOT SYSTEM ***/
/*********************************************************/
2009-10-17 15:51:44 -07:00
2010-04-11 11:16:42 +04:00
void Group :: SendLootStartRoll ( uint32 CountDown , uint32 mapid , const Roll & r )
2008-10-11 14:16:25 -05:00
{
2010-02-14 19:13:14 -07:00
WorldPacket data ( SMSG_LOOT_START_ROLL , ( 8 + 4 + 4 + 4 + 4 + 4 + 4 + 1 ));
2008-10-11 14:16:25 -05:00
data << uint64 ( r . itemGUID ); // guid of rolled item
2010-04-11 11:16:42 +04:00
data << uint32 ( mapid ); // 3.3.3 mapid
2008-10-11 14:16:25 -05:00
data << uint32 ( r . totalPlayersRolling ); // maybe the number of players rolling for it???
data << uint32 ( r . itemid ); // the itemEntryId for the item that shall be rolled for
data << uint32 ( r . itemRandomSuffix ); // randomSuffix
data << uint32 ( r . itemRandomPropId ); // item random property ID
2009-12-17 11:11:54 +01:00
data << uint32 ( r . itemCount ); // items in stack
2008-10-11 14:16:25 -05:00
data << uint32 ( CountDown ); // the countdown time to choose "need" or "greed"
2010-05-21 22:45:47 +02:00
data << uint8 ( r . rollVoteMask ); // roll type mask
2009-10-17 15:51:44 -07:00
2010-04-08 08:20:08 +02:00
for ( Roll :: PlayerVote :: const_iterator itr = r . playerVote . begin (); itr != r . playerVote . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Player * p = ObjectAccessor :: FindPlayer ( itr -> first );
2010-04-07 19:14:10 +02:00
if ( ! p || ! p -> GetSession ())
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-04-17 18:55:17 +02:00
if ( itr -> second == NOT_EMITED_YET )
2010-04-07 22:59:46 +02:00
p -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
void Group :: SendLootRoll ( uint64 SourceGuid , uint64 TargetGuid , uint8 RollNumber , uint8 RollType , const Roll & r )
2008-10-11 14:16:25 -05:00
{
2009-12-17 11:11:54 +01:00
WorldPacket data ( SMSG_LOOT_ROLL , ( 8 + 4 + 8 + 4 + 4 + 4 + 1 + 1 + 1 ));
2008-10-11 14:16:25 -05:00
data << uint64 ( SourceGuid ); // guid of the item rolled
data << uint32 ( 0 ); // unknown, maybe amount of players
data << uint64 ( TargetGuid );
data << uint32 ( r . itemid ); // the itemEntryId for the item that shall be rolled for
data << uint32 ( r . itemRandomSuffix ); // randomSuffix
data << uint32 ( r . itemRandomPropId ); // Item random property ID
data << uint8 ( RollNumber ); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number
data << uint8 ( RollType ); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll
2010-04-17 18:55:17 +02:00
data << uint8 ( 0 ); // auto pass on NeedBeforeGreed loot because player cannot use the object
2009-10-17 15:51:44 -07:00
2010-04-08 08:20:08 +02:00
for ( Roll :: PlayerVote :: const_iterator itr = r . playerVote . begin (); itr != r . playerVote . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Player * p = ObjectAccessor :: FindPlayer ( itr -> first );
2010-04-07 19:14:10 +02:00
if ( ! p || ! p -> GetSession ())
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( itr -> second != NOT_VALID )
2010-04-07 22:59:46 +02:00
p -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
void Group :: SendLootRollWon ( uint64 SourceGuid , uint64 TargetGuid , uint8 RollNumber , uint8 RollType , const Roll & r )
2008-10-11 14:16:25 -05:00
{
WorldPacket data ( SMSG_LOOT_ROLL_WON , ( 8 + 4 + 4 + 4 + 4 + 8 + 1 + 1 ));
data << uint64 ( SourceGuid ); // guid of the item rolled
data << uint32 ( 0 ); // unknown, maybe amount of players
data << uint32 ( r . itemid ); // the itemEntryId for the item that shall be rolled for
data << uint32 ( r . itemRandomSuffix ); // randomSuffix
data << uint32 ( r . itemRandomPropId ); // Item random property
data << uint64 ( TargetGuid ); // guid of the player who won.
data << uint8 ( RollNumber ); // rollnumber realted to SMSG_LOOT_ROLL
data << uint8 ( RollType ); // Rolltype related to SMSG_LOOT_ROLL
2009-10-17 15:51:44 -07:00
2010-04-08 08:20:08 +02:00
for ( Roll :: PlayerVote :: const_iterator itr = r . playerVote . begin (); itr != r . playerVote . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Player * p = ObjectAccessor :: FindPlayer ( itr -> first );
2010-04-07 19:14:10 +02:00
if ( ! p || ! p -> GetSession ())
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( itr -> second != NOT_VALID )
2010-04-07 22:59:46 +02:00
p -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Group :: SendLootAllPassed ( uint32 NumberOfPlayers , const Roll & r )
{
WorldPacket data ( SMSG_LOOT_ALL_PASSED , ( 8 + 4 + 4 + 4 + 4 ));
data << uint64 ( r . itemGUID ); // Guid of the item rolled
data << uint32 ( NumberOfPlayers ); // The number of players rolling for it???
data << uint32 ( r . itemid ); // The itemEntryId for the item that shall be rolled for
data << uint32 ( r . itemRandomPropId ); // Item random property ID
data << uint32 ( r . itemRandomSuffix ); // Item random suffix ID
2009-10-17 15:51:44 -07:00
2010-04-08 08:20:08 +02:00
for ( Roll :: PlayerVote :: const_iterator itr = r . playerVote . begin (); itr != r . playerVote . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Player * p = ObjectAccessor :: FindPlayer ( itr -> first );
2010-04-07 19:14:10 +02:00
if ( ! p || ! p -> GetSession ())
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( itr -> second != NOT_VALID )
2010-04-07 22:59:46 +02:00
p -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
// notify group members which player is the allowed looter for the given creature
2011-10-07 11:08:09 -05:00
void Group :: SendLooter ( Creature * creature , Player * pLooter )
2010-03-11 22:55:02 +01:00
{
2011-10-07 11:08:09 -05:00
ASSERT ( creature );
2010-03-11 22:55:02 +01:00
2010-04-07 18:09:10 +02:00
WorldPacket data ( SMSG_LOOT_LIST , ( 8 + 8 ));
2011-10-07 11:08:09 -05:00
data << uint64 ( creature -> GetGUID ());
2010-03-11 22:55:02 +01:00
data << uint8 ( 0 ); // unk1
2010-04-07 18:09:10 +02:00
2010-03-11 22:55:02 +01:00
if ( pLooter )
data . append ( pLooter -> GetPackGUID ());
else
data << uint8 ( 0 );
BroadcastPacket ( & data , false );
}
2011-09-15 14:08:17 +02:00
void Group :: GroupLoot ( Loot * loot , WorldObject * pLootedObject )
2008-10-11 14:16:25 -05:00
{
std :: vector < LootItem >:: iterator i ;
2011-09-15 14:08:17 +02:00
ItemTemplate const * item ;
2008-10-11 14:16:25 -05:00
uint8 itemSlot = 0 ;
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
for ( i = loot -> items . begin (); i != loot -> items . end (); ++ i , ++ itemSlot )
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
if ( i -> freeforall )
continue ;
2011-04-28 22:42:33 +02:00
item = sObjectMgr -> GetItemTemplate ( i -> itemid );
2008-10-11 14:16:25 -05:00
if ( ! item )
{
2010-12-23 23:25:44 +01:00
//sLog->outDebug("Group::GroupLoot: missing item prototype for item with id: %d", i->itemid);
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//roll for over-threshold item if it's one-player loot
2010-03-11 22:55:02 +01:00
if ( item -> Quality >= uint32 ( m_lootThreshold ))
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
uint64 newitemGUID = MAKE_NEW_GUID ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_ITEM ), 0 , HIGHGUID_ITEM );
Roll * r = new Roll ( newitemGUID , * i );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//a vector is filled with only near party members
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Player * member = itr -> getSource ();
2010-03-11 22:55:02 +01:00
if ( ! member || ! member -> GetSession ())
2008-10-11 14:16:25 -05:00
continue ;
2010-03-11 22:55:02 +01:00
if ( i -> AllowedForPlayer ( member ))
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
if ( member -> IsWithinDistInMap ( pLootedObject , sWorld -> getFloatConfig ( CONFIG_GROUP_XP_DISTANCE ), false ))
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
r -> totalPlayersRolling ++ ;
2010-04-17 18:55:17 +02:00
if ( member -> GetPassOnGroupLoot ())
{
r -> playerVote [ member -> GetGUID ()] = PASS ;
r -> totalPass ++ ;
// can't broadcast the pass now. need to wait until all rolling players are known.
}
else
r -> playerVote [ member -> GetGUID ()] = NOT_EMITED_YET ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
if ( r -> totalPlayersRolling > 0 )
{
r -> setLoot ( loot );
r -> itemSlot = itemSlot ;
2010-05-21 22:45:47 +02:00
if ( item -> DisenchantID && m_maxEnchantingLevel >= item -> RequiredDisenchantSkill )
r -> rollVoteMask |= ROLL_FLAG_TYPE_DISENCHANT ;
2010-03-11 22:55:02 +01:00
loot -> items [ itemSlot ]. is_blocked = true ;
2009-10-17 15:51:44 -07:00
2010-04-17 18:55:17 +02:00
// If there is any "auto pass", broadcast the pass now.
if ( r -> totalPass )
{
for ( Roll :: PlayerVote :: const_iterator itr = r -> playerVote . begin (); itr != r -> playerVote . end (); ++ itr )
{
2011-09-15 14:08:17 +02:00
Player * p = ObjectAccessor :: FindPlayer ( itr -> first );
2010-04-17 18:55:17 +02:00
if ( ! p || ! p -> GetSession ())
continue ;
if ( itr -> second == PASS )
SendLootRoll ( newitemGUID , p -> GetGUID (), 128 , ROLL_PASS , * r );
}
}
2010-04-19 17:13:20 +02:00
2010-04-11 12:57:09 +02:00
SendLootStartRoll ( 60000 , pLootedObject -> GetMapId (), * r );
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
RollId . push_back ( r );
2011-07-08 11:12:19 +02:00
if ( Creature * creature = pLootedObject -> ToCreature ())
2010-03-11 22:55:02 +01:00
{
creature -> m_groupLootTimer = 60000 ;
2010-08-02 17:28:47 +02:00
creature -> lootingGroupLowGUID = GetLowGUID ();
2010-03-11 22:55:02 +01:00
}
2011-07-08 11:12:19 +02:00
else if ( GameObject * go = pLootedObject -> ToGameObject ())
2010-03-11 22:55:02 +01:00
{
go -> m_groupLootTimer = 60000 ;
2010-08-02 17:28:47 +02:00
go -> lootingGroupLowGUID = GetLowGUID ();
2010-03-11 22:55:02 +01:00
}
}
else
delete r ;
2008-10-11 14:16:25 -05:00
}
else
2010-09-21 21:55:16 +02:00
i -> is_underthreshold = true ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Group :: NeedBeforeGreed ( Loot * loot , WorldObject * pLootedObject )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
ItemTemplate const * item ;
2008-10-11 14:16:25 -05:00
uint8 itemSlot = 0 ;
2009-10-17 16:20:24 -07:00
for ( std :: vector < LootItem >:: iterator i = loot -> items . begin (); i != loot -> items . end (); ++ i , ++ itemSlot )
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
if ( i -> freeforall )
continue ;
2011-04-28 22:42:33 +02:00
item = sObjectMgr -> GetItemTemplate ( i -> itemid );
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
//roll for over-threshold item if it's one-player loot
if ( item -> Quality >= uint32 ( m_lootThreshold ))
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
uint64 newitemGUID = MAKE_NEW_GUID ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_ITEM ), 0 , HIGHGUID_ITEM );
Roll * r = new Roll ( newitemGUID , * i );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-06-12 01:47:45 +02:00
Player * playerToRoll = itr -> getSource ();
2010-03-11 22:55:02 +01:00
if ( ! playerToRoll || ! playerToRoll -> GetSession ())
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-09-21 21:55:16 +02:00
bool allowedForPlayer = i -> AllowedForPlayer ( playerToRoll );
if ( playerToRoll -> CanUseItem ( item ) == EQUIP_ERR_OK && allowedForPlayer )
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
if ( playerToRoll -> IsWithinDistInMap ( pLootedObject , sWorld -> getFloatConfig ( CONFIG_GROUP_XP_DISTANCE ), false ))
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
r -> totalPlayersRolling ++ ;
2010-04-17 18:55:17 +02:00
if ( playerToRoll -> GetPassOnGroupLoot ())
{
r -> playerVote [ playerToRoll -> GetGUID ()] = PASS ;
r -> totalPass ++ ;
// can't broadcast the pass now. need to wait until all rolling players are known.
}
else
r -> playerVote [ playerToRoll -> GetGUID ()] = NOT_EMITED_YET ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( r -> totalPlayersRolling > 0 )
{
r -> setLoot ( loot );
r -> itemSlot = itemSlot ;
2010-05-21 22:45:47 +02:00
if ( item -> DisenchantID && m_maxEnchantingLevel >= item -> RequiredDisenchantSkill )
r -> rollVoteMask |= ROLL_FLAG_TYPE_DISENCHANT ;
if ( item -> Flags2 & ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED )
r -> rollVoteMask &= ~ ROLL_FLAG_TYPE_NEED ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
loot -> items [ itemSlot ]. is_blocked = true ;
2009-10-17 15:51:44 -07:00
2010-04-17 18:55:17 +02:00
// If there is any "auto pass", broadcast the pass now.
if ( r -> totalPass )
{
for ( Roll :: PlayerVote :: const_iterator itr = r -> playerVote . begin (); itr != r -> playerVote . end (); ++ itr )
{
2011-09-15 14:08:17 +02:00
Player * p = ObjectAccessor :: FindPlayer ( itr -> first );
2010-04-17 18:55:17 +02:00
if ( ! p || ! p -> GetSession ())
continue ;
if ( itr -> second == PASS )
SendLootRoll ( newitemGUID , p -> GetGUID (), 128 , ROLL_PASS , * r );
}
}
2010-04-11 12:57:09 +02:00
SendLootStartRoll ( 60000 , pLootedObject -> GetMapId (), * r );
2010-03-11 22:55:02 +01:00
2008-10-11 14:16:25 -05:00
RollId . push_back ( r );
2010-03-11 22:55:02 +01:00
2011-07-08 11:12:19 +02:00
if ( Creature * creature = pLootedObject -> ToCreature ())
2010-03-11 22:55:02 +01:00
{
creature -> m_groupLootTimer = 60000 ;
2010-08-02 17:28:47 +02:00
creature -> lootingGroupLowGUID = GetLowGUID ();
2010-03-11 22:55:02 +01:00
}
2008-10-11 14:16:25 -05:00
}
else
delete r ;
}
else
2010-09-21 21:55:16 +02:00
i -> is_underthreshold = true ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
void Group :: MasterLoot ( Loot * /*loot*/ , WorldObject * pLootedObject )
2008-10-11 14:16:25 -05:00
{
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "Group::MasterLoot (SMSG_LOOT_MASTER_LIST, 330)" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 real_count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ( SMSG_LOOT_MASTER_LIST , 330 );
data << ( uint8 ) GetMembersCount ();
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Player * looter = itr -> getSource ();
2008-10-11 14:16:25 -05:00
if ( ! looter -> IsInWorld ())
continue ;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
if ( looter -> IsWithinDistInMap ( pLootedObject , sWorld -> getFloatConfig ( CONFIG_GROUP_XP_DISTANCE ), false ))
2008-10-11 14:16:25 -05:00
{
2010-04-11 11:16:42 +04:00
data << uint64 ( looter -> GetGUID ());
2008-10-11 14:16:25 -05:00
++ real_count ;
}
}
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
data . put < uint8 > ( 0 , real_count );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Player * looter = itr -> getSource ();
2011-04-29 20:47:02 +02:00
if ( looter -> IsWithinDistInMap ( pLootedObject , sWorld -> getFloatConfig ( CONFIG_GROUP_XP_DISTANCE ), false ))
2008-10-11 14:16:25 -05:00
looter -> GetSession () -> SendPacket ( & data );
}
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
void Group :: CountRollVote ( uint64 playerGUID , uint64 Guid , uint32 NumberOfPlayers , uint8 Choice )
2008-10-11 14:16:25 -05:00
{
Rolls :: iterator rollI = GetRoll ( Guid );
if ( rollI == RollId . end ())
return ;
Roll * roll = * rollI ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Roll :: PlayerVote :: iterator itr = roll -> playerVote . find ( playerGUID );
// this condition means that player joins to the party after roll begins
if ( itr == roll -> playerVote . end ())
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( roll -> getLoot ())
if ( roll -> getLoot () -> items . empty ())
return ;
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
switch ( Choice )
2008-10-11 14:16:25 -05:00
{
2009-12-17 11:11:54 +01:00
case ROLL_PASS : // Player choose pass
2010-01-20 20:42:54 +01:00
SendLootRoll ( 0 , playerGUID , 128 , ROLL_PASS , * roll );
2008-10-11 14:16:25 -05:00
++ roll -> totalPass ;
itr -> second = PASS ;
2010-03-11 22:55:02 +01:00
break ;
2009-12-17 11:11:54 +01:00
case ROLL_NEED : // player choose Need
2010-01-20 20:42:54 +01:00
SendLootRoll ( 0 , playerGUID , 0 , 0 , * roll );
2008-10-11 14:16:25 -05:00
++ roll -> totalNeed ;
itr -> second = NEED ;
2010-03-11 22:55:02 +01:00
break ;
2009-12-17 11:11:54 +01:00
case ROLL_GREED : // player choose Greed
SendLootRoll ( 0 , playerGUID , 128 , ROLL_GREED , * roll );
2008-10-11 14:16:25 -05:00
++ roll -> totalGreed ;
itr -> second = GREED ;
2010-03-11 22:55:02 +01:00
break ;
2010-02-14 19:13:14 -07:00
case ROLL_DISENCHANT : // player choose Disenchant
SendLootRoll ( 0 , playerGUID , 128 , ROLL_DISENCHANT , * roll );
++ roll -> totalGreed ;
itr -> second = DISENCHANT ;
2010-03-11 22:55:02 +01:00
break ;
2008-10-11 14:16:25 -05:00
}
2010-03-11 22:55:02 +01:00
2010-02-14 19:13:14 -07:00
if ( roll -> totalPass + roll -> totalNeed + roll -> totalGreed >= roll -> totalPlayersRolling )
2008-10-11 14:16:25 -05:00
CountTheRoll ( rollI , NumberOfPlayers );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//called when roll timer expires
2011-09-15 14:08:17 +02:00
void Group :: EndRoll ( Loot * pLoot )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
for ( Rolls :: iterator itr = RollId . begin (); itr != RollId . end ();)
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
if (( * itr ) -> getLoot () == pLoot ) {
CountTheRoll ( itr , GetMembersCount ()); //i don't have to edit player votes, who didn't vote ... he will pass
itr = RollId . begin ();
}
else
2011-08-23 18:05:01 +03:00
++ itr ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Group :: CountTheRoll ( Rolls :: iterator rollI , uint32 NumberOfPlayers )
{
Roll * roll = * rollI ;
2010-03-11 22:55:02 +01:00
if ( ! roll -> isValid ()) // is loot already deleted ?
2008-10-11 14:16:25 -05:00
{
RollId . erase ( rollI );
delete roll ;
return ;
}
2010-09-11 09:09:41 -07:00
2008-10-11 14:16:25 -05:00
//end of the roll
if ( roll -> totalNeed > 0 )
{
2010-03-11 22:55:02 +01:00
if ( ! roll -> playerVote . empty ())
2008-10-11 14:16:25 -05:00
{
uint8 maxresul = 0 ;
uint64 maxguid = ( * roll -> playerVote . begin ()). first ;
2011-06-12 01:47:45 +02:00
Player * player ;
2009-10-17 15:51:44 -07:00
2010-04-08 08:20:08 +02:00
for ( Roll :: PlayerVote :: const_iterator itr = roll -> playerVote . begin (); itr != roll -> playerVote . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
if ( itr -> second != NEED )
continue ;
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
uint8 randomN = urand ( 1 , 100 );
2009-12-17 11:11:54 +01:00
SendLootRoll ( 0 , itr -> first , randomN , ROLL_NEED , * roll );
2008-10-11 14:16:25 -05:00
if ( maxresul < randomN )
{
maxguid = itr -> first ;
maxresul = randomN ;
}
}
2009-12-17 11:11:54 +01:00
SendLootRollWon ( 0 , maxguid , maxresul , ROLL_NEED , * roll );
2011-07-27 12:14:27 +02:00
player = ObjectAccessor :: FindPlayer ( maxguid );
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
if ( player && player -> GetSession ())
2008-10-11 14:16:25 -05:00
{
2009-01-02 11:03:43 -06:00
player -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT , roll -> itemid , maxresul );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ItemPosCountVec dest ;
2011-09-15 14:08:17 +02:00
LootItem * item = & ( roll -> getLoot () -> items [ roll -> itemSlot ]);
2011-04-29 16:48:15 +06:00
InventoryResult msg = player -> CanStoreNewItem ( NULL_BAG , NULL_SLOT , dest , roll -> itemid , item -> count );
2010-03-11 22:55:02 +01:00
if ( msg == EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
item -> is_looted = true ;
roll -> getLoot () -> NotifyItemRemoved ( roll -> itemSlot );
2010-03-11 22:55:02 +01:00
roll -> getLoot () -> unlootedCount -- ;
2011-10-18 10:44:45 +02:00
AllowedLooterSet looters = item -> GetAllowedLooters ();
player -> StoreNewItem ( dest , roll -> itemid , true , item -> randomPropertyId , looters );
2008-10-11 14:16:25 -05:00
}
else
{
item -> is_blocked = false ;
2010-08-05 22:08:07 +06:00
player -> SendEquipError ( msg , NULL , NULL , roll -> itemid );
2008-10-11 14:16:25 -05:00
}
}
}
}
else if ( roll -> totalGreed > 0 )
{
2010-03-11 22:55:02 +01:00
if ( ! roll -> playerVote . empty ())
2008-10-11 14:16:25 -05:00
{
uint8 maxresul = 0 ;
uint64 maxguid = ( * roll -> playerVote . begin ()). first ;
2011-06-12 01:47:45 +02:00
Player * player ;
2010-04-19 17:03:10 +02:00
RollVote rollvote = NOT_VALID ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Roll :: PlayerVote :: iterator itr ;
2010-03-11 22:55:02 +01:00
for ( itr = roll -> playerVote . begin (); itr != roll -> playerVote . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2010-02-14 19:13:14 -07:00
if ( itr -> second != GREED && itr -> second != DISENCHANT )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
uint8 randomN = urand ( 1 , 100 );
2010-02-14 19:13:14 -07:00
SendLootRoll ( 0 , itr -> first , randomN , itr -> second , * roll );
2008-10-11 14:16:25 -05:00
if ( maxresul < randomN )
{
maxguid = itr -> first ;
maxresul = randomN ;
2010-02-14 19:13:14 -07:00
rollvote = itr -> second ;
2008-10-11 14:16:25 -05:00
}
}
2010-02-14 19:13:14 -07:00
SendLootRollWon ( 0 , maxguid , maxresul , rollvote , * roll );
2011-07-27 12:14:27 +02:00
player = ObjectAccessor :: FindPlayer ( maxguid );
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
if ( player && player -> GetSession ())
2008-10-11 14:16:25 -05:00
{
2009-01-02 11:03:43 -06:00
player -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT , roll -> itemid , maxresul );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
LootItem * item = & ( roll -> getLoot () -> items [ roll -> itemSlot ]);
2010-02-14 19:13:14 -07:00
2010-03-11 22:55:02 +01:00
if ( rollvote == GREED )
2010-02-14 19:13:14 -07:00
{
ItemPosCountVec dest ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = player -> CanStoreNewItem ( NULL_BAG , NULL_SLOT , dest , roll -> itemid , item -> count );
2010-03-11 22:55:02 +01:00
if ( msg == EQUIP_ERR_OK )
2010-02-14 19:13:14 -07:00
{
item -> is_looted = true ;
roll -> getLoot () -> NotifyItemRemoved ( roll -> itemSlot );
2010-03-11 22:55:02 +01:00
roll -> getLoot () -> unlootedCount -- ;
2011-10-18 10:44:45 +02:00
AllowedLooterSet looters = item -> GetAllowedLooters ();
player -> StoreNewItem ( dest , roll -> itemid , true , item -> randomPropertyId , looters );
2010-02-14 19:13:14 -07:00
}
else
{
item -> is_blocked = false ;
2010-08-05 22:08:07 +06:00
player -> SendEquipError ( msg , NULL , NULL , roll -> itemid );
2010-02-14 19:13:14 -07:00
}
}
2010-04-07 19:14:10 +02:00
else if ( rollvote == DISENCHANT )
2008-10-11 14:16:25 -05:00
{
item -> is_looted = true ;
roll -> getLoot () -> NotifyItemRemoved ( roll -> itemSlot );
2010-03-11 22:55:02 +01:00
roll -> getLoot () -> unlootedCount -- ;
2011-09-15 14:08:17 +02:00
ItemTemplate const * pProto = sObjectMgr -> GetItemTemplate ( roll -> itemid );
2010-02-14 19:13:14 -07:00
player -> AutoStoreLoot ( pProto -> DisenchantID , LootTemplates_Disenchant , true );
2008-10-11 14:16:25 -05:00
}
}
}
}
else
{
SendLootAllPassed ( NumberOfPlayers , * roll );
2010-03-11 22:55:02 +01:00
// remove is_blocked so that the item is lootable by all players
2011-09-15 14:08:17 +02:00
LootItem * item = & ( roll -> getLoot () -> items [ roll -> itemSlot ]);
2010-04-07 18:09:10 +02:00
if ( item )
2010-03-11 22:55:02 +01:00
item -> is_blocked = false ;
2008-10-11 14:16:25 -05:00
}
2010-09-11 09:09:41 -07:00
2008-10-11 14:16:25 -05:00
RollId . erase ( rollI );
delete roll ;
}
2009-10-17 15:51:44 -07:00
2010-02-14 19:13:14 -07:00
void Group :: SetTargetIcon ( uint8 id , uint64 whoGuid , uint64 targetGuid )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( id >= TARGETICONCOUNT )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// clean other icons
2010-04-07 22:59:46 +02:00
if ( targetGuid != 0 )
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < TARGETICONCOUNT ; ++ i )
2010-04-07 22:59:46 +02:00
if ( m_targetIcons [ i ] == targetGuid )
2010-02-14 19:13:14 -07:00
SetTargetIcon ( i , 0 , 0 );
2009-10-17 15:51:44 -07:00
2010-02-14 19:13:14 -07:00
m_targetIcons [ id ] = targetGuid ;
2009-10-17 15:51:44 -07:00
2010-02-14 19:13:14 -07:00
WorldPacket data ( MSG_RAID_TARGET_UPDATE , ( 1 + 8 + 1 + 8 ));
data << uint8 ( 0 ); // set targets
data << uint64 ( whoGuid );
data << uint8 ( id );
data << uint64 ( targetGuid );
2009-03-14 20:00:02 -06:00
BroadcastPacket ( & data , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Group :: SendTargetIconList ( WorldSession * session )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! session )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ( MSG_RAID_TARGET_UPDATE , ( 1 + TARGETICONCOUNT * 9 ));
2010-02-14 19:13:14 -07:00
data << uint8 ( 1 ); // list targets
2009-10-17 15:51:44 -07:00
2010-09-11 09:09:41 -07:00
for ( uint8 i = 0 ; i < TARGETICONCOUNT ; ++ i )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( m_targetIcons [ i ] == 0 )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-02-14 19:13:14 -07:00
data << uint8 ( i );
data << uint64 ( m_targetIcons [ i ]);
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
session -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Group :: SendUpdate ()
{
2011-09-17 20:17:41 +02:00
for ( member_witerator witr = m_memberSlots . begin (); witr != m_memberSlots . end (); ++ witr )
2008-10-11 14:16:25 -05:00
{
2011-09-17 20:17:41 +02:00
SendUpdateToPlayer ( witr -> guid , & ( * witr ));
}
}
2010-03-09 20:33:59 +01:00
2011-09-17 20:17:41 +02:00
void Group :: SendUpdateToPlayer ( uint64 playerGUID , MemberSlot * slot )
{
Player * player = ObjectAccessor :: FindPlayer ( playerGUID );
2010-08-11 15:20:20 +02:00
2011-09-17 20:17:41 +02:00
if ( ! player || ! player -> GetSession () || player -> GetGroup () != this )
return ;
2010-09-11 09:09:41 -07:00
2011-09-17 20:17:41 +02:00
// if MemberSlot wasn't provided
if ( ! slot )
{
member_witerator witr = _getMemberWSlot ( playerGUID );
2010-04-07 18:09:10 +02:00
2011-09-17 20:17:41 +02:00
if ( witr == m_memberSlots . end ()) // if there is no MemberSlot for such a player
return ;
2009-10-17 15:51:44 -07:00
2011-09-17 20:17:41 +02:00
slot = & ( * witr );
}
2011-09-29 12:43:05 +02:00
2011-09-17 20:17:41 +02:00
WorldPacket data ( SMSG_GROUP_LIST , ( 1 + 1 + 1 + 1 + 1 + 4 + 8 + 4 + 4 + ( GetMembersCount () - 1 ) * ( 13 + 8 + 1 + 1 + 1 + 1 ) + 8 + 1 + 8 + 1 + 1 + 1 + 1 ));
data << uint8 ( m_groupType ); // group type (flags in 3.3)
data << uint8 ( slot -> group );
data << uint8 ( slot -> flags );
data << uint8 ( slot -> roles );
if ( isLFGGroup ())
{
data << uint8 ( sLFGMgr -> GetState ( m_guid ) == LFG_STATE_FINISHED_DUNGEON ? 2 : 0 ); // FIXME - Dungeon save status? 2 = done
data << uint32 ( sLFGMgr -> GetDungeon ( m_guid ));
}
2010-09-11 09:09:41 -07:00
2011-09-17 20:17:41 +02:00
data << uint64 ( m_guid );
data << uint32 ( m_counter ++ ); // 3.3, value increases every time this packet gets sent
data << uint32 ( GetMembersCount () - 1 );
for ( member_citerator citr = m_memberSlots . begin (); citr != m_memberSlots . end (); ++ citr )
{
if ( slot -> guid == citr -> guid )
continue ;
2010-09-11 09:09:41 -07:00
2011-09-17 20:17:41 +02:00
Player * member = ObjectAccessor :: FindPlayer ( citr -> guid );
uint8 onlineState = ( member ) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE ;
onlineState = onlineState | (( isBGGroup ()) ? MEMBER_STATUS_PVP : 0 );
2010-09-11 09:09:41 -07:00
2011-09-17 20:17:41 +02:00
data << citr -> name ;
data << uint64 ( citr -> guid ); // guid
data << uint8 ( onlineState ); // online-state
data << uint8 ( citr -> group ); // groupid
data << uint8 ( citr -> flags ); // See enum GroupMemberFlags
data << uint8 ( citr -> roles ); // Lfg Roles
2008-10-11 14:16:25 -05:00
}
2011-09-17 20:17:41 +02:00
data << uint64 ( m_leaderGuid ); // leader guid
if ( GetMembersCount () - 1 )
{
data << uint8 ( m_lootMethod ); // loot method
data << uint64 ( m_looterGuid ); // looter guid
data << uint8 ( m_lootThreshold ); // loot threshold
data << uint8 ( m_dungeonDifficulty ); // Dungeon Difficulty
data << uint8 ( m_raidDifficulty ); // Raid Difficulty
data << uint8 ( 0 ); // 3.3
}
player -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-10-07 11:08:09 -05:00
void Group :: UpdatePlayerOutOfRange ( Player * player )
2008-10-11 14:16:25 -05:00
{
2011-10-07 11:08:09 -05:00
if ( ! player || ! player -> IsInWorld ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ;
2011-10-07 11:08:09 -05:00
player -> GetSession () -> BuildPartyMemberStatsChangedPacket ( player , & data );
2009-10-17 15:51:44 -07:00
2011-10-11 23:09:49 +02:00
Player * member ;
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-10-11 23:09:49 +02:00
member = itr -> getSource ();
if ( member && ! member -> IsWithinDist ( player , member -> GetSightRange (), false ))
member -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-06-12 02:06:07 +02:00
void Group :: BroadcastPacket ( WorldPacket * packet , bool ignorePlayersInBGRaid , int group , uint64 ignore )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-10-11 23:09:49 +02:00
Player * plr = itr -> getSource ();
if ( ! plr || ( ignore != 0 && plr -> GetGUID () == ignore ) || ( ignorePlayersInBGRaid && plr -> GetGroup () != this ))
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2011-10-11 23:09:49 +02:00
if ( plr -> GetSession () && ( group == - 1 || itr -> getSubGroup () == group ))
plr -> GetSession () -> SendPacket ( packet );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-06-12 02:06:07 +02:00
void Group :: BroadcastReadyCheck ( WorldPacket * packet )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-10-11 23:09:49 +02:00
Player * plr = itr -> getSource ();
if ( plr && plr -> GetSession ())
if ( IsLeader ( plr -> GetGUID ()) || IsAssistant ( plr -> GetGUID ()))
plr -> GetSession () -> SendPacket ( packet );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Group :: OfflineReadyCheck ()
{
2009-10-17 16:20:24 -07:00
for ( member_citerator citr = m_memberSlots . begin (); citr != m_memberSlots . end (); ++ citr )
2008-10-11 14:16:25 -05:00
{
2011-10-11 23:09:49 +02:00
Player * plr = ObjectAccessor :: FindPlayer ( citr -> guid );
if ( ! plr || ! plr -> GetSession ())
2008-10-11 14:16:25 -05:00
{
WorldPacket data ( MSG_RAID_READY_CHECK_CONFIRM , 9 );
2010-04-11 11:16:42 +04:00
data << uint64 ( citr -> guid );
data << uint8 ( 0 );
2008-10-11 14:16:25 -05:00
BroadcastReadyCheck ( & data );
}
}
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
bool Group :: _setMembersGroup ( uint64 guid , uint8 group )
2008-10-11 14:16:25 -05:00
{
member_witerator slot = _getMemberWSlot ( guid );
2010-04-07 23:25:02 +02:00
if ( slot == m_memberSlots . end ())
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
slot -> group = group ;
2009-10-17 15:51:44 -07:00
2009-02-01 16:38:53 -06:00
SubGroupCounterIncrease ( group );
2009-10-17 15:51:44 -07:00
2010-09-11 09:09:41 -07:00
if ( ! isBGGroup ())
CharacterDatabase . PExecute ( "UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'" , group , GUID_LOPART ( guid ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool Group :: SameSubGroup ( Player const * member1 , Player const * member2 ) const
{
2010-09-11 09:09:41 -07:00
if ( ! member1 || ! member2 )
return false ;
2011-10-11 23:09:49 +02:00
2010-09-11 09:09:41 -07:00
if ( member1 -> GetGroup () != this || member2 -> GetGroup () != this )
return false ;
else
return member1 -> GetSubGroup () == member2 -> GetSubGroup ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-02-18 18:35:52 +01:00
// Allows setting sub groups both for online or offline members
2011-08-30 13:46:36 +02:00
void Group :: ChangeMembersGroup ( uint64 guid , uint8 group )
2008-10-11 14:16:25 -05:00
{
2011-02-18 18:35:52 +01:00
// Only raid groups have sub groups
2010-04-07 19:14:10 +02:00
if ( ! isRaidGroup ())
2008-10-11 14:16:25 -05:00
return ;
2010-06-22 00:42:31 +02:00
2011-02-18 18:35:52 +01:00
// Check if player is really in the raid
member_witerator slot = _getMemberWSlot ( guid );
if ( slot == m_memberSlots . end ())
2008-10-11 14:16:25 -05:00
return ;
2010-08-08 19:45:53 +02:00
2011-02-18 18:35:52 +01:00
// Abort if the player is already in the target sub group
uint8 prevSubGroup = GetMemberGroup ( guid );
2010-06-22 00:42:31 +02:00
if ( prevSubGroup == group )
return ;
2011-02-18 18:35:52 +01:00
// Update the player slot with the new sub group setting
slot -> group = group ;
// Increase the counter of the new sub group..
SubGroupCounterIncrease ( group );
// ..and decrease the counter of the previous one
SubGroupCounterDecrease ( prevSubGroup );
// Preserve new sub group in database for non-raid groups
if ( ! isBGGroup ())
CharacterDatabase . PExecute ( "UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'" , group , GUID_LOPART ( guid ));
// In case the moved player is online, update the player object with the new sub group references
2011-10-11 23:09:49 +02:00
if ( Player * player = ObjectAccessor :: FindPlayer ( guid ))
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( player -> GetGroup () == this )
2009-03-14 20:00:02 -06:00
player -> GetGroupRef (). setSubGroup ( group );
else
{
2011-02-18 18:35:52 +01:00
// If player is in BG raid, it is possible that he is also in normal raid - and that normal raid is stored in m_originalGroup reference
2009-03-14 20:00:02 -06:00
prevSubGroup = player -> GetOriginalSubGroup ();
player -> GetOriginalGroupRef (). setSubGroup ( group );
}
2008-10-11 14:16:25 -05:00
}
2011-02-18 18:35:52 +01:00
// Broadcast the changes to the group
SendUpdate ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
// Retrieve the next Round-Roubin player for the group
//
// No update done if loot method is Master or FFA.
//
// If the RR player is not yet set for the group, the first group member becomes the round-robin player.
// If the RR player is set, the next player in group becomes the round-robin player.
//
2010-04-07 18:09:10 +02:00
// If ifneed is true,
2010-03-11 22:55:02 +01:00
// the current RR player is checked to be near the looted object.
// if yes, no update done.
2010-11-14 23:46:34 +02:00
// if not, he loses his turn.
2010-03-11 22:55:02 +01:00
void Group :: UpdateLooterGuid ( WorldObject * pLootedObject , bool ifneed )
2008-10-11 14:16:25 -05:00
{
switch ( GetLootMethod ())
{
case MASTER_LOOT :
case FREE_FOR_ALL :
return ;
default :
// round robin style looting applies for all low
// quality items in each loot method except free for all and master loot
break ;
}
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
uint64 oldLooterGUID = GetLooterGuid ();
member_citerator guid_itr = _getMemberCSlot ( oldLooterGUID );
if ( guid_itr != m_memberSlots . end ())
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
if ( ifneed )
2008-10-11 14:16:25 -05:00
{
// not update if only update if need and ok
Player * looter = ObjectAccessor :: FindPlayer ( guid_itr -> guid );
2011-04-29 20:47:02 +02:00
if ( looter && looter -> IsWithinDistInMap ( pLootedObject , sWorld -> getFloatConfig ( CONFIG_GROUP_XP_DISTANCE ), false ))
2008-10-11 14:16:25 -05:00
return ;
}
++ guid_itr ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// search next after current
2011-09-15 14:08:17 +02:00
Player * pNewLooter = NULL ;
2010-03-11 22:55:02 +01:00
for ( member_citerator itr = guid_itr ; itr != m_memberSlots . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
if ( Player * pl = ObjectAccessor :: FindPlayer ( itr -> guid ))
2011-04-29 20:47:02 +02:00
if ( pl -> IsWithinDistInMap ( pLootedObject , sWorld -> getFloatConfig ( CONFIG_GROUP_XP_DISTANCE ), false ))
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
pNewLooter = pl ;
break ;
}
}
if ( ! pNewLooter )
{
// search from start
for ( member_citerator itr = m_memberSlots . begin (); itr != guid_itr ; ++ itr )
{
if ( Player * pl = ObjectAccessor :: FindPlayer ( itr -> guid ))
2011-04-29 20:47:02 +02:00
if ( pl -> IsWithinDistInMap ( pLootedObject , sWorld -> getFloatConfig ( CONFIG_GROUP_XP_DISTANCE ), false ))
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
pNewLooter = pl ;
break ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-03-11 22:55:02 +01:00
if ( pNewLooter )
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
if ( oldLooterGUID != pNewLooter -> GetGUID ())
2008-10-11 14:16:25 -05:00
{
2010-03-11 22:55:02 +01:00
SetLooterGuid ( pNewLooter -> GetGUID ());
SendUpdate ();
2008-10-11 14:16:25 -05:00
}
}
2010-03-11 22:55:02 +01:00
else
{
SetLooterGuid ( 0 );
SendUpdate ();
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
GroupJoinBattlegroundResult Group :: CanJoinBattlegroundQueue ( Battleground const * bgOrTemplate , BattlegroundQueueTypeId bgQueueTypeId , uint32 MinPlayerCount , uint32 /*MaxPlayerCount*/ , bool isRated , uint32 arenaSlot )
2008-10-11 14:16:25 -05:00
{
2010-11-24 15:37:22 +01:00
// check if this group is LFG group
if ( isLFGGroup ())
return ERR_LFG_CANT_USE_BATTLEGROUND ;
2010-04-11 11:22:29 +04:00
BattlemasterListEntry const * bgEntry = sBattlemasterListStore . LookupEntry ( bgOrTemplate -> GetTypeID ());
2010-04-11 20:20:38 +02:00
if ( ! bgEntry )
return ERR_GROUP_JOIN_BATTLEGROUND_FAIL ; // shouldn't happen
2010-04-11 11:22:29 +04:00
2008-10-11 14:16:25 -05:00
// check for min / max count
uint32 memberscount = GetMembersCount ();
2010-04-11 20:20:38 +02:00
2010-04-11 11:22:29 +04:00
if ( memberscount > bgEntry -> maxGroupSize ) // no MinPlayerCount for battlegrounds
2010-05-08 01:58:47 +02:00
return ERR_BATTLEGROUND_NONE ; // ERR_GROUP_JOIN_BATTLEGROUND_TOO_MANY handled on client side
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
2011-06-11 22:35:29 +02:00
Player * reference = GetFirstMember () -> getSource ();
2008-10-11 14:16:25 -05:00
// no reference found, can't join this way
2010-04-07 19:14:10 +02:00
if ( ! reference )
2010-04-11 11:22:29 +04:00
return ERR_BATTLEGROUND_JOIN_FAILED ;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
PvPDifficultyEntry const * bracketEntry = GetBattlegroundBracketByLevel ( bgOrTemplate -> GetMapId (), reference -> getLevel ());
2010-04-07 19:14:10 +02:00
if ( ! bracketEntry )
2010-04-11 11:22:29 +04:00
return ERR_BATTLEGROUND_JOIN_FAILED ;
2010-02-15 15:31:27 +01:00
2008-10-11 14:16:25 -05:00
uint32 arenaTeamId = reference -> GetArenaTeamId ( arenaSlot );
uint32 team = reference -> GetTeam ();
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr :: BGQueueTypeId ( BATTLEGROUND_RB , 0 );
2010-05-26 11:34:37 +02:00
2008-10-11 14:16:25 -05:00
// check every member of the group to be able to join
2010-09-12 22:54:12 +02:00
memberscount = 0 ;
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next (), ++ memberscount )
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Player * member = itr -> getSource ();
2008-10-11 14:16:25 -05:00
// offline member? don't let join
2010-04-07 19:14:10 +02:00
if ( ! member )
2010-04-11 11:22:29 +04:00
return ERR_BATTLEGROUND_JOIN_FAILED ;
2008-10-11 14:16:25 -05:00
// don't allow cross-faction join as group
2010-04-07 19:14:10 +02:00
if ( member -> GetTeam () != team )
2010-04-11 11:22:29 +04:00
return ERR_BATTLEGROUND_JOIN_TIMED_OUT ;
2008-10-11 14:16:25 -05:00
// not in the same battleground level braket, don't let join
2011-04-29 20:47:02 +02:00
PvPDifficultyEntry const * memberBracketEntry = GetBattlegroundBracketByLevel ( bracketEntry -> mapId , member -> getLevel ());
2010-04-07 19:14:10 +02:00
if ( memberBracketEntry != bracketEntry )
2010-04-11 11:22:29 +04:00
return ERR_BATTLEGROUND_JOIN_RANGE_INDEX ;
2008-10-11 14:16:25 -05:00
// don't let join rated matches if the arena team id doesn't match
2010-04-07 19:14:10 +02:00
if ( isRated && member -> GetArenaTeamId ( arenaSlot ) != arenaTeamId )
2010-04-11 11:22:29 +04:00
return ERR_BATTLEGROUND_JOIN_FAILED ;
2008-10-11 14:16:25 -05:00
// don't let join if someone from the group is already in that bg queue
2010-08-08 04:37:24 +02:00
if ( member -> InBattlegroundQueueForBattlegroundQueueType ( bgQueueTypeId ))
2010-04-11 11:22:29 +04:00
return ERR_BATTLEGROUND_JOIN_FAILED ; // not blizz-like
2010-05-26 11:34:37 +02:00
// don't let join if someone from the group is in bg queue random
2010-08-08 04:37:24 +02:00
if ( member -> InBattlegroundQueueForBattlegroundQueueType ( bgQueueTypeIdRandom ))
2010-05-26 11:34:37 +02:00
return ERR_IN_RANDOM_BG ;
// don't let join to bg queue random if someone from the group is already in bg queue
2010-08-08 04:37:24 +02:00
if ( bgOrTemplate -> GetTypeID () == BATTLEGROUND_RB && member -> InBattlegroundQueue ())
2010-05-26 11:34:37 +02:00
return ERR_IN_NON_RANDOM_BG ;
2008-10-11 14:16:25 -05:00
// check for deserter debuff in case not arena queue
2010-04-07 19:14:10 +02:00
if ( bgOrTemplate -> GetTypeID () != BATTLEGROUND_AA && ! member -> CanJoinToBattleground ())
2010-04-11 11:22:29 +04:00
return ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS ;
2008-10-11 14:16:25 -05:00
// check if member can join any more battleground queues
2010-08-08 04:37:24 +02:00
if ( ! member -> HasFreeBattlegroundQueueId ())
2010-04-11 11:22:29 +04:00
return ERR_BATTLEGROUND_TOO_MANY_QUEUES ; // not blizz-like
2010-11-24 15:37:22 +01:00
// check if someone in party is using dungeon system
if ( member -> isUsingLfg ())
return ERR_LFG_CANT_USE_BATTLEGROUND ;
2008-10-11 14:16:25 -05:00
}
2010-09-12 17:48:50 +02:00
// only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas...
if ( bgOrTemplate -> isArena () && memberscount != MinPlayerCount )
return ERR_ARENA_TEAM_PARTY_SIZE ;
2010-04-11 11:22:29 +04:00
return GroupJoinBattlegroundResult ( bgOrTemplate -> GetTypeID ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//===================================================
2010-04-07 23:56:35 +02:00
//============== Roll ===============================
2008-10-11 14:16:25 -05:00
//===================================================
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Roll :: targetObjectBuildLink ()
{
// called from link()
2009-02-01 16:38:53 -06:00
getTarget () -> addLootValidatorRef ( this );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-17 11:11:54 +01:00
void Group :: SetDungeonDifficulty ( Difficulty difficulty )
2008-10-11 14:16:25 -05:00
{
2009-12-17 11:11:54 +01:00
m_dungeonDifficulty = difficulty ;
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2011-05-05 10:23:00 +02:00
CharacterDatabase . PExecute ( "UPDATE groups SET difficulty = %u WHERE guid ='%u'" , m_dungeonDifficulty , m_dbStoreId );
2009-12-18 13:41:30 -08:00
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-06-12 01:47:45 +02:00
Player * player = itr -> getSource ();
2011-07-19 20:35:05 +02:00
if ( ! player -> GetSession ())
2008-10-11 14:16:25 -05:00
continue ;
2010-09-11 09:09:41 -07:00
2009-12-17 11:11:54 +01:00
player -> SetDungeonDifficulty ( difficulty );
2008-10-11 14:16:25 -05:00
player -> SendDungeonDifficulty ( true );
2009-12-17 11:11:54 +01:00
}
}
void Group :: SetRaidDifficulty ( Difficulty difficulty )
{
m_raidDifficulty = difficulty ;
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2011-05-05 10:23:00 +02:00
CharacterDatabase . PExecute ( "UPDATE groups SET raiddifficulty = %u WHERE guid ='%u'" , m_raidDifficulty , m_dbStoreId );
2009-12-17 11:11:54 +01:00
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2009-12-17 11:11:54 +01:00
{
2011-06-12 01:47:45 +02:00
Player * player = itr -> getSource ();
2011-07-19 20:35:05 +02:00
if ( ! player -> GetSession ())
2009-12-17 11:11:54 +01:00
continue ;
2010-09-11 09:09:41 -07:00
2009-12-17 11:11:54 +01:00
player -> SetRaidDifficulty ( difficulty );
player -> SendRaidDifficulty ( true );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool Group :: InCombatToInstance ( uint32 instanceId )
{
2011-09-15 14:08:17 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2011-10-07 11:08:09 -05:00
Player * player = itr -> getSource ();
if ( player && ! player -> getAttackers (). empty () && player -> GetInstanceId () == instanceId && ( player -> GetMap () -> IsRaidOrHeroicDungeon ()))
for ( std :: set < Unit *>:: const_iterator i = player -> getAttackers (). begin (); i != player -> getAttackers (). end (); ++ i )
2010-09-11 09:09:41 -07:00
if (( * i ) && ( * i ) -> GetTypeId () == TYPEID_UNIT && ( * i ) -> ToCreature () -> GetCreatureInfo () -> flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND )
2009-02-13 23:53:06 +01:00
return true ;
2008-10-11 14:16:25 -05:00
}
return false ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 11:11:54 +01:00
void Group :: ResetInstances ( uint8 method , bool isRaid , Player * SendMsgTo )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( isBGGroup ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// we assume that when the difficulty changes, all instances that can be reset will be
2009-12-17 11:11:54 +01:00
Difficulty diff = GetDifficulty ( isRaid );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
for ( BoundInstancesMap :: iterator itr = m_boundInstances [ diff ]. begin (); itr != m_boundInstances [ diff ]. end ();)
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
InstanceSave * p = itr -> second . save ;
const MapEntry * entry = sMapStore . LookupEntry ( itr -> first );
2010-08-30 15:25:15 +02:00
if ( ! entry || entry -> IsRaid () != isRaid || ( ! p -> CanReset () && method != INSTANCE_RESET_GROUP_DISBAND ))
2008-10-11 14:16:25 -05:00
{
++ itr ;
continue ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( method == INSTANCE_RESET_ALL )
2008-10-11 14:16:25 -05:00
{
// the "reset all instances" method can only reset normal maps
2009-12-17 11:11:54 +01:00
if ( entry -> map_type == MAP_RAID || diff == DUNGEON_DIFFICULTY_HEROIC )
2008-10-11 14:16:25 -05:00
{
++ itr ;
continue ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool isEmpty = true ;
// if the map is loaded, reset it
2011-09-15 14:08:17 +02:00
Map * map = sMapMgr -> FindMap ( p -> GetMapId (), p -> GetInstanceId ());
2010-04-07 19:14:10 +02:00
if ( map && map -> IsDungeon () && ! ( method == INSTANCE_RESET_GROUP_DISBAND && ! p -> CanReset ()))
2009-06-18 21:35:34 +02:00
{
2010-04-07 19:14:10 +02:00
if ( p -> CanReset ())
2009-06-18 21:35:34 +02:00
isEmpty = (( InstanceMap * ) map ) -> Reset ( method );
else
isEmpty = ! map -> HavePlayers ();
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( SendMsgTo )
2008-10-11 14:16:25 -05:00
{
2010-09-11 09:09:41 -07:00
if ( isEmpty )
SendMsgTo -> SendResetInstanceSuccess ( p -> GetMapId ());
else
SendMsgTo -> SendResetInstanceFailed ( 0 , p -> GetMapId ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( isEmpty || method == INSTANCE_RESET_GROUP_DISBAND || method == INSTANCE_RESET_CHANGE_DIFFICULTY )
2008-10-11 14:16:25 -05:00
{
// do not reset the instance, just unbind if others are permanently bound to it
2010-09-11 09:09:41 -07:00
if ( p -> CanReset ())
p -> DeleteFromDB ();
else
CharacterDatabase . PExecute ( "DELETE FROM group_instance WHERE instance = '%u'" , p -> GetInstanceId ());
2008-10-11 14:16:25 -05:00
// i don't know for sure if hash_map iterators
2009-12-17 11:11:54 +01:00
m_boundInstances [ diff ]. erase ( itr );
itr = m_boundInstances [ diff ]. begin ();
2008-10-11 14:16:25 -05:00
// this unloads the instance save unless online players are bound to it
// (eg. permanent binds or GM solo binds)
p -> RemoveGroup ( this );
}
else
++ itr ;
}
}
2009-10-17 15:51:44 -07:00
2009-12-17 11:11:54 +01:00
InstanceGroupBind * Group :: GetBoundInstance ( Player * player )
2008-10-11 14:16:25 -05:00
{
2009-12-17 11:11:54 +01:00
uint32 mapid = player -> GetMapId ();
MapEntry const * mapEntry = sMapStore . LookupEntry ( mapid );
2010-06-26 17:57:49 +02:00
return GetBoundInstance ( mapEntry );
2010-06-26 13:32:24 +02:00
}
2009-12-17 11:11:54 +01:00
2010-06-26 13:32:24 +02:00
InstanceGroupBind * Group :: GetBoundInstance ( Map * aMap )
{
// Currently spawn numbering not different from map difficulty
Difficulty difficulty = GetDifficulty ( aMap -> IsRaid ());
2009-12-17 11:11:54 +01:00
2008-10-11 14:16:25 -05:00
// some instances only have one difficulty
2011-04-29 20:47:02 +02:00
GetDownscaledMapDifficultyData ( aMap -> GetId (), difficulty );
2009-10-17 15:51:44 -07:00
2010-06-26 13:32:24 +02:00
BoundInstancesMap :: iterator itr = m_boundInstances [ difficulty ]. find ( aMap -> GetId ());
2010-04-07 19:14:10 +02:00
if ( itr != m_boundInstances [ difficulty ]. end ())
2008-10-11 14:16:25 -05:00
return & itr -> second ;
else
return NULL ;
}
2009-10-17 15:51:44 -07:00
2010-06-26 13:32:24 +02:00
InstanceGroupBind * Group :: GetBoundInstance ( MapEntry const * mapEntry )
2009-12-17 11:11:54 +01:00
{
2010-06-26 13:32:24 +02:00
if ( ! mapEntry )
return NULL ;
2010-08-08 19:45:53 +02:00
2010-06-26 13:32:24 +02:00
Difficulty difficulty = GetDifficulty ( mapEntry -> IsRaid ());
2010-08-08 19:45:53 +02:00
2009-12-17 11:11:54 +01:00
// some instances only have one difficulty
2011-04-29 20:47:02 +02:00
GetDownscaledMapDifficultyData ( mapEntry -> MapID , difficulty );
2010-08-08 19:45:53 +02:00
2010-06-26 13:32:24 +02:00
BoundInstancesMap :: iterator itr = m_boundInstances [ difficulty ]. find ( mapEntry -> MapID );
2010-04-07 19:14:10 +02:00
if ( itr != m_boundInstances [ difficulty ]. end ())
2009-12-17 11:11:54 +01:00
return & itr -> second ;
else
return NULL ;
}
2011-09-15 14:08:17 +02:00
InstanceGroupBind * Group :: BindToInstance ( InstanceSave * save , bool permanent , bool load )
2008-10-11 14:16:25 -05:00
{
2010-05-08 01:58:47 +02:00
if ( ! save || isBGGroup ())
return NULL ;
2009-10-17 15:51:44 -07:00
2010-05-08 01:58:47 +02:00
InstanceGroupBind & bind = m_boundInstances [ save -> GetDifficulty ()][ save -> GetMapId ()];
if ( ! load && ( ! bind . save || permanent != bind . perm || save != bind . save ))
2011-05-05 10:23:00 +02:00
CharacterDatabase . PExecute ( "REPLACE INTO group_instance (guid, instance, permanent) VALUES (%u, %u, %u)" , m_dbStoreId , save -> GetInstanceId (), permanent );
2009-10-17 15:51:44 -07:00
2010-05-08 01:58:47 +02:00
if ( bind . save != save )
{
if ( bind . save )
bind . save -> RemoveGroup ( this );
save -> AddGroup ( this );
2008-10-11 14:16:25 -05:00
}
2010-05-08 01:58:47 +02:00
bind . save = save ;
bind . perm = permanent ;
if ( ! load )
2011-02-26 19:49:56 +01:00
sLog -> outDebug ( LOG_FILTER_MAPS , "Group::BindToInstance: Group (guid: %u, storage id: %u) is now bound to map %d, instance %d, difficulty %d" ,
2011-05-05 10:23:00 +02:00
GUID_LOPART ( GetGUID ()), m_dbStoreId , save -> GetMapId (), save -> GetInstanceId (), save -> GetDifficulty ());
2011-02-26 19:49:56 +01:00
2010-05-08 01:58:47 +02:00
return & bind ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Group :: UnbindInstance ( uint32 mapid , uint8 difficulty , bool unload )
{
BoundInstancesMap :: iterator itr = m_boundInstances [ difficulty ]. find ( mapid );
2010-04-07 19:14:10 +02:00
if ( itr != m_boundInstances [ difficulty ]. end ())
2008-10-11 14:16:25 -05:00
{
2010-05-08 01:58:47 +02:00
if ( ! unload )
2011-05-05 10:23:00 +02:00
CharacterDatabase . PExecute ( "DELETE FROM group_instance WHERE guid=%u AND instance=%u" , m_dbStoreId , itr -> second . save -> GetInstanceId ());
2008-10-11 14:16:25 -05:00
itr -> second . save -> RemoveGroup ( this ); // save can become invalid
m_boundInstances [ difficulty ]. erase ( itr );
}
}
2009-10-17 15:51:44 -07:00
2011-06-12 01:47:45 +02:00
void Group :: _homebindIfInstance ( Player * player )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( player && ! player -> isGameMaster () && sMapStore . LookupEntry ( player -> GetMapId ()) -> IsDungeon ())
2010-05-04 18:25:30 +02:00
player -> m_InstanceValid = false ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-01-15 21:29:32 -05:00
void Group :: BroadcastGroupUpdate ( void )
{
// FG: HACK: force flags update on group leave - for values update hack
// -- not very efficient but safe
2009-10-17 16:20:24 -07:00
for ( member_citerator citr = m_memberSlots . begin (); citr != m_memberSlots . end (); ++ citr )
2009-01-15 21:29:32 -05:00
{
2011-09-15 14:08:17 +02:00
Player * pp = ObjectAccessor :: FindPlayer ( citr -> guid );
2010-04-07 19:14:10 +02:00
if ( pp && pp -> IsInWorld ())
2009-01-15 21:29:32 -05:00
{
pp -> ForceValuesUpdateAtIndex ( UNIT_FIELD_BYTES_2 );
pp -> ForceValuesUpdateAtIndex ( UNIT_FIELD_FACTIONTEMPLATE );
2010-12-23 23:25:44 +01:00
sLog -> outStaticDebug ( "-- Forced group value update for '%s'" , pp -> GetName ());
2009-01-15 21:29:32 -05:00
}
}
2009-02-01 16:38:53 -06:00
}
2010-05-21 22:45:47 +02:00
void Group :: ResetMaxEnchantingLevel ()
{
m_maxEnchantingLevel = 0 ;
2011-09-15 14:08:17 +02:00
Player * pMember = NULL ;
2010-05-21 22:45:47 +02:00
for ( member_citerator citr = m_memberSlots . begin (); citr != m_memberSlots . end (); ++ citr )
{
2011-07-27 12:14:27 +02:00
pMember = ObjectAccessor :: FindPlayer ( citr -> guid );
2010-08-30 15:25:15 +02:00
if ( pMember && m_maxEnchantingLevel < pMember -> GetSkillValue ( SKILL_ENCHANTING ))
m_maxEnchantingLevel = pMember -> GetSkillValue ( SKILL_ENCHANTING );
2010-05-21 22:45:47 +02:00
}
}
2010-11-29 07:50:31 +01:00
void Group :: SetLootMethod ( LootMethod method )
{
m_lootMethod = method ;
}
2011-08-30 13:46:36 +02:00
void Group :: SetLooterGuid ( uint64 guid )
2010-11-29 07:50:31 +01:00
{
m_looterGuid = guid ;
}
void Group :: SetLootThreshold ( ItemQualities threshold )
{
m_lootThreshold = threshold ;
}
2011-08-01 14:23:27 +02:00
void Group :: SetLfgRoles ( uint64 guid , const uint8 roles )
2010-11-29 07:50:31 +01:00
{
member_witerator slot = _getMemberWSlot ( guid );
if ( slot == m_memberSlots . end ())
return ;
slot -> roles = roles ;
SendUpdate ();
}
bool Group :: IsFull () const
{
return isRaidGroup () ? ( m_memberSlots . size () >= MAXRAIDSIZE ) : ( m_memberSlots . size () >= MAXGROUPSIZE );
}
bool Group :: isLFGGroup () const
{
return m_groupType & GROUPTYPE_LFG ;
}
bool Group :: isRaidGroup () const
{
return m_groupType & GROUPTYPE_RAID ;
}
bool Group :: isBGGroup () const
{
return m_bgGroup != NULL ;
}
bool Group :: IsCreated () const
{
return GetMembersCount () > 0 ;
}
2011-08-03 11:23:08 +02:00
uint64 Group :: GetLeaderGUID () const
2010-11-29 07:50:31 +01:00
{
return m_leaderGuid ;
}
2011-08-03 11:23:08 +02:00
uint64 Group :: GetGUID () const
2010-11-29 07:50:31 +01:00
{
return m_guid ;
}
uint32 Group :: GetLowGUID () const
{
return GUID_LOPART ( m_guid );
}
const char * Group :: GetLeaderName () const
{
return m_leaderName . c_str ();
}
LootMethod Group :: GetLootMethod () const
{
return m_lootMethod ;
}
2011-08-03 11:23:08 +02:00
uint64 Group :: GetLooterGuid () const
2010-11-29 07:50:31 +01:00
{
return m_looterGuid ;
}
ItemQualities Group :: GetLootThreshold () const
{
return m_lootThreshold ;
}
2011-08-30 13:46:36 +02:00
bool Group :: IsMember ( uint64 guid ) const
2010-11-29 07:50:31 +01:00
{
return _getMemberCSlot ( guid ) != m_memberSlots . end ();
}
2011-08-30 13:46:36 +02:00
bool Group :: IsLeader ( uint64 guid ) const
2010-11-29 07:50:31 +01:00
{
return ( GetLeaderGUID () == guid );
}
uint64 Group :: GetMemberGUID ( const std :: string & name )
{
for ( member_citerator itr = m_memberSlots . begin (); itr != m_memberSlots . end (); ++ itr )
if ( itr -> name == name )
return itr -> guid ;
return 0 ;
}
bool Group :: IsAssistant ( uint64 guid ) const
{
member_citerator mslot = _getMemberCSlot ( guid );
if ( mslot == m_memberSlots . end ())
return false ;
return mslot -> flags & MEMBER_FLAG_ASSISTANT ;
}
2011-08-30 13:46:36 +02:00
bool Group :: SameSubGroup ( uint64 guid1 , uint64 guid2 ) const
2010-11-29 07:50:31 +01:00
{
member_citerator mslot2 = _getMemberCSlot ( guid2 );
if ( mslot2 == m_memberSlots . end ())
return false ;
2011-04-29 20:47:02 +02:00
return SameSubGroup ( guid1 , &* mslot2 );
2010-11-29 07:50:31 +01:00
}
bool Group :: SameSubGroup ( uint64 guid1 , MemberSlot const * slot2 ) const
{
member_citerator mslot1 = _getMemberCSlot ( guid1 );
if ( mslot1 == m_memberSlots . end () || ! slot2 )
return false ;
return ( mslot1 -> group == slot2 -> group );
}
bool Group :: HasFreeSlotSubGroup ( uint8 subgroup ) const
{
return ( m_subGroupsCounts && m_subGroupsCounts [ subgroup ] < MAXGROUPSIZE );
}
Group :: MemberSlotList const & Group :: GetMemberSlots () const
{
return m_memberSlots ;
}
GroupReference * Group :: GetFirstMember ()
{
return m_memberMgr . getFirst ();
}
uint32 Group :: GetMembersCount () const
{
return m_memberSlots . size ();
}
uint8 Group :: GetMemberGroup ( uint64 guid ) const
{
member_citerator mslot = _getMemberCSlot ( guid );
if ( mslot == m_memberSlots . end ())
return ( MAX_RAID_SUBGROUPS + 1 );
return mslot -> group ;
}
2011-09-15 14:08:17 +02:00
void Group :: SetBattlegroundGroup ( Battleground * bg )
2010-11-29 07:50:31 +01:00
{
m_bgGroup = bg ;
}
2011-08-01 14:23:27 +02:00
void Group :: SetGroupMemberFlag ( uint64 guid , bool apply , GroupMemberFlags flag )
2010-11-29 07:50:31 +01:00
{
2011-02-18 18:35:52 +01:00
// Assistants, main assistants and main tanks are only available in raid groups
2010-11-29 07:50:31 +01:00
if ( ! isRaidGroup ())
return ;
2011-02-18 18:35:52 +01:00
// Check if player is really in the raid
member_witerator slot = _getMemberWSlot ( guid );
if ( slot == m_memberSlots . end ())
2010-11-29 07:50:31 +01:00
return ;
2011-02-18 18:35:52 +01:00
// Do flag specific actions, e.g ensure uniqueness
switch ( flag ) {
case MEMBER_FLAG_MAINASSIST :
RemoveUniqueGroupMemberFlag ( MEMBER_FLAG_MAINASSIST ); // Remove main assist flag from current if any.
break ;
case MEMBER_FLAG_MAINTANK :
RemoveUniqueGroupMemberFlag ( MEMBER_FLAG_MAINTANK ); // Remove main tank flag from current if any.
break ;
case MEMBER_FLAG_ASSISTANT :
break ;
default :
return ; // This should never happen
}
2010-11-29 07:50:31 +01:00
2011-02-18 18:35:52 +01:00
// Switch the actual flag
ToggleGroupMemberFlag ( slot , flag , apply );
2010-11-29 07:50:31 +01:00
2011-02-18 18:35:52 +01:00
// Preserve the new setting in the db
CharacterDatabase . PExecute ( "UPDATE group_member SET memberFlags='%u' WHERE memberGuid='%u'" , slot -> flags , GUID_LOPART ( guid ));
// Broadcast the changes to the group
SendUpdate ();
2010-11-29 07:50:31 +01:00
}
Difficulty Group :: GetDifficulty ( bool isRaid ) const
{
return isRaid ? m_raidDifficulty : m_dungeonDifficulty ;
}
Difficulty Group :: GetDungeonDifficulty () const
{
return m_dungeonDifficulty ;
}
Difficulty Group :: GetRaidDifficulty () const
{
return m_raidDifficulty ;
}
bool Group :: isRollLootActive () const
{
return ! RollId . empty ();
}
Group :: Rolls :: iterator Group :: GetRoll ( uint64 Guid )
{
Rolls :: iterator iter ;
for ( iter = RollId . begin (); iter != RollId . end (); ++ iter )
if (( * iter ) -> itemGUID == Guid && ( * iter ) -> isValid ())
return iter ;
return RollId . end ();
}
2011-09-15 14:08:17 +02:00
void Group :: LinkMember ( GroupReference * pRef )
2010-11-29 07:50:31 +01:00
{
m_memberMgr . insertFirst ( pRef );
}
2010-12-06 02:07:53 +01:00
void Group :: DelinkMember ( GroupReference * /*pRef*/ ) const
2010-11-29 07:50:31 +01:00
{
}
Group :: BoundInstancesMap & Group :: GetBoundInstances ( Difficulty difficulty )
{
return m_boundInstances [ difficulty ];
}
void Group :: _initRaidSubGroupsCounter ()
{
// Sub group counters initialization
if ( ! m_subGroupsCounts )
m_subGroupsCounts = new uint8 [ MAX_RAID_SUBGROUPS ];
memset (( void * ) m_subGroupsCounts , 0 , ( MAX_RAID_SUBGROUPS ) * sizeof ( uint8 ));
for ( member_citerator itr = m_memberSlots . begin (); itr != m_memberSlots . end (); ++ itr )
++ m_subGroupsCounts [ itr -> group ];
}
Group :: member_citerator Group :: _getMemberCSlot ( uint64 Guid ) const
{
for ( member_citerator itr = m_memberSlots . begin (); itr != m_memberSlots . end (); ++ itr )
if ( itr -> guid == Guid )
return itr ;
return m_memberSlots . end ();
}
Group :: member_witerator Group :: _getMemberWSlot ( uint64 Guid )
{
for ( member_witerator itr = m_memberSlots . begin (); itr != m_memberSlots . end (); ++ itr )
if ( itr -> guid == Guid )
return itr ;
return m_memberSlots . end ();
}
void Group :: SubGroupCounterIncrease ( uint8 subgroup )
{
if ( m_subGroupsCounts )
++ m_subGroupsCounts [ subgroup ];
}
void Group :: SubGroupCounterDecrease ( uint8 subgroup )
{
if ( m_subGroupsCounts )
-- m_subGroupsCounts [ subgroup ];
}
void Group :: RemoveUniqueGroupMemberFlag ( GroupMemberFlags flag )
{
for ( member_witerator itr = m_memberSlots . begin (); itr != m_memberSlots . end (); ++ itr )
if ( itr -> flags & flag )
itr -> flags &= ~ flag ;
}
void Group :: ToggleGroupMemberFlag ( member_witerator slot , uint8 flag , bool apply )
{
if ( apply )
slot -> flags |= flag ;
else
slot -> flags &= ~ flag ;
2011-10-18 10:44:45 +02:00
}