diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/server/team_control_point_round.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/server/team_control_point_round.cpp')
| -rw-r--r-- | mp/src/game/server/team_control_point_round.cpp | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/mp/src/game/server/team_control_point_round.cpp b/mp/src/game/server/team_control_point_round.cpp new file mode 100644 index 00000000..cc3d0cc7 --- /dev/null +++ b/mp/src/game/server/team_control_point_round.cpp @@ -0,0 +1,420 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#include "cbase.h"
+#include "team_control_point_master.h"
+#include "teamplayroundbased_gamerules.h"
+#include "team_control_point_round.h"
+
+#if defined ( TF_DLL )
+#include "tf_gamerules.h"
+#endif
+
+BEGIN_DATADESC( CTeamControlPointRound )
+ DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
+
+ DEFINE_KEYFIELD( m_iszCPNames, FIELD_STRING, "cpr_cp_names" ),
+ DEFINE_KEYFIELD( m_nPriority, FIELD_INTEGER, "cpr_priority" ),
+ DEFINE_KEYFIELD( m_iInvalidCapWinner, FIELD_INTEGER, "cpr_restrict_team_cap_win" ),
+ DEFINE_KEYFIELD( m_iszPrintName, FIELD_STRING, "cpr_printname" ),
+// DEFINE_FIELD( m_ControlPoints, CUtlVector < CHandle < CTeamControlPoint > > ),
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ),
+
+ DEFINE_OUTPUT( m_OnStart, "OnStart" ),
+ DEFINE_OUTPUT( m_OnEnd, "OnEnd" ),
+ DEFINE_OUTPUT( m_OnWonByTeam1, "OnWonByTeam1" ),
+ DEFINE_OUTPUT( m_OnWonByTeam2, "OnWonByTeam2" ),
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( team_control_point_round, CTeamControlPointRound );
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::Spawn( void )
+{
+ SetTouch( NULL );
+
+ BaseClass::Spawn();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::Activate( void )
+{
+ BaseClass::Activate();
+
+ FindControlPoints();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::FindControlPoints( void )
+{
+ // Let out control point masters know that the round has started
+ CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
+
+ if ( pMaster )
+ {
+ // go through all the points
+ CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, pMaster->GetControlPointName() );
+
+ while( pEnt )
+ {
+ CTeamControlPoint *pPoint = assert_cast<CTeamControlPoint *>(pEnt);
+
+ if ( pPoint )
+ {
+ const char *pString = STRING( m_iszCPNames );
+ const char *pName = STRING( pPoint->GetEntityName() );
+
+ // HACK to work around a problem with cp_a being returned for an entity name with cp_A
+ const char *pos = Q_stristr( pString, pName );
+ if ( pos )
+ {
+ int len = Q_strlen( STRING( pPoint->GetEntityName() ) );
+ if ( *(pos + len) == ' ' || *(pos + len) == '\0' )
+ {
+ if( m_ControlPoints.Find( pPoint ) == m_ControlPoints.InvalidIndex() )
+ {
+ DevMsg( 2, "Adding control point %s to control point round %s\n", pPoint->GetEntityName().ToCStr(), GetEntityName().ToCStr() );
+ m_ControlPoints.AddToHead( pPoint );
+ }
+ }
+ }
+ }
+
+ pEnt = gEntList.FindEntityByClassname( pEnt, pMaster->GetControlPointName() );
+ }
+ }
+
+ if( m_ControlPoints.Count() == 0 )
+ {
+ Warning( "Error! No control points found in map for team_game_round %s!\n", GetEntityName().ToCStr() );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Check that the points aren't all held by one team if they are
+// this will reset the round and will reset all the points
+//-----------------------------------------------------------------------------
+int CTeamControlPointRound::CheckWinConditions( void )
+{
+ int iWinners = TeamOwnsAllPoints();
+ if ( ( m_iInvalidCapWinner != 1 ) &&
+ ( iWinners >= FIRST_GAME_TEAM ) &&
+ ( iWinners != m_iInvalidCapWinner ) )
+ {
+ bool bWinner = true;
+
+#if defined( TF_DLL)
+ if ( TFGameRules() && TFGameRules()->IsInKothMode() )
+ {
+ CTeamRoundTimer *pTimer = NULL;
+ if ( iWinners == TF_TEAM_RED )
+ {
+ pTimer = TFGameRules()->GetRedKothRoundTimer();
+ }
+ else if ( iWinners == TF_TEAM_BLUE )
+ {
+ pTimer = TFGameRules()->GetBlueKothRoundTimer();
+ }
+
+ if ( pTimer )
+ {
+ if ( pTimer->GetTimeRemaining() > 0 || TFGameRules()->TimerMayExpire() == false )
+ {
+ bWinner = false;
+ }
+ }
+ }
+#endif
+ if ( bWinner )
+ {
+ FireTeamWinOutput( iWinners );
+ return iWinners;
+ }
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::FireTeamWinOutput( int iWinningTeam )
+{
+ // Remap team so that first game team = 1
+ switch( iWinningTeam - FIRST_GAME_TEAM+1 )
+ {
+ case 1:
+ m_OnWonByTeam1.FireOutput( this, this );
+ break;
+ case 2:
+ m_OnWonByTeam2.FireOutput( this, this );
+ break;
+ default:
+ Assert(0);
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CTeamControlPointRound::GetPointOwner( int point )
+{
+ Assert( point >= 0 );
+ Assert( point < MAX_CONTROL_POINTS );
+
+ CTeamControlPoint *pPoint = m_ControlPoints[point];
+
+ if ( pPoint )
+ return pPoint->GetOwner();
+
+ return TEAM_UNASSIGNED;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: This function returns the team that owns all the cap points.
+// If its not the case that one team owns them all, it returns 0.
+//
+// Can be passed an overriding team. If this is not null, the passed team
+// number will be used for that cp. Used to predict if that CP changing would
+// win the game.
+//-----------------------------------------------------------------------------
+int CTeamControlPointRound::TeamOwnsAllPoints( CTeamControlPoint *pOverridePoint /* = NULL */, int iOverrideNewTeam /* = TEAM_UNASSIGNED */ )
+{
+ int i;
+
+ int iWinningTeam[MAX_CONTROL_POINT_GROUPS];
+
+ for( i = 0 ; i < MAX_CONTROL_POINT_GROUPS ; i++ )
+ {
+ iWinningTeam[i] = TEAM_INVALID;
+ }
+
+ // if TEAM_INVALID, haven't found a flag for this group yet
+ // if TEAM_UNASSIGNED, the group is still being contested
+
+ // for each control point
+ for( i = 0 ; i < m_ControlPoints.Count() ; i++ )
+ {
+ int group = m_ControlPoints[i]->GetCPGroup();
+ int owner = m_ControlPoints[i]->GetOwner();
+
+ if ( pOverridePoint == m_ControlPoints[i] )
+ {
+ owner = iOverrideNewTeam;
+ }
+
+ // the first one we find in this group, set the win to true
+ if ( iWinningTeam[group] == TEAM_INVALID )
+ {
+ iWinningTeam[group] = owner;
+ }
+ // unassigned means this group is already contested, move on
+ else if ( iWinningTeam[group] == TEAM_UNASSIGNED )
+ {
+ continue;
+ }
+ // if we find another one in the group that isn't the same owner, set the win to false
+ else if ( owner != iWinningTeam[group] )
+ {
+ iWinningTeam[group] = TEAM_UNASSIGNED;
+ }
+ }
+
+ // report the first win we find as the winner
+ for ( i = 0 ; i < MAX_CONTROL_POINT_GROUPS ; i++ )
+ {
+ if ( iWinningTeam[i] >= FIRST_GAME_TEAM )
+ return iWinningTeam[i];
+ }
+
+ // no wins yet
+ return TEAM_UNASSIGNED;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTeamControlPointRound::WouldNewCPOwnerWinGame( CTeamControlPoint *pPoint, int iNewOwner )
+{
+ return ( TeamOwnsAllPoints( pPoint, iNewOwner ) == iNewOwner );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::InputEnable( inputdata_t &input )
+{
+ m_bDisabled = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::InputDisable( inputdata_t &input )
+{
+ m_bDisabled = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::InputRoundSpawn( inputdata_t &input )
+{
+ // clear out old control points
+ m_ControlPoints.RemoveAll();
+
+ // find the control points
+ FindControlPoints();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::SetupSpawnPoints( void )
+{
+ CTeamplayRoundBasedRules *pRules = TeamplayRoundBasedRules();
+
+ if ( pRules )
+ {
+ pRules->SetupSpawnPointsForRound();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::SelectedToPlay( void )
+{
+ SetupSpawnPoints();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::FireOnStartOutput( void )
+{
+ m_OnStart.FireOutput( this, this );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTeamControlPointRound::FireOnEndOutput( void )
+{
+ m_OnEnd.FireOutput( this, this );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTeamControlPointRound::IsControlPointInRound( CTeamControlPoint *pPoint )
+{
+ if ( !pPoint )
+ {
+ return false;
+ }
+
+ return ( m_ControlPoints.Find( pPoint ) != m_ControlPoints.InvalidIndex() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTeamControlPointRound::IsPlayable( void )
+{
+ int iWinners = TeamOwnsAllPoints();
+
+ if ( m_iInvalidCapWinner == 1 ) // neither team can win this round by capping
+ {
+ return true;
+ }
+
+ if ( ( iWinners >= FIRST_GAME_TEAM ) &&
+ ( iWinners != m_iInvalidCapWinner ) )
+ {
+ return false; // someone has already won this round
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// 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: returns the first point found that the given team owns
+//-----------------------------------------------------------------------------
+CHandle<CTeamControlPoint> CTeamControlPointRound::GetPointOwnedBy( int iTeam )
+{
+ for( int i = 0 ; i < m_ControlPoints.Count() ; i++ )
+ {
+ if ( m_ControlPoints[i]->GetOwner() == iTeam )
+ {
+ return m_ControlPoints[i];
+ }
+ }
+
+ return NULL;
+}
|