2010-10-07 15:35:36 +02:00
/*
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
* 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"
#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"
#include "MapInstanced.h"
#include "Util.h"
2009-10-17 15:51:44 -07:00
2010-11-29 07:50:31 +01:00
Roll :: Roll ( uint64 _guid , LootItem const & li ) : itemGUID ( _guid ), itemid ( li . itemid ),
itemRandomPropId ( li . randomPropertyId ), itemRandomSuffix ( li . randomSuffix ), itemCount ( li . count ),
totalPlayersRolling ( 0 ), totalNeed ( 0 ), totalGreed ( 0 ), totalPass ( 0 ), itemSlot ( 0 ),
rollVoteMask ( ROLL_ALL_TYPE_NO_DISENCHANT )
{
}
Roll ::~ Roll ()
{
}
void Roll :: setLoot ( Loot * pLoot )
{
link ( pLoot , this );
}
Loot * Roll :: getLoot ()
{
return getTarget ();
}
2010-12-05 17:50:26 +01:00
Group :: Group () : m_leaderGuid ( 0 ), m_groupType ( GROUPTYPE_NORMAL ), m_bgGroup ( NULL ),
m_lootMethod ( FREE_FOR_ALL ), m_looterGuid ( 0 ), m_lootThreshold ( ITEM_QUALITY_UNCOMMON ),
m_subGroupsCounts ( NULL ), m_guid ( 0 ), m_counter ( 0 ), m_maxEnchantingLevel ( 0 ),
m_LfgState ( LFG_STATE_NONE ), m_LfgOldState ( LFG_STATE_NONE ), m_LfgDungeonEntry ( 0 ), m_Lfgkicks ( 0 )
{
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
{
sLog . outDebug ( "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 );
2008-10-11 14:16:25 -05:00
else sLog . outError ( "Group::~Group: battleground group is not linked to the correct battleground." );
}
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
2008-10-11 14:16:25 -05:00
bool Group :: Create ( const uint64 & guid , const char * name )
{
2010-08-08 05:25:45 +02:00
uint32 lowguid = sObjectMgr . GenerateLowGuid ( HIGHGUID_GROUP );
2010-05-08 01:58:47 +02:00
m_guid = MAKE_NEW_GUID ( lowguid , 0 , HIGHGUID_GROUP );
2008-10-11 14:16:25 -05:00
m_leaderGuid = guid ;
m_leaderName = name ;
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 ;
m_looterGuid = guid ;
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 ;
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2008-10-11 14:16:25 -05:00
{
2010-08-08 05:25:45 +02:00
Player * leader = sObjectMgr . GetPlayer ( guid );
2010-04-07 19:14:10 +02:00
if ( leader )
2009-12-17 11:11:54 +01:00
{
m_dungeonDifficulty = leader -> GetDungeonDifficulty ();
m_raidDifficulty = leader -> GetRaidDifficulty ();
}
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
Player :: ConvertInstancesToGroup ( leader , this , guid );
2009-10-17 15:51:44 -07:00
2010-08-21 03:19:25 +02:00
if ( ! AddMember ( guid , name ))
return false ;
2008-10-11 14:16:25 -05:00
// store group in database
2010-08-21 03:19:25 +02:00
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
trans -> PAppend ( "DELETE FROM groups WHERE guid ='%u'" , lowguid );
2010-11-05 00:54:17 +02:00
trans -> PAppend ( "DELETE FROM group_member WHERE guid = %u OR memberGuid = %u" , lowguid , GUID_LOPART ( guid ));
trans -> PAppend ( "INSERT INTO group_member (guid, memberGuid, subgroup) VALUES (%u, %u, 0)" , lowguid , GUID_LOPART ( guid ));
2010-08-21 03:19:25 +02:00
trans -> PAppend ( "INSERT INTO groups (guid,leaderGuid,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,groupType,difficulty,raiddifficulty) "
2010-05-08 01:58:47 +02:00
"VALUES ('%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u','%u')" ,
lowguid , GUID_LOPART ( m_leaderGuid ), uint32 ( m_lootMethod ),
2010-04-11 11:22:29 +04: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 );
2010-09-11 09:09:41 -07:00
2010-08-21 03:19:25 +02:00
CharacterDatabase . CommitTransaction ( trans );
2008-10-11 14:16:25 -05:00
}
2010-05-08 01:58:47 +02:00
else if ( ! AddMember ( guid , name ))
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
2010-09-11 21:10:54 +02:00
bool Group :: LoadGroupFromDB ( const uint32 & groupGuid , QueryResult result , bool loadMembers )
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 false ;
2009-10-17 15:51:44 -07:00
2010-05-08 01:58:47 +02:00
Field * fields = result -> Fetch ();
2010-08-02 17:28:47 +02:00
m_guid = MAKE_NEW_GUID ( groupGuid , 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-08-08 05:25:45 +02:00
if ( ! sObjectMgr . GetPlayerNameByGUID ( fields [ 0 ]. GetUInt32 (), m_leaderName ))
2008-10-11 14:16:25 -05:00
return false ;
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 )
m_targetIcons [ i ] = fields [ 4 + i ]. GetUInt64 ();
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 );
2009-12-17 11:11:54 +01:00
2010-04-07 19:14:10 +02:00
if ( loadMembers )
2008-10-11 14:16:25 -05:00
{
2010-09-10 13:40:20 +02:00
// 0 1 2 3
result = CharacterDatabase . PQuery ( "SELECT memberGuid, memberFlags, subgroup, roles FROM group_member WHERE guid=%u" , groupGuid );
2010-04-07 19:14:10 +02:00
if ( ! result )
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
do
{
2010-05-08 01:58:47 +02:00
fields = result -> Fetch ();
2010-09-10 13:40:20 +02:00
LoadMemberFromDB ( fields [ 0 ]. GetUInt32 (), fields [ 1 ]. GetUInt8 (), fields [ 2 ]. GetUInt8 (), fields [ 3 ]. GetUInt8 ());
2010-04-07 22:59:46 +02:00
} while ( result -> NextRow ());
2010-05-08 01:58:47 +02:00
if ( GetMembersCount () < 2 ) // group too small
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
2010-09-10 13:40:20 +02:00
bool 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-08-08 05:25:45 +02: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 );
2008-10-11 14:16:25 -05:00
return false ;
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 );
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
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 ())
CharacterDatabase . PExecute ( "UPDATE groups SET groupType='%u' WHERE guid='%u'" , uint8 ( m_groupType ), GUID_LOPART ( m_guid ));
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 ())
2010-05-08 01:58:47 +02:00
CharacterDatabase . PExecute ( "UPDATE groups SET groupType='%u' WHERE guid='%u'" , uint8 ( m_groupType ), GUID_LOPART ( m_guid ));
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 )
2010-08-08 05:25:45 +02:00
if ( Player * player = sObjectMgr . GetPlayer ( 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
2008-10-11 14:16:25 -05:00
bool Group :: AddInvite ( Player * player )
{
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-09-14 16:37:54 +02:00
sScriptMgr . OnGroupInviteMember ( this , player -> GetGUID ());
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 :: AddLeaderInvite ( Player * player )
{
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
2010-12-06 20:25:43 +01: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
2008-12-12 11:21:28 -06:00
Player * Group :: GetInvited ( const uint64 & guid ) const
{
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
2008-10-11 14:16:25 -05:00
bool Group :: AddMember ( const uint64 & guid , const char * name )
{
2010-04-07 19:14:10 +02:00
if ( ! _addMember ( guid , name ))
2008-10-11 14:16:25 -05:00
return false ;
2010-08-11 15:20:20 +02:00
2008-10-11 14:16:25 -05:00
SendUpdate ();
2010-09-14 16:37:54 +02:00
sScriptMgr . OnGroupAddMember ( this , guid );
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
Player * player = sObjectMgr . GetPlayer ( guid );
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!
2009-12-17 11:11:54 +01: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
2010-11-23 20:49:36 +01:00
uint32 Group :: RemoveMember ( const 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-11-23 20:49:36 +01:00
sScriptMgr . OnGroupRemoveMember ( this , guid , method , kicker , reason );
2010-09-14 16:37:54 +02:00
2010-11-23 20:49:57 +01:00
// Lfg group vote kick handled in scripts
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
{
bool leaderChanged = _removeMember ( guid );
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
if ( Player * player = sObjectMgr . GetPlayer ( guid ))
2008-10-11 14:16:25 -05: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
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
2009-03-14 20:00:02 -06:00
//we already removed player from group and in player->GetGroup() is his original group!
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 );
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( leaderChanged )
2008-10-11 14:16:25 -05:00
{
WorldPacket data ( SMSG_GROUP_SET_LEADER , ( m_memberSlots . front (). name . size () + 1 ));
data << m_memberSlots . front (). 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
2008-10-11 14:16:25 -05:00
SendUpdate ();
2010-05-21 22:45:47 +02:00
ResetMaxEnchantingLevel ();
2008-10-11 14:16:25 -05:00
}
// if group before remove <= 2 disband it
else
2010-05-20 23:35:27 +02:00
Disband ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return m_memberSlots . size ();
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Group :: ChangeLeader ( const uint64 & guid )
{
member_citerator slot = _getMemberCSlot ( 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
2008-10-11 14:16:25 -05:00
_setLeader ( guid );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ( SMSG_GROUP_SET_LEADER , slot -> name . size () + 1 );
data << slot -> name ;
2009-03-14 20:00:02 -06:00
BroadcastPacket ( & data , true );
2008-10-11 14:16:25 -05:00
SendUpdate ();
}
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-09-14 16:37:54 +02:00
sScriptMgr . OnGroupDisband ( this );
2009-10-17 15:51:44 -07:00
2010-09-14 16:37:54 +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
{
2010-08-08 05:25:45 +02:00
player = sObjectMgr . GetPlayer ( 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-05-08 01:58:47 +02:00
uint32 lowguid = GUID_LOPART ( m_guid );
2010-08-21 03:19:25 +02:00
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
trans -> PAppend ( "DELETE FROM groups WHERE guid=%u" , lowguid );
trans -> PAppend ( "DELETE FROM group_member WHERE guid=%u" , lowguid );
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 );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-05-08 01:58:47 +02:00
m_guid = 0 ;
2008-10-11 14:16:25 -05:00
m_leaderGuid = 0 ;
m_leaderName = "" ;
}
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
{
2010-08-08 05:25:45 +02:00
Player * p = sObjectMgr . GetPlayer ( 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
2008-10-29 17:09:32 -05:00
void Group :: SendLootRoll ( const uint64 & SourceGuid , const 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
{
2010-08-08 05:25:45 +02:00
Player * p = sObjectMgr . GetPlayer ( 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-29 17:09:32 -05:00
void Group :: SendLootRollWon ( const uint64 & SourceGuid , const 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
{
2010-08-08 05:25:45 +02:00
Player * p = sObjectMgr . GetPlayer ( 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
{
2010-08-08 05:25:45 +02:00
Player * p = sObjectMgr . GetPlayer ( 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
void Group :: SendLooter ( Creature * pCreature , Player * pLooter )
{
2010-07-30 20:04:28 +02:00
ASSERT ( pCreature );
2010-03-11 22:55:02 +01:00
2010-04-07 18:09:10 +02:00
WorldPacket data ( SMSG_LOOT_LIST , ( 8 + 8 ));
2010-03-11 22:55:02 +01:00
data << uint64 ( pCreature -> GetGUID ());
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 );
}
2010-04-11 14:25:02 +04:00
void Group :: GroupLoot ( Loot * loot , WorldObject * pLootedObject )
2008-10-11 14:16:25 -05:00
{
std :: vector < LootItem >:: iterator i ;
ItemPrototype const * item ;
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 ;
2010-08-08 05:25:45 +02:00
item = sObjectMgr . GetItemPrototype ( i -> itemid );
2008-10-11 14:16:25 -05:00
if ( ! item )
{
//sLog.outDebug("Group::GroupLoot: missing item prototype for item with id: %d", i->itemid);
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
{
2010-08-08 05:25:45 +02:00
uint64 newitemGUID = MAKE_NEW_GUID ( sObjectMgr . GenerateLowGuid ( HIGHGUID_ITEM ), 0 , HIGHGUID_ITEM );
2010-03-11 22:55:02 +01:00
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
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05: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
{
2010-08-23 19:56:47 -07:00
if ( member -> IsWithinDistInMap ( pLootedObject , sWorld . getFloatConfig ( CONFIG_GROUP_XP_DISTANCE ), false ))
2008-10-11 14:16:25 -05:00
{
2010-09-21 21:55:16 +02: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 )
{
2010-08-08 05:25:45 +02:00
Player * p = sObjectMgr . GetPlayer ( 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 );
2010-04-07 18:09:10 +02:00
if ( Creature * creature = dynamic_cast < Creature *> ( pLootedObject ))
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
}
2010-04-07 18:09:10 +02:00
else if ( GameObject * go = dynamic_cast < GameObject *> ( pLootedObject ))
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
2010-04-11 14:25:02 +04:00
void Group :: NeedBeforeGreed ( Loot * loot , WorldObject * pLootedObject )
2008-10-11 14:16:25 -05:00
{
ItemPrototype const * item ;
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 ;
2010-08-08 05:25:45 +02:00
item = sObjectMgr . GetItemPrototype ( 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
{
2010-08-08 05:25:45 +02:00
uint64 newitemGUID = MAKE_NEW_GUID ( sObjectMgr . GenerateLowGuid ( HIGHGUID_ITEM ), 0 , HIGHGUID_ITEM );
2008-10-11 14:16:25 -05:00
Roll * r = new Roll ( newitemGUID , * i );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05: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
{
2010-08-23 19:56:47 -07: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 )
{
2010-08-08 05:25:45 +02:00
Player * p = sObjectMgr . GetPlayer ( 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
2010-04-07 18:09:10 +02:00
if ( Creature * creature = dynamic_cast < Creature *> ( pLootedObject ))
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
{
2010-03-11 22:55:02 +01:00
sLog . outDebug ( "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
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
Player * looter = itr -> getSource ();
if ( ! looter -> IsInWorld ())
continue ;
2009-10-17 15:51:44 -07:00
2010-08-23 19:56:47 -07: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
2008-10-11 14:16:25 -05:00
data . put < uint8 > ( 0 , real_count );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
Player * looter = itr -> getSource ();
2010-08-23 19:56:47 -07: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
2010-03-11 22:55:02 +01:00
void Group :: CountRollVote ( const uint64 & playerGUID , const 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
2010-03-11 22:55:02 +01: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
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 ;
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 );
2010-08-08 05:25:45 +02:00
player = sObjectMgr . GetPlayer ( 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 ;
LootItem * item = & ( roll -> getLoot () -> items [ roll -> itemSlot ]);
2010-03-11 22:55:02 +01:00
uint8 msg = player -> CanStoreNewItem ( NULL_BAG , NULL_SLOT , dest , roll -> itemid , item -> count );
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 -- ;
2010-09-21 21:55:16 +02:00
AllowedLooterSet * looters = item -> GetAllowedLooters ();
player -> StoreNewItem ( dest , roll -> itemid , true , item -> randomPropertyId , ( looters -> size () > 1 ) ? looters : NULL );
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 ;
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 );
2010-08-08 05:25:45 +02:00
player = sObjectMgr . GetPlayer ( 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
2008-10-11 14:16:25 -05: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 ;
2010-03-11 22:55:02 +01:00
uint8 msg = player -> CanStoreNewItem ( NULL_BAG , NULL_SLOT , dest , roll -> itemid , item -> count );
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 -- ;
2010-09-21 21:55:16 +02:00
AllowedLooterSet * looters = item -> GetAllowedLooters ();
player -> StoreNewItem ( dest , roll -> itemid , true , item -> randomPropertyId , ( looters -> size () > 1 ) ? looters : NULL );
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 -- ;
2010-02-14 19:13:14 -07:00
ItemPrototype const * pProto = ObjectMgr :: GetItemPrototype ( roll -> itemid );
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
2008-10-11 14:16:25 -05: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
2008-10-26 11:50:07 -05:00
void Group :: GetDataForXPAtKill ( Unit const * victim , uint32 & count , uint32 & sum_level , Player * & member_with_max_level , Player * & not_gray_member_with_max_level )
2008-10-11 14:16:25 -05:00
{
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
Player * member = itr -> getSource ();
2010-04-07 19:14:10 +02:00
if ( ! member || ! member -> isAlive ()) // only for alive
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 ( ! member -> IsAtGroupRewardDistance ( victim )) // at req. distance
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
++ count ;
sum_level += member -> getLevel ();
2010-04-07 19:14:10 +02:00
if ( ! member_with_max_level || member_with_max_level -> getLevel () < member -> getLevel ())
2008-10-11 14:16:25 -05:00
member_with_max_level = member ;
2009-10-17 15:51:44 -07:00
2009-12-20 15:20:04 +01:00
uint32 gray_level = Trinity :: XP :: GetGrayLevel ( member -> getLevel ());
2010-09-11 09:09:41 -07:00
if ( victim -> getLevel () > gray_level && ( ! not_gray_member_with_max_level || not_gray_member_with_max_level -> getLevel () < member -> getLevel ()))
2008-10-26 11:50:07 -05:00
not_gray_member_with_max_level = member ;
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 :: SendTargetIconList ( WorldSession * session )
{
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 ()
{
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
{
2010-08-08 05:25:45 +02:00
player = sObjectMgr . GetPlayer ( citr -> guid );
2010-04-07 22:59:46 +02:00
if ( ! player || ! player -> GetSession () || player -> GetGroup () != this )
2008-10-11 14:16:25 -05:00
continue ;
2010-03-09 20:33:59 +01: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 ));
2010-02-14 19:13:14 -07:00
data << uint8 ( m_groupType ); // group type (flags in 3.3)
2010-03-09 20:33:59 +01:00
data << uint8 ( citr -> group );
data << uint8 ( citr -> flags );
2010-09-30 02:20:48 +02:00
data << uint8 ( citr -> roles );
2010-08-11 15:20:20 +02:00
if ( isLFGGroup ())
2010-10-07 14:00:52 +02:00
{
2010-12-05 17:50:26 +01:00
data << uint8 ( m_LfgState == LFG_STATE_FINISHED_DUNGEON ? 2 : 0 ); // FIXME - Dungeon save status? 2 = done
2010-08-11 15:20:20 +02:00
data << uint32 ( m_LfgDungeonEntry );
2010-02-14 19:13:14 -07:00
}
2010-08-11 15:20:20 +02:00
2010-05-08 01:58:47 +02:00
data << uint64 ( m_guid );
data << uint32 ( m_counter ++ ); // 3.3, value increases every time this packet gets sent
2008-10-11 14:16:25 -05:00
data << uint32 ( GetMembersCount () - 1 );
2009-10-17 16:20:24 -07:00
for ( member_citerator citr2 = m_memberSlots . begin (); citr2 != m_memberSlots . end (); ++ citr2 )
2008-10-11 14:16:25 -05:00
{
2010-03-09 20:33:59 +01:00
if ( citr -> guid == citr2 -> guid )
2008-10-11 14:16:25 -05:00
continue ;
2010-09-11 09:09:41 -07:00
2010-08-08 05:25:45 +02:00
Player * member = sObjectMgr . GetPlayer ( citr2 -> guid );
2010-04-07 18:09:10 +02:00
2009-03-14 20:00:02 -06:00
uint8 onlineState = ( member ) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE ;
onlineState = onlineState | (( isBGGroup ()) ? MEMBER_STATUS_PVP : 0 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data << citr2 -> name ;
2009-12-22 19:39:02 +01:00
data << uint64 ( citr2 -> guid ); // guid
data << uint8 ( onlineState ); // online-state
data << uint8 ( citr2 -> group ); // groupid
data << uint8 ( citr2 -> flags ); // See enum GroupMemberFlags
2010-08-11 15:20:20 +02:00
data << uint8 ( citr2 -> roles ); // Lfg Roles
2008-10-11 14:16:25 -05:00
}
2010-09-11 09:09:41 -07:00
2008-10-11 14:16:25 -05:00
data << uint64 ( m_leaderGuid ); // leader guid
2010-09-11 09:09:41 -07:00
if ( GetMembersCount () - 1 )
2008-10-11 14:16:25 -05:00
{
2009-12-22 19:39:02 +01:00
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
2010-02-14 19:13:14 -07:00
data << uint8 ( 0 ); // 3.3
2008-10-11 14:16:25 -05:00
}
2010-09-11 09:09:41 -07:00
2010-04-07 22:59:46 +02:00
player -> 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 :: UpdatePlayerOutOfRange ( Player * pPlayer )
{
2010-04-07 19:14:10 +02:00
if ( ! pPlayer || ! pPlayer -> 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
Player * player ;
WorldPacket data ;
pPlayer -> GetSession () -> BuildPartyMemberStatsChangedPacket ( pPlayer , & data );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
2010-11-16 14:08:12 +01:00
player = itr -> getSource ();
if ( player && ! player -> IsWithinDist ( pPlayer , player -> GetSightRange (), false ))
player -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-14 20:00:02 -06:00
void Group :: BroadcastPacket ( WorldPacket * packet , bool ignorePlayersInBGRaid , int group , uint64 ignore )
2008-10-11 14:16:25 -05:00
{
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
Player * pl = itr -> getSource ();
2010-04-07 22:59:46 +02:00
if ( ! pl || ( ignore != 0 && pl -> GetGUID () == ignore ) || ( ignorePlayersInBGRaid && pl -> GetGroup () != this ))
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
if ( pl -> GetSession () && ( group == - 1 || itr -> getSubGroup () == group ))
2008-10-11 14:16:25 -05:00
pl -> GetSession () -> SendPacket ( packet );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Group :: BroadcastReadyCheck ( WorldPacket * packet )
{
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
Player * pl = itr -> getSource ();
2010-04-07 19:14:10 +02:00
if ( pl && pl -> GetSession ())
if ( IsLeader ( pl -> GetGUID ()) || IsAssistant ( pl -> GetGUID ()))
2008-10-11 14:16:25 -05:00
pl -> GetSession () -> SendPacket ( packet );
}
}
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
{
2010-08-08 05:25:45 +02:00
Player * pl = sObjectMgr . GetPlayer ( citr -> guid );
2008-10-11 14:16:25 -05:00
if ( ! pl || ! pl -> GetSession ())
{
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
2009-12-22 19:39:02 +01:00
bool Group :: _addMember ( const uint64 & guid , const char * name )
2008-10-11 14:16:25 -05:00
{
// get first not-full group
uint8 groupid = 0 ;
2008-10-29 17:09:32 -05:00
if ( m_subGroupsCounts )
2008-10-11 14:16:25 -05:00
{
2008-10-29 17:09:32 -05:00
bool groupFound = false ;
2010-06-22 00:42:31 +02:00
for (; groupid < MAX_RAID_SUBGROUPS ; ++ groupid )
2009-02-01 16:38:53 -06:00
{
if ( m_subGroupsCounts [ groupid ] < MAXGROUPSIZE )
{
groupFound = true ;
break ;
}
}
// We are raid group and no one slot is free
if ( ! groupFound )
return false ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-22 19:39:02 +01:00
return _addMember ( guid , name , groupid );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-22 19:39:02 +01:00
bool Group :: _addMember ( const uint64 & guid , const char * name , uint8 group )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( IsFull ())
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! guid )
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
Player * player = sObjectMgr . GetPlayer ( guid );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
MemberSlot member ;
member . guid = guid ;
member . name = name ;
member . group = group ;
2009-12-22 19:39:02 +01:00
member . flags = 0 ;
2010-08-11 15:20:20 +02:00
member . roles = 0 ;
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 ( group );
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
{
player -> SetGroupInvite ( NULL );
2010-09-11 09:09:41 -07:00
if ( player -> GetGroup () && isBGGroup ()) //if player is in group and he is being added to BG raid group, then call SetBattlegroundRaid()
2010-08-08 04:37:24 +02:00
player -> SetBattlegroundRaid ( this , group );
2010-09-11 09:09:41 -07:00
else if ( player -> GetGroup ()) //if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
2009-03-14 20:00:02 -06:00
player -> SetOriginalGroup ( this , group );
2010-09-11 09:09:41 -07:00
else //if player is not in group, then call set group
2009-03-14 20:00:02 -06:00
player -> SetGroup ( this , group );
2010-09-11 09:09:41 -07:00
2008-10-11 14:16:25 -05:00
// if the same group invites the player back, cancel the homebind timer
2009-12-17 11:11:54 +01:00
InstanceGroupBind * bind = GetBoundInstance ( player );
2010-04-07 19:14:10 +02:00
if ( bind && bind -> save -> GetInstanceId () == player -> GetInstanceId ())
2008-10-11 14:16:25 -05:00
player -> m_InstanceValid = true ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! isRaidGroup ()) // reset targetIcons for non-raid-groups
2008-10-11 14:16:25 -05: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
2010-09-11 09:09:41 -07:00
// insert into the table if we're not a battleground group
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2010-09-10 13:40:20 +02:00
CharacterDatabase . PExecute ( "INSERT INTO group_member (guid, memberGuid, memberFlags, subgroup, roles) VALUES(%u, %u, %u, %u, %u)" , GUID_LOPART ( m_guid ), GUID_LOPART ( member . guid ), member . flags , member . group , member . roles );
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 :: _removeMember ( const uint64 & guid )
{
2010-08-08 05:25:45 +02:00
Player * player = sObjectMgr . GetPlayer ( guid );
2008-10-11 14:16:25 -05:00
if ( player )
{
2009-03-14 20:00:02 -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:00:02 -06:00
else
{
//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:00:02 -06:00
player -> SetOriginalGroup ( NULL );
else
player -> SetGroup ( 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
_removeRolls ( guid );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
member_witerator slot = _getMemberWSlot ( guid );
if ( slot != m_memberSlots . end ())
2009-02-01 16:38:53 -06:00
{
SubGroupCounterDecrease ( slot -> group );
2008-10-11 14:16:25 -05:00
m_memberSlots . erase ( slot );
2009-02-01 16:38:53 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2010-05-08 01:58:47 +02:00
CharacterDatabase . PExecute ( "DELETE FROM group_member WHERE memberGuid=%u" , GUID_LOPART ( guid ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_leaderGuid == guid ) // leader was removed
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( GetMembersCount () > 0 )
2008-10-11 14:16:25 -05:00
_setLeader ( m_memberSlots . front (). guid );
return true ;
}
2009-10-17 15:51:44 -07:00
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
void Group :: _setLeader ( const uint64 & guid )
{
2010-03-09 20:33:59 +01: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 ;
2009-10-17 15:51:44 -07:00
2010-10-19 19:17:36 +02:00
sScriptMgr . OnGroupChangeLeader ( this , m_leaderGuid , guid );
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2008-10-11 14:16:25 -05:00
{
// TODO: set a time limit to have this function run rarely cause it can be slow
2010-08-21 03:19:25 +02:00
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// update the group's bound instances when changing leaders
// remove all permanent binds from the group
// in the DB also remove solo binds that will be replaced with permbinds
// from the new leader
2010-08-21 03:19:25 +02:00
trans -> PAppend (
2010-05-08 01:58:47 +02:00
"DELETE FROM group_instance WHERE guid=%u AND (permanent = 1 OR "
2008-10-11 14:16:25 -05:00
"instance IN (SELECT instance FROM character_instance WHERE guid = '%u')"
2010-05-08 01:58:47 +02:00
")" , GUID_LOPART ( m_guid ), GUID_LOPART ( slot -> guid )
2010-05-03 16:30:53 +02:00
);
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
Player * player = sObjectMgr . GetPlayer ( slot -> guid );
2010-04-07 19:14:10 +02:00
if ( player )
2008-10-11 14:16:25 -05:00
{
2009-12-17 11:11:54 +01:00
for ( uint8 i = 0 ; i < MAX_DIFFICULTY ; ++ i )
2008-10-11 14:16:25 -05:00
{
2009-11-20 19:11:28 -08:00
for ( BoundInstancesMap :: iterator itr = m_boundInstances [ i ]. begin (); itr != m_boundInstances [ i ]. end ();)
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( itr -> second . perm )
2008-10-11 14:16:25 -05:00
{
itr -> second . save -> RemoveGroup ( this );
m_boundInstances [ i ]. erase ( itr ++ );
}
else
++ itr ;
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// copy the permanent binds from the new leader to the group
// overwriting the solo binds with permanent ones if necessary
// in the DB those have been deleted already
Player :: ConvertInstancesToGroup ( player , this , slot -> guid );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// update the group leader
2010-08-21 03:19:25 +02:00
trans -> PAppend ( "UPDATE groups SET leaderGuid='%u' WHERE guid='%u'" , GUID_LOPART ( slot -> guid ), GUID_LOPART ( m_guid ));
CharacterDatabase . CommitTransaction ( trans );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_leaderGuid = slot -> guid ;
m_leaderName = slot -> name ;
2010-03-09 20:33:59 +01:00
ToggleGroupMemberFlag ( slot , MEMBER_FLAG_ASSISTANT , false );
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 :: _removeRolls ( const uint64 & guid )
{
2009-06-04 16:09:01 -05:00
for ( Rolls :: iterator it = RollId . begin (); it != RollId . end (); ++ it )
2008-10-11 14:16:25 -05:00
{
Roll * roll = * it ;
Roll :: PlayerVote :: iterator itr2 = roll -> playerVote . find ( guid );
2010-04-07 19:14:10 +02:00
if ( itr2 == roll -> playerVote . end ())
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-09-11 09:09:41 -07:00
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 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
roll -> playerVote . erase ( itr2 );
2009-10-17 15:51:44 -07:00
2009-12-17 11:11:54 +01:00
CountRollVote ( guid , roll -> itemGUID , GetMembersCount () - 1 , MAX_ROLL_TYPE );
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 :: _setMembersGroup ( const uint64 & guid , const uint8 & group )
{
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
2009-12-22 19:39:02 +01:00
bool Group :: _setAssistantFlag ( const uint64 & guid , const bool & apply )
2008-10-11 14:16:25 -05:00
{
member_witerator slot = _getMemberWSlot ( guid );
2009-12-22 19:39:02 +01:00
if ( slot == m_memberSlots . end ())
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2009-12-22 19:39:02 +01:00
ToggleGroupMemberFlag ( slot , MEMBER_FLAG_ASSISTANT , apply );
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2010-03-09 20:33:59 +01:00
CharacterDatabase . PExecute ( "UPDATE group_member SET memberFlags='%u' WHERE memberGuid='%u'" , slot -> flags , GUID_LOPART ( guid ));
2010-09-11 09:09:41 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2009-12-22 19:39:02 +01:00
bool Group :: _setMainTank ( const uint64 & guid , const bool & apply )
2008-10-11 14:16:25 -05:00
{
2009-12-22 19:39:02 +01:00
member_witerator slot = _getMemberWSlot ( guid ); // First check member slots to see if the target exists
if ( slot == m_memberSlots . end ())
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2009-12-22 19:39:02 +01:00
RemoveUniqueGroupMemberFlag ( MEMBER_FLAG_MAINTANK ); // Remove main tank flag from current if any.
ToggleGroupMemberFlag ( slot , MEMBER_FLAG_MAINTANK , apply ); // And apply main tank flag on new main tank.
2010-04-07 18:09:10 +02:00
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2010-03-09 20:33:59 +01:00
CharacterDatabase . PExecute ( "UPDATE group_member SET memberFlags='%u' WHERE memberGuid='%u'" , slot -> flags , GUID_LOPART ( guid ));
2010-09-11 09:09:41 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2009-12-22 19:39:02 +01:00
bool Group :: _setMainAssistant ( const uint64 & guid , const bool & apply )
2008-10-11 14:16:25 -05:00
{
member_witerator slot = _getMemberWSlot ( guid );
2009-12-22 19:39:02 +01:00
if ( slot == m_memberSlots . end ())
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2009-12-22 19:39:02 +01:00
RemoveUniqueGroupMemberFlag ( MEMBER_FLAG_MAINASSIST ); // Remove main assist flag from current if any.
ToggleGroupMemberFlag ( slot , MEMBER_FLAG_MAINASSIST , apply ); // Apply main assist flag on new main assist.
2010-02-14 19:13:14 -07:00
2010-04-07 19:14:10 +02:00
if ( ! isBGGroup ())
2010-03-09 20:33:59 +01:00
CharacterDatabase . PExecute ( "UPDATE group_member SET memberFlags='%u' WHERE memberGuid='%u'" , slot -> flags , GUID_LOPART ( guid ));
2010-09-11 09:09:41 -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 ;
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
2008-10-11 14:16:25 -05:00
// allows setting subgroup for offline members
void Group :: ChangeMembersGroup ( const uint64 & guid , const uint8 & group )
{
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
2010-08-08 05:25:45 +02:00
Player * player = sObjectMgr . GetPlayer ( guid );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! player )
{
2010-06-22 00:42:31 +02:00
uint8 prevSubGroup = GetMemberGroup ( guid );
if ( prevSubGroup == group )
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( _setMembersGroup ( guid , group ))
2010-06-22 00:42:31 +02:00
{
SubGroupCounterDecrease ( prevSubGroup );
2008-10-11 14:16:25 -05:00
SendUpdate ();
2010-06-22 00:42:31 +02:00
}
2008-10-11 14:16:25 -05:00
}
2008-10-29 17:09:32 -05:00
else
2009-02-01 16:38:53 -06:00
// This methods handles itself groupcounter decrease
ChangeMembersGroup ( player , group );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// only for online members
void Group :: ChangeMembersGroup ( Player * player , const uint8 & group )
{
2010-04-07 19:14:10 +02:00
if ( ! player || ! isRaidGroup ())
2008-10-11 14:16:25 -05:00
return ;
2010-08-08 19:45:53 +02:00
2010-06-22 00:42:31 +02:00
uint8 prevSubGroup = player -> GetSubGroup ();
if ( prevSubGroup == group )
return ;
2010-04-07 19:14:10 +02:00
if ( _setMembersGroup ( player -> GetGUID (), group ))
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
{
2010-09-11 09:09:41 -07: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 );
}
2009-10-17 15:51:44 -07:00
2010-09-11 09:09:41 -07:00
SubGroupCounterDecrease ( prevSubGroup );
2008-10-11 14:16:25 -05:00
SendUpdate ();
}
}
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 );
2010-08-23 19:56:47 -07: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
2010-03-11 22:55:02 +01:00
Player * pNewLooter = NULL ;
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 ))
2010-08-23 19:56:47 -07: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 ))
2010-08-23 19:56:47 -07: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.)
Player * reference = GetFirstMember () -> getSource ();
// 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
2010-02-15 15:31:27 +01: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 ;
2010-09-12 17:48:50 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next (), ++ memberscount )
2008-10-11 14:16:25 -05:00
{
Player * member = itr -> getSource ();
// 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
2010-02-15 15:31:27 +01: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 ())
2010-05-08 01:58:47 +02:00
CharacterDatabase . PExecute ( "UPDATE groups SET difficulty = %u WHERE guid ='%u'" , m_dungeonDifficulty , GUID_LOPART ( m_guid ));
2009-12-18 13:41:30 -08:00
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
Player * player = itr -> getSource ();
2010-04-07 19:14:10 +02:00
if ( ! player -> GetSession () || player -> getLevel () < LEVELREQUIREMENT_HEROIC )
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 ())
2010-05-08 01:58:47 +02:00
CharacterDatabase . PExecute ( "UPDATE groups SET raiddifficulty = %u WHERE guid ='%u'" , m_raidDifficulty , GUID_LOPART ( m_guid ));
2009-12-17 11:11:54 +01:00
2010-04-07 19:12:44 +02:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2009-12-17 11:11:54 +01:00
{
Player * player = itr -> getSource ();
2010-04-07 19:14:10 +02:00
if ( ! player -> GetSession () || player -> getLevel () < LEVELREQUIREMENT_HEROIC )
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 )
{
2009-10-17 16:20:24 -07:00
for ( GroupReference * itr = GetFirstMember (); itr != NULL ; itr = itr -> next ())
2008-10-11 14:16:25 -05:00
{
Player * pPlayer = itr -> getSource ();
2010-04-07 19:14:10 +02:00
if ( pPlayer && pPlayer -> getAttackers (). size () && pPlayer -> GetInstanceId () == instanceId && ( pPlayer -> GetMap () -> IsRaidOrHeroicDungeon ()))
2010-04-08 08:20:08 +02:00
for ( std :: set < Unit *>:: const_iterator i = pPlayer -> getAttackers (). begin (); i != pPlayer -> 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
{
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
2010-06-25 00:18:01 +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
2010-08-30 15:25:15 +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
2010-08-30 15:25:15 +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 ;
}
2008-10-11 14:16:25 -05:00
InstanceGroupBind * Group :: BindToInstance ( InstanceSave * save , bool permanent , bool load )
{
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 ))
CharacterDatabase . PExecute ( "REPLACE INTO group_instance (guid, instance, permanent) VALUES (%u, %u, %u)" , GUID_LOPART ( GetGUID ()), 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 )
sLog . outDebug ( "Group::BindToInstance: %d is now bound to map %d, instance %d, difficulty %d" , GUID_LOPART ( GetGUID ()), save -> GetMapId (), save -> GetInstanceId (), save -> GetDifficulty ());
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 )
CharacterDatabase . PExecute ( "DELETE FROM group_instance WHERE guid=%u AND instance=%u" , GUID_LOPART ( GetGUID ()), 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
2008-10-11 14:16:25 -05:00
void Group :: _homebindIfInstance ( Player * player )
{
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
{
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
Player * pp = sObjectMgr . GetPlayer ( 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-08-22 01:57:04 +02: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 ;
Player * pMember = NULL ;
for ( member_citerator citr = m_memberSlots . begin (); citr != m_memberSlots . end (); ++ citr )
{
2010-08-30 15:25:15 +02:00
pMember = sObjectMgr . GetPlayer ( citr -> guid );
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 ;
}
void Group :: SetLooterGuid ( const uint64 & guid )
{
m_looterGuid = guid ;
}
void Group :: SetLootThreshold ( ItemQualities threshold )
{
m_lootThreshold = threshold ;
}
2010-12-05 17:50:26 +01:00
void Group :: SetLfgState ( LfgState state )
2010-11-29 07:50:31 +01:00
{
2010-12-05 17:50:26 +01:00
m_LfgState = state ;
2010-11-29 07:50:31 +01:00
}
2010-12-06 02:07:53 +01:00
LfgState Group :: GetLfgState () const
2010-11-29 07:50:31 +01:00
{
2010-12-05 17:50:26 +01:00
return m_LfgState ;
2010-11-29 07:50:31 +01:00
}
2010-12-05 17:50:26 +01:00
void Group :: RestoreLfgState ()
2010-11-29 07:50:31 +01:00
{
2010-12-05 17:50:26 +01:00
m_LfgState = m_LfgOldState ;
2010-11-29 07:50:31 +01:00
}
void Group :: SetLfgDungeonEntry ( uint32 dungeonEntry )
{
m_LfgDungeonEntry = dungeonEntry ;
}
2010-12-06 02:07:53 +01:00
uint32 Group :: GetLfgDungeonEntry ( bool id /* = true*/ ) const
2010-11-29 07:50:31 +01:00
{
if ( id )
return ( m_LfgDungeonEntry & 0x00FFFFFF );
else
return m_LfgDungeonEntry ;
}
uint8 Group :: GetLfgKicks () const
{
return m_Lfgkicks ;
}
void Group :: SetLfgKicks ( uint8 kicks )
{
m_Lfgkicks = kicks ;
}
void Group :: SetLfgRoles ( uint64 guid , const uint8 roles )
{
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 ;
}
const uint64 & Group :: GetLeaderGUID () const
{
return m_leaderGuid ;
}
const uint64 & Group :: GetGUID () const
{
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 ;
}
const uint64 & Group :: GetLooterGuid () const
{
return m_looterGuid ;
}
ItemQualities Group :: GetLootThreshold () const
{
return m_lootThreshold ;
}
bool Group :: IsMember ( const uint64 & guid ) const
{
return _getMemberCSlot ( guid ) != m_memberSlots . end ();
}
bool Group :: IsLeader ( const uint64 & guid ) const
{
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 ;
}
bool Group :: SameSubGroup ( uint64 guid1 , const uint64 & guid2 ) const
{
member_citerator mslot2 = _getMemberCSlot ( guid2 );
if ( mslot2 == m_memberSlots . end ())
return false ;
return SameSubGroup ( guid1 , &* mslot2 );
}
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 ;
}
void Group :: SetBattlegroundGroup ( Battleground * bg )
{
m_bgGroup = bg ;
}
void Group :: SetAssistant ( uint64 guid , const bool & apply )
{
if ( ! isRaidGroup ())
return ;
if ( _setAssistantFlag ( guid , apply ))
SendUpdate ();
}
void Group :: SetMainTank ( uint64 guid , const bool & apply )
{
if ( ! isRaidGroup ())
return ;
if ( _setMainTank ( guid , apply ))
SendUpdate ();
}
void Group :: SetMainAssistant ( uint64 guid , const bool & apply )
{
if ( ! isRaidGroup ())
return ;
if ( _setMainAssistant ( guid , apply ))
SendUpdate ();
}
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 ();
}
void Group :: LinkMember ( GroupReference * pRef )
{
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 ;
}