2023-10-03 17:23:56 +03:00
//===== Copyright <20> 1996-2006, Valve Corporation, All rights reserved. ======//
2020-04-22 12:56:21 -04:00
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
# include "cbase.h"
# include "team_control_point_master.h"
# include "teamplayroundbased_gamerules.h"
# include "team_control_point_round.h"
2023-10-03 17:23:56 +03:00
// NOTE: This has to be the last file included!
# include "tier0/memdbgon.h"
2020-04-22 12:56:21 -04:00
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 ( ) ;
2023-10-03 17:23:56 +03:00
if ( ( iWinners > = FIRST_GAME_TEAM ) & &
2020-04-22 12:56:21 -04:00
( iWinners ! = m_iInvalidCapWinner ) )
{
2023-10-03 17:23:56 +03:00
FireTeamWinOutput ( iWinners ) ;
return iWinners ;
2020-04-22 12:56:21 -04:00
}
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.
//-----------------------------------------------------------------------------
2022-03-01 23:00:42 +03:00
int CTeamControlPointRound : : TeamOwnsAllPoints ( CTeamControlPoint * pOverridePoint /* = NULL */ , int iOverrideNewTeam /* = TEAM_UNASSIGNED */ )
2020-04-22 12:56:21 -04:00
{
2023-10-03 17:23:56 +03:00
int iWinningTeam = TEAM_INVALID ;
2020-04-22 12:56:21 -04:00
2023-10-03 17:23:56 +03:00
// if TEAM_INVALID, haven't found a flag yet
// if TEAM_UNASSIGNED, it's still being contested
2020-04-22 12:56:21 -04:00
// for each control point
2023-10-03 17:23:56 +03:00
for ( int i = 0 ; i < m_ControlPoints . Count ( ) ; i + + )
2020-04-22 12:56:21 -04:00
{
int owner = m_ControlPoints [ i ] - > GetOwner ( ) ;
if ( pOverridePoint = = m_ControlPoints [ i ] )
{
owner = iOverrideNewTeam ;
}
2023-10-03 17:23:56 +03:00
// the first one we find, set the win to true
if ( iWinningTeam = = TEAM_INVALID )
2020-04-22 12:56:21 -04:00
{
2023-10-03 17:23:56 +03:00
iWinningTeam = owner ;
2020-04-22 12:56:21 -04:00
}
2023-10-03 17:23:56 +03:00
// unassigned means this is being contested, move on
else if ( iWinningTeam = = TEAM_UNASSIGNED )
2020-04-22 12:56:21 -04:00
{
continue ;
}
// if we find another one in the group that isn't the same owner, set the win to false
2023-10-03 17:23:56 +03:00
else if ( owner ! = iWinningTeam )
2020-04-22 12:56:21 -04:00
{
2023-10-03 17:23:56 +03:00
iWinningTeam = TEAM_UNASSIGNED ;
2020-04-22 12:56:21 -04:00
}
}
// report the first win we find as the winner
2023-10-03 17:23:56 +03:00
if ( iWinningTeam > = FIRST_GAME_TEAM )
2020-04-22 12:56:21 -04:00
{
2023-10-03 17:23:56 +03:00
return iWinningTeam ;
2020-04-22 12:56:21 -04:00
}
// 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 ( ( 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
2023-10-03 17:23:56 +03:00
for ( int i = FIRST_GAME_TEAM ; i < GetNumberOfTeams ( ) ; i + + )
2020-04-22 12:56:21 -04:00
{
2023-10-03 17:23:56 +03:00
for ( int j = 0 ; j < m_ControlPoints . Count ( ) ; j + + )
2020-04-22 12:56:21 -04:00
{
2023-10-03 17:23:56 +03:00
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
2020-04-22 12:56:21 -04:00
{
// need to find the trigger area associated with this point
2023-10-03 17:23:56 +03:00
CBaseEntity * pEnt = gEntList . FindEntityByClassname ( NULL , pMaster - > GetTriggerAreaCaptureName ( ) ) ;
while ( pEnt )
2020-04-22 12:56:21 -04:00
{
2023-10-03 17:23:56 +03:00
CTriggerAreaCapture * pArea = assert_cast < CTriggerAreaCapture * > ( pEnt ) ;
if ( pArea )
{
if ( pArea - > TeamCanCap ( i ) )
2020-04-22 12:56:21 -04:00
{
2023-10-03 17:23:56 +03:00
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 ;
}
2020-04-22 12:56:21 -04:00
}
}
2023-10-03 17:23:56 +03:00
pEnt = gEntList . FindEntityByClassname ( pEnt , pMaster - > GetTriggerAreaCaptureName ( ) ) ;
2020-04-22 12:56:21 -04:00
}
}
}
}
}
}
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 ;
}