diff options
Diffstat (limited to 'src/game/Group.cpp')
| -rw-r--r-- | src/game/Group.cpp | 160 | 
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());          }  | 
