Esempio n. 1
0
void BattleGround::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool SendPacket)
{
    Team team = GetPlayerTeam(guid);
    bool participant = false;
    // Remove from lists/maps
    BattleGroundPlayerMap::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;
    }

    BattleGroundScoreMap::iterator itr2 = m_PlayerScores.find(guid);
    if (itr2 != m_PlayerScores.end())
    {
        delete itr2->second;                                // delete player's score
        m_PlayerScores.erase(itr2);
    }

    Player* plr = sObjectMgr.GetPlayer(guid);

    if (plr)
    {
        // should remove spirit of redemption
        if (plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
            plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);

        if (!plr->isAlive())                                // resurrect on exit
        {
            plr->ResurrectPlayer(1.0f);
            plr->SpawnCorpseBones();
        }
    }

    RemovePlayer(plr, guid);                                // BG subclass specific code

    if (participant) // if the player was a match participant, remove auras, calc rating, update queue
    {
        BattleGroundTypeId bgTypeId = GetTypeID();
        BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID());
        if (plr)
        {
            if (!team) team = plr->GetTeam();

            if (SendPacket)
            {
                WorldPacket data;
                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, 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);
        }

        // remove from raid group if player is member
        if (Group* group = GetBgRaid(team))
        {
            if (!group->RemoveMember(guid, 0))              // group was disbanded
            {
                SetBgRaid(team, NULL);
                delete group;
            }
        }
        DecreaseInvitedCount(team);
        // we should update battleground queue, but only if bg isn't ending
        if (GetStatus() < STATUS_WAIT_LEAVE)
        {
            // a player has left the battleground, so there are free slots -> add to queue
            AddToBGFreeSlotQueue();
            sBattleGroundMgr.ScheduleQueueUpdate(bgQueueTypeId, bgTypeId, GetBracketId());
        }

        // Let others know
        WorldPacket data;
        sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, guid);
        SendPacketToTeam(team, &data, plr, false);
    }

    if (plr)
    {
        // Do next only if found in battleground
        plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE);  // We're not in BG.
        // reset destination bg team
        plr->SetBGTeam(TEAM_NONE);

        if (Transport)
            plr->TeleportToBGEntryPoint();

        DETAIL_LOG("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName());
    }

    // battleground object will be deleted next BattleGround::Update() call
}
Esempio n. 2
0
//remove player from queue and from group info, if group info is empty then remove it too
void BattlegroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
{
    int32 bracket_id = -1;                                     // signed for proper for-loop finish
    QueuedPlayersMap::iterator itr;

    //remove player from map, if he's there
    itr = m_QueuedPlayers.find(guid);
    if (itr == m_QueuedPlayers.end())
    {
        std::string playerName = "Unknown";
        if (Player* player = ObjectAccessor::FindPlayer(guid))
            playerName = player->GetName();
        TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: couldn't find player %s (GUID: %u)", playerName.c_str(), GUID_LOPART(guid));
        return;
    }

    GroupQueueInfo* group = itr->second.GroupInfo;
    GroupsQueueType::iterator group_itr;
    // mostly people with the highest levels are in battlegrounds, thats why
    // we count from MAX_BATTLEGROUND_QUEUES - 1 to 0

    uint32 index = (group->Team == HORDE) ? BG_QUEUE_PREMADE_HORDE : BG_QUEUE_PREMADE_ALLIANCE;

    for (int32 bracket_id_tmp = MAX_BATTLEGROUND_BRACKETS - 1; bracket_id_tmp >= 0 && bracket_id == -1; --bracket_id_tmp)
    {
        //we must check premade and normal team's queue - because when players from premade are joining bg,
        //they leave groupinfo so we can't use its players size to find out index
        for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT; j += BG_TEAMS_COUNT)
        {
            GroupsQueueType::iterator k = m_QueuedGroups[bracket_id_tmp][j].begin();
            for (; k != m_QueuedGroups[bracket_id_tmp][j].end(); ++k)
            {
                if ((*k) == group)
                {
                    bracket_id = bracket_id_tmp;
                    group_itr = k;
                    //we must store index to be able to erase iterator
                    index = j;
                    break;
                }
            }
        }
    }

    //player can't be in queue without group, but just in case
    if (bracket_id == -1)
    {
        TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: ERROR Cannot find groupinfo for player GUID: %u", GUID_LOPART(guid));
        return;
    }
    TC_LOG_DEBUG("bg.battleground", "BattlegroundQueue: Removing player GUID %u, from bracket_id %u", GUID_LOPART(guid), (uint32)bracket_id);

    // ALL variables are correctly set
    // We can ignore leveling up in queue - it should not cause crash
    // remove player from group
    // if only one player there, remove group

    // remove player queue info from group queue info
    std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid);
    if (pitr != group->Players.end())
        group->Players.erase(pitr);

    // if invited to bg, and should decrease invited count, then do it
    if (decreaseInvitedCount && group->IsInvitedToBGInstanceGUID)
        if (Battleground* bg = sBattlegroundMgr->GetBattleground(group->IsInvitedToBGInstanceGUID, group->BgTypeId))
            bg->DecreaseInvitedCount(group->Team);

    // remove player queue info
    m_QueuedPlayers.erase(itr);

    // announce to world if arena team left queue for rated match, show only once
    if (group->ArenaType && group->IsRated && group->Players.empty() && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
        if (ArenaTeam* Team = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
            sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, Team->GetName().c_str(), group->ArenaType, group->ArenaType, group->ArenaTeamRating);

    // if player leaves queue and he is invited to rated arena match, then he have to lose
    if (group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount)
    {
        if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
        {
            TC_LOG_DEBUG("bg.battleground", "UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(guid), group->OpponentsTeamRating);
            if (Player* player = ObjectAccessor::FindPlayer(guid))
                at->MemberLost(player, group->OpponentsMatchmakerRating);
            else
                at->OfflineMemberLost(guid, group->OpponentsMatchmakerRating);
            at->SaveToDB();
        }
    }

    // remove group queue info if needed
    if (group->Players.empty())
    {
        m_QueuedGroups[bracket_id][index].erase(group_itr);
        delete group;
        return;
    }

    // if group wasn't empty, so it wasn't deleted, and player have left a rated
    // queue -> everyone from the group should leave too
    // don't remove recursively if already invited to bg!
    if (!group->IsInvitedToBGInstanceGUID && group->IsRated)
    {
        // remove next player, this is recursive
        // first send removal information
        if (Player* plr2 = ObjectAccessor::FindPlayer(group->Players.begin()->first))
        {
            Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(group->BgTypeId);
            BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType);
            uint32 queueSlot = plr2->GetBattlegroundQueueIndex(bgQueueTypeId);

            plr2->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to
                                                            // queue->removeplayer, it causes bugs
            WorldPacket data;
            sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, plr2, queueSlot, STATUS_NONE, plr2->GetBattlegroundQueueJoinTime(group->BgTypeId), 0, 0);
            plr2->GetSession()->SendPacket(&data);
        }
        // then actually delete, this may delete the group as well!
        RemovePlayer(group->Players.begin()->first, decreaseInvitedCount);
    }
}
Esempio n. 3
0
void ArathiBasin::HookOnAreaTrigger(Player* plr, uint32 id)
{
    uint32 spellid = 0;
    int32 buffslot = -1;
    switch(id)
    {
    case 3866:			// stables
        buffslot = AB_BUFF_STABLES;
        break;

    case 3867:			// farm
        buffslot = AB_BUFF_FARM;
        break;

    case 3870:			// blacksmith
        buffslot = AB_BUFF_BLACKSMITH;
        break;

    case 3869:			// mine
        buffslot = AB_BUFF_MINE;
        break;

    case 3868:			// lumbermill
        buffslot = AB_BUFF_LUMBERMILL;
        break;

    case 3948:			// alliance/horde exits
    case 3949:
    {
        RemovePlayer(plr, false);
        return;
    }
    break;
    case 4020:			// Trollbane Hall
    case 4021:			// Defiler's Den
        return;
        break;
    default:
        sLog.Error("ArathiBasin", "Encountered unhandled areatrigger id %u", id);
        return;
        break;
    }

    if(plr->IsDead())		// don't apply to dead players... :P
        return;

    uint32 x = (uint32)buffslot;
    if(m_buffs[x] && m_buffs[x]->IsInWorld())
    {
        // apply the spell
        spellid = m_buffs[x]->GetInfo()->sound3;
        m_buffs[x]->RemoveFromWorld(false);

        // respawn it in buffrespawntime
        sEventMgr.AddEvent(this, &ArathiBasin::SpawnBuff, x, EVENT_AB_RESPAWN_BUFF, AB_BUFF_RESPAWN_TIME, 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);

        // cast the spell on the player
        SpellEntry* sp = dbcSpell.LookupEntryForced(spellid);
        if(sp)
        {
            Spell* pSpell = sSpellFactoryMgr.NewSpell(plr, sp, true, NULL);
            SpellCastTargets targets(plr->GetGUID());
            pSpell->prepare(&targets);
        }
    }
}
Esempio n. 4
0
void ArathiBasin::AssaultControlPoint(Player* pPlayer, uint32 Id)
{
#ifdef ANTI_CHEAT
    if(!m_started)
    {
        Anticheat_Log->writefromsession(pPlayer->GetSession(), "%s tried to assault control point in arathi basin before battleground (ID %u) started.", pPlayer->GetName(), this->m_id);
        SendChatMessage(CHAT_MSG_BG_EVENT_NEUTRAL, pPlayer->GetGUID(), "%s will be removed from the game for cheating.", pPlayer->GetName());
        // Remove player from battleground.
        RemovePlayer(pPlayer, false);
        // Kick player from server.
        pPlayer->Kick(6000);
        return;
    }
#endif

    uint32 Team = pPlayer->m_bgTeam;
    uint32 Owner;

    pPlayer->m_bgScore.MiscData[BG_SCORE_AB_BASES_ASSAULTED]++;

    if(m_basesOwnedBy[Id] == -1 && m_basesAssaultedBy[Id] == -1)
    {
        // omgwtfbbq our flag is a virgin?
        SetWorldState(NeutralFields[Id], 0);
    }

    if(m_basesOwnedBy[Id] != -1)
    {
        Owner = m_basesOwnedBy[Id];

        // set it to uncontrolled for now
        m_basesOwnedBy[Id] = -1;
        m_basesLastOwnedBy[Id] = Owner;

        // this control point just got taken over by someone! oh noes!
        if(m_spiritGuides[Id] != NULL)
        {
            map<Creature*, set<uint32> >::iterator itr = m_resurrectMap.find(m_spiritGuides[Id]);
            if(itr != m_resurrectMap.end())
            {
                for(set<uint32>::iterator it2 = itr->second.begin(); it2 != itr->second.end(); ++it2)
                {
                    Player* r_plr = m_mapMgr->GetPlayer(*it2);
                    if(r_plr != NULL && r_plr->IsDead())
                        HookHandleRepop(r_plr);
                }
            }
            m_resurrectMap.erase(itr);
            m_spiritGuides[Id]->Despawn(0, 0);
            m_spiritGuides[Id] = NULL;
        }

        // detract one from the teams controlled points
        m_capturedBases[Owner] -= 1;
        SetWorldState(Owner ? WORLDSTATE_AB_HORDE_CAPTUREBASE : WORLDSTATE_AB_ALLIANCE_CAPTUREBASE, m_capturedBases[Owner]);

        // reset the world states
        SetWorldState(OwnedFields[Id][Owner], 0);

        // modify the resource update time period
        if(m_capturedBases[Owner] == 0)
            this->event_RemoveEvents(EVENT_AB_RESOURCES_UPDATE_TEAM_0 + Owner);
        else
            this->event_ModifyTime(EVENT_AB_RESOURCES_UPDATE_TEAM_0 + Owner, ResourceUpdateIntervals[m_capturedBases[Owner]]);
    }

    // n***a stole my flag!
    if(m_basesAssaultedBy[Id] != -1)
    {
        Owner = m_basesAssaultedBy[Id];

        // woah! vehicle hijack!
        m_basesAssaultedBy[Id] = -1;
        SetWorldState(AssaultFields[Id][Owner], 0);

        // make sure the event does not trigger
        sEventMgr.RemoveEvents(this, EVENT_AB_CAPTURE_CP_1 + Id);
        if(m_basesLastOwnedBy[Id] == (int32)Team)
        {
            m_basesAssaultedBy[Id] = (int32)Team;
            CaptureControlPoint(Id, Team);
            return;
        }

        // no need to remove the spawn, SpawnControlPoint will do this.
    }

    m_basesAssaultedBy[Id] = Team;

    // spawn the new control point gameobject
    SpawnControlPoint(Id, Team ? AB_SPAWN_TYPE_HORDE_ASSAULT : AB_SPAWN_TYPE_ALLIANCE_ASSAULT);

    // update the client's map with the new assaulting field
    SetWorldState(AssaultFields[Id][Team], 1);

    // Check Assault/Defense, the time of capture is not the same.
    if(DefFlag[Id][0] && !DefFlag[Id][1])
    {
        DefFlag[Id][0] = false;
        SendChatMessage(Team ? CHAT_MSG_BG_EVENT_HORDE : CHAT_MSG_BG_EVENT_ALLIANCE, pPlayer->GetGUID(), "$N defend %s", ControlPointNames[Id]);
        sEventMgr.AddEvent(this, &ArathiBasin::CaptureControlPoint, Id, Team, EVENT_AB_CAPTURE_CP_1 + Id, 1000, 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);
        pPlayer->m_bgScore.MiscData[BG_SCORE_AB_BASES_CAPTURED]++;
        UpdatePvPData();
    }
    else if(!DefFlag[Id][0] && !DefFlag[Id][1])
    {
        DefFlag[Id][0] = true;
        SendChatMessage(Team ? CHAT_MSG_BG_EVENT_HORDE : CHAT_MSG_BG_EVENT_ALLIANCE, pPlayer->GetGUID(), "$N assault %s !", ControlPointNames[Id]);
        PlaySoundToAll(Team ? 8212 : 8174);
        if(Team)
        {
            QuestLogEntry* en = pPlayer->GetQuestLogForEntry(8120);
            switch(Id)
            {
            case AB_CONTROL_POINT_MINE:
            {
                if(en && en->GetMobCount(0) < en->GetQuest()->required_mobcount[0])
                {
                    en->SetMobCount(0, en->GetMobCount(0) + 1);
                    en->SendUpdateAddKill(0);
                    en->UpdatePlayerFields();
                }
            }
            break;
            case AB_CONTROL_POINT_LUMBERMILL:
            {
                if(en && en->GetMobCount(1) < en->GetQuest()->required_mobcount[1])
                {
                    en->SetMobCount(1, en->GetMobCount(1) + 1);
                    en->SendUpdateAddKill(1);
                    en->UpdatePlayerFields();
                }
            }
            break;
            case AB_CONTROL_POINT_BLACKSMITH:
            {
                if(en && en->GetMobCount(2) < en->GetQuest()->required_mobcount[2])
                {
                    en->SetMobCount(2, en->GetMobCount(2) + 1);
                    en->SendUpdateAddKill(2);
                    en->UpdatePlayerFields();
                }
            }
            break;
            case AB_CONTROL_POINT_STABLE:
            {
                if(en && en->GetMobCount(3) < en->GetQuest()->required_mobcount[3])
                {
                    en->SetMobCount(3, en->GetMobCount(3) + 1);
                    en->SendUpdateAddKill(3);
                    en->UpdatePlayerFields();
                }
            }
            break;
            }
        }
        else
        {
            QuestLogEntry* en = pPlayer->GetQuestLogForEntry(8105);
            switch(Id)
            {
            case AB_CONTROL_POINT_MINE:
            {
                if(en && en->GetMobCount(0) < en->GetQuest()->required_mobcount[0])
                {
                    en->SetMobCount(0, en->GetMobCount(0) + 1);
                    en->SendUpdateAddKill(0);
                    en->UpdatePlayerFields();
                }
            }
            break;
            case AB_CONTROL_POINT_LUMBERMILL:
            {
                if(en && en->GetMobCount(1) < en->GetQuest()->required_mobcount[1])
                {
                    en->SetMobCount(1, en->GetMobCount(1) + 1);
                    en->SendUpdateAddKill(1);
                    en->UpdatePlayerFields();
                }
            }
            break;
            case AB_CONTROL_POINT_BLACKSMITH:
            {
                if(en && en->GetMobCount(2) < en->GetQuest()->required_mobcount[2])
                {
                    en->SetMobCount(2, en->GetMobCount(2) + 1);
                    en->SendUpdateAddKill(2);
                    en->UpdatePlayerFields();
                }
            }
            break;
            case AB_CONTROL_POINT_FARM:
            {
                if(en && en->GetMobCount(3) < en->GetQuest()->required_mobcount[3])
                {
                    en->SetMobCount(3, en->GetMobCount(3) + 1);
                    en->SendUpdateAddKill(3);
                    en->UpdatePlayerFields();
                }
            }
            break;
            }
        }
        sEventMgr.AddEvent(this, &ArathiBasin::CaptureControlPoint, Id, Team, EVENT_AB_CAPTURE_CP_1 + Id, MSTIME_MINUTE, 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);
        pPlayer->m_bgScore.MiscData[BG_SCORE_AB_BASES_ASSAULTED]++;
        UpdatePvPData();
    }
    else
    {
        DefFlag[Id][0] = true;
        SendChatMessage(Team ? CHAT_MSG_BG_EVENT_HORDE : CHAT_MSG_BG_EVENT_ALLIANCE, pPlayer->GetGUID(), "$N claims the %s! If left unchallenged, the %s will control it in 1 minute!", ControlPointNames[Id],
                        Team ? "Horde" : "Alliance");
        PlaySoundToAll(8192);
        sEventMgr.AddEvent(this, &ArathiBasin::CaptureControlPoint, Id, Team, EVENT_AB_CAPTURE_CP_1 + Id, MSTIME_MINUTE, 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);
    }
}
Esempio n. 5
0
BOOL IncomingPlayerManager::ProcessInputs( )
{
__ENTER_FUNCTION

	BOOL ret = FALSE ;

	if (m_MinFD == INVALID_SOCKET && m_MaxFD == INVALID_SOCKET) // no player exist
	{ 
		return TRUE ;
	}

	//新连接接入:
	if( FD_ISSET(m_SocketID,&m_ReadFDs[SELECT_USE]) )
	{
		for( INT i=0; i<ACCEPT_ONESTEP; i++ )
		{
			if( !AcceptNewConnection() )
				break;
		}
	}

	//数据读取
	uint nPlayerCount = GetPlayerNumber() ;
	for( uint i=0; i<nPlayerCount; i++ )
	{
		if( m_pPlayers[i]==INVALID_ID )
			continue ;

		GamePlayer* pPlayer = g_pPlayerPool->GetPlayer(m_pPlayers[i]) ;
		Assert( pPlayer ) ;

		SOCKET s = pPlayer->GetSocket()->getSOCKET() ;
		if( s == m_SocketID )
			continue ;

		if( FD_ISSET( s, &m_ReadFDs[SELECT_USE] ) )
		{
			if( pPlayer->GetSocket()->isSockError() )
			{//连接出现错误
				RemovePlayer( pPlayer ) ;
			}
			else
			{//连接正常
				_MY_TRY
				{
					ret = pPlayer->ProcessInput( ) ;
					if( !ret )
					{
						RemovePlayer( pPlayer ) ;
					}
				}
				_MY_CATCH
				{
					SaveCodeLog( ) ;
					RemovePlayer( pPlayer ) ;
				}
			}
		}
	}


	return TRUE ;

__LEAVE_FUNCTION

	return FALSE ;
}