// Called when a player leave the zone void Battlefield::HandlePlayerLeaveZone(Player* player, uint32 /*zone*/) { if (IsWarTime()) { // If the player is participating to the battle if (m_PlayersInWar[player->GetTeamId()].find(player->GetGUID()) != m_PlayersInWar[player->GetTeamId()].end()) { m_PlayersInWar[player->GetTeamId()].erase(player->GetGUID()); player->GetSession()->SendBfLeaveMessage(m_Guid); if (Group* group = player->GetGroup()) // Remove the player from the raid group group->RemoveMember(player->GetGUID()); OnPlayerLeaveWar(player); } } for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) itr->second->HandlePlayerLeave(player); m_InvitedPlayers[player->GetTeamId()].erase(player->GetGUID()); m_PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID()); m_players[player->GetTeamId()].erase(player->GetGUID()); SendRemoveWorldStates(player); RemovePlayerFromResurrectQueue(player->GetGUID()); OnPlayerLeaveZone(player); }
//Called when a player leave the zone void Battlefield::HandlePlayerLeaveZone(Player* player, uint32 /*zone */ ) { if (IsWarTime()) { //if player is in war list if (m_PlayersInWar[player->GetTeamId()].find(player->GetGUID()) != m_PlayersInWar[player->GetTeamId()].end()) { m_PlayersInWar[player->GetTeamId()].erase(player->GetGUID()); player->GetSession()->SendBfLeaveMessage(m_BattleId); if (Group* group = GetGroupPlayer(player->GetGUID(), player->GetTeamId())) // remove from raid group if player is member { // I think that now is not a hack if (!group->RemoveMember(player->GetGUID())) // group was disbanded { m_Groups[player->GetTeamId()].erase(group->GetGUID()); group->SetBattlefieldGroup(NULL); sGroupMgr->RemoveGroup(group); delete group; } } OnPlayerLeaveWar(player); //For scripting } } for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) itr->second->HandlePlayerLeave(player); m_InvitedPlayers[player->GetTeamId()].erase(player->GetGUID()); m_PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID()); m_players[player->GetTeamId()].erase(player->GetGUID()); SendRemoveWorldStates(player); RemovePlayerFromResurrectQueue(player->GetGUID()); OnPlayerLeaveZone(player); //For scripting }
void BattleGround::Update(time_t diff) { if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) //BG is empty return; WorldPacket data; if(GetRemovedPlayersSize()) { for(std::map<uint64, uint8>::iterator itr = m_RemovedPlayers.begin(); itr != m_RemovedPlayers.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); switch(itr->second) { //following code is handled by event: /*case 0: sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].RemovePlayer(itr->first); //RemovePlayerFromQueue(itr->first); if(plr) { sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } break;*/ case 1: // currently in bg and was removed from bg if(plr) RemovePlayerAtLeave(itr->first, true, true); else RemovePlayerAtLeave(itr->first, false, false); break; case 2: // revive queue RemovePlayerFromResurrectQueue(itr->first); break; default: sLog.outError("BattleGround: Unknown remove player case!"); } } m_RemovedPlayers.clear(); } // this code isn't efficient and its idea isn't implemented yet /* offline players are removed from battleground in worldsession::LogoutPlayer() // remove offline players from bg after ~5 minutes if(GetPlayersSize()) { for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); itr->second.LastOnlineTime += diff; if(plr) itr->second.LastOnlineTime = 0; // update last online time else if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) // 5 minutes m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) } }*/ m_LastResurrectTime += diff; if (m_LastResurrectTime >= RESURRECTION_INTERVAL) { if(GetReviveQueueSize()) { for(std::map<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr) { Creature *sh = NULL; for(std::vector<uint64>::iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2) { Player *plr = objmgr.GetPlayer(*itr2); if(!plr) continue; if (!sh) { sh = ObjectAccessor::GetCreature(*plr, itr->first); // only for visual effect if (sh) sh->CastSpell(sh, SPELL_SPIRIT_HEAL, true); // Spirit Heal, effect 117 } plr->CastSpell(plr, SPELL_RESURRECTION_VISUAL, true); // Resurrection visual m_ResurrectQueue.push_back(*itr2); } (itr->second).clear(); } m_ReviveQueue.clear(); m_LastResurrectTime = 0; } else // queue is clear and time passed, just update last resurrection time m_LastResurrectTime = 0; } else if (m_LastResurrectTime > 500) // Resurrect players only half a second later, to see spirit heal effect on NPC { for(std::vector<uint64>::iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr) { Player *plr = objmgr.GetPlayer(*itr); if(!plr) continue; plr->ResurrectPlayer(1.0f); plr->CastSpell(plr, SPELL_SPIRIT_HEAL_MANA, true); ObjectAccessor::Instance().ConvertCorpseForPlayer(*itr); } m_ResurrectQueue.clear(); } if(GetStatus() == STATUS_WAIT_LEAVE) { // remove all players from battleground after 2 minutes m_EndTime += diff; if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes { for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) } // do not change any battleground's private variables } } }
void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) { // Remove from lists/maps std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid); if(itr != m_Players.end()) { UpdatePlayersCountByTeam(itr->second.Team, true); // -1 player m_Players.erase(itr); } std::map<uint64, BattleGroundScore*>::iterator itr2 = m_PlayerScores.find(guid); if(itr2 != m_PlayerScores.end()) { delete itr2->second; // delete player's score m_PlayerScores.erase(itr2); } RemovePlayerFromResurrectQueue(guid); Player *plr = objmgr.GetPlayer(guid); if(plr && !plr->isAlive()) // resurrect on exit { plr->ResurrectPlayer(1.0f); plr->SpawnCorpseBones(); } RemovePlayer(plr, guid); // BG subclass specific code if(plr) { plr->ClearAfkReports(); if(isArena()) { if(!sWorld.IsFFAPvPRealm()) plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); } WorldPacket data; if(SendPacket) { sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg plr->RemoveBattleGroundQueueId(m_TypeID); DecreaseInvitedCount(plr->GetTeam()); //we should update battleground queue, but only if bg isn't ending if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType()); if(!plr->GetBattleGroundId()) return; Group * group = plr->GetGroup(); // remove from raid group if exist if(group && group == GetBgRaid(plr->GetTeam())) { if(!group->RemoveMember(guid, 0)) // group was disbanded { SetBgRaid(plr->GetTeam(), NULL); delete group; } } // Do next only if found in battleground plr->SetBattleGroundId(0); // We're not in BG. // Let others know sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); SendPacketToTeam(plr->GetTeam(), &data, plr, false); if(Transport) { plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); //sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O); } // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); } /// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist // we always should check if BG is in that queue before adding.. if(!GetPlayersSize()) { Reset(); } }
void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) { uint32 team = GetPlayerTeam(guid); bool participant = false; // Remove from lists/maps std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid); if(itr != m_Players.end()) { UpdatePlayersCountByTeam(team, true); // -1 player m_Players.erase(itr); // check if the player was a participant of the match, or only entered through gm command (goname) participant = true; } std::map<uint64, BattleGroundScore*>::iterator itr2 = m_PlayerScores.find(guid); if(itr2 != m_PlayerScores.end()) { delete itr2->second; // delete player's score m_PlayerScores.erase(itr2); } RemovePlayerFromResurrectQueue(guid); Player *plr = objmgr.GetPlayer(guid); // should remove spirit of redemption if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); if(plr && !plr->isAlive()) // resurrect on exit { plr->ResurrectPlayer(1.0f); plr->SpawnCorpseBones(); } RemovePlayer(plr, guid); // BG subclass specific code if(plr) { plr->ClearAfkReports(); if(participant) // if the player was a match participant, remove auras, calc rating, update queue { if(!team) team = plr->GetTeam(); uint32 bgTypeId = GetTypeID(); uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID()); WorldPacket data; if(SendPacket) { sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg plr->RemoveBattleGroundQueueId(bgQueueTypeId); DecreaseInvitedCount(team); //we should update battleground queue, but only if bg isn't ending if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType()); Group * group = plr->GetGroup(); // remove from raid group if exist if(group && group == GetBgRaid(team)) { if(!group->RemoveMember(guid, 0)) // group was disbanded { SetBgRaid(team, NULL); delete group; } } // Let others know sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); SendPacketToTeam(team, &data, plr, false); } // Do next only if found in battleground plr->SetBattleGroundId(0); // We're not in BG. // reset destination bg team plr->SetBGTeam(0); if(Transport) { plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); } // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); } if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE)) { // if no players left AND no invitees left, set this bg to delete in next update // direct deletion could cause crashes m_SetDeleteThis = true; // return to prevent addition to freeslotqueue return; } // a player exited the battleground, so there are free slots. add to queue this->AddToBGFreeSlotQueue(); }