[7455] Implemented condition that player can be in 2 groups in 1 time - BG raid and normal group / raid.

Patch is tested, but can cause problems / unexpected behaviour.
TODO: set raid leader of battleground raid to raid leader who entered BG
TODO: when player leaves group, he is removed from GroupQueueInfo, and for him is created new GroupQueueInfo in normal queue.

Signed-off-by: Triply <triply@getmangos.com>
This commit is contained in:
Triply 2009-03-14 16:57:49 +01:00
parent f280c96770
commit b45b075668
10 changed files with 171 additions and 68 deletions

View file

@ -1159,7 +1159,7 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid,
if(group->IsMember(plr_guid))
{
uint8 subgroup = group->GetMemberGroup(plr_guid);
plr->SetGroup(group, subgroup);
plr->SetBattleGroundRaid(group, subgroup);
}
else
GetBgRaid(team)->AddMember(plr_guid, plr->GetName());

View file

@ -430,8 +430,6 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
_player->GetMotionMaster()->MovementExpired();
_player->m_taxi.ClearTaxiDestinations();
}
//TODO FIX ME this call must be removed!
_player->RemoveFromGroup();
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType());
_player->GetSession()->SendPacket(&data);

View file

@ -232,13 +232,15 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty())
break;
Group *group = GetPlayer()->GetGroup();
if(!group)
// if player is in battleground, he cannot say to battleground members by /p
Group *group = GetPlayer()->GetOriginalGroup();
// so if player hasn't OriginalGroup and his player->GetGroup() is BG raid, then return
if( !group && (!(group = GetPlayer()->GetGroup()) || group->isBGGroup()) )
return;
WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_PARTY, lang, NULL, 0, msg.c_str(),NULL);
group->BroadcastPacket(&data, group->GetMemberGroup(GetPlayer()->GetGUID()));
group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID()));
}
break;
case CHAT_MSG_GUILD:
@ -312,13 +314,15 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty())
break;
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup())
// if player is in battleground, he cannot say to battleground members by /ra
Group *group = GetPlayer()->GetOriginalGroup();
// so if player hasn't OriginalGroup and his player->GetGroup() is BG raid or his group isn't raid, then return
if( !group && !(group = GetPlayer()->GetGroup()) || group->isBGGroup() || !group->isRaidGroup() )
return;
WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data);
group->BroadcastPacket(&data, false);
} break;
case CHAT_MSG_RAID_LEADER:
{
@ -338,13 +342,14 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty())
break;
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
// if player is in battleground, he cannot say to battleground members by /ra
Group *group = GetPlayer()->GetOriginalGroup();
if( !group && !(group = GetPlayer()->GetGroup()) || group->isBGGroup() || !group->isRaidGroup() )
return;
WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data);
group->BroadcastPacket(&data, false);
} break;
case CHAT_MSG_RAID_WARNING:
{
@ -363,8 +368,9 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
return;
WorldPacket data;
//in battleground, raid warning is sent only to players in battleground - code is ok
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data);
group->BroadcastPacket(&data, false);
} break;
case CHAT_MSG_BATTLEGROUND:
@ -379,13 +385,14 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty())
break;
//battleground raid is always in Player->GetGroup(), never in GetOriginalGroup()
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup())
if(!group || !group->isBGGroup())
return;
WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data);
group->BroadcastPacket(&data, false);
} break;
case CHAT_MSG_BATTLEGROUND_LEADER:
@ -400,13 +407,14 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty())
break;
//battleground raid is always in Player->GetGroup(), never in GetOriginalGroup()
Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
if(!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
return;
WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data);
group->BroadcastPacket(&data, false);
} break;
case CHAT_MSG_CHANNEL:

View file

@ -201,7 +201,8 @@ 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)
@ -212,7 +213,12 @@ void Group::ConvertToRaid()
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);
@ -323,9 +329,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);
}
@ -334,7 +348,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();
@ -357,7 +371,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();
}
@ -371,13 +385,26 @@ void Group::Disband(bool hideDestroy)
if(!player)
continue;
player->SetGroup(NULL);
//we cannot call _removeMember because it would invalidate member iterator
if (player)
{
//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;
@ -388,9 +415,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);
}
@ -838,7 +873,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)
@ -891,7 +926,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));
@ -905,11 +940,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
}
@ -943,12 +981,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))
@ -1027,7 +1065,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())
@ -1054,7 +1100,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);
@ -1246,12 +1302,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();
}
}

View file

@ -291,7 +291,7 @@ class MANGOS_DLL_SPEC Group
void SendUpdate();
void UpdatePlayerOutOfRange(Player* pPlayer);
// ignore: GUID of player that will be ignored
void BroadcastPacket(WorldPacket *packet, int group=-1, uint64 ignore=0);
void BroadcastPacket(WorldPacket *packet, bool ignorePlayersInBGRaid, int group=-1, uint64 ignore=0);
void BroadcastReadyCheck(WorldPacket *packet);
void OfflineReadyCheck();

View file

@ -55,12 +55,6 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
std::string membername;
recv_data >> membername;
if(_player->InBattleGround())
{
SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_INVITE_RESTRICTED);
return;
}
// attempt add selected player
// cheating
@ -97,15 +91,20 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
return;
}
Group *group = GetPlayer()->GetGroup();
if( group && group->isBGGroup() )
group = GetPlayer()->GetOriginalGroup();
Group *group2 = player->GetGroup();
if( group2 && group2->isBGGroup() )
group2 = player->GetOriginalGroup();
// player already in another group or invited
if(player->GetGroup() || player->GetGroupInvite() )
if( group2 || player->GetGroupInvite() )
{
SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_ALREADY_IN_GROUP);
return;
}
Group *group = GetPlayer()->GetGroup();
if(group)
{
// not have permissions for invite
@ -114,7 +113,6 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_YOU_NOT_LEADER);
return;
}
// not have place
if(group->IsFull())
{
@ -185,27 +183,20 @@ void WorldSession::HandleGroupAcceptOpcode( WorldPacket & /*recv_data*/ )
Player* leader = objmgr.GetPlayer(group->GetLeaderGUID());
if(leader && leader->InBattleGround())
{
SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_INVITE_RESTRICTED);
return;
}
// forming a new group, create it
if(!group->IsCreated())
{
if(leader) group->RemoveInvite(leader);
if( leader )
group->RemoveInvite(leader);
group->Create(group->GetLeaderGUID(), group->GetLeaderName());
objmgr.AddGroup(group);
}
// everything's fine, do it
// everything's fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
if(!group->AddMember(GetPlayer()->GetGUID(), GetPlayer()->GetName()))
return;
uint8 subgroup = group->GetMemberGroup(GetPlayer()->GetGUID());
GetPlayer()->SetGroup(group, subgroup);
}
void WorldSession::HandleGroupDeclineOpcode( WorldPacket & /*recv_data*/ )
@ -424,7 +415,7 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data)
data << GetPlayer()->GetGUID();
data << x;
data << y;
GetPlayer()->GetGroup()->BroadcastPacket(&data, -1, GetPlayer()->GetGUID());
GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID());
}
void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data)
@ -451,7 +442,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data)
data << roll;
data << GetPlayer()->GetGUID();
if(GetPlayer()->GetGroup())
GetPlayer()->GetGroup()->BroadcastPacket(&data);
GetPlayer()->GetGroup()->BroadcastPacket(&data, false);
else
SendPacket(&data);
}
@ -512,6 +503,7 @@ void WorldSession::HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data,1+1);
// we will get correct pointer for group here, so we don't have to check if group is BG raid
Group *group = GetPlayer()->GetGroup();
if(!group)
return;
@ -604,7 +596,7 @@ void WorldSession::HandleRaidReadyCheckOpcode( WorldPacket & recv_data )
// everything's fine, do it
WorldPacket data(MSG_RAID_READY_CHECK, 8);
data << GetPlayer()->GetGUID();
group->BroadcastPacket(&data, -1);
group->BroadcastPacket(&data, false, -1);
group->OfflineReadyCheck();
}

View file

@ -12286,7 +12286,7 @@ void Player::SendNewItem(Item *item, uint32 count, bool received, bool created,
data << GetItemCount(item->GetEntry()); // count of items in inventory
if (broadcast && GetGroup())
GetGroup()->BroadcastPacket(&data);
GetGroup()->BroadcastPacket(&data, true);
else
GetSession()->SendPacket(&data);
}
@ -18319,7 +18319,8 @@ void Player::ClearComboPoints()
void Player::SetGroup(Group *group, int8 subgroup)
{
if(group == NULL) m_group.unlink();
if(group == NULL)
m_group.unlink();
else
{
// never use SetGroup without a subgroup unless you specify NULL for group
@ -19414,6 +19415,41 @@ PartyResult Player::CanUninviteFromGroup() const
return PARTY_RESULT_OK;
}
void Player::SetBattleGroundRaid(Group* group, int8 subgroup)
{
//we must move references from m_group to m_originalGroup
SetOriginalGroup(GetGroup(), GetSubGroup());
m_group.unlink();
m_group.link(group, this);
m_group.setSubGroup((uint8)subgroup);
}
void Player::RemoveFromBattleGroundRaid()
{
//remove existing reference
m_group.unlink();
if( Group* group = GetOriginalGroup() )
{
m_group.link(group, this);
m_group.setSubGroup(GetOriginalSubGroup());
}
SetOriginalGroup(NULL);
}
void Player::SetOriginalGroup(Group *group, int8 subgroup)
{
if( group == NULL )
m_originalGroup.unlink();
else
{
// never use SetOriginalGroup without a subgroup unless you specify NULL for group
assert(subgroup >= 0);
m_originalGroup.link(group, this);
m_originalGroup.setSubGroup((uint8)subgroup);
}
}
void Player::UpdateUnderwaterState( Map* m, float x, float y, float z )
{
LiquidData liquid_status;

View file

@ -2131,6 +2131,13 @@ class MANGOS_DLL_SPEC Player : public Unit
void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
Player* GetNextRandomRaidMember(float radius);
PartyResult CanUninviteFromGroup() const;
// BattleGround Group System
void SetBattleGroundRaid(Group *group, int8 subgroup = -1);
void RemoveFromBattleGroundRaid();
Group * GetOriginalGroup() { return m_originalGroup.getTarget(); }
GroupReference& GetOriginalGroupRef() { return m_originalGroup; }
uint8 GetOriginalSubGroup() const { return m_originalGroup.getSubGroup(); }
void SetOriginalGroup(Group *group, int8 subgroup = -1);
GridReference<Player> &GetGridRef() { return m_gridRef; }
MapReference &GetMapRef() { return m_mapRef; }
@ -2374,6 +2381,7 @@ class MANGOS_DLL_SPEC Player : public Unit
// Groups
GroupReference m_group;
GroupReference m_originalGroup;
Group *m_groupInvite;
uint32 m_groupUpdateMask;
uint64 m_auraUpdateMask;

View file

@ -75,7 +75,7 @@ enum SpellAuraInterruptFlags
AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting
AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up
AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported
AURA_INTERRUPT_FLAG_UNK20 = 0x00100000, // 20
AURA_INTERRUPT_FLAG_IMMUNE_OR_STEALTH = 0x00100000, // 20 removed when player on himself casts immunity spell or vanish?
AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21
AURA_INTERRUPT_FLAG_UNK22 = 0x00400000, // 22
AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "7454"
#define REVISION_NR "7455"
#endif // __REVISION_NR_H__