Esempio n. 1
0
//-----------------------------------------------------------------------------
// Purpose: Get a pointer to the specified team manager
//-----------------------------------------------------------------------------
CTeam *GetGlobalTeam( int iIndex )
{
	if ( iIndex < 0 || iIndex >= GetNumberOfTeams() )
		return NULL;

	return g_Teams[ iIndex ];
}
Esempio n. 2
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CTeamControlPoint::CTeamControlPoint()
{
	m_TeamData.SetSize( GetNumberOfTeams() );
	m_pCaptureInProgressSound = NULL;


}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTriggerAreaCapture::InputSetTeamCanCap( inputdata_t &inputdata )
{
	// Get the interaction name & target
	char parseString[255];
	Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString));

	char *pszParam = strtok(parseString," ");
	if ( pszParam && pszParam[0] )
	{
		int iTeam = atoi( pszParam );
		pszParam = strtok(NULL," ");

		if ( pszParam && pszParam[0] )
		{
			bool bCanCap = (atoi(pszParam) != 0);

			if ( iTeam >= 0 && iTeam < GetNumberOfTeams() )
			{
				m_TeamData[iTeam].bCanCap = bCanCap;
				if ( m_hPoint )
				{
					ObjectiveResource()->SetTeamCanCap( m_hPoint->GetPointIndex(), iTeam, m_TeamData[iTeam].bCanCap );
				}
				return;
			}
		}
	}

	Warning("%s(%s) received SetTeamCanCap input with invalid format. Format should be: <team number> <can cap (0/1)>.\n", GetClassname(), GetDebugName() );
}
//-----------------------------------------------------------------------------
// 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 CTriggerAreaCapture::InputRoundSpawn( inputdata_t &inputdata )
{
	// find the flag we're linked to
	if( !m_hPoint )
	{
		m_hPoint = dynamic_cast<CTeamControlPoint*>( gEntList.FindEntityByName(NULL, STRING(m_iszCapPointName) ) );

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

			for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ )
			{
				m_hPoint->SetCappersRequiredForTeam( i, m_TeamData[i].iNumRequiredToCap );

				ObjectiveResource()->SetCPRequiredCappers( m_hPoint->GetPointIndex(), i, m_TeamData[i].iNumRequiredToCap );
				ObjectiveResource()->SetTeamCanCap( m_hPoint->GetPointIndex(), i, m_TeamData[i].bCanCap );

				if ( CaptureModeScalesWithPlayers() )
				{
					ObjectiveResource()->SetCPCapTime( m_hPoint->GetPointIndex(), i, (m_flCapTime * 2) * m_TeamData[i].iNumRequiredToCap );
				}
				else
				{
					ObjectiveResource()->SetCPCapTime( m_hPoint->GetPointIndex(), i, m_flCapTime );
				}

				ObjectiveResource()->SetCPCapTimeScalesWithPlayers( m_hPoint->GetPointIndex(), CaptureModeScalesWithPlayers() );
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTeamplayRules::Precache( void )
{
	// Call the Team Manager's precaches
	for ( int i = 0; i < GetNumberOfTeams(); i++ )
	{
		CTeam *pTeam = GetGlobalTeam( i );
		pTeam->Precache();
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CTeamControlPoint::CTeamControlPoint()
{
	m_TeamData.SetSize( GetNumberOfTeams() );
	m_pCaptureInProgressSound = NULL;

#ifdef  TF_DLL
	UseClientSideAnimation();
#endif
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTeamControlPoint::Spawn( void )
{
	// Validate our default team
	if ( m_iDefaultOwner < 0 || m_iDefaultOwner >= GetNumberOfTeams() )
	{
		Warning( "team_control_point '%s' has bad point_default_owner.\n", GetDebugName() );
		m_iDefaultOwner = TEAM_UNASSIGNED;
	}

#ifdef TF_DLL
	if ( m_iszCaptureStartSound == NULL_STRING )
	{
		m_iszCaptureStartSound = AllocPooledString( "Hologram.Start" );
	}
	if ( m_iszCaptureEndSound == NULL_STRING )
	{
		m_iszCaptureEndSound = AllocPooledString( "Hologram.Stop" );
	}
	if ( m_iszCaptureInProgress == NULL_STRING )
	{
		m_iszCaptureInProgress = AllocPooledString( "Hologram.Move" );
	}
	if ( m_iszCaptureInterrupted == NULL_STRING )
	{
		m_iszCaptureInterrupted = AllocPooledString( "Hologram.Interrupted" );
	}
#endif

	Precache();

	InternalSetOwner( m_iDefaultOwner, false );	//init the owner of this point

	SetActive( !m_bStartDisabled );

	BaseClass::Spawn();

	SetPlaybackRate( 1.0 );
	SetThink( &CTeamControlPoint::AnimThink );
	SetNextThink( gpGlobals->curtime + 0.1f );

	if ( FBitSet( m_spawnflags, SF_CAP_POINT_HIDE_MODEL ) )
	{
		AddEffects( EF_NODRAW );
	}

	if ( FBitSet( m_spawnflags, SF_CAP_POINT_HIDE_SHADOW ) )
	{
		AddEffects( EF_NOSHADOW );
	}

	m_flLastContestedAt = -1;

	m_pCaptureInProgressSound = NULL;


}
Esempio n. 9
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CTeamControlPoint::CTeamControlPoint()
{
	m_TeamData.SetSize( GetNumberOfTeams() );
	m_pCaptureInProgressSound = NULL;

	m_bLocked = false;
	m_flUnlockTime = -1;

#if defined (TF_DLL) || defined (TF_CLASSIC)
	UseClientSideAnimation();
#endif
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CBaseTeamObjectiveResource::Spawn( void )
{
	m_iNumControlPoints = 0;

	// If you hit this, you've got too many teams for the control point system to handle.
	Assert( GetNumberOfTeams() < MAX_CONTROL_POINT_TEAMS );

	for ( int i=0; i < MAX_CONTROL_POINTS; i++ )
	{
		// data variables
		m_vCPPositions.Set( i, vec3_origin );
		m_bCPIsVisible.Set( i, true );
		m_bBlocked.Set( i, false );

		// state variables
		m_iOwner.Set( i, TEAM_UNASSIGNED );
		m_iCappingTeam.Set( i, TEAM_UNASSIGNED );
		m_iTeamInZone.Set( i, TEAM_UNASSIGNED );
		m_bInMiniRound.Set( i, true );
		m_bWarnOnCap.Set( i, false );
		m_flLazyCapPerc.Set( i, 0.0 );

		for ( int team = 0; team < MAX_CONTROL_POINT_TEAMS; team++ )
		{
			int iTeamIndex = TEAM_ARRAY( i, team );

			m_iTeamIcons.Set( iTeamIndex, 0 );
			m_iTeamOverlays.Set( iTeamIndex, 0 );
			m_iTeamReqCappers.Set( iTeamIndex, 0 );
			m_flTeamCapTime.Set( iTeamIndex, 0.0f );
			m_iNumTeamMembers.Set( TEAM_ARRAY( i, team ), 0 );
			for ( int ipoint = 0; ipoint < MAX_PREVIOUS_POINTS; ipoint++ )
			{
				int iIntIndex = ipoint + (i * MAX_PREVIOUS_POINTS) + (team * MAX_CONTROL_POINTS * MAX_PREVIOUS_POINTS);
				m_iPreviousPoints.Set( iIntIndex, -1 );
			}
			m_bTeamCanCap.Set( iTeamIndex, false );
		}
	}

	for ( int i = 0; i < MAX_TEAMS; i++ )
	{
		m_iBaseControlPoints.Set( i, -1 );
	}

	SetThink( &CBaseTeamObjectiveResource::ObjectiveThink );
	SetNextThink( gpGlobals->curtime + LAZY_UPDATE_TIME );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CTeamControlPointRound::MakePlayable( void )
{
	CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
	if ( pMaster )
	{
		if ( !IsPlayable() )
		{
			// we need to try switching the owners of the teams to make this round playable
			for ( int i = FIRST_GAME_TEAM ; i < GetNumberOfTeams() ; i++ )
			{
				for ( int j = 0 ; j < m_ControlPoints.Count() ; j++ )
				{
					if ( ( !pMaster->IsBaseControlPoint( m_ControlPoints[j]->GetPointIndex() ) ) && // this is NOT the base point for one of the teams (we don't want to assign the base to the wrong team)
						 ( !WouldNewCPOwnerWinGame( m_ControlPoints[j], i ) ) ) // making this change would make this round playable
					{
						// need to find the trigger area associated with this point
						CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, pMaster->GetTriggerAreaCaptureName() );
						while( pEnt )
						{
							CTriggerAreaCapture *pArea = assert_cast<CTriggerAreaCapture*>( pEnt );
							if ( pArea )
							{	
								if ( pArea->TeamCanCap( i ) )
								{
									CHandle<CTeamControlPoint> hPoint = pArea->GetControlPoint();
									if ( hPoint == m_ControlPoints[j] )
									{
										// found! 
										pArea->ForceOwner( i ); // this updates the trigger_area *and* the control_point
										return true;
									}
								}
							}

							pEnt = gEntList.FindEntityByClassname( pEnt, pMaster->GetTriggerAreaCaptureName() );
						}
					}
				}
			}
		}
	}

	return false;
}
//-----------------------------------------------------------------------------
// 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: 
//-----------------------------------------------------------------------------
bool CTeamControlPointRound::MakePlayable( void )
{
	CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
	if ( pMaster )
	{
		if ( !IsPlayable() )
		{
			// we need to try switching the owners of the teams to make this round playable
			for ( int iTeam = FIRST_GAME_TEAM ; iTeam < GetNumberOfTeams() ; iTeam++ )
			{
				for ( int iControlPoint = 0 ; iControlPoint < m_ControlPoints.Count() ; iControlPoint++ )
				{
					if ( ( !pMaster->IsBaseControlPoint( m_ControlPoints[iControlPoint]->GetPointIndex() ) ) && // this is NOT the base point for one of the teams (we don't want to assign the base to the wrong team)
						 ( !WouldNewCPOwnerWinGame( m_ControlPoints[iControlPoint], iTeam ) ) ) // making this change would make this round playable
					{
						// need to find the trigger area associated with this point
						for ( int iObj=0; iObj<ITriggerAreaCaptureAutoList::AutoList().Count(); ++iObj )
						{
							CTriggerAreaCapture *pArea = static_cast< CTriggerAreaCapture * >( ITriggerAreaCaptureAutoList::AutoList()[iObj] );	
							if ( pArea->TeamCanCap( iTeam ) )
							{
								CHandle<CTeamControlPoint> hPoint = pArea->GetControlPoint();
								if ( hPoint == m_ControlPoints[iControlPoint] )
								{
									// found! 
									pArea->ForceOwner( iTeam ); // this updates the trigger_area *and* the control_point
									return true;
								}
							}
						}
					}
				}
			}
		}
	}

	return false;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CTriggerAreaCapture::CTriggerAreaCapture()
{
	m_TeamData.SetSize( GetNumberOfTeams() );
	m_bStartTouch = false;
	m_hTrainWatcher = NULL;
}
//-----------------------------------------------------------------------------
// 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: 
//-----------------------------------------------------------------------------
CTriggerAreaCapture::CTriggerAreaCapture()
{
	m_TeamData.SetSize( GetNumberOfTeams() );
}
//-----------------------------------------------------------------------------
// 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() );
	}
}
Esempio n. 18
0
//-----------------------------------------------------------------------------
// Purpose: Checks to see if it's time to change controllers
//-----------------------------------------------------------------------------
void CControlZone::ReevaluateControllingTeam( void )
{
	// Count the number of players in each team
	int i;
	memset( m_iPlayersInZone, 0, sizeof( m_iPlayersInZone ) );
	for ( i = 0; i < m_ZonePlayerList.Size(); i++ )
	{
		if ( m_ZonePlayerList[i] != NULL && (m_ZonePlayerList[i]->GetTeamNumber() > 0) )
		{
			m_iPlayersInZone[ m_ZonePlayerList[i]->GetTeamNumber() ] += 1;
		}
	}

	// Abort immediately if we're not using touches to changes teams
	if ( HasSpawnFlags( CZF_DONT_USE_TOUCHES ) )
		return;

	// if we're locked in place, no changes can occur to controlling team except through an explicit map ResetTeam
	if ( m_iLocked )
		return;

	bool foundAnyTeam = false;
	int teamFound = 0;

	// check to see if any teams have no players
	for ( i = 1; i <= GetNumberOfTeams(); i++ )
	{
		if ( m_iPlayersInZone[i] )
		{
			if ( foundAnyTeam )
			{
				// we've already found a team, so it's being contested;
				teamFound = ZONE_CONTESTED;
				break;
			}

			foundAnyTeam = true;
			teamFound = i;			
		}
	}

	// no one in the area!
	if ( teamFound == 0 )
	{
		// just leave it as it is, let it continue to change team
		// exception: if the zone state is contested, and there aren't any players in the zone,
		// just return to the team who used to own the zone.
		if ( GetTeamNumber() == ZONE_CONTESTED )
		{
			ChangeTeam(m_iDefendingTeam);
			SetControllingTeam( this, m_iDefendingTeam );
		}

		return;
	}

	// if it's the same controlling team, don't worry about it
	if ( teamFound == GetTeamNumber() )
	{
		// the right team is in control, don't even think of switching
		m_iTryingToChangeToTeam = 0;
		SetNextThink( TICK_NEVER_THINK );
		return;
	}

	// Find out if the zone isn't owned by anyone at all (hasn't been touched since the map started, and it started un-owned)
	bool bHasBeenOwned = true;
	if ( m_iDefendingTeam == 0 && GetTeamNumber() == 0 ) 
		bHasBeenOwned = false;

	// if it's not contested, always go to contested mode 
	if ( GetTeamNumber() != ZONE_CONTESTED && teamFound != GetTeamNumber() )
	{
		// Unowned zones are captured immediately (no contesting stage)
		if ( bHasBeenOwned )
			teamFound = ZONE_CONTESTED;
	}

	// if it's the team we're trying to change to, don't worry about it
	if ( teamFound == m_iTryingToChangeToTeam )
		return;

	// set up the time to change to the new team soon
	m_iTryingToChangeToTeam = teamFound;

	// changing from contested->uncontested and visa-versa have different delays
	if ( m_iTryingToChangeToTeam != ZONE_CONTESTED )
	{
		if ( !bHasBeenOwned )
		{
			DevMsg( 1, "trigger_controlzone: (%s) changing team to %d NOW\n", GetDebugName(), m_iTryingToChangeToTeam );
			SetNextThink( gpGlobals->curtime + 0.1f );
		}
		else
		{
			DevMsg( 1, "trigger_controlzone: (%s) changing team to %d in %.2f seconds\n", GetDebugName(), m_iTryingToChangeToTeam, m_flTimeTillCaptured );
			SetNextThink( gpGlobals->curtime + m_flTimeTillCaptured );
		}
	}
	else
	{
		DevMsg( 1, "trigger_controlzone: (%s) changing to contested in %f seconds\n", GetDebugName(), m_flTimeTillContested );
		SetNextThink( gpGlobals->curtime + m_flTimeTillContested );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CBaseTeamObjectiveResource::Spawn( void )
{
	m_iNumControlPoints = 0;

	// If you hit this, you've got too many teams for the control point system to handle.
	Assert( GetNumberOfTeams() < MAX_CONTROL_POINT_TEAMS );

	for ( int i=0; i < MAX_CONTROL_POINTS; i++ )
	{
		// data variables
		m_vCPPositions.Set( i, vec3_origin );
		m_bCPIsVisible.Set( i, true );
		m_bBlocked.Set( i, false );

		// state variables
		m_iOwner.Set( i, TEAM_UNASSIGNED );
		m_iCappingTeam.Set( i, TEAM_UNASSIGNED );
		m_iTeamInZone.Set( i, TEAM_UNASSIGNED );
		m_bInMiniRound.Set( i, true );
		m_iWarnOnCap.Set( i, CP_WARN_NORMAL );
		m_iCPGroup.Set( i, TEAM_INVALID );
		m_flLazyCapPerc.Set( i, 0.0 );
		m_bCPLocked.Set( i, false );
		m_flUnlockTimes.Set( i, 0.0 );
		m_flCPTimerTimes.Set( i, -1.0 );
		m_bCPCapRateScalesWithPlayers.Set( i, true );

		for ( int team = 0; team < MAX_CONTROL_POINT_TEAMS; team++ )
		{
			int iTeamIndex = TEAM_ARRAY( i, team );

			m_iTeamIcons.Set( iTeamIndex, 0 );
			m_iTeamOverlays.Set( iTeamIndex, 0 );
			m_iTeamReqCappers.Set( iTeamIndex, 0 );
			m_flTeamCapTime.Set( iTeamIndex, 0.0f );
			m_iNumTeamMembers.Set( TEAM_ARRAY( i, team ), 0 );
			for ( int ipoint = 0; ipoint < MAX_PREVIOUS_POINTS; ipoint++ )
			{
				int iIntIndex = ipoint + (i * MAX_PREVIOUS_POINTS) + (team * MAX_CONTROL_POINTS * MAX_PREVIOUS_POINTS);
				m_iPreviousPoints.Set( iIntIndex, -1 );
			}
			m_bTeamCanCap.Set( iTeamIndex, false );
		}
	}

	for ( int i = 0; i < MAX_TEAMS; i++ )
	{
		m_iBaseControlPoints.Set( i, -1 );
	}

	int nNumEntriesPerTeam = TEAM_TRAIN_MAX_HILLS * TEAM_TRAIN_FLOATS_PER_HILL;
	for ( int i = 0; i < TEAM_TRAIN_MAX_TEAMS; i++ )
	{
		m_nNumNodeHillData.Set( i, 0 );
		m_bTrackAlarm.Set( i, false );

		int iStartingIndex = i * nNumEntriesPerTeam;
		for ( int j = 0 ; j < nNumEntriesPerTeam ; j++ )
		{
			m_flNodeHillData.Set( iStartingIndex + j, 0 );
		}

		iStartingIndex = i * TEAM_TRAIN_MAX_HILLS;
		for ( int j = 0; j < TEAM_TRAIN_MAX_HILLS; j++ )
		{
			m_bHillIsDownhill.Set( iStartingIndex + j, 0 );
		}
	}

	SetThink( &CBaseTeamObjectiveResource::ObjectiveThink );
	SetNextThink( gpGlobals->curtime + LAZY_UPDATE_TIME );
}
//-----------------------------------------------------------------------------
// Purpose: Add seconds to the timer while it is running or paused
//-----------------------------------------------------------------------------
void CTeamRoundTimer::AddTimerSeconds( int iSecondsToAdd, int iTeamResponsible /* = TEAM_UNASSIGNED*/ )
{
	if ( IsDisabled() )
		return;

	if ( TeamplayRoundBasedRules()->InStalemate() )
		return;

	// we only want to add time if we're round_running or team_win so the control points 
	// don't add time when they try to set their default owner when the map is first loading
	if ( TeamplayRoundBasedRules()->State_Get() != GR_STATE_RND_RUNNING && TeamplayRoundBasedRules()->State_Get() != GR_STATE_TEAM_WIN )
		return;

	if ( m_nTimerMaxLength > 0 )
	{
		// will adding this many seconds push us over our max length?
		if ( GetTimeRemaining() + iSecondsToAdd > m_nTimerMaxLength )
		{
			// adjust to only add up to our max length
			iSecondsToAdd = m_nTimerMaxLength - GetTimeRemaining();
		}
	}

	if ( m_bTimerPaused )
	{
		m_flTimeRemaining += (float)iSecondsToAdd;
	}
	else
	{
		m_flTimerEndTime += (float)iSecondsToAdd;
	}

	m_nTimerLength += iSecondsToAdd;
	CalculateOutputMessages();

	if ( ObjectiveResource() && ObjectiveResource()->GetTimerInHUD() == entindex() )
	{
		if ( !TeamplayRoundBasedRules()->InStalemate() && !TeamplayRoundBasedRules()->RoundHasBeenWon() )
		{
			if ( iTeamResponsible >= LAST_SHARED_TEAM+1 )
			{
				for ( int iTeam = LAST_SHARED_TEAM+1 ; iTeam < GetNumberOfTeams(); iTeam++ )
				{
					if ( iTeam == iTeamResponsible )
					{
						CTeamRecipientFilter filter( iTeam, true );
						EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED_WINNER );
					}
					else
					{
						CTeamRecipientFilter filter( iTeam, true );
						EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED_LOSER );
					}
				}
			}
			else
			{
				CReliableBroadcastRecipientFilter filter;
				EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED );
			}
		}

		// is this the timer we're showing in the HUD?
		if ( m_bShowInHUD )
		{
			IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_timer_time_added" );
			if ( event )
			{
				event->SetInt( "timer", entindex() );
				event->SetInt( "seconds_added", iSecondsToAdd );
				gameeventmanager->FireEvent( event );
			}
		}
	}
}