You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1543 lines
43 KiB
1543 lines
43 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Team gamerules round timer |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "teamplay_round_timer.h" |
|
#include "teamplayroundbased_gamerules.h" |
|
|
|
#ifdef CLIENT_DLL |
|
#include "iclientmode.h" |
|
#include "vgui_controls/AnimationController.h" |
|
#include "c_playerresource.h" |
|
#include "c_team_objectiveresource.h" |
|
#if defined( TF_CLIENT_DLL ) |
|
#include "tf_gamerules.h" |
|
#include "c_tf_player.h" |
|
#endif // TF_CLIENT_DLL |
|
#else |
|
#include "team.h" |
|
#include "team_objectiveresource.h" |
|
#if defined( TF_DLL ) |
|
#include "tf_player.h" |
|
#endif // TF_DLL |
|
#endif |
|
|
|
#define ROUND_TIMER_60SECS "Announcer.RoundEnds60seconds" |
|
#define ROUND_TIMER_30SECS "Announcer.RoundEnds30seconds" |
|
#define ROUND_TIMER_10SECS "Announcer.RoundEnds10seconds" |
|
#define ROUND_TIMER_5SECS "Announcer.RoundEnds5seconds" |
|
#define ROUND_TIMER_4SECS "Announcer.RoundEnds4seconds" |
|
#define ROUND_TIMER_3SECS "Announcer.RoundEnds3seconds" |
|
#define ROUND_TIMER_2SECS "Announcer.RoundEnds2seconds" |
|
#define ROUND_TIMER_1SECS "Announcer.RoundEnds1seconds" |
|
|
|
#define ROUND_SETUP_60SECS "Announcer.RoundBegins60Seconds" |
|
#define ROUND_SETUP_30SECS "Announcer.RoundBegins30Seconds" |
|
#define ROUND_SETUP_10SECS "Announcer.RoundBegins10Seconds" |
|
#define ROUND_SETUP_5SECS "Announcer.RoundBegins5Seconds" |
|
#define ROUND_SETUP_4SECS "Announcer.RoundBegins4Seconds" |
|
#define ROUND_SETUP_3SECS "Announcer.RoundBegins3Seconds" |
|
#define ROUND_SETUP_2SECS "Announcer.RoundBegins2Seconds" |
|
#define ROUND_SETUP_1SECS "Announcer.RoundBegins1Seconds" |
|
|
|
#ifdef TF_CLIENT_DLL |
|
#define MERASMUS_SETUP_5SECS "Merasmus.RoundBegins5Seconds" |
|
#define MERASMUS_SETUP_4SECS "Merasmus.RoundBegins4Seconds" |
|
#define MERASMUS_SETUP_3SECS "Merasmus.RoundBegins3Seconds" |
|
#define MERASMUS_SETUP_2SECS "Merasmus.RoundBegins2Seconds" |
|
#define MERASMUS_SETUP_1SECS "Merasmus.RoundBegins1Seconds" |
|
#endif |
|
|
|
#define ROUND_START_BELL "Ambient.Siren" |
|
|
|
#define ROUND_TIMER_TIME_ADDED "Announcer.TimeAdded" |
|
#define ROUND_TIMER_TIME_ADDED_LOSER "Announcer.TimeAddedForEnemy" |
|
#define ROUND_TIMER_TIME_ADDED_WINNER "Announcer.TimeAwardedForTeam" |
|
|
|
enum |
|
{ |
|
RT_THINK_SETUP, |
|
RT_THINK_NORMAL, |
|
}; |
|
|
|
enum |
|
{ |
|
RT_WARNING_60SECS, |
|
RT_WARNING_30SECS, |
|
RT_WARNING_10SECS, |
|
RT_WARNING_5SECS, |
|
RT_WARNING_4SECS, |
|
RT_WARNING_3SECS, |
|
RT_WARNING_2SECS, |
|
RT_WARNING_1SECS, |
|
RT_WARNING_TIME_START, |
|
}; |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
extern bool IsInCommentaryMode(); |
|
|
|
#if defined( GAME_DLL ) && defined( TF_DLL ) |
|
ConVar tf_overtime_nag( "tf_overtime_nag", "0", FCVAR_NOTIFY, "Announcer overtime nag." ); |
|
#endif |
|
|
|
#ifdef CLIENT_DLL |
|
|
|
// Use this proxy to flash the round timer whenever the timer is restarted |
|
// because trapping the round start event doesn't work ( the event also flushes |
|
// all hud events and obliterates our TimerFlash event ) |
|
static void RecvProxy_TimerPaused( const CRecvProxyData *pData, void *pStruct, void *pOut ) |
|
{ |
|
CTeamRoundTimer *pTimer = (CTeamRoundTimer *) pStruct; |
|
|
|
bool bTimerPaused = ( pData->m_Value.m_Int > 0 ); |
|
|
|
if ( bTimerPaused == false ) |
|
{ |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "TimerFlash" ); |
|
} |
|
|
|
if ( pTimer ) |
|
{ |
|
pTimer->InternalSetPaused( bTimerPaused ); |
|
} |
|
} |
|
|
|
#endif |
|
|
|
LINK_ENTITY_TO_CLASS( team_round_timer, CTeamRoundTimer ); |
|
PRECACHE_REGISTER( team_round_timer ); |
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( TeamRoundTimer, DT_TeamRoundTimer ) |
|
|
|
BEGIN_NETWORK_TABLE_NOBASE( CTeamRoundTimer, DT_TeamRoundTimer ) |
|
#ifdef CLIENT_DLL |
|
|
|
RecvPropInt( RECVINFO( m_bTimerPaused ), 0, RecvProxy_TimerPaused ), |
|
RecvPropTime( RECVINFO( m_flTimeRemaining ) ), |
|
RecvPropTime( RECVINFO( m_flTimerEndTime ) ), |
|
RecvPropInt( RECVINFO( m_nTimerMaxLength ) ), |
|
RecvPropBool( RECVINFO( m_bIsDisabled ) ), |
|
RecvPropBool( RECVINFO( m_bShowInHUD ) ), |
|
RecvPropInt( RECVINFO( m_nTimerLength ) ), |
|
RecvPropInt( RECVINFO( m_nTimerInitialLength ) ), |
|
RecvPropBool( RECVINFO( m_bAutoCountdown ) ), |
|
RecvPropInt( RECVINFO( m_nSetupTimeLength ) ), |
|
RecvPropInt( RECVINFO( m_nState ) ), |
|
RecvPropBool( RECVINFO( m_bStartPaused ) ), |
|
RecvPropBool( RECVINFO( m_bShowTimeRemaining ) ), |
|
RecvPropBool( RECVINFO( m_bInCaptureWatchState ) ), |
|
RecvPropBool( RECVINFO( m_bStopWatchTimer ) ), |
|
RecvPropTime( RECVINFO( m_flTotalTime ) ), |
|
|
|
#else |
|
|
|
SendPropBool( SENDINFO( m_bTimerPaused ) ), |
|
SendPropTime( SENDINFO( m_flTimeRemaining ) ), |
|
SendPropTime( SENDINFO( m_flTimerEndTime ) ), |
|
SendPropInt( SENDINFO( m_nTimerMaxLength ) ), |
|
SendPropBool( SENDINFO( m_bIsDisabled ) ), |
|
SendPropBool( SENDINFO( m_bShowInHUD ) ), |
|
SendPropInt( SENDINFO( m_nTimerLength ) ), |
|
SendPropInt( SENDINFO( m_nTimerInitialLength ) ), |
|
SendPropBool( SENDINFO( m_bAutoCountdown ) ), |
|
SendPropInt( SENDINFO( m_nSetupTimeLength ) ), |
|
SendPropInt( SENDINFO( m_nState ) ), |
|
SendPropBool( SENDINFO( m_bStartPaused ) ), |
|
SendPropBool( SENDINFO( m_bShowTimeRemaining ) ), |
|
SendPropBool( SENDINFO( m_bStopWatchTimer ) ), |
|
SendPropBool( SENDINFO( m_bInCaptureWatchState ) ), |
|
SendPropTime( SENDINFO( m_flTotalTime ) ), |
|
|
|
#endif |
|
END_NETWORK_TABLE() |
|
|
|
#ifndef CLIENT_DLL |
|
BEGIN_DATADESC(CTeamRoundTimer) |
|
DEFINE_KEYFIELD( m_nTimerInitialLength, FIELD_INTEGER, "timer_length" ), |
|
DEFINE_KEYFIELD( m_nTimerMaxLength, FIELD_INTEGER, "max_length" ), |
|
DEFINE_KEYFIELD( m_bShowInHUD, FIELD_BOOLEAN, "show_in_hud" ), |
|
DEFINE_KEYFIELD( m_bIsDisabled, FIELD_BOOLEAN, "StartDisabled" ), |
|
DEFINE_KEYFIELD( m_bAutoCountdown, FIELD_BOOLEAN, "auto_countdown" ), |
|
DEFINE_KEYFIELD( m_nSetupTimeLength, FIELD_INTEGER, "setup_length" ), |
|
DEFINE_KEYFIELD( m_bResetTimeOnRoundStart, FIELD_BOOLEAN, "reset_time" ), |
|
DEFINE_KEYFIELD( m_bStartPaused, FIELD_BOOLEAN, "start_paused" ), |
|
DEFINE_KEYFIELD( m_bShowTimeRemaining, FIELD_BOOLEAN, "show_time_remaining" ), |
|
|
|
DEFINE_FUNCTION( RoundTimerSetupThink ), |
|
DEFINE_FUNCTION( RoundTimerThink ), |
|
|
|
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Pause", InputPause ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Resume", InputResume ), |
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTime", InputSetTime ), |
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "AddTime", InputAddTime ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Restart", InputRestart ), |
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "ShowInHUD", InputShowInHUD ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ), |
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxTime", InputSetMaxTime ), |
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "AutoCountdown", InputAutoCountdown ), |
|
DEFINE_INPUTFUNC( FIELD_STRING, "AddTeamTime", InputAddTeamTime ), |
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetSetupTime", InputSetSetupTime ), |
|
|
|
DEFINE_OUTPUT( m_OnRoundStart, "OnRoundStart" ), |
|
DEFINE_OUTPUT( m_OnFinished, "OnFinished" ), |
|
DEFINE_OUTPUT( m_On5MinRemain, "On5MinRemain" ), |
|
DEFINE_OUTPUT( m_On4MinRemain, "On4MinRemain" ), |
|
DEFINE_OUTPUT( m_On3MinRemain, "On3MinRemain" ), |
|
DEFINE_OUTPUT( m_On2MinRemain, "On2MinRemain" ), |
|
DEFINE_OUTPUT( m_On1MinRemain, "On1MinRemain" ), |
|
DEFINE_OUTPUT( m_On30SecRemain, "On30SecRemain" ), |
|
DEFINE_OUTPUT( m_On10SecRemain, "On10SecRemain" ), |
|
DEFINE_OUTPUT( m_On5SecRemain, "On5SecRemain" ), |
|
DEFINE_OUTPUT( m_On4SecRemain, "On4SecRemain" ), |
|
DEFINE_OUTPUT( m_On3SecRemain, "On3SecRemain" ), |
|
DEFINE_OUTPUT( m_On2SecRemain, "On2SecRemain" ), |
|
DEFINE_OUTPUT( m_On1SecRemain, "On1SecRemain" ), |
|
DEFINE_OUTPUT( m_OnSetupStart, "OnSetupStart" ), |
|
DEFINE_OUTPUT( m_OnSetupFinished, "OnSetupFinished" ), |
|
|
|
END_DATADESC(); |
|
#endif |
|
|
|
#ifndef CLIENT_DLL |
|
#define ROUND_TIMER_THINK "CTeamplayRoundTimerThink" |
|
#define ROUND_TIMER_SETUP_THINK "CTeamplayRoundTimerSetupThink" |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: constructor |
|
//----------------------------------------------------------------------------- |
|
CTeamRoundTimer::CTeamRoundTimer( void ) |
|
{ |
|
m_bTimerPaused = false; |
|
m_flTimeRemaining = 0; |
|
m_nTimerLength = 0; |
|
m_nTimerInitialLength = 0; |
|
m_nTimerMaxLength = 0; |
|
m_flTimerEndTime = 0; |
|
m_bIsDisabled = false; |
|
m_bAutoCountdown = true; |
|
m_nState.Set( RT_STATE_NORMAL ); // we'll assume no setup time for now |
|
m_bStartPaused = true; |
|
m_bShowTimeRemaining = true; |
|
|
|
m_bFireFinished = true; |
|
m_bFire5MinRemain = true; |
|
m_bFire4MinRemain = true; |
|
m_bFire3MinRemain = true; |
|
m_bFire2MinRemain = true; |
|
m_bFire1MinRemain = true; |
|
m_bFire30SecRemain = true; |
|
m_bFire10SecRemain = true; |
|
m_bFire5SecRemain = true; |
|
m_bFire4SecRemain = true; |
|
m_bFire3SecRemain = true; |
|
m_bFire2SecRemain = true; |
|
m_bFire1SecRemain = true; |
|
|
|
m_bStopWatchTimer = false; |
|
|
|
m_flTotalTime = 0.0f; |
|
|
|
m_nSetupTimeLength = 0; |
|
|
|
#ifndef CLIENT_DLL |
|
m_bPauseDueToWin = false; |
|
m_bResetTimeOnRoundStart = false; |
|
m_nTimeToUseAfterSetupFinished = 0; |
|
m_flNextOvertimeNag = 0; |
|
m_flLastTime = 0.f; |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: destructor |
|
//----------------------------------------------------------------------------- |
|
CTeamRoundTimer::~CTeamRoundTimer( void ) |
|
{ |
|
|
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: destructor |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::Precache( void ) |
|
{ |
|
#if defined( TF_DLL ) || defined( TF_CLIENT_DLL ) |
|
PrecacheScriptSound( ROUND_TIMER_60SECS ); |
|
PrecacheScriptSound( ROUND_TIMER_30SECS ); |
|
PrecacheScriptSound( ROUND_TIMER_10SECS ); |
|
PrecacheScriptSound( ROUND_TIMER_5SECS ); |
|
PrecacheScriptSound( ROUND_TIMER_4SECS ); |
|
PrecacheScriptSound( ROUND_TIMER_3SECS ); |
|
PrecacheScriptSound( ROUND_TIMER_2SECS ); |
|
PrecacheScriptSound( ROUND_TIMER_1SECS ); |
|
PrecacheScriptSound( ROUND_SETUP_60SECS ); |
|
PrecacheScriptSound( ROUND_SETUP_30SECS ); |
|
PrecacheScriptSound( ROUND_SETUP_10SECS ); |
|
PrecacheScriptSound( ROUND_SETUP_5SECS ); |
|
PrecacheScriptSound( ROUND_SETUP_4SECS ); |
|
PrecacheScriptSound( ROUND_SETUP_3SECS ); |
|
PrecacheScriptSound( ROUND_SETUP_2SECS ); |
|
PrecacheScriptSound( ROUND_SETUP_1SECS ); |
|
PrecacheScriptSound( ROUND_TIMER_TIME_ADDED ); |
|
PrecacheScriptSound( ROUND_TIMER_TIME_ADDED_LOSER ); |
|
PrecacheScriptSound( ROUND_TIMER_TIME_ADDED_WINNER ); |
|
PrecacheScriptSound( ROUND_START_BELL ); |
|
|
|
#ifdef TF_CLIENT_DLL |
|
PrecacheScriptSound( MERASMUS_SETUP_5SECS ); |
|
PrecacheScriptSound( MERASMUS_SETUP_4SECS ); |
|
PrecacheScriptSound( MERASMUS_SETUP_3SECS ); |
|
PrecacheScriptSound( MERASMUS_SETUP_2SECS ); |
|
PrecacheScriptSound( MERASMUS_SETUP_1SECS ); |
|
#endif // TF_CLIENT_DLL |
|
#endif // TF_DLL || TF_CLIENT_DLL |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::Activate( void ) |
|
{ |
|
BaseClass::Activate(); |
|
|
|
#ifndef CLIENT_DLL |
|
if ( m_bShowInHUD ) |
|
{ |
|
SetActiveTimer( this ); |
|
} |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::Spawn( void ) |
|
{ |
|
Precache(); |
|
|
|
#ifdef CLIENT_DLL |
|
SetNextClientThink( CLIENT_THINK_ALWAYS ); |
|
#else |
|
|
|
int nTimerTime = 0; |
|
|
|
// do we have a setup time? |
|
if ( m_nSetupTimeLength > 0 ) |
|
{ |
|
nTimerTime = m_nSetupTimeLength; |
|
SetState( RT_STATE_SETUP ); |
|
} |
|
else |
|
{ |
|
nTimerTime = m_nTimerInitialLength; |
|
SetState( RT_STATE_NORMAL ); |
|
} |
|
|
|
m_nTimeToUseAfterSetupFinished = m_nTimerInitialLength; |
|
|
|
if ( IsDisabled() ) // we need to get the data initialized before actually become disabled |
|
{ |
|
m_bIsDisabled = false; |
|
PauseTimer(); // start paused |
|
SetTimeRemaining( nTimerTime ); |
|
m_bIsDisabled = true; |
|
} |
|
else |
|
{ |
|
PauseTimer(); // start paused |
|
SetTimeRemaining( nTimerTime ); |
|
} |
|
|
|
m_nTimerLength = nTimerTime; |
|
|
|
BaseClass::Spawn(); |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTeamRoundTimer::ShowInHud( void ) |
|
{ |
|
return m_bShowInHUD; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Gets the seconds left on the timer, paused or not. |
|
//----------------------------------------------------------------------------- |
|
float CTeamRoundTimer::GetTimeRemaining( void ) |
|
{ |
|
float flSecondsRemaining; |
|
|
|
if ( IsStopWatchTimer() == true && m_bInCaptureWatchState == true ) |
|
{ |
|
flSecondsRemaining = m_flTotalTime; |
|
} |
|
else |
|
{ |
|
if ( m_bTimerPaused ) |
|
{ |
|
flSecondsRemaining = m_flTimeRemaining; |
|
} |
|
else |
|
{ |
|
flSecondsRemaining = m_flTimerEndTime - gpGlobals->curtime; |
|
} |
|
} |
|
|
|
if ( flSecondsRemaining < 0 ) |
|
{ |
|
flSecondsRemaining = 0.0f; |
|
} |
|
|
|
return flSecondsRemaining; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::SetCaptureWatchState( bool bCaptureWatch ) |
|
{ |
|
m_bInCaptureWatchState = bCaptureWatch; |
|
|
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CTeamRoundTimer::GetTimerMaxLength( void ) |
|
{ |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
return m_nSetupTimeLength; |
|
} |
|
else |
|
{ |
|
if ( m_nTimerMaxLength ) |
|
return m_nTimerMaxLength; |
|
|
|
return m_nTimerLength; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::CalculateOutputMessages( void ) |
|
{ |
|
float flTime = GetTimeRemaining(); |
|
|
|
#ifndef GAME_DLL |
|
// We need to add a couple seconds to the time remaining because we've probably lost ~0.5 seconds from the timer while |
|
// waiting for the update to arrive from the server and we don't want to miss any critical countdown messages. If the time |
|
// remaining is over 10 seconds...adding 2 seconds to the total when calculating our output messages won't affect anything |
|
if ( flTime > 10.0f ) |
|
{ |
|
flTime += 2.0f; |
|
} |
|
#endif |
|
|
|
m_bFireFinished = ( flTime > 0.0f ); |
|
m_bFire5MinRemain = ( flTime >= 300.0f ); |
|
m_bFire4MinRemain = ( flTime >= 240.0f ); |
|
m_bFire3MinRemain = ( flTime >= 180.0f ); |
|
m_bFire2MinRemain = ( flTime >= 120.0f ); |
|
m_bFire1MinRemain = ( flTime >= 60.0f ); |
|
m_bFire30SecRemain = ( flTime >= 30.0f ); |
|
m_bFire10SecRemain = ( flTime >= 10.0f ); |
|
m_bFire5SecRemain = ( flTime >= 5.0f ); |
|
m_bFire4SecRemain = ( flTime >= 4.0f ); |
|
m_bFire3SecRemain = ( flTime >= 3.0f ); |
|
m_bFire2SecRemain = ( flTime >= 2.0f ); |
|
m_bFire1SecRemain = ( flTime >= 1.0f ); |
|
} |
|
|
|
#ifdef CLIENT_DLL |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::ClientThink() |
|
{ |
|
if ( IsDisabled() || m_bTimerPaused || IsInCommentaryMode() ) |
|
return; |
|
|
|
if ( IsStopWatchTimer() == true && IsWatchingTimeStamps() == true ) |
|
return; |
|
|
|
float flTime = GetTimeRemaining(); |
|
|
|
if ( flTime <= 61.0 && m_bFire1MinRemain ) |
|
{ |
|
m_bFire1MinRemain = false; |
|
SendTimeWarning( RT_WARNING_60SECS ); |
|
} |
|
else if ( flTime <= 31.0 && m_bFire30SecRemain ) |
|
{ |
|
m_bFire30SecRemain = false; |
|
SendTimeWarning( RT_WARNING_30SECS ); |
|
} |
|
else if ( flTime <= 11.0 && m_bFire10SecRemain ) |
|
{ |
|
m_bFire10SecRemain = false; |
|
SendTimeWarning( RT_WARNING_10SECS ); |
|
} |
|
else if ( flTime <= 6.0 && m_bFire5SecRemain ) |
|
{ |
|
m_bFire5SecRemain = false; |
|
SendTimeWarning( RT_WARNING_5SECS ); |
|
} |
|
else if ( flTime <= 5.0 && m_bFire4SecRemain ) |
|
{ |
|
m_bFire4SecRemain = false; |
|
SendTimeWarning( RT_WARNING_4SECS ); |
|
} |
|
else if ( flTime <= 4.0 && m_bFire3SecRemain ) |
|
{ |
|
m_bFire3SecRemain = false; |
|
SendTimeWarning( RT_WARNING_3SECS ); |
|
} |
|
else if ( flTime <= 3.0 && m_bFire2SecRemain ) |
|
{ |
|
m_bFire2SecRemain = false; |
|
SendTimeWarning( RT_WARNING_2SECS ); |
|
} |
|
else if ( flTime <= 2.0 && m_bFire1SecRemain ) |
|
{ |
|
m_bFire1SecRemain = false; |
|
SendTimeWarning( RT_WARNING_1SECS ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::OnPreDataChanged( DataUpdateType_t updateType ) |
|
{ |
|
BaseClass::OnPreDataChanged( updateType ); |
|
|
|
m_nOldTimerLength = m_nTimerLength; |
|
m_nOldTimerState = m_nState; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::OnDataChanged( DataUpdateType_t updateType ) |
|
{ |
|
BaseClass::OnDataChanged( updateType ); |
|
|
|
if ( m_nOldTimerLength != m_nTimerLength ) |
|
{ |
|
// recalculate our output messages because the timer length has changed |
|
CalculateOutputMessages(); |
|
} |
|
|
|
// if we were in state_setup and now we're in state_normal, play the bell sound |
|
if ( ( m_nOldTimerState == RT_STATE_SETUP ) && ( m_nState == RT_STATE_NORMAL ) ) |
|
{ |
|
SendTimeWarning( RT_WARNING_TIME_START ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char *CTeamRoundTimer::GetTimeWarningSound( int nWarning ) |
|
{ |
|
const char *pszRetVal; |
|
|
|
switch( nWarning ) |
|
{ |
|
case RT_WARNING_60SECS: |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
pszRetVal = ROUND_SETUP_60SECS; |
|
} |
|
else |
|
{ |
|
pszRetVal = ROUND_TIMER_60SECS; |
|
} |
|
break; |
|
case RT_WARNING_30SECS: |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
pszRetVal = ROUND_SETUP_30SECS; |
|
} |
|
else |
|
{ |
|
pszRetVal = ROUND_TIMER_30SECS; |
|
} |
|
break; |
|
case RT_WARNING_10SECS: |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
pszRetVal = ROUND_SETUP_10SECS; |
|
} |
|
else |
|
{ |
|
pszRetVal = ROUND_TIMER_10SECS; |
|
} |
|
break; |
|
case RT_WARNING_5SECS: |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
#ifdef TF_CLIENT_DLL |
|
if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) |
|
{ |
|
pszRetVal = MERASMUS_SETUP_5SECS; |
|
} |
|
else |
|
#endif |
|
{ |
|
pszRetVal = ROUND_SETUP_5SECS; |
|
} |
|
} |
|
else |
|
{ |
|
pszRetVal = ROUND_TIMER_5SECS; |
|
} |
|
break; |
|
case RT_WARNING_4SECS: |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
#ifdef TF_CLIENT_DLL |
|
if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) |
|
{ |
|
pszRetVal = MERASMUS_SETUP_4SECS; |
|
} |
|
else |
|
#endif |
|
{ |
|
pszRetVal = ROUND_SETUP_4SECS; |
|
} |
|
} |
|
else |
|
{ |
|
pszRetVal = ROUND_TIMER_4SECS; |
|
} |
|
break; |
|
case RT_WARNING_3SECS: |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
#ifdef TF_CLIENT_DLL |
|
if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) |
|
{ |
|
pszRetVal = MERASMUS_SETUP_3SECS; |
|
} |
|
else |
|
#endif |
|
{ |
|
pszRetVal = ROUND_SETUP_3SECS; |
|
} |
|
} |
|
else |
|
{ |
|
pszRetVal = ROUND_TIMER_3SECS; |
|
} |
|
break; |
|
case RT_WARNING_2SECS: |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
#ifdef TF_CLIENT_DLL |
|
if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) |
|
{ |
|
pszRetVal = MERASMUS_SETUP_2SECS; |
|
} |
|
else |
|
#endif |
|
{ |
|
pszRetVal = ROUND_SETUP_2SECS; |
|
} |
|
} |
|
else |
|
{ |
|
pszRetVal = ROUND_TIMER_2SECS; |
|
} |
|
break; |
|
case RT_WARNING_1SECS: |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
#ifdef TF_CLIENT_DLL |
|
if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) |
|
{ |
|
pszRetVal = MERASMUS_SETUP_1SECS; |
|
} |
|
else |
|
#endif |
|
{ |
|
pszRetVal = ROUND_SETUP_1SECS; |
|
} |
|
} |
|
else |
|
{ |
|
pszRetVal = ROUND_TIMER_1SECS; |
|
} |
|
break; |
|
case RT_WARNING_TIME_START: |
|
pszRetVal = ROUND_START_BELL; |
|
break; |
|
default: |
|
pszRetVal = ""; |
|
} |
|
|
|
return pszRetVal; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::SendTimeWarning( int nWarning ) |
|
{ |
|
#if defined( TF_CLIENT_DLL ) |
|
// don't play any time warnings for Helltower |
|
if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_HIGHTOWER ) ) |
|
return; |
|
#endif |
|
|
|
// don't play sounds if the level designer has turned them off or if it's during the WaitingForPlayers time |
|
if ( !m_bTimerPaused && m_bAutoCountdown && !TeamplayRoundBasedRules()->IsInWaitingForPlayers() ) |
|
{ |
|
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); |
|
if ( pPlayer ) |
|
{ |
|
if ( ObjectiveResource() ) |
|
{ |
|
bool bShouldPlaySound = false; |
|
|
|
if ( TeamplayRoundBasedRules()->IsInTournamentMode() == true && TeamplayRoundBasedRules()->IsInStopWatch() == true ) |
|
{ |
|
int iActiveTimer = ObjectiveResource()->GetTimerToShowInHUD(); |
|
int iStopWatchTimer = ObjectiveResource()->GetStopWatchTimer(); |
|
|
|
if ( IsStopWatchTimer() == true && IsWatchingTimeStamps() == false ) |
|
{ |
|
CTeamRoundTimer *pTimer = dynamic_cast< CTeamRoundTimer* >( ClientEntityList().GetEnt( iActiveTimer ) ); |
|
|
|
if ( pTimer && pTimer->IsTimerPaused() == false && pTimer->GetTimeRemaining() > GetTimeRemaining() ) |
|
{ |
|
bShouldPlaySound = true; |
|
} |
|
} |
|
else |
|
{ |
|
CTeamRoundTimer *pStopWatch = dynamic_cast< CTeamRoundTimer* >( ClientEntityList().GetEnt( iStopWatchTimer ) ); |
|
|
|
if ( ObjectiveResource()->GetTimerToShowInHUD() == entindex() ) |
|
{ |
|
if ( pStopWatch ) |
|
{ |
|
if ( pStopWatch->IsTimerPaused() == true ) |
|
{ |
|
bShouldPlaySound = true; |
|
} |
|
|
|
if ( pStopWatch->GetTimeRemaining() > GetTimeRemaining() && pStopWatch->IsWatchingTimeStamps() == false ) |
|
{ |
|
bShouldPlaySound = true; |
|
} |
|
|
|
if ( pStopWatch->IsWatchingTimeStamps() == true ) |
|
{ |
|
bShouldPlaySound = true; |
|
} |
|
} |
|
else |
|
{ |
|
bShouldPlaySound = true; |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if( ObjectiveResource()->GetTimerToShowInHUD() == entindex() ) |
|
{ |
|
bShouldPlaySound = true; |
|
} |
|
|
|
if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->IsInKothMode() ) |
|
{ |
|
bShouldPlaySound = true; |
|
} |
|
} |
|
|
|
#ifdef TF_CLIENT_DLL |
|
if ( bShouldPlaySound == true ) |
|
{ |
|
pPlayer->EmitSound( GetTimeWarningSound( nWarning ) ); |
|
} |
|
#endif // TF_CLIENT_DLL |
|
} |
|
} |
|
} |
|
} |
|
|
|
#else |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::SetState( int nState, bool bFireOutput ) |
|
{ |
|
m_nState = nState; |
|
|
|
if ( nState == RT_STATE_SETUP ) |
|
{ |
|
if ( IsStopWatchTimer() == false ) |
|
{ |
|
TeamplayRoundBasedRules()->SetSetup( true ); |
|
} |
|
|
|
SetTimerThink( RT_THINK_SETUP ); |
|
|
|
if ( bFireOutput ) |
|
{ |
|
m_OnSetupStart.FireOutput( this, this ); |
|
} |
|
} |
|
else |
|
{ |
|
if ( IsStopWatchTimer() == false ) |
|
{ |
|
TeamplayRoundBasedRules()->SetSetup( false ); |
|
} |
|
|
|
SetTimerThink( RT_THINK_NORMAL ); |
|
|
|
if ( bFireOutput ) |
|
{ |
|
m_OnRoundStart.FireOutput( this, this ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::SetTimerThink( int nType ) |
|
{ |
|
if ( nType == RT_THINK_SETUP ) |
|
{ |
|
SetContextThink( &CTeamRoundTimer::RoundTimerSetupThink, gpGlobals->curtime + 0.05, ROUND_TIMER_SETUP_THINK ); |
|
SetContextThink( NULL, 0, ROUND_TIMER_THINK ); |
|
} |
|
else |
|
{ |
|
SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); |
|
SetContextThink( NULL, 0, ROUND_TIMER_SETUP_THINK ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::RoundTimerSetupThink( void ) |
|
{ |
|
float flLastTime = m_flLastTime; |
|
m_flLastTime = GetTimeRemaining(); |
|
|
|
if ( TeamplayRoundBasedRules()->IsInPreMatch() == true && IsDisabled() == false ) |
|
{ |
|
inputdata_t data; |
|
InputDisable( data ); |
|
m_OnSetupFinished.FireOutput( this, this ); |
|
} |
|
|
|
if ( IsDisabled() || m_bTimerPaused ) |
|
{ |
|
SetContextThink( &CTeamRoundTimer::RoundTimerSetupThink, gpGlobals->curtime + 0.05, ROUND_TIMER_SETUP_THINK ); |
|
return; |
|
} |
|
|
|
float flTime = GetTimeRemaining(); |
|
TeamplayRoundBasedRules()->SetOvertime( false ); |
|
|
|
if ( m_flLastTime > 0.f ) |
|
{ |
|
int nLastSecond = floor( flLastTime ); |
|
int nThisSecond = floor( flTime ); |
|
|
|
if ( nLastSecond != nThisSecond ) |
|
{ |
|
IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_pre_round_time_left" ); |
|
if ( event ) |
|
{ |
|
event->SetInt( "time", nThisSecond ); |
|
gameeventmanager->FireEvent( event ); |
|
} |
|
} |
|
} |
|
|
|
if ( flTime <= 0.0f && m_bFireFinished ) |
|
{ |
|
IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_setup_finished" ); |
|
if ( event ) |
|
{ |
|
gameeventmanager->FireEvent( event ); |
|
} |
|
|
|
m_OnSetupFinished.FireOutput( this, this ); |
|
m_bFireFinished = false; |
|
|
|
SetState( RT_STATE_NORMAL ); |
|
SetTimeRemaining( m_nTimeToUseAfterSetupFinished ); |
|
|
|
if ( ShowInHud() && !TeamplayRoundBasedRules()->IsInWaitingForPlayers() ) |
|
{ |
|
UTIL_LogPrintf( "World triggered \"Round_Setup_End\"\n" ); |
|
} |
|
return; |
|
} |
|
else if ( flTime <= 60.0 && m_bFire1MinRemain ) |
|
{ |
|
m_On1MinRemain.FireOutput( this, this ); |
|
m_bFire1MinRemain = false; |
|
} |
|
else if ( flTime <= 30.0 && m_bFire30SecRemain ) |
|
{ |
|
m_On30SecRemain.FireOutput( this, this ); |
|
m_bFire30SecRemain = false; |
|
} |
|
else if ( flTime <= 10.0 && m_bFire10SecRemain ) |
|
{ |
|
m_On10SecRemain.FireOutput( this, this ); |
|
m_bFire10SecRemain = false; |
|
} |
|
else if ( flTime <= 5.0 && m_bFire5SecRemain ) |
|
{ |
|
m_On5SecRemain.FireOutput( this, this ); |
|
m_bFire5SecRemain = false; |
|
} |
|
else if ( flTime <= 4.0 && m_bFire4SecRemain ) |
|
{ |
|
m_On4SecRemain.FireOutput( this, this ); |
|
m_bFire4SecRemain = false; |
|
} |
|
else if ( flTime <= 3.0 && m_bFire3SecRemain ) |
|
{ |
|
m_On3SecRemain.FireOutput( this, this ); |
|
m_bFire3SecRemain = false; |
|
} |
|
else if ( flTime <= 2.0 && m_bFire2SecRemain ) |
|
{ |
|
m_On2SecRemain.FireOutput( this, this ); |
|
m_bFire2SecRemain = false; |
|
} |
|
else if ( flTime <= 1.0 && m_bFire1SecRemain ) |
|
{ |
|
m_On1SecRemain.FireOutput( this, this ); |
|
m_bFire1SecRemain = false; |
|
} |
|
|
|
SetContextThink( &CTeamRoundTimer::RoundTimerSetupThink, gpGlobals->curtime + 0.05, ROUND_TIMER_SETUP_THINK ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::RoundTimerThink( void ) |
|
{ |
|
if ( TeamplayRoundBasedRules()->IsInPreMatch() == true && IsDisabled() == false ) |
|
{ |
|
inputdata_t data; |
|
InputDisable( data ); |
|
} |
|
|
|
if ( IsDisabled() || m_bTimerPaused || IsInCommentaryMode() || gpGlobals->eLoadType == MapLoad_Background ) |
|
{ |
|
SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); |
|
return; |
|
} |
|
|
|
// Don't do anything when the game has been won or if we're loading a bugbait report |
|
if ( TeamplayRoundBasedRules()->RoundHasBeenWon() || |
|
TeamplayRoundBasedRules()->IsLoadingBugBaitReport() ) |
|
{ |
|
// We want to stop timers when the round has been won, but we don't want to |
|
// force mapmakers to deal with having to unpause it. This little hack works around that. |
|
if ( !m_bTimerPaused ) |
|
{ |
|
PauseTimer(); |
|
m_bPauseDueToWin = true; |
|
} |
|
|
|
SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); |
|
return; |
|
} |
|
else if ( m_bPauseDueToWin ) |
|
{ |
|
ResumeTimer(); |
|
m_bPauseDueToWin = false; |
|
} |
|
|
|
float flTime = GetTimeRemaining(); |
|
|
|
if ( flTime > 0 && ShowInHud() ) // is this the timer we're showing in the HUD? |
|
{ |
|
TeamplayRoundBasedRules()->SetOvertime( false ); |
|
} |
|
|
|
if ( flTime <= 0.0f && m_bFireFinished ) |
|
{ |
|
// Allow the gamerules to prevent timer expiration (i.e. while a control point is contested) |
|
if ( !TeamplayGameRules()->TimerMayExpire() ) |
|
{ |
|
// we don't want the timer to keep going (negative time) |
|
m_flTimerEndTime = gpGlobals->curtime; |
|
|
|
// is this the timer we're showing in the HUD? |
|
if ( ShowInHud() ) |
|
{ |
|
if ( !TeamplayRoundBasedRules()->InOvertime() ) |
|
{ |
|
TeamplayRoundBasedRules()->SetOvertime( true ); |
|
} |
|
#if defined( TF_DLL ) |
|
else |
|
{ |
|
if ( tf_overtime_nag.GetBool() && ( gpGlobals->curtime > m_flNextOvertimeNag ) ) |
|
{ |
|
m_flNextOvertimeNag = gpGlobals->curtime + 1.0f; |
|
|
|
if ( RandomInt( 0, 1 ) > 0 ) |
|
{ |
|
IGameEvent *event = gameeventmanager->CreateEvent( "overtime_nag" ); |
|
if ( event ) |
|
{ |
|
gameeventmanager->FireEvent( event ); |
|
} |
|
} |
|
} |
|
} |
|
#endif |
|
} |
|
|
|
SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); |
|
return; |
|
} |
|
|
|
m_OnFinished.FireOutput( this, this ); |
|
m_bFireFinished = false; |
|
} |
|
else if ( flTime <= 300.0 && m_bFire5MinRemain ) |
|
{ |
|
m_On5MinRemain.FireOutput( this, this ); |
|
m_bFire5MinRemain = false; |
|
} |
|
else if ( flTime <= 240.0 && m_bFire4MinRemain ) |
|
{ |
|
m_On4MinRemain.FireOutput( this, this ); |
|
m_bFire4MinRemain = false; |
|
} |
|
else if ( flTime <= 180.0 && m_bFire3MinRemain ) |
|
{ |
|
m_On3MinRemain.FireOutput( this, this ); |
|
m_bFire3MinRemain = false; |
|
} |
|
else if ( flTime <= 120.0 && m_bFire2MinRemain ) |
|
{ |
|
m_On2MinRemain.FireOutput( this, this ); |
|
m_bFire2MinRemain = false; |
|
} |
|
else if ( flTime <= 60.0 && m_bFire1MinRemain ) |
|
{ |
|
m_On1MinRemain.FireOutput( this, this ); |
|
m_bFire1MinRemain = false; |
|
} |
|
else if ( flTime <= 30.0 && m_bFire30SecRemain ) |
|
{ |
|
m_On30SecRemain.FireOutput( this, this ); |
|
m_bFire30SecRemain = false; |
|
} |
|
else if ( flTime <= 10.0 && m_bFire10SecRemain ) |
|
{ |
|
m_On10SecRemain.FireOutput( this, this ); |
|
m_bFire10SecRemain = false; |
|
} |
|
else if ( flTime <= 5.0 && m_bFire5SecRemain ) |
|
{ |
|
m_On5SecRemain.FireOutput( this, this ); |
|
m_bFire5SecRemain = false; |
|
} |
|
else if ( flTime <= 4.0 && m_bFire4SecRemain ) |
|
{ |
|
m_On4SecRemain.FireOutput( this, this ); |
|
m_bFire4SecRemain = false; |
|
} |
|
else if ( flTime <= 3.0 && m_bFire3SecRemain ) |
|
{ |
|
m_On3SecRemain.FireOutput( this, this ); |
|
m_bFire3SecRemain = false; |
|
} |
|
else if ( flTime <= 2.0 && m_bFire2SecRemain ) |
|
{ |
|
m_On2SecRemain.FireOutput( this, this ); |
|
m_bFire2SecRemain = false; |
|
} |
|
else if ( flTime <= 1.0 && m_bFire1SecRemain ) |
|
{ |
|
m_On1SecRemain.FireOutput( this, this ); |
|
m_bFire1SecRemain = false; |
|
} |
|
|
|
SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputRoundSpawn( inputdata_t &input ) |
|
{ |
|
if ( !m_bResetTimeOnRoundStart && ( m_nState == RT_STATE_NORMAL ) ) |
|
{ |
|
m_nTimeToUseAfterSetupFinished = GetTimeRemaining(); |
|
} |
|
else |
|
{ |
|
m_nTimeToUseAfterSetupFinished = m_nTimerInitialLength; |
|
} |
|
|
|
if ( m_nSetupTimeLength > 0 ) |
|
{ |
|
SetState( RT_STATE_SETUP ); |
|
SetTimeRemaining( m_nSetupTimeLength ); |
|
|
|
if ( ShowInHud() && !TeamplayRoundBasedRules()->IsInWaitingForPlayers() ) |
|
{ |
|
UTIL_LogPrintf( "World triggered \"Round_Setup_Begin\"\n" ); |
|
} |
|
} |
|
else |
|
{ |
|
SetState( RT_STATE_NORMAL ); |
|
SetTimeRemaining( m_nTimeToUseAfterSetupFinished ); |
|
} |
|
|
|
if ( !m_bStartPaused && !TeamplayRoundBasedRules()->IsInWaitingForPlayers() ) |
|
{ |
|
ResumeTimer(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: To set the initial timer duration |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::SetTimeRemaining( int iTimerSeconds ) |
|
{ |
|
if ( IsDisabled() ) |
|
return; |
|
|
|
// make sure we don't go over our max length |
|
iTimerSeconds = m_nTimerMaxLength > 0 ? MIN( iTimerSeconds, m_nTimerMaxLength ) : iTimerSeconds; |
|
|
|
float flTimerSeconds = (float)iTimerSeconds; |
|
if ( TeamplayRoundBasedRules()->IsInTournamentMode() && TeamplayRoundBasedRules()->IsInStopWatch() && ObjectiveResource() && !IsStopWatchTimer() && !TeamplayRoundBasedRules()->InSetup() ) |
|
{ |
|
// make sure we don't go over our stop watch timer |
|
int iStopWatchTimer = ObjectiveResource()->GetStopWatchTimer(); |
|
CTeamRoundTimer *pStopWatch = dynamic_cast< CTeamRoundTimer* >( UTIL_EntityByIndex( iStopWatchTimer ) ); |
|
if ( pStopWatch && !pStopWatch->IsWatchingTimeStamps() && TeamplayRoundBasedRules()->StopWatchShouldBeTimedWin() ) |
|
{ |
|
float flStopWatchRemainingTime = pStopWatch->GetTimeRemaining(); |
|
flTimerSeconds = flStopWatchRemainingTime > 0 ? MIN( flTimerSeconds, flStopWatchRemainingTime ) : flTimerSeconds; |
|
iTimerSeconds = (int)ceil( flTimerSeconds ); |
|
} |
|
} |
|
|
|
m_flTimeRemaining = flTimerSeconds; |
|
m_flTimerEndTime = gpGlobals->curtime + m_flTimeRemaining; |
|
m_nTimerLength = iTimerSeconds; |
|
|
|
CalculateOutputMessages(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: To set the initial timer duration |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::SetStopWatchTimeStamp( void ) |
|
{ |
|
if ( IsDisabled() ) |
|
return; |
|
|
|
if ( IsWatchingTimeStamps() == false ) |
|
return; |
|
|
|
m_flTotalTime = m_flTotalTime + (gpGlobals->curtime - m_flTimerEndTime); |
|
m_flTimerEndTime = gpGlobals->curtime; |
|
|
|
CalculateOutputMessages(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Timer is paused at round end, stops the countdown |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::PauseTimer( void ) |
|
{ |
|
if ( IsDisabled() ) |
|
return; |
|
|
|
if ( m_bTimerPaused == false ) |
|
{ |
|
m_bTimerPaused = true; |
|
|
|
m_flTimeRemaining = m_flTimerEndTime - gpGlobals->curtime; |
|
} |
|
|
|
// Clear pause on win flag, because we've been set by the mapmaker |
|
m_bPauseDueToWin = false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: To start or re-start the timer after a pause |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::ResumeTimer( void ) |
|
{ |
|
if ( IsDisabled() ) |
|
return; |
|
|
|
if ( m_bTimerPaused == true ) |
|
{ |
|
m_bTimerPaused = false; |
|
|
|
if ( IsStopWatchTimer() == true && m_bInCaptureWatchState == true ) |
|
{ |
|
m_flTimerEndTime = gpGlobals->curtime; |
|
} |
|
else |
|
{ |
|
m_flTimerEndTime = gpGlobals->curtime + m_flTimeRemaining; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add seconds to the timer while it is running or paused |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::AddTimerSeconds( int iSecondsToAdd, int iTeamResponsible /* = TEAM_UNASSIGNED*/ ) |
|
{ |
|
if ( IsDisabled() ) |
|
return; |
|
|
|
if ( TeamplayRoundBasedRules()->InStalemate() ) |
|
return; |
|
|
|
// we only want to add time if we're round_running or team_win so the control points |
|
// don't add time when they try to set their default owner when the map is first loading |
|
if ( TeamplayRoundBasedRules()->State_Get() != GR_STATE_RND_RUNNING && TeamplayRoundBasedRules()->State_Get() != GR_STATE_TEAM_WIN ) |
|
return; |
|
|
|
if ( m_nTimerMaxLength > 0 ) |
|
{ |
|
// will adding this many seconds push us over our max length? |
|
if ( GetTimeRemaining() + iSecondsToAdd > m_nTimerMaxLength ) |
|
{ |
|
// adjust to only add up to our max length |
|
iSecondsToAdd = m_nTimerMaxLength - GetTimeRemaining(); |
|
} |
|
} |
|
|
|
float flSecondsToAdd = (float)iSecondsToAdd; |
|
if ( TeamplayRoundBasedRules()->IsInTournamentMode() && TeamplayRoundBasedRules()->IsInStopWatch() && ObjectiveResource() && !IsStopWatchTimer() && !TeamplayRoundBasedRules()->InSetup() ) |
|
{ |
|
int iStopWatchTimer = ObjectiveResource()->GetStopWatchTimer(); |
|
CTeamRoundTimer *pStopWatch = dynamic_cast< CTeamRoundTimer* >( UTIL_EntityByIndex( iStopWatchTimer ) ); |
|
if ( pStopWatch && !pStopWatch->IsWatchingTimeStamps() && TeamplayRoundBasedRules()->StopWatchShouldBeTimedWin() ) |
|
{ |
|
float flStopWatchRemainingTime = pStopWatch->GetTimeRemaining(); |
|
float flRemainingTime = GetTimeRemaining(); |
|
// will adding this many seconds push us over our stop watch timer? |
|
if ( flRemainingTime + flSecondsToAdd > flStopWatchRemainingTime ) |
|
{ |
|
// adjust to only add up to our stop watch timer |
|
flSecondsToAdd = flStopWatchRemainingTime - flRemainingTime; |
|
iSecondsToAdd = ( int )ceil( flSecondsToAdd ); |
|
} |
|
} |
|
} |
|
|
|
if ( m_bTimerPaused ) |
|
{ |
|
m_flTimeRemaining += flSecondsToAdd; |
|
} |
|
else |
|
{ |
|
m_flTimerEndTime += flSecondsToAdd; |
|
} |
|
|
|
m_nTimerLength += iSecondsToAdd; |
|
CalculateOutputMessages(); |
|
|
|
if ( ( ObjectiveResource() && ObjectiveResource()->GetTimerInHUD() == entindex() ) || ( TeamplayRoundBasedRules()->IsInKothMode() ) ) |
|
{ |
|
if ( !TeamplayRoundBasedRules()->InStalemate() && !TeamplayRoundBasedRules()->RoundHasBeenWon() && !TeamplayRoundBasedRules()->IsInKothMode() ) |
|
{ |
|
if ( iTeamResponsible >= LAST_SHARED_TEAM+1 ) |
|
{ |
|
for ( int iTeam = LAST_SHARED_TEAM+1 ; iTeam < GetNumberOfTeams(); iTeam++ ) |
|
{ |
|
if ( iTeam == iTeamResponsible ) |
|
{ |
|
CTeamRecipientFilter filter( iTeam, true ); |
|
EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED_WINNER ); |
|
|
|
} |
|
else |
|
{ |
|
CTeamRecipientFilter filter( iTeam, true ); |
|
EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED_LOSER ); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
CReliableBroadcastRecipientFilter filter; |
|
EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED ); |
|
} |
|
} |
|
|
|
// is this the timer we're showing in the HUD? |
|
if ( m_bShowInHUD ) |
|
{ |
|
IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_timer_time_added" ); |
|
if ( event ) |
|
{ |
|
event->SetInt( "timer", entindex() ); |
|
event->SetInt( "seconds_added", iSecondsToAdd ); |
|
gameeventmanager->FireEvent( event ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: The timer is always transmitted to clients |
|
//----------------------------------------------------------------------------- |
|
int CTeamRoundTimer::UpdateTransmitState() |
|
{ |
|
// ALWAYS transmit to all clients. |
|
return SetTransmitState( FL_EDICT_ALWAYS ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputPause( inputdata_t &input ) |
|
{ |
|
PauseTimer(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputResume( inputdata_t &input ) |
|
{ |
|
ResumeTimer(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputSetTime( inputdata_t &input ) |
|
{ |
|
if ( IsStopWatchTimer() == true && IsWatchingTimeStamps() == true ) |
|
{ |
|
SetStopWatchTimeStamp(); |
|
} |
|
else |
|
{ |
|
int nSeconds = input.value.Int(); |
|
SetTimeRemaining( nSeconds ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputSetMaxTime( inputdata_t &input ) |
|
{ |
|
int nSeconds = input.value.Int(); |
|
m_nTimerMaxLength = nSeconds; |
|
|
|
if ( m_nTimerMaxLength > 0 ) |
|
{ |
|
// make sure our current time is not above the max length |
|
if ( GetTimeRemaining() > m_nTimerMaxLength ) |
|
{ |
|
SetTimeRemaining( m_nTimerMaxLength ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputAddTime( inputdata_t &input ) |
|
{ |
|
int nSeconds = input.value.Int(); |
|
AddTimerSeconds( nSeconds ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputAddTeamTime( inputdata_t &input ) |
|
{ |
|
char token[128]; |
|
const char *p = STRING( input.value.StringID() ); |
|
int nTeam = TEAM_UNASSIGNED; |
|
int nSeconds = 0; |
|
|
|
// get the team |
|
p = nexttoken( token, p, ' ' ); |
|
if ( token[0] ) |
|
{ |
|
nTeam = Q_atoi( token ); |
|
} |
|
|
|
// get the time |
|
p = nexttoken( token, p, ' ' ); |
|
if ( token[0] ) |
|
{ |
|
nSeconds = Q_atoi( token ); |
|
} |
|
|
|
if ( nSeconds != 0 ) |
|
{ |
|
AddTimerSeconds( nSeconds, nTeam ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputRestart( inputdata_t &input ) |
|
{ |
|
SetTimeRemaining( m_nTimerInitialLength ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputEnable( inputdata_t &input ) |
|
{ |
|
m_bIsDisabled = false; |
|
ResumeTimer(); |
|
|
|
if ( m_bShowInHUD ) |
|
{ |
|
SetActiveTimer( this ); |
|
} |
|
|
|
if ( IsStopWatchTimer() == true && IsWatchingTimeStamps() == true ) |
|
{ |
|
m_flTimerEndTime = gpGlobals->curtime; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputDisable( inputdata_t &input ) |
|
{ |
|
PauseTimer(); |
|
m_bIsDisabled = true; |
|
|
|
if ( m_bShowInHUD ) |
|
{ |
|
SetActiveTimer( NULL ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputShowInHUD( inputdata_t &input ) |
|
{ |
|
int nShow = input.value.Int(); |
|
|
|
if ( m_bShowInHUD && !nShow ) |
|
{ |
|
SetActiveTimer( NULL ); |
|
} |
|
else if ( nShow == 1 ) |
|
{ |
|
SetActiveTimer( this ); |
|
SetState( m_nState, false ); // set our current state again so the gamerules are updated with our setup state |
|
} |
|
|
|
m_bShowInHUD = ( nShow == 1 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputAutoCountdown( inputdata_t &input ) |
|
{ |
|
int nAuto = input.value.Int(); |
|
SetAutoCountdown( nAuto == 1 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::InputSetSetupTime( inputdata_t &input ) |
|
{ |
|
int nSetupTime = input.value.Int(); |
|
if ( nSetupTime >= 0 ) |
|
{ |
|
m_nSetupTimeLength = nSetupTime; |
|
} |
|
|
|
if ( !IsDisabled() ) |
|
{ |
|
if ( m_nState == RT_STATE_SETUP ) |
|
{ |
|
SetTimeRemaining( m_nSetupTimeLength ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTeamRoundTimer::SetActiveTimer( CTeamRoundTimer *pNewlyActive ) |
|
{ |
|
CBaseEntity *pChosenTimer = pNewlyActive; |
|
|
|
// Ensure all other timers are off. |
|
CBaseEntity *pEntity = NULL; |
|
while ((pEntity = gEntList.FindEntityByClassname( pEntity, "team_round_timer" )) != NULL) |
|
{ |
|
if ( pEntity == pNewlyActive ) |
|
continue; |
|
|
|
CTeamRoundTimer *pTimer = assert_cast< CTeamRoundTimer* >( pEntity ); |
|
if ( !pTimer->IsDisabled() && pTimer->ShowInHud() ) |
|
{ |
|
if ( pChosenTimer ) |
|
{ |
|
// Turn off all other hud timers |
|
pTimer->SetShowInHud( false ); |
|
} |
|
else |
|
{ |
|
// Found a timer. Use it. |
|
pChosenTimer = pTimer; |
|
} |
|
} |
|
} |
|
|
|
ObjectiveResource()->SetTimerInHUD( pChosenTimer ); |
|
} |
|
|
|
#endif
|
|
|