summaryrefslogtreecommitdiff
path: root/game/server/dod/dod_control_point_master.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/dod/dod_control_point_master.cpp')
-rw-r--r--game/server/dod/dod_control_point_master.cpp587
1 files changed, 587 insertions, 0 deletions
diff --git a/game/server/dod/dod_control_point_master.cpp b/game/server/dod/dod_control_point_master.cpp
new file mode 100644
index 0000000..b511ef5
--- /dev/null
+++ b/game/server/dod/dod_control_point_master.cpp
@@ -0,0 +1,587 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "dod_control_point_master.h"
+
+BEGIN_DATADESC( CControlPointMaster )
+ DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
+
+ DEFINE_KEYFIELD( m_iTimerLength, FIELD_INTEGER, "cpm_timer_length" ),
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "RoundInit", InputRoundInit ),
+
+ DEFINE_FUNCTION( CPMThink ),
+
+ DEFINE_OUTPUT( m_AlliesWinOutput, "OnAlliesWin" ),
+ DEFINE_OUTPUT( m_AxisWinOutput, "OnAxisWin" ),
+
+ DEFINE_INPUTFUNC( FIELD_INTEGER, "AddTimerSeconds", InputAddTimerSeconds ),
+
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( dod_control_point_master, CControlPointMaster );
+
+CControlPointMaster::CControlPointMaster()
+{
+ m_bUseTimer = false;
+ m_iTimerTeam = TEAM_UNASSIGNED;
+
+ SetDefLessFunc( m_ControlPoints );
+}
+
+void CControlPointMaster::Spawn( void )
+{
+ SetTouch( NULL );
+ m_bFoundPoints = false;
+ BaseClass::Spawn();
+}
+
+ConVar mp_tickpointinterval( "mp_tickpointinterval", "30", FCVAR_GAMEDLL, "Delay between point gives.", true, 1, false, 0 );
+
+void CControlPointMaster::RoundRespawn( void )
+{
+ m_fGivePointsTime = gpGlobals->curtime + mp_tickpointinterval.GetInt();
+}
+
+
+// KeyValue
+// ========
+// this function interfaces with the keyvalues set by the mapper
+//
+// Values
+// point_give_delay_time - how often to give time based points ( seconds )
+// allies_capture_target - target to fire on allies complete capture
+// axis_capture_target - target to fire on axis complete capture
+
+bool CControlPointMaster::KeyValue( const char *szKeyName, const char *szValue )
+{
+ if (FStrEq(szKeyName, "cpm_use_timer"))
+ {
+ m_bUseTimer = ( atoi(szValue) > 0 );
+ }
+ else if (FStrEq(szKeyName, "cpm_timer_team"))
+ {
+ m_iTimerTeam = atoi(szValue);
+ }
+ else
+ {
+ return CBaseEntity::KeyValue( szKeyName, szValue );
+ }
+
+ return true;
+}
+
+void CControlPointMaster::Reset( void )
+{
+
+}
+
+bool CControlPointMaster::FindControlPoints( void )
+{
+ //go through all the points
+ CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "dod_control_point" );
+
+ int numFound = 0;
+
+ while( pEnt )
+ {
+ CControlPoint *pPoint = (CControlPoint *)pEnt;
+
+ if( pPoint->IsActive() )
+ {
+ int index = pPoint->GetPointIndex();
+
+ Assert( index >= 0 );
+
+ if( m_ControlPoints.Find( index ) == m_ControlPoints.InvalidIndex())
+ {
+ DevMsg( 2, "Adding control point %s with index %d\n", pPoint->GetName(), index );
+ m_ControlPoints.Insert( index, pPoint );
+ numFound++;
+ }
+ else
+ {
+ Warning( "!!!!\nMultiple control points with the same index, duplicates ignored\n!!!!\n" );
+ UTIL_Remove( pPoint );
+ }
+ }
+
+ pEnt = gEntList.FindEntityByClassname( pEnt, "dod_control_point" );
+ }
+
+ if( numFound > MAX_CONTROL_POINTS )
+ {
+ Warning( "Too many control points! Max is %d\n", MAX_CONTROL_POINTS );
+ }
+
+ //Remap the indeces of the control points so they are 0-based
+ //======================
+ unsigned int j;
+
+ bool bHandled[MAX_CONTROL_POINTS];
+ memset( bHandled, 0, sizeof(bHandled) );
+
+ unsigned int numPoints = m_ControlPoints.Count();
+ unsigned int newIndex = 0;
+
+ while( newIndex < numPoints )
+ {
+ //Find the lowest numbered, unhandled point
+ int lowestIndex = -1;
+ int lowestValue = 999;
+
+ //find the lowest unhandled index
+ for( j=0; j<numPoints; j++ )
+ {
+ if( !bHandled[j] && m_ControlPoints[j]->GetPointIndex() < lowestValue )
+ {
+ lowestIndex = j;
+ lowestValue = m_ControlPoints[j]->GetPointIndex();
+ }
+ }
+
+ //Don't examine this point again
+ Assert( lowestIndex >= 0 );
+ bHandled[lowestIndex] = true;
+
+ //Give it its new index
+ m_ControlPoints[lowestIndex]->SetPointIndex( newIndex );
+ newIndex++;
+ }
+
+ if( m_ControlPoints.Count() == 0 )
+ {
+ Warning( "Error! No control points found in map!\n");
+ return false;
+ }
+
+ g_pObjectiveResource->SetNumControlPoints( m_ControlPoints.Count() );
+
+ unsigned int i;
+ for( i=0;i<m_ControlPoints.Count();i++ )
+ {
+ CControlPoint *pPoint = m_ControlPoints[i];
+
+ int iPointIndex = m_ControlPoints[i]->GetPointIndex();
+
+ g_pObjectiveResource->SetOwningTeam( iPointIndex, pPoint->GetOwner() );
+ g_pObjectiveResource->SetCPVisible( iPointIndex, pPoint->PointIsVisible() );
+ g_pObjectiveResource->SetCPPosition( iPointIndex, pPoint->GetAbsOrigin() );
+
+ g_pObjectiveResource->SetBombsRequired( iPointIndex, pPoint->GetBombsRequired() );
+ g_pObjectiveResource->SetBombsRemaining( iPointIndex, pPoint->GetBombsRemaining() );
+
+ g_pObjectiveResource->SetCPIcons( iPointIndex,
+ pPoint->GetHudIconIndexForTeam(TEAM_ALLIES),
+ pPoint->GetHudIconIndexForTeam(TEAM_AXIS),
+ pPoint->GetHudIconIndexForTeam(TEAM_UNASSIGNED),
+ pPoint->GetTimerCapHudIcon(),
+ pPoint->GetBombedHudIcon() );
+ }
+
+ return true;
+}
+
+// Think
+// =====
+// Think is called every 0.1 seconds and checks the status of all the control points
+// if one team owns them all, it gives points and resets
+// Think also gives the time based points at the specified time intervals
+//
+// I moved the search for spawn points to the initial think - sometimes the points spawned
+// after the master and it wasnt finding them.
+
+void CControlPointMaster::CPMThink( void )
+{
+ // search for all "dod_control_point" entities in the map
+ // and put them in the array
+ // only done the first Think
+
+ //try to establish if any dod_area_capture ents are linked to our flags
+ //via dod_point_relay
+
+ //if there exists a point relay that has this as the target,
+ //AND there exists a capture area that has that relay as a target
+ //then we have our area!
+
+ //every think
+
+ //go through all the control points and make sure theyre the same as the last think
+ //check masters
+
+ //if they are, do nothing
+ //else
+ //
+
+ //Note! Only one cpm should ever be active at the same time
+ //funny things may happen if there are two of em!
+ //if we are recently mastered on or off, touch the cps
+
+ //---------------------------------------------------------------------------
+ //below here we shouldn't execute unless we are an active control point master
+
+ //if the round has been decided, don't do any more thinking
+ //if this cpm is not active, dont' do any thinking
+
+ int iRoundState = DODGameRules()->State_Get();
+
+ // No points or triggering new wins if we are not active
+ if( m_bDisabled || iRoundState != STATE_RND_RUNNING )
+ {
+ SetContextThink( &CControlPointMaster::CPMThink, gpGlobals->curtime + 0.2, FLAGS_CONTEXT );
+ return;
+ }
+
+ // is it time to give time-based points yet?
+ if( gpGlobals->curtime > m_fGivePointsTime )
+ {
+ int AlliesPoints = 0;
+ int AxisPoints = 0;
+
+ //give points based on who owns what
+ unsigned int i;
+ for( i=0;i<m_ControlPoints.Count();i++ )
+ {
+ switch( m_ControlPoints[i]->GetOwner() )
+ {
+ case TEAM_ALLIES:
+ AlliesPoints += m_ControlPoints[i]->PointValue();
+ break;
+ case TEAM_AXIS:
+ AxisPoints += m_ControlPoints[i]->PointValue();
+ break;
+ default:
+ break;
+ }
+ }
+
+ //================
+ //give team points
+ //================
+ // See if there are players active on these teams
+
+ bool bFoundAllies = ( GetGlobalTeam(TEAM_ALLIES)->GetNumPlayers() > 0 );
+ bool bFoundAxis = ( GetGlobalTeam(TEAM_AXIS)->GetNumPlayers() > 0 );
+
+ bool bReportScore = true;
+
+ // don't give team points to a team with no-one on it!
+ if( AlliesPoints > 0 && bFoundAllies && DODGameRules()->State_Get() == STATE_RND_RUNNING )
+ {
+ if( bReportScore )
+ {
+ if (AlliesPoints == 1)
+ UTIL_ClientPrintAll( HUD_PRINTTALK, "#game_score_allie_point" );
+ else
+ {
+ char buf[8];
+ Q_snprintf( buf, sizeof(buf), "%d", AlliesPoints );
+ UTIL_ClientPrintAll( HUD_PRINTTALK, "#game_score_allie_points", buf );
+ }
+
+ }
+ GetGlobalTeam(TEAM_ALLIES)->AddScore( AlliesPoints );
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "dod_tick_points" );
+
+ if ( event )
+ {
+ event->SetInt( "team", TEAM_ALLIES );
+ event->SetInt( "score", AlliesPoints );
+ event->SetInt( "totalscore", GetGlobalTeam(TEAM_ALLIES)->GetScore() );
+
+ gameeventmanager->FireEvent( event );
+ }
+ }
+
+ if( AxisPoints > 0 && bFoundAxis && DODGameRules()->State_Get() == STATE_RND_RUNNING )
+ {
+ if( bReportScore )
+ {
+ if (AxisPoints == 1)
+ UTIL_ClientPrintAll( HUD_PRINTTALK, "#game_score_axis_point" );
+ else
+ {
+ char buf[8];
+ Q_snprintf( buf, sizeof(buf), "%d", AxisPoints );
+ UTIL_ClientPrintAll( HUD_PRINTTALK, "#game_score_axis_points", buf );
+ }
+ }
+ GetGlobalTeam(TEAM_AXIS)->AddScore( AxisPoints );
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "dod_tick_points" );
+
+ if ( event )
+ {
+ event->SetInt( "team", TEAM_AXIS );
+ event->SetInt( "score", AxisPoints );
+ event->SetInt( "totalscore", GetGlobalTeam(TEAM_AXIS)->GetScore() );
+ gameeventmanager->FireEvent( event );
+ }
+ }
+
+ // the next time we'll give points
+ m_fGivePointsTime = gpGlobals->curtime + mp_tickpointinterval.GetInt();
+ }
+
+ // If we call this from dod_control_point, this function should never
+ // trigger a win. but we'll leave it here just incase.
+ CheckWinConditions();
+
+ // the next time we 'think'
+ SetContextThink( &CControlPointMaster::CPMThink, gpGlobals->curtime + 0.2, FLAGS_CONTEXT );
+}
+
+void CControlPointMaster::CheckWinConditions( void )
+{
+ // ============
+ // 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
+ // ============
+ switch( TeamOwnsAllPoints() )
+ {
+ case TEAM_ALLIES: //allies own all
+ {
+ TeamWins( TEAM_ALLIES );
+ }
+ break;
+ case TEAM_AXIS: //axis owns all
+ {
+ TeamWins( TEAM_AXIS );
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void CControlPointMaster::InputRoundInit( inputdata_t &input )
+{
+ //clear out old control points
+ m_ControlPoints.RemoveAll();
+
+ //find the control points
+
+ //if successful, do CPMThink
+ if( FindControlPoints() )
+ {
+ SetContextThink( &CControlPointMaster::CPMThink, gpGlobals->curtime + 0.1, FLAGS_CONTEXT );
+ }
+
+ //init the ClientAreas
+ int index = 0;
+
+ CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "dod_capture_area" );
+ while( pEnt )
+ {
+ CAreaCapture *pArea = (CAreaCapture *)pEnt;
+ Assert( pArea );
+ pArea->area_SetIndex( index );
+ index++;
+
+ pEnt = gEntList.FindEntityByClassname( pEnt, "dod_capture_area" );
+ }
+
+ g_pObjectiveResource->ResetControlPoints();
+}
+
+void CControlPointMaster::FireTeamWinOutput( int iWinningTeam )
+{
+ switch( iWinningTeam )
+ {
+ case TEAM_ALLIES:
+ m_AlliesWinOutput.FireOutput(this,this);
+ break;
+ case TEAM_AXIS:
+ m_AxisWinOutput.FireOutput(this,this);
+ break;
+ default:
+ Assert(0);
+ break;
+ }
+}
+
+void CControlPointMaster::TeamWins( int iWinningTeam )
+{
+ DODGameRules()->SetWinningTeam( iWinningTeam );
+
+ FireTeamWinOutput( iWinningTeam );
+}
+
+void CControlPointMaster::BecomeActive( void )
+{
+ Assert( m_bDisabled );
+ m_bDisabled = false;
+}
+
+void CControlPointMaster::BecomeInactive( void )
+{
+ Assert( !m_bDisabled );
+ m_bDisabled = true;
+}
+
+int CControlPointMaster::GetPointOwner( int point )
+{
+ Assert( point >= 0 );
+ Assert( point < MAX_CONTROL_POINTS );
+
+ CControlPoint *pPoint = m_ControlPoints[point];
+
+ if( pPoint )
+ {
+ return pPoint->GetOwner();
+ }
+ else
+ return TEAM_UNASSIGNED;
+}
+
+// TeamOwnsAllPoints
+// =================
+// 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
+
+// New - cps are now broken into groups.
+// A team can win by owning all flags within a single group.
+
+// 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 CControlPointMaster::TeamOwnsAllPoints( CControlPoint *pOverridePoint /* = NULL */, int iOverrideNewTeam /* = TEAM_UNASSIGNED */ )
+{
+ unsigned 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] == TEAM_ALLIES || iWinningTeam[i] == TEAM_AXIS )
+ return iWinningTeam[i];
+ }
+
+ // no wins yet
+ return TEAM_UNASSIGNED;
+}
+
+// an advantage flag is a flag that we've taken that didn't initially
+// belong to our team
+int CControlPointMaster::CountAdvantageFlags( int team )
+{
+ int numFlags = 0;
+
+ unsigned int i;
+ for( i = 0;i<m_ControlPoints.Count();i++ )
+ {
+ CControlPoint *pPoint = m_ControlPoints[i];
+
+ if ( pPoint->GetOwner() != pPoint->GetDefaultOwner() )
+ {
+ if ( pPoint->GetOwner() == team )
+ {
+ // we own a flag we didn't initially
+ numFlags++;
+ }
+ else //
+ {
+ // the enemy owns one of our flags
+ numFlags--;
+ }
+ }
+ }
+
+ return numFlags;
+}
+
+void CControlPointMaster::InputAddTimerSeconds( inputdata_t &inputdata )
+{
+ DODGameRules()->AddTimerSeconds( inputdata.value.Int() );
+}
+
+void CControlPointMaster::GetTimerData( int &iTimerSeconds, int &iTimerWinTeam )
+{
+ iTimerSeconds = m_iTimerLength;
+ iTimerWinTeam = m_iTimerTeam;
+}
+
+bool CControlPointMaster::WouldNewCPOwnerWinGame( CControlPoint *pPoint, int iNewOwner )
+{
+ return ( TeamOwnsAllPoints( pPoint, iNewOwner ) == iNewOwner );
+}
+
+int CControlPointMaster::GetNumPoints( void )
+{
+ return m_ControlPoints.Count();
+}
+
+CControlPoint *CControlPointMaster::GetCPByIndex( int index )
+{
+ CControlPoint *pPoint = NULL;
+
+ if ( index >= 0 && index < (int)m_ControlPoints.Count() )
+ {
+ pPoint = m_ControlPoints[index];
+ }
+
+ return pPoint;
+}
+
+// custom scoring entity
+BEGIN_DATADESC( CDODCustomScoring )
+ DEFINE_INPUTFUNC( FIELD_INTEGER, "GiveTickPoints", InputGivePoints ),
+
+ DEFINE_KEYFIELD( m_iPointTeam, FIELD_INTEGER, "TeamNum" ),
+ DEFINE_KEYFIELD( m_iTickLength, FIELD_INTEGER, "point_give_delay" ),
+ DEFINE_KEYFIELD( m_iPointsToGive, FIELD_INTEGER, "point_give_amount" ),
+ DEFINE_KEYFIELD( m_iNumPointGives, FIELD_INTEGER, "point_give_max_times" ),
+
+ DEFINE_THINKFUNC( PointsThink ),
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( dod_scoring, CDODCustomScoring ); \ No newline at end of file