diff options
| author | John Schoenick <[email protected]> | 2015-09-09 18:35:41 -0700 |
|---|---|---|
| committer | John Schoenick <[email protected]> | 2015-09-09 18:35:41 -0700 |
| commit | 0d8dceea4310fde5706b3ce1c70609d72a38efdf (patch) | |
| tree | c831ef32c2c801a5c5a80401736b52c7b5a528ec /mp/src/game/shared/teamplayroundbased_gamerules.cpp | |
| parent | Updated the SDK with the latest code from the TF and HL2 branches. (diff) | |
| download | source-sdk-2013-master.tar.xz source-sdk-2013-master.zip | |
Diffstat (limited to 'mp/src/game/shared/teamplayroundbased_gamerules.cpp')
| -rw-r--r-- | mp/src/game/shared/teamplayroundbased_gamerules.cpp | 467 |
1 files changed, 300 insertions, 167 deletions
diff --git a/mp/src/game/shared/teamplayroundbased_gamerules.cpp b/mp/src/game/shared/teamplayroundbased_gamerules.cpp index 3930798d..8d2b3e00 100644 --- a/mp/src/game/shared/teamplayroundbased_gamerules.cpp +++ b/mp/src/game/shared/teamplayroundbased_gamerules.cpp @@ -35,17 +35,15 @@ #if defined(TF_CLIENT_DLL) || defined(TF_DLL) #include "tf_gamerules.h" - #if defined(TF_CLIENT_DLL) || defined(TF_DLL) - #include "tf_lobby.h" - #ifdef GAME_DLL - #include "player_vs_environment/tf_population_manager.h" - #include "../server/tf/tf_gc_server.h" - #include "../server/tf/tf_objective_resource.h" - #else - #include "../client/tf/tf_gc_client.h" - #include "../client/tf/c_tf_objective_resource.h" - #endif // GAME_DLL - #endif // #if defined(TF_CLIENT_DLL) || defined(TF_DLL) + #include "tf_lobby.h" + #ifdef GAME_DLL + #include "player_vs_environment/tf_population_manager.h" + #include "../server/tf/tf_gc_server.h" + #include "../server/tf/tf_objective_resource.h" + #else + #include "../client/tf/tf_gc_client.h" + #include "../client/tf/c_tf_objective_resource.h" + #endif // GAME_DLL #endif // memdbgon must be the last include file in a .cpp file!!! @@ -196,9 +194,14 @@ ConVar mp_maxrounds( "mp_maxrounds", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "max ConVar mp_winlimit( "mp_winlimit", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "Max score one team can reach before server changes maps", true, 0, false, 0 ); ConVar mp_disable_respawn_times( "mp_disable_respawn_times", "0", FCVAR_NOTIFY | FCVAR_REPLICATED ); ConVar mp_bonusroundtime( "mp_bonusroundtime", "15", FCVAR_REPLICATED, "Time after round win until round restarts", true, 5, true, 15 ); +ConVar mp_bonusroundtime_final( "mp_bonusroundtime_final", "15", FCVAR_REPLICATED, "Time after final round ends until round restarts", true, 5, true, 300 ); ConVar mp_stalemate_meleeonly( "mp_stalemate_meleeonly", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "Restrict everyone to melee weapons only while in Sudden Death." ); ConVar mp_forceautoteam( "mp_forceautoteam", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "Automatically assign players to teams when joining." ); +#if defined( _DEBUG ) || defined( STAGING_ONLY ) +ConVar mp_developer( "mp_developer", "0", FCVAR_ARCHIVE | FCVAR_REPLICATED | FCVAR_NOTIFY, "1: basic conveniences (instant respawn and class change, etc). 2: add combat conveniences (infinite ammo, buddha, etc)" ); +#endif // _DEBUG || STAGING_ONLY + #ifdef GAME_DLL ConVar mp_showroundtransitions( "mp_showroundtransitions", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show gamestate round transitions." ); ConVar mp_enableroundwaittime( "mp_enableroundwaittime", "1", FCVAR_REPLICATED, "Enable timers to wait between rounds." ); @@ -358,25 +361,21 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) m_flNextRespawnWave.Set( i, 0 ); m_TeamRespawnWaveTimes.Set( i, -1.0f ); - m_bTeamReady.Set( i, false ); - #ifdef GAME_DLL m_flOriginalTeamRespawnWaveTime[i] = -1.0f; #endif } - for ( int i = 0; i < MAX_PLAYERS; i++ ) - { - m_bPlayerReady.Set( i, false ); - } - m_bInOvertime = false; m_bInSetup = false; m_bSwitchedTeamsThisRound = false; m_flStopWatchTotalTime = -1.0f; m_bMultipleTrains = false; + m_bAllowBetweenRounds = true; #ifdef GAME_DLL + ListenForGameEvent( "server_changelevel_failed" ); + m_pCurStateInfo = NULL; State_Transition( GR_STATE_PREGAME ); @@ -390,8 +389,8 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) SetRoundToPlayNext( NULL_STRING ); m_bInWaitingForPlayers = false; m_bAwaitingReadyRestart = false; - m_flRestartRoundTime = -1; - m_flMapResetTime = 0; + m_flRestartRoundTime = -1.0f; + m_flMapResetTime = 0.0f; m_bPrevRoundWasWaitingForPlayers = false; m_iWinningTeam = TEAM_UNASSIGNED; @@ -400,12 +399,13 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) m_bAllowStalemateAtTimelimit = false; m_bChangelevelAfterStalemate = false; - m_flRoundStartTime = 0; - m_flNewThrottledAlertTime = 0; - m_flStartBalancingTeamsAt = 0; + m_flRoundStartTime = 0.0f; + m_flNewThrottledAlertTime = 0.0f; + m_flStartBalancingTeamsAt = 0.0f; m_bPrintedUnbalanceWarning = false; - m_flFoundUnbalancedTeamsTime = -1; + m_flFoundUnbalancedTeamsTime = -1.0f; m_flWaitingForPlayersTimeEnds = 0.0f; + m_flLastTeamWin = -1.0f; m_nRoundsPlayed = 0; m_bUseAddScoreAnim = false; @@ -413,18 +413,20 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) m_bStopWatch = false; m_bAwaitingReadyRestart = false; - if ( IsInTournamentMode() == true ) + if ( IsInTournamentMode() ) { m_bAwaitingReadyRestart = true; } - m_flAutoBalanceQueueTimeEnd = -1; + m_flAutoBalanceQueueTimeEnd = -1.0f; m_nAutoBalanceQueuePlayerIndex = -1; m_nAutoBalanceQueuePlayerScore = -1; SetDefLessFunc( m_GameTeams ); m_bCheatsEnabledDuringLevel = false; + ResetPlayerAndTeamReadyState(); + #endif } @@ -580,6 +582,22 @@ float CTeamplayRoundBasedRules::GetRespawnTimeScalar( int iTeam ) return flScale; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTeamplayRoundBasedRules::FireGameEvent( IGameEvent * event ) +{ +#ifdef GAME_DLL + const char *eventName = event->GetName(); + if ( g_fGameOver && !Q_strcmp( eventName, "server_changelevel_failed" ) ) + { + Warning( "In gameover, but failed to load the next map. Trying next map in cycle.\n" ); + nextlevel.SetValue( "" ); + ChangeLevel(); + } +#endif +} + #ifdef GAME_DLL //----------------------------------------------------------------------------- // Purpose: @@ -616,7 +634,7 @@ void CTeamplayRoundBasedRules::Think( void ) // Don't run this code again m_flIntermissionEndTime = 0.f; - } + } return; } @@ -853,7 +871,14 @@ void CTeamplayRoundBasedRules::CheckWaitingForPlayers( void ) mp_waitingforplayers_restart.SetValue( 0 ); } - if( (mp_waitingforplayers_cancel.GetBool() || IsInItemTestingMode()) && IsInTournamentMode() == false ) + bool bCancelWait = ( mp_waitingforplayers_cancel.GetBool() || IsInItemTestingMode() ) && !IsInTournamentMode(); + +#if defined( _DEBUG ) || defined( STAGING_ONLY ) + if ( mp_developer.GetBool() ) + bCancelWait = true; +#endif // _DEBUG || STAGING_ONLY + + if ( bCancelWait ) { // Cancel the wait period and manually Resume() the timer if // it's not supposed to start paused at the beginning of a round. @@ -975,11 +1000,7 @@ void CTeamplayRoundBasedRules::CheckRestartRound( void ) int iDelayMax = 60; #if defined(TF_CLIENT_DLL) || defined(TF_DLL) -#ifdef STAGING_ONLY - if ( TFGameRules() && ( TFGameRules()->IsMannVsMachineMode() || TFGameRules()->IsRatedTournamentMode() ) ) -#else - if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) -#endif // STAGING_ONLY + if ( TFGameRules() && ( TFGameRules()->IsMannVsMachineMode() || TFGameRules()->IsCompetitiveMode() ) ) { iDelayMax = 180; } @@ -1068,7 +1089,7 @@ void CTeamplayRoundBasedRules::CheckRestartRound( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckTimeLimit( void ) +bool CTeamplayRoundBasedRules::CheckTimeLimit( bool bAllowEnd /*= true*/ ) { if ( IsInPreMatch() == true ) return false; @@ -1095,18 +1116,21 @@ bool CTeamplayRoundBasedRules::CheckTimeLimit( void ) bSwitchDueToTime = false; } - if( GetTimeLeft() <= 0 || m_bChangelevelAfterStalemate || bSwitchDueToTime ) + if ( GetTimeLeft() <= 0 || m_bChangelevelAfterStalemate || bSwitchDueToTime ) { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) + if ( bAllowEnd ) { - event->SetString( "reason", "Reached Time Limit" ); - gameeventmanager->FireEvent( event ); - } + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); + if ( event ) + { + event->SetString( "reason", "Reached Time Limit" ); + gameeventmanager->FireEvent( event ); + } - SendTeamScoresEvent(); + SendTeamScoresEvent(); - GoToIntermission(); + GoToIntermission(); + } return true; } } @@ -1145,20 +1169,23 @@ int CTeamplayRoundBasedRules::GetTimeLeft( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckNextLevelCvar( void ) +bool CTeamplayRoundBasedRules::CheckNextLevelCvar( bool bAllowEnd /*= true*/ ) { if ( m_bForceMapReset ) { - if ( nextlevel.GetString() && *nextlevel.GetString() && engine->IsMapValid( nextlevel.GetString() ) ) + if ( nextlevel.GetString() && *nextlevel.GetString() ) { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) + if ( bAllowEnd ) { - event->SetString( "reason", "NextLevel CVAR" ); - gameeventmanager->FireEvent( event ); - } + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); + if ( event ) + { + event->SetString( "reason", "NextLevel CVAR" ); + gameeventmanager->FireEvent( event ); + } - GoToIntermission(); + GoToIntermission(); + } return true; } } @@ -1169,7 +1196,7 @@ bool CTeamplayRoundBasedRules::CheckNextLevelCvar( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckWinLimit( void ) +bool CTeamplayRoundBasedRules::CheckWinLimit( bool bAllowEnd /*= true*/ ) { // has one team won the specified number of rounds? int iWinLimit = mp_winlimit.GetInt(); @@ -1183,14 +1210,17 @@ bool CTeamplayRoundBasedRules::CheckWinLimit( void ) if ( pTeam->GetScore() >= iWinLimit ) { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) + if ( bAllowEnd ) { - event->SetString( "reason", "Reached Win Limit" ); - gameeventmanager->FireEvent( event ); - } + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); + if ( event ) + { + event->SetString( "reason", "Reached Win Limit" ); + gameeventmanager->FireEvent( event ); + } - GoToIntermission(); + GoToIntermission(); + } return true; } } @@ -1202,20 +1232,23 @@ bool CTeamplayRoundBasedRules::CheckWinLimit( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckMaxRounds() +bool CTeamplayRoundBasedRules::CheckMaxRounds( bool bAllowEnd /*= true*/ ) { if ( mp_maxrounds.GetInt() > 0 && IsInPreMatch() == false ) { if ( m_nRoundsPlayed >= mp_maxrounds.GetInt() ) { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) + if ( bAllowEnd ) { - event->SetString( "reason", "Reached Round Limit" ); - gameeventmanager->FireEvent( event ); - } + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); + if ( event ) + { + event->SetString( "reason", "Reached Round Limit" ); + gameeventmanager->FireEvent( event ); + } - GoToIntermission(); + GoToIntermission(); + } return true; } } @@ -1435,17 +1468,17 @@ void CTeamplayRoundBasedRules::State_Enter_PREROUND( void ) m_flStateTransitionTime = gpGlobals->curtime + tf_arena_preround_time.GetInt(); } #if defined(TF_CLIENT_DLL) || defined(TF_DLL) - else if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) - { - State_Transition( GR_STATE_BETWEEN_RNDS ); - TFObjectiveResource()->SetMannVsMachineBetweenWaves( true ); - } -#ifdef STAGING_ONLY - else if ( TFGameRules() && TFGameRules()->IsRatedTournamentMode() ) + // Only allow at the very beginning of the game, or between waves in mvm + else if ( TFGameRules() && TFGameRules()->UsePlayerReadyStatusMode() && m_bAllowBetweenRounds ) { State_Transition( GR_STATE_BETWEEN_RNDS ); + m_bAllowBetweenRounds = false; + + if ( TFGameRules()->IsMannVsMachineMode() ) + { + TFObjectiveResource()->SetMannVsMachineBetweenWaves( true ); + } } -#endif // STAGING_ONLY #endif // #if defined(TF_CLIENT_DLL) || defined(TF_DLL) else { @@ -1527,28 +1560,33 @@ void CTeamplayRoundBasedRules::State_Enter_RND_RUNNING( void ) void CTeamplayRoundBasedRules::CheckReadyRestart( void ) { // check round restart - if( m_flRestartRoundTime > 0 && m_flRestartRoundTime <= gpGlobals->curtime && !g_pServerBenchmark->IsBenchmarkRunning() ) + if ( m_flRestartRoundTime > 0 && m_flRestartRoundTime <= gpGlobals->curtime && !g_pServerBenchmark->IsBenchmarkRunning() ) { m_flRestartRoundTime = -1; #ifdef TF_DLL if ( TFGameRules() ) { - if ( TFGameRules()->IsMannVsMachineMode() && g_pPopulationManager ) + if ( TFGameRules()->IsMannVsMachineMode() ) { - if ( TFObjectiveResource()->GetMannVsMachineIsBetweenWaves() ) + if ( g_pPopulationManager && TFObjectiveResource()->GetMannVsMachineIsBetweenWaves() ) { g_pPopulationManager->StartCurrentWave(); + m_bAllowBetweenRounds = true; return; } } -#ifdef STAGING_ONLY - else if ( TFGameRules()->IsRatedTournamentMode() ) + else if ( TFGameRules()->IsCompetitiveMode() ) + { + TFGameRules()->StartCompetitiveMatch(); + return; + } + else if ( mp_tournament.GetBool() ) { - TFGameRules()->StartRatedTournamentMatch(); + // Temp + TFGameRules()->StartCompetitiveMatch(); return; } -#endif // STAGING_ONLY } #endif // TF_DLL @@ -1556,34 +1594,28 @@ void CTeamplayRoundBasedRules::CheckReadyRestart( void ) State_Transition( GR_STATE_RESTART ); } - // check ready restart - if( m_bAwaitingReadyRestart ) - { - int nTime = 5; - bool bTeamReady = false; + bool bProcessReadyRestart = m_bAwaitingReadyRestart; #ifdef TF_DLL - if ( TFGameRules() ) + bProcessReadyRestart &= TFGameRules() && !TFGameRules()->UsePlayerReadyStatusMode(); +#endif // TF_DLL + + // check ready restart + if ( bProcessReadyRestart ) + { + bool bTeamNotReady = false; + for ( int i = LAST_SHARED_TEAM + 1; i < GetNumberOfTeams(); i++ ) { - if ( TFGameRules()->IsMannVsMachineMode() ) + if ( !m_bTeamReady[i] ) { - bTeamReady = AreDefendingPlayersReady(); - if ( bTeamReady ) - { - nTime = 10; - } - } - else - { - bTeamReady = m_bTeamReady[TF_TEAM_BLUE] && m_bTeamReady[TF_TEAM_RED]; + bTeamNotReady = true; + break; } } -#endif // TF_DLL - if ( bTeamReady ) + if ( !bTeamNotReady ) { - //State_Transition( GR_STATE_RESTART ); - mp_restartgame.SetValue( nTime ); + mp_restartgame.SetValue( 5 ); m_bAwaitingReadyRestart = false; ShouldResetScores( true, true ); @@ -1596,31 +1628,31 @@ void CTeamplayRoundBasedRules::CheckReadyRestart( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::AreDefendingPlayersReady() +bool CTeamplayRoundBasedRules::AreLobbyPlayersOnTeamReady( int iTeam ) { - // Get list of defenders - CUtlVector<LobbyPlayerInfo_t> vecMvMDefenders; - GetMvMPotentialDefendersLobbyPlayerInfo( vecMvMDefenders ); + if ( !TFGameRules() ) + return false; + + if ( TFGameRules()->IsMannVsMachineMode() && iTeam == TF_TEAM_PVE_INVADERS ) + return true; - // Scan all the players, and bail as soon as we find one person - // worth waiting for bool bAtLeastOnePersonReady = false; - for ( int i = 0; i < vecMvMDefenders.Count(); i++ ) - { + + CUtlVector<LobbyPlayerInfo_t> vecLobbyPlayers; + GetPotentialPlayersLobbyPlayerInfo( vecLobbyPlayers ); - // Are they on the red team? - const LobbyPlayerInfo_t &p = vecMvMDefenders[i]; - if ( !p.m_bConnected || p.m_iTeam == TEAM_UNASSIGNED || p.m_nEntNum <= 0 || p.m_nEntNum >= MAX_PLAYERS ) + for ( int i = 0; i < vecLobbyPlayers.Count(); i++ ) + { + const LobbyPlayerInfo_t &p = vecLobbyPlayers[i]; + + // Make sure all lobby players are connected + if ( !AreLobbyPlayersConnected() ) { - // They're still getting set up. We'll wait for them, - // but only if they are in the lobby - if ( p.m_bInLobby ) - return false; + return false; } - else if ( p.m_iTeam == TF_TEAM_PVE_DEFENDERS ) + // All are connected, make sure their team is ready + else if ( p.m_iTeam == iTeam ) { - - // If he isn't ready, then we aren't ready if ( !m_bPlayerReady[ p.m_nEntNum ] ) return false; @@ -1629,8 +1661,12 @@ bool CTeamplayRoundBasedRules::AreDefendingPlayersReady() } else { - // And you may ask yourself, "How did I get here?" - Assert( p.m_iTeam == TF_TEAM_PVE_DEFENDERS ); + // In MvM, only the red team should pass through here + if ( TFGameRules()->IsMannVsMachineMode() ) + { + // And you may ask yourself, "How did I get here?" + Assert( p.m_iTeam == iTeam ); + } } } @@ -1639,6 +1675,32 @@ bool CTeamplayRoundBasedRules::AreDefendingPlayersReady() return bAtLeastOnePersonReady; } +//----------------------------------------------------------------------------- +// Purpose: Is everyone in the lobby connected to the server? +//----------------------------------------------------------------------------- +bool CTeamplayRoundBasedRules::AreLobbyPlayersConnected( void ) +{ + CUtlVector<LobbyPlayerInfo_t> vecLobbyPlayers; + GetPotentialPlayersLobbyPlayerInfo( vecLobbyPlayers ); + + // If you're calling this, you should have lobby members + Assert( vecLobbyPlayers.Count() ); + + for ( int i = 0; i < vecLobbyPlayers.Count(); i++ ) + { + const LobbyPlayerInfo_t &pLobbyPlayer = vecLobbyPlayers[i]; + if ( !pLobbyPlayer.m_bConnected || + pLobbyPlayer.m_nEntNum <= 0 || + pLobbyPlayer.m_nEntNum >= MAX_PLAYERS || + ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && pLobbyPlayer.m_iTeam == TEAM_UNASSIGNED ) ) + { + if ( pLobbyPlayer.m_bInLobby ) + return false; + } + } + + return true; +} #endif // #if defined(TF_CLIENT_DLL) || defined(TF_DLL) //----------------------------------------------------------------------------- @@ -1657,6 +1719,15 @@ void CTeamplayRoundBasedRules::State_Think_RND_RUNNING( void ) } #endif +#ifdef TF_DLL + // Mass time-out? Clean everything up. + if ( TFGameRules() && TFGameRules()->IsCompetitiveMode() ) + { + TFGameRules()->EndCompetitiveMatch(); + return; + } +#endif // TF_DLL + State_Transition( GR_STATE_PREGAME ); return; } @@ -1672,9 +1743,8 @@ void CTeamplayRoundBasedRules::State_Think_RND_RUNNING( void ) // check round restart CheckReadyRestart(); - // See if we're coming up to the server timelimit, in which case force a stalemate immediately. - if ( State_Get() == GR_STATE_RND_RUNNING && mp_timelimit.GetInt() > 0 && IsInPreMatch() == false && GetTimeLeft() <= 0 ) + if ( mp_timelimit.GetInt() > 0 && IsInPreMatch() == false && GetTimeLeft() <= 0 ) { if ( m_bAllowStalemateAtTimelimit || ( mp_match_end_at_timelimit.GetBool() && !IsValveMap() ) ) { @@ -1730,9 +1800,7 @@ void CTeamplayRoundBasedRules::State_Think_RND_RUNNING( void ) //----------------------------------------------------------------------------- void CTeamplayRoundBasedRules::State_Enter_TEAM_WIN( void ) { - float flTime = GetBonusRoundTime(); - - m_flStateTransitionTime = gpGlobals->curtime + flTime; + m_flStateTransitionTime = gpGlobals->curtime + GetBonusRoundTime(); // if we're forcing the map to reset it must be the end of a "full" round not a mini-round if ( m_bForceMapReset ) @@ -1744,18 +1812,14 @@ void CTeamplayRoundBasedRules::State_Enter_TEAM_WIN( void ) SendWinPanelInfo(); -#ifdef STAGING_ONLY #ifdef TF_DLL - if ( TFGameRules() && TFGameRules()->IsRatedTournamentMode() ) + // Do this now, so players don't leave before the usual CheckWinLimit() call happens + bool bDone = ( CheckTimeLimit( false ) || CheckWinLimit( false ) || CheckMaxRounds( false ) || CheckNextLevelCvar( false ) ); + if ( TFGameRules() && TFGameRules()->IsCompetitiveMode() && bDone ) { - // Do this now, so players don't leave before the usual CheckWinLimit() call happens - if ( CheckWinLimit() ) - { - TFGameRules()->SkillRating_CalculateAdjustmentForTeams( m_iWinningTeam ); - } + TFGameRules()->StopCompetitiveMatch( CMsgGC_Match_Result_Status_MATCH_SUCCEEDED ); } #endif // TF_DLL -#endif // STAGING_ONLY } //----------------------------------------------------------------------------- @@ -1773,10 +1837,10 @@ void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) } #endif // TF_DLL - bool bDone = !(!CheckTimeLimit() && !CheckWinLimit() && !CheckMaxRounds() && !CheckNextLevelCvar()); + bool bDone = ( CheckTimeLimit() || CheckWinLimit() || CheckMaxRounds() || CheckNextLevelCvar() ); // check the win limit, max rounds, time limit and nextlevel cvar before starting the next round - if ( bDone == false ) + if ( !bDone ) { PreviousRoundEnd(); @@ -1797,7 +1861,7 @@ void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) State_Transition( GR_STATE_PREROUND ); } } - else if ( IsInTournamentMode() == true ) + else if ( IsInTournamentMode() ) { for ( int i = 1; i <= MAX_PLAYERS; i++ ) { @@ -1811,7 +1875,7 @@ void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) RestartTournament(); - if ( IsInArenaMode() == true ) + if ( IsInArenaMode() ) { #if defined( REPLAY_ENABLED ) if ( g_pReplay ) @@ -1823,33 +1887,43 @@ void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) State_Transition( GR_STATE_PREROUND ); } - else - { #ifdef TF_DLL - if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) + else if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && g_pPopulationManager ) + { + // one of the convars mp_timelimit, mp_winlimit, mp_maxrounds, or nextlevel has been triggered + for ( int i = 1; i <= MAX_PLAYERS; i++ ) { - // one of the convars mp_timelimit, mp_winlimit, mp_maxrounds, or nextlevel has been triggered - if ( g_pPopulationManager ) - { - for ( int i = 1; i <= MAX_PLAYERS; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; - if ( !pPlayer ) - continue; + pPlayer->AddFlag( FL_FROZEN ); + } - pPlayer->AddFlag( FL_FROZEN ); - pPlayer->ShowViewPortPanel( PANEL_SCOREBOARD ); - } + g_fGameOver = true; + g_pPopulationManager->SetMapRestartTime( gpGlobals->curtime + 10.0f ); + State_Enter( GR_STATE_GAME_OVER ); + return; + } + else if ( TFGameRules() && TFGameRules()->UsePlayerReadyStatusMode() ) + { + for ( int i = 1; i <= MAX_PLAYERS; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; - g_fGameOver = true; - g_pPopulationManager->SetMapRestartTime( gpGlobals->curtime + 10.0f ); - State_Enter( GR_STATE_GAME_OVER ); - return; - } + pPlayer->AddFlag( FL_FROZEN ); } + g_fGameOver = true; + State_Enter( GR_STATE_GAME_OVER ); + m_flStateTransitionTime = gpGlobals->curtime + GetBonusRoundTime( true ); + return; + } #endif // TF_DLL + else + { State_Transition( GR_STATE_RND_RUNNING ); } } @@ -2180,7 +2254,7 @@ int TeamScoreSort( CTeam* const *pTeam1, CTeam* const *pTeam2 ) //----------------------------------------------------------------------------- // Purpose: Input for other entities to declare a round winner. //----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetWinningTeam( int team, int iWinReason, bool bForceMapReset /* = true */, bool bSwitchTeams /* = false*/, bool bDontAddScore /* = false*/ ) +void CTeamplayRoundBasedRules::SetWinningTeam( int team, int iWinReason, bool bForceMapReset /* = true */, bool bSwitchTeams /* = false*/, bool bDontAddScore /* = false*/, bool bFinal /*= false*/ ) { // Commentary doesn't let anyone win if ( IsInCommentaryMode() ) @@ -2224,6 +2298,8 @@ void CTeamplayRoundBasedRules::SetWinningTeam( int team, int iWinReason, bool bF State_Transition( GR_STATE_TEAM_WIN ); + m_flLastTeamWin = gpGlobals->curtime; + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_round_win" ); if ( event ) { @@ -2438,6 +2514,10 @@ void CTeamplayRoundBasedRules::RestartTournament( void ) m_flStopWatchTotalTime = -1.0f; m_bStopWatch = false; + // we might have had a stalemate during the last round + // so reset this bool each time we restart the tournament + m_bChangelevelAfterStalemate = false; + for ( int i = 0; i < MAX_TEAMS; i++ ) { m_bTeamReady.Set( i, false ); @@ -2582,6 +2662,30 @@ void CTeamplayRoundBasedRules::HandleTimeLimitChange( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- +void CTeamplayRoundBasedRules::ResetPlayerAndTeamReadyState( void ) +{ + for ( int i = 0; i < MAX_TEAMS; i++ ) + { + m_bTeamReady.Set( i, false ); + } + + for ( int i = 0; i < MAX_PLAYERS; i++ ) + { + m_bPlayerReady.Set( i, false ); + } + +#ifdef GAME_DLL + // Note <= MAX_PLAYERS vs < MAX_PLAYERS above + for ( int i = 0; i <= MAX_PLAYERS; i++ ) + { + m_bPlayerReadyBefore[i] = false; + } +#endif // GAME_DLL +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- bool CTeamplayRoundBasedRules::MapHasActiveTimer( void ) { #ifndef CSTRIKE_DLL @@ -2606,6 +2710,12 @@ void CTeamplayRoundBasedRules::CreateTimeLimitTimer( void ) if ( IsInArenaMode () == true || IsInKothMode() == true ) return; + // this is the same check we use in State_Think_RND_RUNNING() + // don't show the timelimit timer if we're not going to end the map when it runs out + bool bAllowStalemate = ( m_bAllowStalemateAtTimelimit || ( mp_match_end_at_timelimit.GetBool() && !IsValveMap() ) ); + if ( !bAllowStalemate ) + return; + #ifndef CSTRIKE_DLL if ( !m_hTimeLimitTimer ) { @@ -2886,6 +2996,11 @@ void CTeamplayRoundBasedRules::BalanceTeams( bool bRequireSwitcheesToBeDead ) return; } +#if defined( _DEBUG ) || defined( STAGING_ONLY ) + if ( mp_developer.GetBool() ) + return; +#endif // _DEBUG || STAGING_ONLY + if ( IsInTraining() || IsInItemTestingMode() ) { return; @@ -3314,9 +3429,12 @@ bool CTeamplayRoundBasedRules::IsInHighlanderMode( void ) #endif } -int CTeamplayRoundBasedRules::GetBonusRoundTime( void ) +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CTeamplayRoundBasedRules::GetBonusRoundTime( bool bFinal /*= false*/ ) { - return MAX( 5, mp_bonusroundtime.GetFloat() ); + return bFinal ? mp_bonusroundtime_final.GetInt() : Max( 5, mp_bonusroundtime.GetInt() ); } //----------------------------------------------------------------------------- @@ -3330,6 +3448,11 @@ bool CTeamplayRoundBasedRules::ShouldBalanceTeams( void ) if ( IsInTraining() == true || IsInItemTestingMode() ) return false; +#if defined( _DEBUG ) || defined( STAGING_ONLY ) + if ( mp_developer.GetBool() ) + return false; +#endif // _DEBUG || STAGING_ONLY + if ( mp_teams_unbalance_limit.GetInt() <= 0 ) return false; @@ -3349,6 +3472,11 @@ bool CTeamplayRoundBasedRules::WouldChangeUnbalanceTeams( int iNewTeam, int iCur if ( ShouldBalanceTeams() == false ) return false; +#if defined( _DEBUG ) || defined( STAGING_ONLY ) + if ( mp_developer.GetBool() ) + return false; +#endif // _DEBUG || STAGING_ONLY + // if they are joining a non-playing team, allow if ( iNewTeam < FIRST_GAME_TEAM ) return false; @@ -3524,25 +3652,30 @@ void CTeamplayRoundBasedRules::ResetTeamsRoundWinTracking( void ) //----------------------------------------------------------------------------- // Purpose: Are you now, or are you ever going to be, a member of the defending party? //----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::GetMvMPotentialDefendersLobbyPlayerInfo( CUtlVector<LobbyPlayerInfo_t> &vecMvMDefenders, bool bIncludeBots /*= false*/ ) +void CTeamplayRoundBasedRules::GetPotentialPlayersLobbyPlayerInfo( CUtlVector<LobbyPlayerInfo_t> &vecLobbyPlayers, bool bIncludeBots /*= false*/ ) { - GetAllPlayersLobbyInfo( vecMvMDefenders, bIncludeBots ); + GetAllPlayersLobbyInfo( vecLobbyPlayers, bIncludeBots ); // Now scan through and remove the spectators - for (int i = vecMvMDefenders.Count() - 1 ; i >= 0 ; --i ) + for ( int i = vecLobbyPlayers.Count() - 1; i >= 0; --i ) { - switch ( vecMvMDefenders[i].m_iTeam ) + switch ( vecLobbyPlayers[i].m_iTeam ) { case TEAM_UNASSIGNED: - case TF_TEAM_PVE_DEFENDERS: + case TF_TEAM_RED: + break; + + case TF_TEAM_BLUE: + if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) + vecLobbyPlayers.FastRemove( i ); break; - default: - AssertMsg1( false, "Bogus team %d", vecMvMDefenders[i].m_iTeam ); - case TF_TEAM_PVE_INVADERS: case TEAM_SPECTATOR: - vecMvMDefenders.FastRemove( i ); + vecLobbyPlayers.FastRemove( i ); break; + + default: + AssertMsg1( false, "Bogus team %d", vecLobbyPlayers[i].m_iTeam ); } } } |