diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/dod/dod_area_capture.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/server/dod/dod_area_capture.cpp')
| -rw-r--r-- | game/server/dod/dod_area_capture.cpp | 590 |
1 files changed, 590 insertions, 0 deletions
diff --git a/game/server/dod/dod_area_capture.cpp b/game/server/dod/dod_area_capture.cpp new file mode 100644 index 0000000..cd9e4e9 --- /dev/null +++ b/game/server/dod/dod_area_capture.cpp @@ -0,0 +1,590 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "dod_area_capture.h" +#include "dod_player.h" +#include "dod_gamerules.h" +#include "dod_control_point.h" +#include "dod_team.h" +#include "dod_objective_resource.h" + + +//------------------------------------------------------------------- +// CAreaCapture +// An area entity that players must remain in in order to active another entity +// Triggers are fired on start of capture, on end of capture and on broken capture +// Can either be capped by both teams at once, or just by one +// Time to capture and number of people required to capture are both passed by the mapper + + + +BEGIN_DATADESC(CAreaCapture) + + // Touch functions + DEFINE_FUNCTION( AreaTouch ), + + // Think functions + DEFINE_THINKFUNC( Think ), + + // Keyfields + DEFINE_KEYFIELD( m_iszCapPointName, FIELD_STRING, "area_cap_point" ), + + DEFINE_KEYFIELD( m_nAlliesNumCap, FIELD_INTEGER, "area_allies_numcap" ), + DEFINE_KEYFIELD( m_nAxisNumCap, FIELD_INTEGER, "area_axis_numcap" ), + DEFINE_KEYFIELD( m_flCapTime, FIELD_FLOAT, "area_time_to_cap" ), + + DEFINE_KEYFIELD( m_bAlliesCanCap, FIELD_BOOLEAN, "area_allies_cancap" ), + DEFINE_KEYFIELD( m_bAxisCanCap, FIELD_BOOLEAN, "area_axis_cancap" ), + + DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), + + // Inputs + DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), + DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), + DEFINE_INPUTFUNC( FIELD_VOID, "RoundInit", InputRoundInit ), + + // Outputs + DEFINE_OUTPUT( m_AlliesStartOutput, "OnAlliesStartCap" ), + DEFINE_OUTPUT( m_AlliesBreakOutput, "OnAlliesBreakCap" ), + DEFINE_OUTPUT( m_AlliesCapOutput, "OnAlliesEndCap" ), + + DEFINE_OUTPUT( m_AxisStartOutput, "OnAxisStartCap" ), + DEFINE_OUTPUT( m_AxisBreakOutput, "OnAxisBreakCap" ), + DEFINE_OUTPUT( m_AxisCapOutput, "OnAxisEndCap" ), + + DEFINE_OUTPUT( m_StartOutput, "OnStartCap" ), + DEFINE_OUTPUT( m_BreakOutput, "OnBreakCap" ), + DEFINE_OUTPUT( m_CapOutput, "OnEndCap" ), + +// DEFINE_OUTPUT( m_OnStartCap, "OnStartCap" ); +// DEFINE_OUTPUT( m_OnBreakCap, + +// DEFINE_OUTPUT( m_OnEnterNoObj, "OnEnterNoObj" ); + +END_DATADESC(); + +LINK_ENTITY_TO_CLASS( dod_capture_area, CAreaCapture ); + +void CAreaCapture::Spawn( void ) +{ + BaseClass::Spawn(); + + InitTrigger(); + + Precache(); + + m_iAreaIndex = -1; + + SetTouch ( &CAreaCapture::AreaTouch ); + + m_bCapturing = false; + m_nCapturingTeam = TEAM_UNASSIGNED; + m_nOwningTeam = TEAM_UNASSIGNED; + m_fTimeRemaining = 0.0f; + + SetNextThink( gpGlobals->curtime + AREA_THINK_TIME ); + + if( m_nAlliesNumCap < 1 ) + m_nAlliesNumCap = 1; + + if( m_nAxisNumCap < 1 ) + m_nAxisNumCap = 1; + + m_bDisabled = false; + + m_iCapAttemptNumber = 0; +} + +void CAreaCapture::Precache( void ) +{ +} + +bool CAreaCapture::KeyValue( const char *szKeyName, const char *szValue ) +{ + return BaseClass::KeyValue( szKeyName, szValue ); +} + +//sends to all players at the start of the round +//needed? +void CAreaCapture::area_SetIndex( int index ) +{ + m_iAreaIndex = index; +} + +bool CAreaCapture::IsActive( void ) +{ + return !m_bDisabled; +} + +void CAreaCapture::AreaTouch( CBaseEntity *pOther ) +{ + //if they are touching, set their SIGNAL flag on, and their m_iCapAreaNum to ours + //then in think do all the scoring + + if( !IsActive() ) + return; + + //Don't cap areas unless the round is running + if( DODGameRules()->State_Get() != STATE_RND_RUNNING || DODGameRules()->IsInWarmup() ) + return; + + Assert( m_iAreaIndex != -1 ); + + if( m_pPoint ) + { + m_nOwningTeam = m_pPoint->GetOwner(); + } + + //dont touch for non-alive or non-players + if( !pOther->IsPlayer() ) + return; + + if( !pOther->IsAlive() ) + return; + + CDODPlayer *pPlayer = ToDODPlayer(pOther); + + ASSERT( pPlayer ); + + if ( pPlayer->GetTeamNumber() != m_nOwningTeam ) + { + bool bAbleToCap = ( pPlayer->GetTeamNumber() == TEAM_ALLIES && m_bAlliesCanCap ) || + ( pPlayer->GetTeamNumber() == TEAM_AXIS && m_bAxisCanCap ); + + if ( bAbleToCap ) + pPlayer->HintMessage( HINT_IN_AREA_CAP ); + } + + pPlayer->m_signals.Signal( SIGNAL_CAPTUREAREA ); + + //add them to this area + pPlayer->SetCapAreaIndex( m_iAreaIndex ); + + if ( m_pPoint ) + { + pPlayer->SetCPIndex( m_pPoint->GetPointIndex() ); + } +} + +/* three ways to be capturing a cap area + * 1) have the required number of people in the area + * 2) have less than the required number on your team, new required num is everyone + * 3) have less than the required number alive, new required is numAlive, but time is lengthened + */ + +ConVar dod_simulatemultiplecappers( "dod_simulatemultiplecappers", "1", FCVAR_CHEAT ); + +void CAreaCapture::Think( void ) +{ + SetNextThink( gpGlobals->curtime + AREA_THINK_TIME ); + + if( DODGameRules()->State_Get() != STATE_RND_RUNNING ) + { + // If we were being capped, cancel it + if( m_nNumAllies > 0 || m_nNumAxis > 0 ) + { + m_nNumAllies = 0; + m_nNumAxis = 0; + SendNumPlayers(); + + if( m_pPoint ) + { + g_pObjectiveResource->SetCappingTeam( m_pPoint->GetPointIndex(), TEAM_UNASSIGNED ); + } + } + return; + } + + // go through our list of players + + int iNumAllies = 0; + int iNumAxis = 0; + + CDODPlayer *pFirstAlliedTouching = NULL; + CDODPlayer *pFirstAxisTouching = NULL; + + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBaseEntity *ent = UTIL_PlayerByIndex( i ); + if ( ent ) + { + CDODPlayer *pPlayer = ToDODPlayer(ent); + + //First check if the player is in fact in this area + if ( ( pPlayer->m_signals.GetState() & SIGNAL_CAPTUREAREA ) && + pPlayer->GetCapAreaIndex() == m_iAreaIndex && + pPlayer->IsAlive() ) // alive check is kinda unnecessary, but there is some + // case where non-present people are messing up this count + { + if ( pPlayer->GetTeamNumber() == TEAM_ALLIES ) + { + if ( iNumAllies == 0 ) + pFirstAlliedTouching = pPlayer; + + iNumAllies++; + } + else if ( pPlayer->GetTeamNumber() == TEAM_AXIS ) + { + if ( iNumAxis == 0 ) + pFirstAxisTouching = pPlayer; + + iNumAxis++; + } + } + } + } + + iNumAllies *= dod_simulatemultiplecappers.GetInt(); + iNumAxis *= dod_simulatemultiplecappers.GetInt(); + + if( iNumAllies != m_nNumAllies || iNumAxis != m_nNumAxis ) + { + m_nNumAllies = iNumAllies; + m_nNumAxis = iNumAxis; + SendNumPlayers(); + } + + // 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 ) + { + //its a regular cap + //Subtract some time from the cap + m_fTimeRemaining -= AREA_THINK_TIME; + + //if both teams are in the area + if( iNumAllies > 0 && iNumAxis > 0 ) + { + // See if anyone gets credit for the block + float flPercentToGo = m_fTimeRemaining / m_flCapTime; + if ( flPercentToGo <= 0.5 && m_pPoint ) + { + // 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 + CDODPlayer *pBlockingPlayer = ( m_nCapturingTeam == TEAM_ALLIES ) ? pFirstAxisTouching : pFirstAlliedTouching; + + if ( pBlockingPlayer ) + { + if ( pBlockingPlayer->GetCapAreaIndex() == m_iAreaIndex && + pBlockingPlayer->GetLastBlockCapAttempt() == m_iCapAttemptNumber ) + { + // this is a repeat block on the same cap, ignore it + NULL; + } + else + { + m_pPoint->CaptureBlocked( pBlockingPlayer ); + pBlockingPlayer->StoreCaptureBlock( m_iAreaIndex, m_iCapAttemptNumber ); + } + } + } + + BreakCapture( false ); + return; + } + + //if no-one is in the area + if( iNumAllies == 0 && iNumAxis == 0 ) + { + BreakCapture( true ); + return; + } + + if( m_nCapturingTeam == TEAM_ALLIES ) + { + if( iNumAllies < m_nAlliesNumCap ) + { + BreakCapture( true ); + } + } + else if( m_nCapturingTeam == TEAM_AXIS ) + { + if( iNumAxis < m_nAxisNumCap ) + { + BreakCapture( true ); + } + } + + //if the cap is done + if( m_fTimeRemaining <= 0 ) + { + EndCapture( m_nCapturingTeam ); + return; //we're done + } + } + else //not capturing yet + { + bool bStarted = false; + + if( iNumAllies > 0 && iNumAxis <= 0 && m_bAlliesCanCap && m_nOwningTeam != TEAM_ALLIES ) + { + if( iNumAllies >= m_nAlliesNumCap ) + { + m_iCappingRequired = m_nAlliesNumCap; + m_iCappingPlayers = iNumAllies; + StartCapture( TEAM_ALLIES, CAPTURE_NORMAL ); + bStarted = true; + } + } + else if( iNumAxis > 0 && iNumAllies <= 0 && m_bAxisCanCap && m_nOwningTeam != TEAM_AXIS ) + { + if( iNumAxis >= m_nAxisNumCap ) + { + m_iCappingRequired = m_nAxisNumCap; + m_iCappingPlayers = iNumAxis; + StartCapture( TEAM_AXIS, CAPTURE_NORMAL ); + bStarted = true; + } + } + } +} + +void CAreaCapture::SetOwner( int team ) +{ + //break any current capturing + BreakCapture( false ); + + //set the owner to the passed value + m_nOwningTeam = team; + g_pObjectiveResource->SetOwningTeam( m_pPoint->GetPointIndex(), m_nOwningTeam ); +} + +void CAreaCapture::SendNumPlayers( CBasePlayer *pPlayer ) +{ + if( !m_pPoint ) + return; + + int index = m_pPoint->GetPointIndex(); + + g_pObjectiveResource->SetNumPlayers( index, TEAM_ALLIES, m_nNumAllies ); + g_pObjectiveResource->SetNumPlayers( index, TEAM_AXIS, m_nNumAxis ); +} + +void CAreaCapture::StartCapture( int team, int capmode ) +{ + int iNumCappers = 0; + + //trigger start + if( team == TEAM_ALLIES ) + { + m_AlliesStartOutput.FireOutput(this,this); + iNumCappers = m_nAlliesNumCap; + } + else if( team == TEAM_AXIS ) + { + m_AxisStartOutput.FireOutput(this,this); + iNumCappers = m_nAxisNumCap; + } + + m_StartOutput.FireOutput(this,this); + + m_nCapturingTeam = team; + m_fTimeRemaining = m_flCapTime; + m_bCapturing = true; + m_iCapMode = capmode; + + if( m_pPoint ) + { + //send a message that we're starting to cap this area + g_pObjectiveResource->SetCappingTeam( m_pPoint->GetPointIndex(), m_nCapturingTeam ); + } +} + +#define MAX_AREA_CAPPERS 9 + +void CAreaCapture::EndCapture( int team ) +{ + m_iCapAttemptNumber++; + + //do the triggering + if( team == TEAM_ALLIES ) + { + m_AlliesCapOutput.FireOutput(this,this); + } + else if( team == TEAM_AXIS ) + { + m_AxisCapOutput.FireOutput(this,this); + } + + m_CapOutput.FireOutput(this,this); + + m_iCappingRequired = 0; + m_iCappingPlayers = 0; + + int numcappers = 0; + int cappingplayers[MAX_AREA_CAPPERS]; + + CDODPlayer *pCappingPlayer = NULL; + + CDODTeam *pTeam = GetGlobalDODTeam(team); + if ( pTeam ) + { + int iCount = pTeam->GetNumPlayers(); + + for ( int i=0;i<iCount;i++ ) + { + CDODPlayer *pPlayer = ToDODPlayer( pTeam->GetPlayer(i) ); + if ( pPlayer ) + { + if( ( pPlayer->m_signals.GetState() & SIGNAL_CAPTUREAREA ) && + pPlayer->GetCapAreaIndex() == m_iAreaIndex && + pPlayer->IsAlive() ) + { + if( pCappingPlayer == NULL ) + pCappingPlayer = pPlayer; + + if ( numcappers < MAX_AREA_CAPPERS-1 ) + { + cappingplayers[numcappers] = pPlayer->entindex(); + numcappers++; + } + } + } + } + } + + if ( numcappers < MAX_AREA_CAPPERS ) + { + cappingplayers[numcappers] = 0; //null terminate :) + } + + m_nOwningTeam = team; + m_bCapturing = false; + m_fTimeRemaining = 0.0f; + + //there may have been more than one capper, but only report this one. + //he hasnt gotten points yet, and his name will go in the cap string if its needed + //first capper gets name sent and points given by flag. + //other cappers get points manually above, no name in message + + //send the player in the cap string + if( m_pPoint ) + { + DODGameRules()->CapEvent( CAP_EVENT_FLAG, m_nOwningTeam ); + + g_pObjectiveResource->SetOwningTeam( m_pPoint->GetPointIndex(), m_nOwningTeam ); + m_pPoint->SetOwner( m_nOwningTeam, true, numcappers, cappingplayers ); + } +} + +void CAreaCapture::BreakCapture( bool bNotEnoughPlayers ) +{ + if( m_bCapturing ) + { + m_iCappingRequired = 0; + m_iCappingPlayers = 0; + + if( m_nCapturingTeam == TEAM_ALLIES ) + m_AlliesBreakOutput.FireOutput(this,this); + + else if( m_nCapturingTeam == TEAM_AXIS ) + m_AxisBreakOutput.FireOutput(this,this); + + m_BreakOutput.FireOutput(this,this); + + m_bCapturing = false; + + if( m_pPoint ) + { + g_pObjectiveResource->SetCappingTeam( m_pPoint->GetPointIndex(), TEAM_UNASSIGNED ); + } + + if ( bNotEnoughPlayers ) + { + m_iCapAttemptNumber++; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CAreaCapture::InputDisable( inputdata_t &inputdata ) +{ + m_bDisabled = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CAreaCapture::InputEnable( inputdata_t &inputdata ) +{ + m_bDisabled = false; +} + +void CAreaCapture::InputRoundInit( inputdata_t &inputdata ) +{ + // find the flag we're linked to + if( !m_pPoint ) + { + m_pPoint = dynamic_cast<CControlPoint*>( gEntList.FindEntityByName(NULL, STRING(m_iszCapPointName) ) ); + + if ( m_pPoint ) + { + m_pPoint->SetNumCappersRequired( m_nAlliesNumCap, m_nAxisNumCap ); + g_pObjectiveResource->SetCPRequiredCappers( m_pPoint->GetPointIndex(), m_nAlliesNumCap, m_nAxisNumCap ); + g_pObjectiveResource->SetCPCapTime( m_pPoint->GetPointIndex(), m_flCapTime, m_flCapTime ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Check if this player's death causes a block +// return FALSE if the player is not in this area +// return TRUE otherwise ( eg player is in area, but his death does not cause break ) +//----------------------------------------------------------------------------- +bool CAreaCapture::CheckIfDeathCausesBlock( CDODPlayer *pVictim, CDODPlayer *pKiller ) +{ + // This shouldn't happen + if ( !pVictim || !pKiller ) + { + Assert( !"Why are null players getting here?" ); + return false; + } + + // make sure this player is in this area + if ( pVictim->GetCapAreaIndex() != m_iAreaIndex ) + return false; + + // Teamkills shouldn't give a block reward + if ( pVictim->GetTeamNumber() == pKiller->GetTeamNumber() ) + return true; + + // return if the area is not being capped + if ( !m_bCapturing ) + return true; + + int iTeam = pVictim->GetTeamNumber(); + + // return if this player's team is not capping the area + if ( iTeam != m_nCapturingTeam ) + return true; + + bool bBlocked = false; + + if ( m_nCapturingTeam == TEAM_ALLIES ) + { + if ( m_nNumAllies-1 < m_nAlliesNumCap ) + bBlocked = true; + } + else if ( m_nCapturingTeam == TEAM_AXIS ) + { + if ( m_nNumAxis-1 < m_nAxisNumCap ) + bBlocked = true; + } + + // break early incase we kill multiple people in the same frame + if ( bBlocked ) + { + m_pPoint->CaptureBlocked( pKiller ); + BreakCapture( false ); + } + + return true; +} |