aboutsummaryrefslogtreecommitdiff
path: root/src/game/Group.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/Group.cpp')
-rw-r--r--src/game/Group.cpp160
1 files changed, 120 insertions, 40 deletions
diff --git a/src/game/Group.cpp b/src/game/Group.cpp
index f0a9ce5add8..f4a977c3d7c 100644
--- a/src/game/Group.cpp
+++ b/src/game/Group.cpp
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
- * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
*
* 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
@@ -10,12 +10,12 @@
*
* 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
+ * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Common.h"
@@ -74,6 +74,8 @@ Group::~Group()
for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++)
for(BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
itr->second.save->RemoveGroup(this);
+
+ // Sub group counters clean up
if (m_subGroupsCounts)
delete[] m_subGroupsCounts;
}
@@ -201,13 +203,24 @@ void Group::ConvertToRaid()
_initRaidSubGroupsCounter();
- if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
+ if(!isBGGroup())
+ CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
SendUpdate();
+
+ // update quest related GO states (quest activity dependent from raid membership)
+ for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
+ if(Player* player = objmgr.GetPlayer(citr->guid))
+ player->UpdateForQuestsGO();
}
bool Group::AddInvite(Player *player)
{
- if(!player || player->GetGroupInvite() || player->GetGroup())
+ if( !player || player->GetGroupInvite() )
+ return false;
+ Group* group = player->GetGroup();
+ if( group && group->isBGGroup() )
+ group = player->GetOriginalGroup();
+ if( group )
return false;
RemoveInvite(player);
@@ -288,6 +301,10 @@ bool Group::AddMember(const uint64 &guid, const char* name)
}
player->SetGroupUpdateFlag(GROUP_UPDATE_FULL);
UpdatePlayerOutOfRange(player);
+
+ // quest related GO state dependent from raid memebership
+ if(isRaidGroup())
+ player->UpdateForQuestsGO();
}
return true;
@@ -302,9 +319,12 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
{
bool leaderChanged = _removeMember(guid);
- Player *player = objmgr.GetPlayer( guid ); // FG: TODO: could be removed, its just here for consistency
- if (player)
+ if(Player *player = objmgr.GetPlayer( guid ))
{
+ // quest related GO state dependent from raid membership
+ if(isRaidGroup())
+ player->UpdateForQuestsGO();
+
WorldPacket data;
if(method == 1)
@@ -313,9 +333,17 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
player->GetSession()->SendPacket( &data );
}
- data.Initialize(SMSG_GROUP_LIST, 24);
- data << uint64(0) << uint64(0) << uint64(0);
- player->GetSession()->SendPacket(&data);
+ //we already removed player from group and in player->GetGroup() is his original group!
+ if( Group* group = player->GetGroup() )
+ {
+ group->SendUpdate();
+ }
+ else
+ {
+ data.Initialize(SMSG_GROUP_LIST, 24);
+ data << uint64(0) << uint64(0) << uint64(0);
+ player->GetSession()->SendPacket(&data);
+ }
_homebindIfInstance(player);
}
@@ -324,7 +352,7 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
{
WorldPacket data(SMSG_GROUP_SET_LEADER, (m_memberSlots.front().name.size()+1));
data << m_memberSlots.front().name;
- BroadcastPacket(&data);
+ BroadcastPacket(&data, true);
}
SendUpdate();
@@ -347,7 +375,7 @@ void Group::ChangeLeader(const uint64 &guid)
WorldPacket data(SMSG_GROUP_SET_LEADER, slot->name.size()+1);
data << slot->name;
- BroadcastPacket(&data);
+ BroadcastPacket(&data, true);
SendUpdate();
}
@@ -361,7 +389,22 @@ void Group::Disband(bool hideDestroy)
if(!player)
continue;
- player->SetGroup(NULL);
+ //we cannot call _removeMember because it would invalidate member iterator
+ //if we are removing player from battleground raid
+ if( isBGGroup() )
+ player->RemoveFromBattleGroundRaid();
+ else
+ {
+ //we can remove player who is in battleground from his original group
+ if( player->GetOriginalGroup() == this )
+ player->SetOriginalGroup(NULL);
+ else
+ player->SetGroup(NULL);
+ }
+
+ // quest related GO state dependent from raid membership
+ if(isRaidGroup())
+ player->UpdateForQuestsGO();
if(!player->GetSession())
continue;
@@ -373,9 +416,17 @@ void Group::Disband(bool hideDestroy)
player->GetSession()->SendPacket(&data);
}
- data.Initialize(SMSG_GROUP_LIST, 24);
- data << uint64(0) << uint64(0) << uint64(0);
- player->GetSession()->SendPacket(&data);
+ //we already removed player from group and in player->GetGroup() is his original group, send update
+ if( Group* group = player->GetGroup() )
+ {
+ group->SendUpdate();
+ }
+ else
+ {
+ data.Initialize(SMSG_GROUP_LIST, 24);
+ data << uint64(0) << uint64(0) << uint64(0);
+ player->GetSession()->SendPacket(&data);
+ }
_homebindIfInstance(player);
}
@@ -729,6 +780,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
if(player && player->GetSession())
{
+ player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul);
+
ItemPosCountVec dest;
LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);
uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count );
@@ -774,6 +827,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
if(player && player->GetSession())
{
+ player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul);
+
ItemPosCountVec dest;
LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);
uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count );
@@ -819,7 +874,7 @@ void Group::SetTargetIcon(uint8 id, uint64 guid)
data << (uint8)0;
data << id;
data << guid;
- BroadcastPacket(&data);
+ BroadcastPacket(&data, true);
}
void Group::GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_level, Player* & member_with_max_level, Player* & not_gray_member_with_max_level)
@@ -835,13 +890,10 @@ void Group::GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_lev
++count;
sum_level += member->getLevel();
- // store maximum member level
if(!member_with_max_level || member_with_max_level->getLevel() < member->getLevel())
member_with_max_level = member;
- uint32 gray_level = Trinity::XP::GetGrayLevel(member->getLevel());
- // if the victim is higher level than the gray level of the currently examined group member,
- // then set not_gray_member_with_max_level if needed.
+ uint32 gray_level = MaNGOS::XP::GetGrayLevel(member->getLevel());
if( victim->getLevel() > gray_level && (!not_gray_member_with_max_level
|| not_gray_member_with_max_level->getLevel() < member->getLevel()))
not_gray_member_with_max_level = member;
@@ -875,7 +927,7 @@ void Group::SendUpdate()
for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
{
player = objmgr.GetPlayer(citr->guid);
- if(!player || !player->GetSession())
+ if(!player || !player->GetSession() || player->GetGroup() != this )
continue;
// guess size
WorldPacket data(SMSG_GROUP_LIST, (1+1+1+1+8+4+GetMembersCount()*20));
@@ -889,11 +941,14 @@ void Group::SendUpdate()
{
if(citr->guid == citr2->guid)
continue;
+ Player* member = objmgr.GetPlayer(citr2->guid);
+ uint8 onlineState = (member) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE;
+ onlineState = onlineState | ((isBGGroup()) ? MEMBER_STATUS_PVP : 0);
data << citr2->name;
data << (uint64)citr2->guid;
// online-state
- data << (uint8)(objmgr.GetPlayer(citr2->guid) ? 1 : 0);
+ data << (uint8)(onlineState);
data << (uint8)(citr2->group); // groupid
data << (uint8)(citr2->assistant?0x01:0); // 0x2 main assist, 0x4 main tank
}
@@ -905,7 +960,6 @@ void Group::SendUpdate()
data << (uint64)m_looterGuid; // looter guid
data << (uint8)m_lootThreshold; // loot threshold
data << (uint8)m_difficulty; // Heroic Mod Group
-
}
player->GetSession()->SendPacket( &data );
}
@@ -928,12 +982,12 @@ void Group::UpdatePlayerOutOfRange(Player* pPlayer)
}
}
-void Group::BroadcastPacket(WorldPacket *packet, int group, uint64 ignore)
+void Group::BroadcastPacket(WorldPacket *packet, bool ignorePlayersInBGRaid, int group, uint64 ignore)
{
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *pl = itr->getSource();
- if(!pl || (ignore != 0 && pl->GetGUID() == ignore))
+ if(!pl || (ignore != 0 && pl->GetGUID() == ignore) || (ignorePlayersInBGRaid && pl->GetGroup() != this) )
continue;
if (pl->GetSession() && (group==-1 || itr->getSubGroup()==group))
@@ -984,7 +1038,7 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant)
}
// We are raid group and no one slot is free
if (!groupFound)
- return false;
+ return false;
}
return _addMember(guid, name, isAssistant, groupid);
@@ -1012,7 +1066,15 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant, u
if(player)
{
player->SetGroupInvite(NULL);
- player->SetGroup(this, group);
+ //if player is in group and he is being added to BG raid group, then call SetBattleGroundRaid()
+ if( player->GetGroup() && isBGGroup() )
+ player->SetBattleGroundRaid(this, group);
+ //if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
+ else if ( player->GetGroup() )
+ player->SetOriginalGroup(this, group);
+ //if player is not in group, then call set group
+ else
+ player->SetGroup(this, group);
// if the same group invites the player back, cancel the homebind timer
InstanceGroupBind *bind = GetBoundInstance(player->GetMapId(), player->GetDifficulty());
if(bind && bind->save->GetInstanceId() == player->GetInstanceId())
@@ -1039,7 +1101,17 @@ bool Group::_removeMember(const uint64 &guid)
Player *player = objmgr.GetPlayer(guid);
if (player)
{
- player->SetGroup(NULL);
+ //if we are removing player from battleground raid
+ if( isBGGroup() )
+ player->RemoveFromBattleGroundRaid();
+ else
+ {
+ //we can remove player who is in battleground from his original group
+ if( player->GetOriginalGroup() == this )
+ player->SetOriginalGroup(NULL);
+ else
+ player->SetGroup(NULL);
+ }
}
_removeRolls(guid);
@@ -1048,6 +1120,7 @@ bool Group::_removeMember(const uint64 &guid)
if (slot != m_memberSlots.end())
{
SubGroupCounterDecrease(slot->group);
+
m_memberSlots.erase(slot);
}
@@ -1207,6 +1280,7 @@ void Group::ChangeMembersGroup(const uint64 &guid, const uint8 &group)
if(!isRaidGroup())
return;
Player *player = objmgr.GetPlayer(guid);
+
if (!player)
{
uint8 prevSubGroup;
@@ -1218,6 +1292,7 @@ void Group::ChangeMembersGroup(const uint64 &guid, const uint8 &group)
SendUpdate();
}
else
+ // This methods handles itself groupcounter decrease
ChangeMembersGroup(player, group);
}
@@ -1228,12 +1303,17 @@ void Group::ChangeMembersGroup(Player *player, const uint8 &group)
return;
if(_setMembersGroup(player->GetGUID(), group))
{
- uint8 prevSubGroup;
- prevSubGroup = player->GetSubGroup();
-
+ uint8 prevSubGroup = player->GetSubGroup();
+ if( player->GetGroup() == this )
+ player->GetGroupRef().setSubGroup(group);
+ //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
+ else
+ {
+ prevSubGroup = player->GetOriginalSubGroup();
+ player->GetOriginalGroupRef().setSubGroup(group);
+ }
SubGroupCounterDecrease(prevSubGroup);
- player->GetGroupRef().setSubGroup(group);
SendUpdate();
}
}
@@ -1311,7 +1391,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
SendUpdate();
}
-uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot)
+uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot)
{
// check for min / max count
uint32 memberscount = GetMembersCount();
@@ -1326,7 +1406,7 @@ uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint
if(!reference)
return BG_JOIN_ERR_OFFLINE_MEMBER;
- uint32 bgQueueId = reference->GetBattleGroundQueueIdFromLevel();
+ BGQueueIdBasedOnLevel queue_id = reference->GetBattleGroundQueueIdFromLevel(bgTypeId);
uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
uint32 team = reference->GetTeam();
@@ -1341,13 +1421,13 @@ uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint
if(member->GetTeam() != team)
return BG_JOIN_ERR_MIXED_FACTION;
// not in the same battleground level braket, don't let join
- if(member->GetBattleGroundQueueIdFromLevel() != bgQueueId)
+ if(member->GetBattleGroundQueueIdFromLevel(bgTypeId) != queue_id)
return BG_JOIN_ERR_MIXED_LEVELS;
// don't let join rated matches if the arena team id doesn't match
if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
return BG_JOIN_ERR_MIXED_ARENATEAM;
// don't let join if someone from the group is already in that bg queue
- if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueType))
+ if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueTypeId))
return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE;
// check for deserter debuff in case not arena queue
if(bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground())
@@ -1366,7 +1446,7 @@ uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint
void Roll::targetObjectBuildLink()
{
// called from link()
- this->getTarget()->addLootValidatorRef(this);
+ getTarget()->addLootValidatorRef(this);
}
void Group::SetDifficulty(uint8 difficulty)
@@ -1476,7 +1556,7 @@ InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, boo
InstanceGroupBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()];
if(bind.save)
{
- // when a boss is killed or when copying the player's binds to the group
+ // when a boss is killed or when copying the players's binds to the group
if(permanent != bind.perm || save != bind.save)
if(!load) CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u', permanent = '%u' WHERE leaderGuid = '%u' AND instance = '%u'", save->GetInstanceId(), permanent, GUID_LOPART(GetLeaderGUID()), bind.save->GetInstanceId());
}