//-----------------------------------------------------------------------------
// Purpose: Used by Area caps to set the owner
//-----------------------------------------------------------------------------
void CTeamControlPoint::InputSetOwner( inputdata_t &input )
{
	int iCapTeam = input.value.Int();

	Assert( iCapTeam >= 0 && iCapTeam < GetNumberOfTeams() );

	Assert( input.pCaller );

	if ( GetOwner() == iCapTeam )
		return;

	if ( TeamplayGameRules()->PointsMayBeCaptured() )
	{
		// must be done before setting the owner
		HandleScoring( iCapTeam );

		if ( input.pCaller->IsPlayer() )
		{
			int iCappingPlayer = input.pCaller->entindex();
			InternalSetOwner( iCapTeam, true, 1, &iCappingPlayer );
		}
		else
		{
			InternalSetOwner( iCapTeam, false );
		}

		ObjectiveResource()->SetOwningTeam( GetPointIndex(), m_iTeam );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTeamControlPoint::SetOwner( int iCapTeam, bool bMakeSound, int iNumCappers, int *pCappingPlayers )
{
	if ( TeamplayGameRules()->PointsMayBeCaptured() )
	{
		// must be done before setting the owner
		HandleScoring( iCapTeam );

		InternalSetOwner( iCapTeam, bMakeSound, iNumCappers, pCappingPlayers );
		ObjectiveResource()->SetOwningTeam( GetPointIndex(), m_iTeam );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTriggerAreaCapture::AreaTouch( CBaseEntity *pOther )
{
	if ( !IsActive() )
		return;
	if ( !PassesTriggerFilters(pOther) )
		return;

	// Don't cap areas unless the round is running
	if ( !TeamplayGameRules()->PointsMayBeCaptured() )
		return;

	Assert( m_iAreaIndex != -1 );

	// dont touch for non-alive or non-players
	if( !pOther->IsPlayer() || !pOther->IsAlive() )
		return;

	// make sure this point is in the round being played (if we're playing one)
	CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
	if ( pMaster && m_hPoint )
	{
		if ( !pMaster->IsInRound( m_hPoint ) )
		{
			return;
		}
	}

	if ( m_hPoint )
	{
		m_nOwningTeam = m_hPoint->GetOwner();
	}

	CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer(pOther);
	Assert( pPlayer );

	if ( pPlayer->GetTeamNumber() != m_nOwningTeam )
	{
		if ( m_TeamData[ pPlayer->GetTeamNumber() ].bCanCap )
		{
			DisplayCapHintTo( pPlayer );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Lock cap points when neither team can cap them for map-specific reasons
//-----------------------------------------------------------------------------
bool CControlPointIcon::IsPointLocked( void )
{
	bool bAnyTeamCanCap = false;
	for ( int gameteam = FIRST_GAME_TEAM; gameteam < GetNumberOfTeams(); gameteam++ )
	{
		// Ignore teams that already own the point
		if ( ObjectiveResource()->GetOwningTeam(m_iCPIndex) != gameteam )
		{
			if ( (ObjectiveResource()->TeamCanCapPoint( m_iCPIndex, gameteam)) )
			{
				if ( TeamplayGameRules()->TeamMayCapturePoint( gameteam, m_iCPIndex ) )
				{
					bAnyTeamCanCap = true;
				}
			}
		}
	}

	return ( !bAnyTeamCanCap );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CControlPointProgressBar::UpdateBarText( void )
{
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( !pPlayer || !m_pBarText || !m_pAttachedToIcon )
		return;

	m_pBarText->SetVisible( true );

	int iCP = m_pAttachedToIcon->GetCapIndex();
	int iCappingTeam = ObjectiveResource()->GetCappingTeam( iCP );
	int iPlayerTeam = pPlayer->GetTeamNumber();
	int iOwnerTeam = ObjectiveResource()->GetOwningTeam( iCP );

	m_pBarText->SetPos( XRES(25), YRES(20) );

	if ( !TeamplayGameRules()->PointsMayBeCaptured() )
	{
		m_pBarText->SetText( "#Team_Capture_NotNow" );
		return;
	}

	if ( mp_blockstyle.GetInt() == 1 && iCappingTeam != TEAM_UNASSIGNED && iCappingTeam != iPlayerTeam )
	{
		if ( ObjectiveResource()->IsCPBlocked(iCP) )
		{
			m_pBarText->SetText( "#Team_Blocking_Capture" );
			return;
		}
		else if ( iOwnerTeam == TEAM_UNASSIGNED )
		{
			m_pBarText->SetText( "#Team_Reverting_Capture" );
			return;
		}
	}

	if ( ObjectiveResource()->GetOwningTeam(iCP) == iPlayerTeam )
	{
		// If the opponents can never recapture this point back, we use a different string
		if ( iPlayerTeam != TEAM_UNASSIGNED )
		{
			int iEnemyTeam = ( iPlayerTeam == TF_TEAM_RED ) ? TF_TEAM_BLUE : TF_TEAM_RED;
			if ( !ObjectiveResource()->TeamCanCapPoint( iCP, iEnemyTeam ) )
			{
				m_pBarText->SetText( "#Team_Capture_Owned" );
				return;
			}
		}

		m_pBarText->SetText( "#Team_Capture_OwnPoint" );
		m_pBarText->SetPos( XRES(30), YRES(20) );
		return;
	}

	if ( !TeamplayGameRules()->TeamMayCapturePoint( iPlayerTeam, iCP ) )
	{
		if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->IsInArenaMode() == true )
		{
			m_pBarText->SetText( "#Team_Capture_NotNow" );
		}
		else
		{
			m_pBarText->SetText( "#Team_Capture_Linear" );
		}

		return;
	}

	char szReason[256];
	if ( !TeamplayGameRules()->PlayerMayCapturePoint( pPlayer, iCP, szReason, sizeof(szReason) ) )
	{
		m_pBarText->SetText( szReason );
		return;
	}

	bool bHaveRequiredPlayers = true;

	// In Capstyle 1, more players simply cap faster, no required amounts.
	if ( mp_capstyle.GetInt() != 1 )
	{
		int nNumTeammates = ObjectiveResource()->GetNumPlayersInArea( iCP, iPlayerTeam );
		int nRequiredTeammates = ObjectiveResource()->GetRequiredCappers( iCP, iPlayerTeam );
		bHaveRequiredPlayers = (nNumTeammates >= nRequiredTeammates);
	}

	if ( iCappingTeam == iPlayerTeam && bHaveRequiredPlayers )
	{
		m_pBarText->SetText( "#Team_Capture_Blocked" );
		return;
	}

	if ( !ObjectiveResource()->TeamCanCapPoint( iCP, iPlayerTeam ) )
	{
		m_pBarText->SetText( "#Team_Cannot_Capture" );
		return;
	}

	m_pBarText->SetText( "#Team_Waiting_for_teammate" );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTriggerAreaCapture::CaptureThink( void )
{
	SetNextThink( gpGlobals->curtime + AREA_THINK_TIME );

	// make sure this point is in the round being played (if we're playing one)
	CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
	if ( pMaster && m_hPoint )
	{
		if ( !pMaster->IsInRound( m_hPoint ) )
		{
			return;
		}
	}

	if ( !TeamplayGameRules()->PointsMayBeCaptured() )
	{
		// Points aren't allowed to be captured. If we were 
		// being captured, we need to clean up and reset.
		if ( m_bCapturing )
		{
			BreakCapture( false );
			UpdateNumPlayers();
		}
		return;
	}

	// go through our list of players
	Assert( GetNumberOfTeams() <= MAX_CAPTURE_TEAMS );
	int iNumPlayers[MAX_CAPTURE_TEAMS];
	int iNumBlockablePlayers[MAX_CAPTURE_TEAMS]; // Players in the zone who can't cap, but can block / pause caps
	CBaseMultiplayerPlayer *pFirstPlayerTouching[MAX_CAPTURE_TEAMS];
	for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ )
	{
		iNumPlayers[i] = 0;
		iNumBlockablePlayers[i] = 0;
		pFirstPlayerTouching[i] = NULL;
	}

	if ( m_hPoint )
	{
		// Loop through the entities we're touching, and find players
		for ( int i = 0; i < m_hTouchingEntities.Count(); i++ )
		{
			CBaseEntity *ent = m_hTouchingEntities[i];
			if ( ent && ent->IsPlayer() )
			{
				CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer(ent);
				if ( pPlayer->IsAlive() )
				{	
					int iTeam = pPlayer->GetTeamNumber();

					// If a team's not allowed to cap a point, don't count players in it at all
					if ( !TeamplayGameRules()->TeamMayCapturePoint( iTeam, m_hPoint->GetPointIndex() ) )
						continue;

					if ( !TeamplayGameRules()->PlayerMayCapturePoint( pPlayer, m_hPoint->GetPointIndex() ) )
					{
						if ( TeamplayGameRules()->PlayerMayBlockPoint( pPlayer, m_hPoint->GetPointIndex() ) )
						{
							if ( iNumPlayers[iTeam] == 0 && iNumBlockablePlayers[iTeam] == 0 )
							{
								pFirstPlayerTouching[iTeam] = pPlayer;
							}

							iNumBlockablePlayers[iTeam] += TeamplayGameRules()->GetCaptureValueForPlayer( pPlayer );
						}
						continue;
					}

					if ( iTeam >= FIRST_GAME_TEAM )
					{
						if ( iNumPlayers[iTeam] == 0 && iNumBlockablePlayers[iTeam] == 0 )
						{
							pFirstPlayerTouching[iTeam] = pPlayer;
						}

						iNumPlayers[iTeam] += TeamplayGameRules()->GetCaptureValueForPlayer( pPlayer );
					}
				}
			}
		}
	}

	int iTeamsInZone = 0;
	bool bUpdatePlayers = false;
	m_nTeamInZone = TEAM_UNASSIGNED;
	for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ )
	{
		iNumPlayers[i] *= mp_simulatemultiplecappers.GetInt();

		if ( m_TeamData[i].iNumTouching != iNumPlayers[i] )
		{
			m_TeamData[i].iNumTouching = iNumPlayers[i];
			bUpdatePlayers = true;
		}
		m_TeamData[i].iBlockedTouching = m_TeamData[i].iNumTouching;

		if ( m_TeamData[i].iNumTouching )
		{
			iTeamsInZone++;

			m_nTeamInZone = i;
		}
	}

	if ( iTeamsInZone > 1 )
	{
		m_nTeamInZone = TEAM_UNASSIGNED;
	}
	else
	{
		// If we've got non-cappable, yet blockable players here for the team that's defending, they 
		// need to block the cap. This catches cases like the TF invulnerability, which needs to block
		// caps, but isn't allowed to contribute to a cap.
		for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ )
		{
			if ( !iNumBlockablePlayers[i] || m_nTeamInZone == i )
				continue;

			iTeamsInZone++;
		}
	}

	UpdateTeamInZone();

	bool bBlocked = false;

	// If the cap is being blocked, reset the number of players so the client
	// knows to stop the capture as well.
	if ( mp_blockstyle.GetInt() == 1 )
	{
		if ( m_bCapturing && iTeamsInZone > 1 )
		{
			bBlocked = true;

			for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ )
			{
				iNumPlayers[i] = 0;
				if ( m_TeamData[i].iNumTouching != iNumPlayers[i] )
				{
					m_TeamData[i].iNumTouching = iNumPlayers[i];
					bUpdatePlayers = true;
				}
			}
		}
	}

	if ( bUpdatePlayers )
	{
		UpdateNumPlayers( bBlocked );
	}

	// When a player blocks, tell them the cap index and attempt number
	// only give successive blocks to them if the attempt number is different
	if ( m_bCapturing )
	{
		if ( m_hPoint )
		{
			m_hPoint->SetLastContestedAt( gpGlobals->curtime );
		}

		// Calculate the amount of modification to the cap time
		float flTimeDelta = gpGlobals->curtime - m_flLastReductionTime;

		float flReduction = flTimeDelta;
		if ( CaptureModeScalesWithPlayers() )
		{
			// Diminishing returns for successive players.
			for ( int i = 1; i < m_TeamData[m_nTeamInZone].iNumTouching; i++ )
			{
				flReduction += (flTimeDelta / (float)(i+1));
			}
		}
		m_flLastReductionTime = gpGlobals->curtime;

		//if more than one team is in the zone
		if( iTeamsInZone > 1 )
		{
			if ( !m_bBlocked )
			{
				m_bBlocked = true;
				UpdateBlocked();
			}

			// See if anyone gets credit for the block
			float flPercentToGo = m_fTimeRemaining / m_flCapTime;
			if ( CaptureModeScalesWithPlayers() )
			{
				flPercentToGo = m_fTimeRemaining / ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap);
			}

			if ( ( flPercentToGo <= 0.5 || TeamplayGameRules()->PointsMayAlwaysBeBlocked() ) && m_hPoint )
			{
				// find the first player that is not on the capturing team
				// they have just broken a cap and should be rewarded		
				// tell the player the capture attempt number, for checking later
				CBaseMultiplayerPlayer *pBlockingPlayer = NULL;
				for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ )
				{
					if ( m_nCapturingTeam == i )
						continue;

					if ( pFirstPlayerTouching[i] )
					{
						pBlockingPlayer = pFirstPlayerTouching[i];
						break;
					}
				}
				Assert( pBlockingPlayer );

				if ( pBlockingPlayer )
				{
					bool bRepeatBlocker = false;
					for ( int i = m_Blockers.Count()-1; i >= 0; i-- )
					{
						if ( m_Blockers[i].hPlayer != pBlockingPlayer )
							continue;

						// If this guy's was a blocker, but not valid now, remove him from the list
						if ( m_Blockers[i].iCapAttemptNumber != m_iCapAttemptNumber || !IsTouching(m_Blockers[i].hPlayer) ||
							 ( TeamplayGameRules()->PointsMayAlwaysBeBlocked() && m_Blockers[i].flNextBlockTime < gpGlobals->curtime && m_bStartTouch ) )
						{
							m_Blockers.Remove(i);
							continue;
						}

						bRepeatBlocker = true;
						break;
					}

					if ( !bRepeatBlocker )
					{
                        m_hPoint->CaptureBlocked( pBlockingPlayer );

						// Add this guy to our blocker list
						int iNew = m_Blockers.AddToTail();
						m_Blockers[iNew].hPlayer = pBlockingPlayer;
						m_Blockers[iNew].iCapAttemptNumber = m_iCapAttemptNumber;
						m_Blockers[iNew].flNextBlockTime = gpGlobals->curtime + 10.0f;
					}
				}
			}

			if ( mp_blockstyle.GetInt() == 0 )
			{
				BreakCapture( false );
			}
			return;
		}

		if ( m_bBlocked )
		{
			m_bBlocked = false;
			UpdateBlocked();
		}

		float flTotalTimeToCap = m_flCapTime;
		if ( CaptureModeScalesWithPlayers() )
		{
			flTotalTimeToCap = ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap);
		}

		// Now remove the reduction amount after we've determined there's only 1 team in the area
		if ( m_nCapturingTeam == m_nTeamInZone )
		{
			SetCapTimeRemaining( m_fTimeRemaining - flReduction );
		}
		else if ( m_nOwningTeam == TEAM_UNASSIGNED && m_nTeamInZone != TEAM_UNASSIGNED )
		{
			SetCapTimeRemaining( m_fTimeRemaining + flReduction );
		}
		else
		{
			// Caps deteriorate over time
			if ( TeamplayRoundBasedRules() && m_hPoint && TeamplayRoundBasedRules()->TeamMayCapturePoint(m_nCapturingTeam,m_hPoint->GetPointIndex()) )
			{
				float flDecreaseScale = CaptureModeScalesWithPlayers() ? mp_capdeteriorate_time.GetFloat() : flTotalTimeToCap;
				float flDecrease = (flTotalTimeToCap / flDecreaseScale) * flTimeDelta;
				if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->InOvertime() )
				{
					flDecrease *= 6;
				}
				SetCapTimeRemaining( m_fTimeRemaining + flDecrease );
			}
			else
			{
				SetCapTimeRemaining( flTotalTimeToCap );
			}
		}

		/*
		//if no-one is in the area
		if( iTeamsInZone == 0 )
		{
			BreakCapture( true );
			return;
		}
		
		//if they've lost the number of players needed to cap
		int iTeamMembersHere = m_TeamData[m_nCapturingTeam].iNumTouching + iNumBlockablePlayers[m_nCapturingTeam];
		if ( (iTeamMembersHere == 0 ) || (mp_capstyle.GetInt() == 0 && iTeamMembersHere < m_TeamData[m_nCapturingTeam].iNumRequiredToCap) )
		{
			BreakCapture( true );
			return;
		}
		*/

		// if the cap is done
		if ( m_fTimeRemaining <= 0 )
		{
			EndCapture( m_nCapturingTeam );
			return;		//we're done
		}
		else
		{
			// We may get several simultaneous CaptureThink calls from StartTouch if there are several players on the trigger 
			// when it is enabled (like in Raid mode). We haven't started reducing m_fTimeRemaining yet but the second call to CaptureThink
			// from StartTouch has m_bCapturing set to true and we hit this condition and call BreakCapture right away.
			// We put this check here to prevent calling BreakCapture from the StartTouch call to CaptureThink. If the capture should
			// really be broken it will happen the next time the trigger thinks on its own.
			if ( !m_bStartTouch )
			{
				if ( m_fTimeRemaining >= flTotalTimeToCap )
				{
					BreakCapture( false );
					return;
				}
			}
		}
	}
	else	
	{
		// If there are any teams in the zone that aren't the owner, try to start capping
		if ( iTeamsInZone > 0 )
		{
			for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ )
			{
				if ( !m_TeamData[i].bCanCap || m_nOwningTeam == i )
					continue;

				if ( m_TeamData[i].iNumTouching == 0 )
					continue;

				if ( m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToStartCap )
					continue;

				if ( !CaptureModeScalesWithPlayers() && m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToCap )
					continue;

				StartCapture( i, CAPTURE_NORMAL );
				break;
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTeamRoundTimer::RoundTimerThink( void )
{
	if ( TeamplayRoundBasedRules()->IsInPreMatch() == true && IsDisabled() == false )
	{
		inputdata_t data;
		InputDisable( data );
	}

	if ( IsDisabled() || m_bTimerPaused || IsInCommentaryMode() || gpGlobals->eLoadType == MapLoad_Background )
	{
		SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK );
		return;
	}

	// Don't do anything when the game has been won or if we're loading a bugbait report
	if ( TeamplayRoundBasedRules()->RoundHasBeenWon() ||
		 TeamplayRoundBasedRules()->IsLoadingBugBaitReport() )
	{
		// We want to stop timers when the round has been won, but we don't want to 
		// force mapmakers to deal with having to unpause it. This little hack works around that.
		if ( !m_bTimerPaused )
		{
			PauseTimer();
			m_bPauseDueToWin = true;
		}

		SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK );
		return;
	}
	else if ( m_bPauseDueToWin )
	{
		ResumeTimer();
		m_bPauseDueToWin = false;
	}

	float flTime = GetTimeRemaining();

	if ( flTime > 0 && ShowInHud() ) // is this the timer we're showing in the HUD?
	{
		TeamplayRoundBasedRules()->SetOvertime( false );
	}

	if ( flTime <= 0.0f && m_bFireFinished )
	{
		// Allow the gamerules to prevent timer expiration (i.e. while a control point is contested)
		if ( !TeamplayGameRules()->TimerMayExpire() )
		{
			// we don't want the timer to keep going (negative time)
			m_flTimerEndTime = gpGlobals->curtime;

			// is this the timer we're showing in the HUD?
			if ( ShowInHud() )
			{
				TeamplayRoundBasedRules()->SetOvertime( true );
			}

			// Think slower
			SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 1.0, ROUND_TIMER_THINK );
			return;
		}

		m_OnFinished.FireOutput( this, this );
		m_bFireFinished = false;
	}
	else if ( flTime <= 300.0 && m_bFire5MinRemain )
	{
		m_On5MinRemain.FireOutput( this, this );
		m_bFire5MinRemain = false;
	}
	else if ( flTime <= 240.0 && m_bFire4MinRemain )
	{
		m_On4MinRemain.FireOutput( this, this );
		m_bFire4MinRemain = false;
	}
	else if ( flTime <= 180.0 && m_bFire3MinRemain )
	{
		m_On3MinRemain.FireOutput( this, this );
		m_bFire3MinRemain = false;
	}
	else if ( flTime <= 120.0 && m_bFire2MinRemain )
	{
		m_On2MinRemain.FireOutput( this, this );
		m_bFire2MinRemain = false;
	}
	else if ( flTime <= 60.0 && m_bFire1MinRemain )
	{
		m_On1MinRemain.FireOutput( this, this );
		m_bFire1MinRemain = false;
	}
	else if ( flTime <= 30.0 && m_bFire30SecRemain )
	{
		m_On30SecRemain.FireOutput( this, this );
		m_bFire30SecRemain = false;
	}
	else if ( flTime <= 10.0 && m_bFire10SecRemain )
	{
		m_On10SecRemain.FireOutput( this, this );
		m_bFire10SecRemain = false;
	}
	else if ( flTime <= 5.0 && m_bFire5SecRemain )
	{
		m_On5SecRemain.FireOutput( this, this );
		m_bFire5SecRemain = false;
	}
	else if ( flTime <= 4.0 && m_bFire4SecRemain )
	{
		m_On4SecRemain.FireOutput( this, this );
		m_bFire4SecRemain = false;
	}
	else if ( flTime <= 3.0 && m_bFire3SecRemain )
	{
		m_On3SecRemain.FireOutput( this, this );
		m_bFire3SecRemain = false;
	}
	else if ( flTime <= 2.0 && m_bFire2SecRemain )
	{
		m_On2SecRemain.FireOutput( this, this );
		m_bFire2SecRemain = false;
	}
	else if ( flTime <= 1.0 && m_bFire1SecRemain )
	{
		m_On1SecRemain.FireOutput( this, this );
		m_bFire1SecRemain = false;
	}

	SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK );
}
//-----------------------------------------------------------------------------
// Purpose: Sets the new owner of the point, plays the appropriate sound and shows the right model
//-----------------------------------------------------------------------------
void CTeamControlPoint::InternalSetOwner( int iCapTeam, bool bMakeSound, int iNumCappers, int *pCappingPlayers )
{
	Assert( iCapTeam >= 0 && iCapTeam < GetNumberOfTeams() );

	int iOldTeam = m_iTeam;

	m_iTeam = iCapTeam;
	ChangeTeam( iCapTeam );

	if ( bMakeSound )
	{
		CBroadcastRecipientFilter filter;
		EmitSound( filter, entindex(), STRING( m_TeamData[m_iTeam].iszCapSound ) );
	}

	// Update visuals
	SetModel( STRING(m_TeamData[m_iTeam].iszModel) );
	SetBodygroup( 0, m_iTeam );
	m_nSkin = ( m_iTeam == TEAM_UNASSIGNED ) ? 2 : (m_iTeam - 2);
	ResetSequence( LookupSequence("idle") );

	// We add 1 to the index because we consider the default "no points capped" as 0.
	TeamplayGameRules()->SetLastCapPointChanged( m_iPointIndex+1 );

	// Determine the pose parameters for each team
	for ( int i = 0; i < m_TeamData.Count(); i++ )
	{
		// Skip spectator
		if ( i == TEAM_SPECTATOR )
			continue;

		if ( GetModelPtr() && GetModelPtr()->SequencesAvailable() )
		{
			m_TeamData[i].iTeamPoseParam = LookupPoseParameter( UTIL_VarArgs( "cappoint_%d_percentage", i ) );
		}
		else
		{
			m_TeamData[i].iTeamPoseParam = -1;
		}
	}
	UpdateCapPercentage();

	if ( m_iTeam == TEAM_UNASSIGNED )
	{
		m_OnCapReset.FireOutput( this, this );
	}
	else
	{
		// Remap team to get first game team = 1
		switch ( m_iTeam - FIRST_GAME_TEAM+1 )
		{
		case 1: 
			m_OnCapTeam1.FireOutput( this, this );
			break;
		case 2: 
			m_OnCapTeam2.FireOutput( this, this );
			break;
		default:
			Assert(0);
			break;
		}
	}

	// If we're playing a sound, this is a true cap by players.
	if ( bMakeSound )	
	{
		if ( iOldTeam > LAST_SHARED_TEAM && iOldTeam != m_iTeam )
		{
			// Make the members of our old team say something
			for ( int i = 1; i <= gpGlobals->maxClients; i++ )
			{
				CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( i ) );
				if ( !pPlayer )
					continue;
				if ( pPlayer->GetTeamNumber() == iOldTeam )
				{
					pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_LOST_CONTROL_POINT );
				}
			}
		}

		for( int i = 0; i < iNumCappers; i++ )
		{
			int playerIndex = pCappingPlayers[i];

			Assert( playerIndex > 0 && playerIndex <= gpGlobals->maxClients );

			PlayerCapped( ToBaseMultiplayerPlayer(UTIL_PlayerByIndex( playerIndex )) );
		}

		// Remap team to get first game team = 1
		switch ( m_iTeam - FIRST_GAME_TEAM+1 )
		{
		case 1: 
			m_OnOwnerChangedToTeam1.FireOutput( this, this );
			break;
		case 2: 
			m_OnOwnerChangedToTeam2.FireOutput( this, this );
			break;
		}

		if ( m_iTeam != TEAM_UNASSIGNED && iNumCappers )
		{
			SendCapString( m_iTeam, iNumCappers, pCappingPlayers );
		}
	}

	// Have control point master check the win conditions now!
	CBaseEntity *pEnt =	gEntList.FindEntityByClassname( NULL, GetControlPointMasterName() );

	while( pEnt )
	{
		CTeamControlPointMaster *pMaster = dynamic_cast<CTeamControlPointMaster *>( pEnt );

		if ( pMaster->IsActive() )
		{
			pMaster->CheckWinConditions();
		}

		pEnt = gEntList.FindEntityByClassname( pEnt, GetControlPointMasterName() );
	}
}