Counter Strike : Global Offensive Source Code
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.

1913 lines
61 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============
  2. //
  3. // Purpose: CS-specific things to vote on
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "cs_voteissues.h"
  8. #include "cs_player.h"
  9. #include "vote_controller.h"
  10. #include "fmtstr.h"
  11. #include "eiface.h"
  12. #include "cs_gamerules.h"
  13. #include "inetchannelinfo.h"
  14. #include "cs_gamestats.h"
  15. #include "gametypes.h"
  16. //[tj]removing this to get voting to compile
  17. //#include "cs_gcmessages.h"
  18. #ifdef CLIENT_DLL
  19. #include "gc_clientsystem.h"
  20. #endif // CLIENT_DLL
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. extern ConVar mp_maxrounds;
  24. extern ConVar mp_winlimit;
  25. //-----------------------------------------------------------------------------
  26. // Purpose: Base CS Issue
  27. //-----------------------------------------------------------------------------
  28. //-----------------------------------------------------------------------------
  29. // Purpose: Restart Round Issue
  30. //-----------------------------------------------------------------------------
  31. ConVar sv_vote_issue_restart_game_allowed( "sv_vote_issue_restart_game_allowed", "0", FCVAR_RELEASE, "Can people hold votes to restart the game?" );
  32. ConVar sv_arms_race_vote_to_restart_disallowed_after( "sv_arms_race_vote_to_restart_disallowed_after", "0", FCVAR_REPLICATED | FCVAR_RELEASE, "Arms Race gun level after which vote to restart is disallowed" );
  33. //-----------------------------------------------------------------------------
  34. // Purpose:
  35. //-----------------------------------------------------------------------------
  36. void CRestartGameIssue::ExecuteCommand( void )
  37. {
  38. engine->ServerCommand( CFmtStr( "mp_restartgame 1;" ) );
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose:
  42. //-----------------------------------------------------------------------------
  43. bool CRestartGameIssue::IsEnabled( void )
  44. {
  45. if ( sv_vote_issue_restart_game_allowed.GetBool() )
  46. {
  47. // Vote to restart is allowed
  48. if ( sv_arms_race_vote_to_restart_disallowed_after.GetInt() > 0 )
  49. {
  50. // Need to test if a player has surpassed the maximum weapon progression
  51. if ( sv_arms_race_vote_to_restart_disallowed_after.GetInt() > CSGameRules()->GetMaxGunGameProgressiveWeaponIndex() )
  52. {
  53. // No players have surpassed the maximum weapon progression, so enable vote to restart
  54. return true;
  55. }
  56. else
  57. {
  58. // A player has surpassed the maximum weapon progression, so disable vote to restart
  59. return false;
  60. }
  61. }
  62. // No maximum weapon progression value is defined, so enable vote to restart
  63. return true;
  64. }
  65. // Vote to restart is not enabled
  66. return false;
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. bool CRestartGameIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  72. {
  73. if( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  74. return false;
  75. if( !IsEnabled() )
  76. {
  77. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  78. return false;
  79. }
  80. return true;
  81. }
  82. //-----------------------------------------------------------------------------
  83. // Purpose:
  84. //-----------------------------------------------------------------------------
  85. const char *CRestartGameIssue::GetDisplayString( void )
  86. {
  87. return "#SFUI_vote_restart_game";
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Purpose:
  91. //-----------------------------------------------------------------------------
  92. const char *CRestartGameIssue::GetVotePassedString( void )
  93. {
  94. return "#SFUI_vote_passed_restart_game";
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose:
  98. //-----------------------------------------------------------------------------
  99. void CRestartGameIssue::ListIssueDetails( CBasePlayer *pForWhom )
  100. {
  101. if( !sv_vote_issue_restart_game_allowed.GetBool() )
  102. return;
  103. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  104. }
  105. //-----------------------------------------------------------------------------
  106. // Purpose: Kick Player Issue
  107. //-----------------------------------------------------------------------------
  108. ConVar sv_vote_issue_kick_allowed( "sv_vote_issue_kick_allowed", "1", FCVAR_REPLICATED | FCVAR_NOTIFY | FCVAR_RELEASE, "Can people hold votes to kick players from the server?" );
  109. ConVar sv_vote_kick_ban_duration( "sv_vote_kick_ban_duration", "15", FCVAR_REPLICATED | FCVAR_NOTIFY | FCVAR_RELEASE, "How long should a kick vote ban someone from the server? (in minutes)" );
  110. //-----------------------------------------------------------------------------
  111. // Purpose:
  112. //-----------------------------------------------------------------------------
  113. void CKickIssue::ExecuteCommand( void )
  114. {
  115. CCSPlayer *subject = NULL;
  116. //[tj] Not applicable without TF-specific GC code
  117. //uint32 unReason = kVoteKickBanPlayerReason_Other;
  118. uint32 unReason;
  119. ExtractDataFromDetails( m_szDetailsString, &subject, &unReason );
  120. if( subject )
  121. {
  122. // Check the cached value of player crashed state
  123. if ( ( sv_vote_kick_ban_duration.GetInt() > 0 ) && !m_bPlayerCrashed )
  124. {
  125. CSGameRules()->SendKickBanToGC( subject, k_EMsgGCCStrike15_v2_MatchmakingKickBanReason_VotedOff );
  126. // don't roll the kick command into this, it will fail on a lan, where kickid will go through
  127. engine->ServerCommand( CFmtStr( "banid %d %d;", sv_vote_kick_ban_duration.GetInt(), subject->GetUserID() ) );
  128. }
  129. engine->ServerCommand( CFmtStr( "kickid_ex %d %d You have been voted off;", subject->GetUserID(), CSGameRules()->IsPlayingOffline() ? 0 : 1 ) );
  130. }
  131. else if ( !m_bPlayerCrashed && m_steamIDtoBan.IsValid() && ( sv_vote_kick_ban_duration.GetInt() > 0 ) )
  132. {
  133. // Player has already disconnected, but let's still ban him!
  134. CSGameRules()->SendKickBanToGCforAccountId( m_steamIDtoBan.GetAccountID(), k_EMsgGCCStrike15_v2_MatchmakingKickBanReason_VotedOff );
  135. // Also enlist this user's SteamID in the banlist
  136. engine->ServerCommand( CFmtStr( "banid %d STEAM64BITID_%llu;", sv_vote_kick_ban_duration.GetInt(), m_steamIDtoBan.ConvertToUint64() ) );
  137. }
  138. }
  139. //-----------------------------------------------------------------------------
  140. // Purpose:
  141. //-----------------------------------------------------------------------------
  142. bool CKickIssue::IsEnabled( void )
  143. {
  144. return sv_vote_issue_kick_allowed.GetBool();
  145. }
  146. //-----------------------------------------------------------------------------
  147. // Purpose:
  148. //-----------------------------------------------------------------------------
  149. bool CKickIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  150. {
  151. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  152. return false;
  153. if ( CSGameRules() && CSGameRules()->IsPlayingCooperativeGametype() )
  154. {
  155. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  156. return false;
  157. }
  158. if( !IsEnabled() )
  159. {
  160. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  161. return false;
  162. }
  163. CCSPlayer *pSubject = NULL;
  164. ExtractDataFromDetails( pszDetails, &pSubject );
  165. if ( !pSubject || pSubject->IsBot() )
  166. {
  167. nFailCode = VOTE_FAILED_PLAYERNOTFOUND;
  168. return false;
  169. }
  170. if ( pSubject->IsReplay() || pSubject->IsHLTV() )
  171. {
  172. nFailCode = VOTE_FAILED_PLAYERNOTFOUND;
  173. return false;
  174. }
  175. CBaseEntity *pVoteCaller = UTIL_EntityByIndex( iEntIndex );
  176. if ( pVoteCaller )
  177. {
  178. CCSPlayer *pPlayer = ToCSPlayer( pVoteCaller );
  179. bool bCanKickVote = false;
  180. if ( pSubject && pPlayer )
  181. {
  182. int voterTeam = pPlayer->GetTeamNumber();
  183. int nSubjectTeam = pSubject->GetTeamNumber();
  184. bCanKickVote = ( voterTeam == TEAM_TERRORIST || voterTeam == TEAM_CT ) && ( voterTeam == nSubjectTeam || nSubjectTeam == TEAM_SPECTATOR );
  185. }
  186. if ( pSubject )
  187. {
  188. bool bDeny = false;
  189. if ( !engine->IsDedicatedServer() )
  190. {
  191. if ( pSubject->entindex() == 1 )
  192. {
  193. bDeny = true;
  194. }
  195. }
  196. // This should only be set if we've successfully authenticated via rcon
  197. if ( pSubject->IsAutoKickDisabled() )
  198. {
  199. bDeny = true;
  200. }
  201. if ( bDeny )
  202. {
  203. nFailCode = VOTE_FAILED_CANNOT_KICK_ADMIN;
  204. return false;
  205. }
  206. }
  207. if ( !bCanKickVote )
  208. {
  209. // Can't initiate a vote to kick a player on the other team
  210. return false;
  211. }
  212. }
  213. return true;
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Purpose:
  217. //-----------------------------------------------------------------------------
  218. void CKickIssue::OnVoteFailed( void )
  219. {
  220. CBaseCSIssue::OnVoteFailed();
  221. CCSPlayer *subject = NULL;
  222. uint32 unReason;// = kVoteKickBanPlayerReason_Other;
  223. ExtractDataFromDetails( m_szDetailsString, &subject, &unReason );
  224. //[tj]removing this to get voting to compile
  225. //NotifyGC( subject, false, unReason );
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Purpose:
  229. //-----------------------------------------------------------------------------
  230. void CKickIssue::OnVoteStarted( void )
  231. {
  232. CCSPlayer *pSubject = NULL;
  233. ExtractDataFromDetails( m_szDetailsString, &pSubject );
  234. // Auto vote 'No' for the person being kicked unless they are idle
  235. // NOTE: Subtle. There's a problem with IsAwayFromKeyboard where if a player
  236. // has idled and is taken over by a bot, IsAwayFromKeyboard will return false
  237. // because the camera controller that takes over when idling will spoof
  238. // input messages, making it impossible to know if the player is moving his
  239. // joystick or not. Being on TEAM_SPECTATOR, however, means you're idling,
  240. // so we don't want to autovote NO if they are on team spectator
  241. if ( m_pVoteController && pSubject && ( pSubject->GetTeamNumber( ) != TEAM_SPECTATOR ) && !pSubject->IsBot( ) )
  242. {
  243. m_pVoteController->TryCastVote( pSubject->entindex( ), "Option2" );
  244. }
  245. // Also when the vote starts, figure out if the player should not be banned
  246. // if the player is crashed/hung. Need to perform the check here instead of
  247. // inside Execute to prevent cheaters quitting before the vote finishes and
  248. // not getting banned.
  249. m_bPlayerCrashed = false;
  250. if ( pSubject )
  251. {
  252. INetChannelInfo *pNetChanInfo = engine->GetPlayerNetInfo( pSubject->entindex() );
  253. if ( !pNetChanInfo || pNetChanInfo->IsTimingOut() )
  254. {
  255. // don't ban the player
  256. DevMsg( "Will not ban kicked player: net channel was idle for %.2f sec.\n", pNetChanInfo ? pNetChanInfo->GetTimeSinceLastReceived() : 0.0f );
  257. m_bPlayerCrashed = true;
  258. }
  259. pSubject->GetSteamID( &m_steamIDtoBan );
  260. }
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Purpose:
  264. //-----------------------------------------------------------------------------
  265. const char *CKickIssue::GetDisplayString( void )
  266. {
  267. uint32 unReason = kVoteKickBanPlayerReason_Other;
  268. ExtractDataFromDetails( m_szDetailsString, NULL, &unReason );
  269. switch ( unReason )
  270. {
  271. case kVoteKickBanPlayerReason_Other: return "#SFUI_vote_kick_player_other";
  272. case kVoteKickBanPlayerReason_Cheating: return "#SFUI_vote_kick_player_cheating";
  273. case kVoteKickBanPlayerReason_Idle: return "#SFUI_vote_kick_player_idle";
  274. case kVoteKickBanPlayerReason_Scamming: return "#SFUI_vote_kick_player_scamming";
  275. }
  276. return "#SFUI_vote_kick_player_other";
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Purpose:
  280. //-----------------------------------------------------------------------------
  281. const char *CKickIssue::GetOtherTeamDisplayString( void )
  282. {
  283. return "#SFUI_otherteam_vote_kick_player";
  284. }
  285. //-----------------------------------------------------------------------------
  286. // Purpose:
  287. //-----------------------------------------------------------------------------
  288. const char *CKickIssue::GetVotePassedString( void )
  289. {
  290. return "#SFUI_vote_passed_kick_player";
  291. }
  292. //-----------------------------------------------------------------------------
  293. // Purpose:
  294. //-----------------------------------------------------------------------------
  295. const char *CKickIssue::GetDetailsString( void )
  296. {
  297. int iUserID = 0;
  298. const char *pReason = strstr( m_szDetailsString, " " );
  299. if ( pReason != NULL )
  300. {
  301. pReason += 1;
  302. CUtlString userID;
  303. userID.SetDirect( m_szDetailsString, pReason - m_szDetailsString );
  304. iUserID = atoi( userID );
  305. }
  306. else
  307. {
  308. iUserID = atoi( m_szDetailsString );
  309. }
  310. CBasePlayer *pPlayer = UTIL_PlayerByUserId( iUserID );
  311. if ( pPlayer )
  312. {
  313. return pPlayer->GetPlayerName();
  314. }
  315. else
  316. {
  317. return "unnamed";
  318. }
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Purpose:
  322. //-----------------------------------------------------------------------------
  323. void CKickIssue::ExtractDataFromDetails( const char *pszDetails, CCSPlayer **pSubject, uint32 *pReason )
  324. {
  325. int iUserID = 0;
  326. const char *pReasonString = strstr( pszDetails, " " );
  327. if ( pReasonString != NULL )
  328. {
  329. pReasonString += 1;
  330. CUtlString userID;
  331. userID.SetDirect( pszDetails, pReasonString - pszDetails );
  332. iUserID = atoi( userID );
  333. if ( pReason )
  334. {
  335. //[tj] Not applicable without TF-specific GC code
  336. //*pReason = GetKickBanPlayerReason( pReasonString );
  337. }
  338. }
  339. else
  340. {
  341. iUserID = atoi( pszDetails );
  342. }
  343. if ( iUserID >= 0 )
  344. {
  345. if( pSubject )
  346. {
  347. *pSubject = ToCSPlayer( UTIL_PlayerByUserId( iUserID ) );
  348. }
  349. }
  350. }
  351. //-----------------------------------------------------------------------------
  352. // Purpose:
  353. //-----------------------------------------------------------------------------
  354. void CKickIssue::ListIssueDetails( CBasePlayer *pForWhom )
  355. {
  356. if( !sv_vote_issue_kick_allowed.GetBool() )
  357. return;
  358. char szBuffer[MAX_COMMAND_LENGTH];
  359. Q_snprintf( szBuffer, MAX_COMMAND_LENGTH, "callvote %s <userID>\n", GetTypeString() );
  360. ClientPrint( pForWhom, HUD_PRINTCONSOLE, szBuffer );
  361. }
  362. //-----------------------------------------------------------------------------
  363. // Purpose: LoadBackup Player Issue
  364. //-----------------------------------------------------------------------------
  365. ConVar sv_vote_issue_loadbackup_allowed( "sv_vote_issue_loadbackup_allowed", "1", FCVAR_REPLICATED | FCVAR_NOTIFY | FCVAR_RELEASE, "Can people hold votes to load match from backup?" );
  366. //-----------------------------------------------------------------------------
  367. // Purpose:
  368. //-----------------------------------------------------------------------------
  369. void CLoadBackupIssue::ExecuteCommand( void )
  370. {
  371. CSGameRules()->LoadRoundDataInformation( m_szDetailsString );
  372. }
  373. //-----------------------------------------------------------------------------
  374. // Purpose:
  375. //-----------------------------------------------------------------------------
  376. bool CLoadBackupIssue::IsEnabled( void )
  377. {
  378. return sv_vote_issue_loadbackup_allowed.GetBool( );
  379. }
  380. //-----------------------------------------------------------------------------
  381. // Purpose:
  382. //-----------------------------------------------------------------------------
  383. bool CLoadBackupIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  384. {
  385. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  386. return false;
  387. if ( !IsEnabled() )
  388. {
  389. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  390. return false;
  391. }
  392. return true;
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Purpose:
  396. //-----------------------------------------------------------------------------
  397. void CLoadBackupIssue::OnVoteFailed( void )
  398. {
  399. CBaseCSIssue::OnVoteFailed( );
  400. }
  401. //-----------------------------------------------------------------------------
  402. // Purpose:
  403. //-----------------------------------------------------------------------------
  404. const char *CLoadBackupIssue::GetDisplayString( void )
  405. {
  406. return "#SFUI_vote_loadbackup";
  407. }
  408. //-----------------------------------------------------------------------------
  409. // Purpose:
  410. //-----------------------------------------------------------------------------
  411. const char *CLoadBackupIssue::GetVotePassedString( void )
  412. {
  413. return "#SFUI_vote_passed_loadbackup";
  414. }
  415. //-----------------------------------------------------------------------------
  416. // Purpose:
  417. //-----------------------------------------------------------------------------
  418. const char *CLoadBackupIssue::GetDetailsString( void )
  419. {
  420. // create human readable name
  421. if ( !FStrEq( m_szDetailsString, m_szPrevDetailsString ) )
  422. {
  423. V_strcpy_safe( m_szNiceName, m_szDetailsString );
  424. KeyValues *kvSaveFile = new KeyValues( "" );
  425. KeyValues::AutoDelete autodelete_kvSaveFile( kvSaveFile );
  426. autodelete_kvSaveFile->UsesEscapeSequences( true );
  427. if ( kvSaveFile->LoadFromFile( filesystem, m_szDetailsString ) )
  428. {
  429. V_sprintf_safe( m_szNiceName,
  430. "Score %d:%d",
  431. kvSaveFile->GetInt( "FirstHalfScore/team1" ) + kvSaveFile->GetInt( "SecondHalfScore/team1" ) + kvSaveFile->GetInt( "OvertimeScore/team1" ),
  432. kvSaveFile->GetInt( "FirstHalfScore/team2" ) + kvSaveFile->GetInt( "SecondHalfScore/team2" ) + kvSaveFile->GetInt( "OvertimeScore/team2" ) );
  433. }
  434. V_strcpy_safe( m_szPrevDetailsString, m_szDetailsString );
  435. }
  436. return m_szNiceName;
  437. }
  438. //-----------------------------------------------------------------------------
  439. // Purpose:
  440. //-----------------------------------------------------------------------------
  441. void CLoadBackupIssue::ListIssueDetails( CBasePlayer *pForWhom )
  442. {
  443. if ( !sv_vote_issue_loadbackup_allowed.GetBool( ) )
  444. return;
  445. char szBuffer[ MAX_COMMAND_LENGTH ];
  446. Q_snprintf( szBuffer, MAX_COMMAND_LENGTH, "callvote %s <backup filename>\n", GetTypeString( ) );
  447. ClientPrint( pForWhom, HUD_PRINTCONSOLE, szBuffer );
  448. }
  449. //-----------------------------------------------------------------------------
  450. // Purpose: Changelevel
  451. //-----------------------------------------------------------------------------
  452. ConVar sv_vote_issue_changelevel_allowed( "sv_vote_issue_changelevel_allowed", "1", 0, "Can people hold votes to change levels?" );
  453. ConVar sv_vote_to_changelevel_before_match_point( "sv_vote_to_changelevel_before_match_point", "0", FCVAR_REPLICATED | FCVAR_RELEASE, "Restricts vote to change level to rounds prior to match point (default 0, vote is never disallowed)" );
  454. //-----------------------------------------------------------------------------
  455. // Purpose:
  456. //-----------------------------------------------------------------------------
  457. void CChangeLevelIssue::ExecuteCommand( void )
  458. {
  459. engine->ServerCommand( CFmtStr( "changelevel %s;", m_szDetailsString ) );
  460. }
  461. //-----------------------------------------------------------------------------
  462. // Purpose:
  463. //-----------------------------------------------------------------------------
  464. bool CChangeLevelIssue::CanTeamCallVote( int iTeam ) const
  465. {
  466. return true;
  467. }
  468. //-----------------------------------------------------------------------------
  469. // Purpose:
  470. //-----------------------------------------------------------------------------
  471. bool CChangeLevelIssue::IsEnabled( void )
  472. {
  473. if ( sv_vote_issue_changelevel_allowed.GetBool() )
  474. {
  475. return ( sv_vote_to_changelevel_before_match_point.GetInt() > 0 &&
  476. CSGameRules() &&
  477. ( CSGameRules()->IsMatchPoint() || CSGameRules()->IsIntermission() ) ) == false;
  478. }
  479. // Change Level vote disabled
  480. return false;
  481. }
  482. //-----------------------------------------------------------------------------
  483. // Purpose:
  484. //-----------------------------------------------------------------------------
  485. bool CChangeLevelIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  486. {
  487. if( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  488. return false;
  489. if( !IsEnabled() )
  490. {
  491. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  492. return false;
  493. }
  494. if ( !Q_strcmp( pszDetails, "" ) )
  495. {
  496. nFailCode = VOTE_FAILED_MAP_NAME_REQUIRED;
  497. return false;
  498. }
  499. else
  500. {
  501. if ( !g_pGameTypes->IsWorkshopMapGroup( gpGlobals->mapGroupName.ToCStr() ) && !engine->IsMapValid( pszDetails ) )
  502. {
  503. nFailCode = VOTE_FAILED_MAP_NOT_FOUND;
  504. return false;
  505. }
  506. }
  507. bool mapIsInGroup = false;
  508. if ( gpGlobals )
  509. {
  510. const char* groupName = gpGlobals->mapGroupName.ToCStr();
  511. const CUtlStringList* mapsInGroup = g_pGameTypes->GetMapGroupMapList( groupName );
  512. if ( mapsInGroup )
  513. {
  514. int numMaps = mapsInGroup->Count();
  515. for( int i = 0 ; i < numMaps ; ++i )
  516. {
  517. const char* internalMapName = ( *mapsInGroup )[i];
  518. if ( !V_strcmp( pszDetails, internalMapName ) )
  519. {
  520. mapIsInGroup = true;
  521. break;
  522. }
  523. }
  524. }
  525. }
  526. return mapIsInGroup;
  527. }
  528. //-----------------------------------------------------------------------------
  529. // Purpose:
  530. //-----------------------------------------------------------------------------
  531. const char *CChangeLevelIssue::GetDisplayString( void )
  532. {
  533. return "#SFUI_vote_changelevel";
  534. }
  535. //-----------------------------------------------------------------------------
  536. // Purpose:
  537. //-----------------------------------------------------------------------------
  538. const char *CChangeLevelIssue::GetVotePassedString( void )
  539. {
  540. return "#SFUI_vote_passed_changelevel";
  541. }
  542. //-----------------------------------------------------------------------------
  543. // Purpose:
  544. //-----------------------------------------------------------------------------
  545. const char *CChangeLevelIssue::GetDetailsString( void )
  546. {
  547. return m_szDetailsString;
  548. }
  549. //-----------------------------------------------------------------------------
  550. // Purpose:
  551. //-----------------------------------------------------------------------------
  552. void CChangeLevelIssue::ListIssueDetails( CBasePlayer *pForWhom )
  553. {
  554. if( !sv_vote_issue_changelevel_allowed.GetBool() )
  555. return;
  556. char szBuffer[MAX_COMMAND_LENGTH];
  557. Q_snprintf( szBuffer, MAX_COMMAND_LENGTH, "callvote %s <mapname>\n", GetTypeString() );
  558. ClientPrint( pForWhom, HUD_PRINTCONSOLE, szBuffer );
  559. }
  560. //-----------------------------------------------------------------------------
  561. // Purpose:
  562. //-----------------------------------------------------------------------------
  563. bool CChangeLevelIssue::IsYesNoVote( void )
  564. {
  565. return true;
  566. }
  567. //-----------------------------------------------------------------------------
  568. // Purpose: Nextlevel
  569. //-----------------------------------------------------------------------------
  570. ConVar sv_vote_issue_nextlevel_allowed( "sv_vote_issue_nextlevel_allowed", "1", 1, "Can people hold votes to set the next level?" );
  571. ConVar sv_vote_issue_nextlevel_choicesmode( "sv_vote_issue_nextlevel_choicesmode", "1", 0, "Present players with a list of lowest playtime maps to choose from?" );
  572. ConVar sv_vote_issue_nextlevel_allowextend( "sv_vote_issue_nextlevel_allowextend", "1", 0, "Allow players to extend the current map?" );
  573. ConVar sv_vote_issue_nextlevel_prevent_change( "sv_vote_issue_nextlevel_prevent_change", "1", 1, "Not allowed to vote for a nextlevel if one has already been set." );
  574. //-----------------------------------------------------------------------------
  575. // Purpose:
  576. //-----------------------------------------------------------------------------
  577. void CNextLevelIssue::ExecuteCommand( void )
  578. {
  579. if ( Q_strcmp( m_szDetailsString, "Extend current Map" ) == 0 )
  580. {
  581. // Players want to extend the current map, so extend any existing limits
  582. if ( mp_timelimit.GetInt() > 0 )
  583. {
  584. engine->ServerCommand( CFmtStr( "mp_timelimit %d;", mp_timelimit.GetInt() + 20 ) );
  585. }
  586. if ( mp_maxrounds.GetInt() > 0 )
  587. {
  588. engine->ServerCommand( CFmtStr( "mp_maxrounds %d;", mp_maxrounds.GetInt() + 2 ) );
  589. }
  590. if ( mp_winlimit.GetInt() > 0 )
  591. {
  592. engine->ServerCommand( CFmtStr( "mp_winlimit %d;", mp_winlimit.GetInt() + 2 ) );
  593. }
  594. }
  595. else
  596. {
  597. engine->ServerCommand( CFmtStr( "nextlevel %s;", m_szDetailsString ) );
  598. if ( gpGlobals )
  599. {
  600. const char* groupName = gpGlobals->mapGroupName.ToCStr();
  601. const CUtlStringList* mapsInGroup = g_pGameTypes->GetMapGroupMapList( groupName );
  602. if ( mapsInGroup )
  603. {
  604. int numMaps = mapsInGroup->Count();
  605. for( int i = 0 ; i < numMaps ; ++i )
  606. {
  607. const char* internalMapName = ( *mapsInGroup )[i];
  608. if ( !V_strcmp( m_szDetailsString, internalMapName ) )
  609. {
  610. CSGameRules()->SetNextMapInMapGroup(i);
  611. break;
  612. }
  613. }
  614. }
  615. }
  616. }
  617. }
  618. //-----------------------------------------------------------------------------
  619. // Purpose:
  620. //-----------------------------------------------------------------------------
  621. bool CNextLevelIssue::CanTeamCallVote( int iTeam ) const
  622. {
  623. return true;
  624. }
  625. //-----------------------------------------------------------------------------
  626. // Purpose:
  627. //-----------------------------------------------------------------------------
  628. bool CNextLevelIssue::IsEnabled( void )
  629. {
  630. return sv_vote_issue_nextlevel_allowed.GetBool();
  631. }
  632. //-----------------------------------------------------------------------------
  633. // Purpose:
  634. //-----------------------------------------------------------------------------
  635. bool CNextLevelIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  636. {
  637. if( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  638. return false;
  639. // CSGameRules created vote
  640. if ( sv_vote_issue_nextlevel_choicesmode.GetBool() && iEntIndex == 99 )
  641. {
  642. // Invokes a UI down stream
  643. if ( Q_strcmp( pszDetails, "" ) == 0 )
  644. {
  645. return true;
  646. }
  647. return false;
  648. }
  649. if( !IsEnabled() )
  650. {
  651. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  652. return false;
  653. }
  654. if ( Q_strcmp( pszDetails, "" ) == 0 )
  655. {
  656. nFailCode = VOTE_FAILED_MAP_NAME_REQUIRED;
  657. return false;
  658. }
  659. else
  660. {
  661. if ( !g_pGameTypes->IsWorkshopMapGroup( gpGlobals->mapGroupName.ToCStr() ) && !engine->IsMapValid( pszDetails ) )
  662. {
  663. nFailCode = VOTE_FAILED_MAP_NOT_FOUND;
  664. return false;
  665. }
  666. }
  667. if ( sv_vote_issue_nextlevel_prevent_change.GetBool() )
  668. {
  669. if ( nextlevel.GetString() && *nextlevel.GetString() &&
  670. ( g_pGameTypes->IsWorkshopMapGroup( gpGlobals->mapGroupName.ToCStr() ) || engine->IsMapValid( nextlevel.GetString() ) ) )
  671. {
  672. nFailCode = VOTE_FAILED_NEXTLEVEL_SET;
  673. return false;
  674. }
  675. }
  676. bool mapIsInGroup = false;
  677. if ( gpGlobals )
  678. {
  679. const char* groupName = gpGlobals->mapGroupName.ToCStr();
  680. const CUtlStringList* mapsInGroup = g_pGameTypes->GetMapGroupMapList( groupName );
  681. if ( mapsInGroup )
  682. {
  683. int numMaps = mapsInGroup->Count();
  684. for( int i = 0 ; i < numMaps ; ++i )
  685. {
  686. const char* internalMapName = ( *mapsInGroup )[i];
  687. if ( !V_strcmp( pszDetails, internalMapName ) )
  688. {
  689. mapIsInGroup = true;
  690. break;
  691. }
  692. }
  693. }
  694. }
  695. return mapIsInGroup;
  696. }
  697. //-----------------------------------------------------------------------------
  698. // Purpose:
  699. //-----------------------------------------------------------------------------
  700. const char *CNextLevelIssue::GetDisplayString( void )
  701. {
  702. // If we don't have a map passed in already...
  703. if ( Q_strcmp( m_szDetailsString, "" ) == 0 )
  704. {
  705. if ( sv_vote_issue_nextlevel_choicesmode.GetBool() )
  706. {
  707. return "#SFUI_vote_nextlevel_choices";
  708. }
  709. }
  710. return "#SFUI_vote_nextlevel";
  711. }
  712. //-----------------------------------------------------------------------------
  713. // Purpose:
  714. //-----------------------------------------------------------------------------
  715. const char *CNextLevelIssue::GetVotePassedString( void )
  716. {
  717. if ( Q_strcmp( m_szDetailsString, STRING( gpGlobals->mapname ) ) == 0 )
  718. {
  719. return "#SFUI_vote_passed_nextlevel_extend";
  720. }
  721. return "#SFUI_vote_passed_nextlevel";
  722. }
  723. //-----------------------------------------------------------------------------
  724. // Purpose:
  725. //-----------------------------------------------------------------------------
  726. const char *CNextLevelIssue::GetDetailsString( void )
  727. {
  728. return m_szDetailsString;
  729. }
  730. //-----------------------------------------------------------------------------
  731. // Purpose:
  732. //-----------------------------------------------------------------------------
  733. void CNextLevelIssue::ListIssueDetails( CBasePlayer *pForWhom )
  734. {
  735. if( !sv_vote_issue_nextlevel_allowed.GetBool() )
  736. return;
  737. if ( !sv_vote_issue_nextlevel_choicesmode.GetBool() )
  738. {
  739. char szBuffer[MAX_COMMAND_LENGTH];
  740. Q_snprintf( szBuffer, MAX_COMMAND_LENGTH, "callvote %s <mapname>\n", GetTypeString() );
  741. ClientPrint( pForWhom, HUD_PRINTCONSOLE, szBuffer );
  742. }
  743. }
  744. //-----------------------------------------------------------------------------
  745. // Purpose:
  746. //-----------------------------------------------------------------------------
  747. bool CNextLevelIssue::IsYesNoVote( void )
  748. {
  749. // If we don't have a map name already, this will trigger a list of choices
  750. if ( Q_strcmp( m_szDetailsString, "" ) == 0 )
  751. {
  752. if ( sv_vote_issue_nextlevel_choicesmode.GetBool() )
  753. return false;
  754. }
  755. return true;
  756. }
  757. //-----------------------------------------------------------------------------
  758. // Purpose:
  759. //-----------------------------------------------------------------------------
  760. int CNextLevelIssue::GetNumberVoteOptions( void )
  761. {
  762. // If we don't have a map name already, this will trigger a list of choices
  763. if ( Q_strcmp( m_szDetailsString, "" ) == 0 )
  764. {
  765. if ( sv_vote_issue_nextlevel_choicesmode.GetBool() )
  766. return MAX_VOTE_OPTIONS;
  767. }
  768. // Vote on a specific map - Yes, No
  769. return 2;
  770. }
  771. //-----------------------------------------------------------------------------
  772. // Purpose: Scramble Teams Issue
  773. //-----------------------------------------------------------------------------
  774. ConVar sv_vote_issue_scramble_teams_allowed( "sv_vote_issue_scramble_teams_allowed", "1", 0, "Can people hold votes to scramble the teams?" );
  775. //-----------------------------------------------------------------------------
  776. // Purpose:
  777. //-----------------------------------------------------------------------------
  778. void CScrambleTeams::ExecuteCommand( void )
  779. {
  780. engine->ServerCommand( CFmtStr( "mp_scrambleteams 2;" ) );
  781. }
  782. //-----------------------------------------------------------------------------
  783. // Purpose:
  784. //-----------------------------------------------------------------------------
  785. bool CScrambleTeams::IsEnabled( void )
  786. {
  787. return sv_vote_issue_scramble_teams_allowed.GetBool();
  788. }
  789. //-----------------------------------------------------------------------------
  790. // Purpose:
  791. //-----------------------------------------------------------------------------
  792. bool CScrambleTeams::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  793. {
  794. if( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  795. return false;
  796. if( !IsEnabled() )
  797. {
  798. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  799. return false;
  800. }
  801. if ( CSGameRules() && CSGameRules()->GetScrambleTeamsOnRestart() )
  802. {
  803. nFailCode = VOTE_FAILED_SCRAMBLE_IN_PROGRESS;
  804. return false;
  805. }
  806. return true;
  807. }
  808. //-----------------------------------------------------------------------------
  809. // Purpose:
  810. //-----------------------------------------------------------------------------
  811. const char *CScrambleTeams::GetDisplayString( void )
  812. {
  813. return "#SFUI_vote_scramble_teams";
  814. }
  815. //-----------------------------------------------------------------------------
  816. // Purpose:
  817. //-----------------------------------------------------------------------------
  818. const char *CScrambleTeams::GetVotePassedString( void )
  819. {
  820. return "#SFUI_vote_passed_scramble_teams";
  821. }
  822. //-----------------------------------------------------------------------------
  823. // Purpose:
  824. //-----------------------------------------------------------------------------
  825. void CScrambleTeams::ListIssueDetails( CBasePlayer *pForWhom )
  826. {
  827. if( !sv_vote_issue_scramble_teams_allowed.GetBool() )
  828. return;
  829. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  830. }
  831. //-----------------------------------------------------------------------------
  832. // Purpose: Pause Match
  833. //-----------------------------------------------------------------------------
  834. ConVar sv_vote_issue_pause_match_allowed( "sv_vote_issue_pause_match_allowed", "1", 0, "Can people hold votes to pause/unpause the match?" );
  835. //-----------------------------------------------------------------------------
  836. // Purpose:
  837. //-----------------------------------------------------------------------------
  838. void CPauseMatchIssue::ExecuteCommand( void )
  839. {
  840. engine->ServerCommand( CFmtStr( "mp_pause_match;" ) );
  841. CBaseEntity *pVoteCaller = UTIL_EntityByIndex( m_pVoteController->GetCallingEntity( ) );
  842. if ( !pVoteCaller )
  843. return;
  844. CCSPlayer *pPlayer = ToCSPlayer( pVoteCaller );
  845. if ( !pPlayer )
  846. return;
  847. CFmtStr fmtEntName;
  848. if ( pPlayer )
  849. fmtEntName.AppendFormat( "#ENTNAME[%d]%s", pPlayer->entindex(), pPlayer->GetPlayerName() );
  850. UTIL_ClientPrintAll( HUD_PRINTTALK, "#SFUI_vote_passed_pause_match_chat", fmtEntName.Access() );
  851. }
  852. //-----------------------------------------------------------------------------
  853. // Purpose:
  854. //-----------------------------------------------------------------------------
  855. bool CPauseMatchIssue::IsEnabled( void )
  856. {
  857. return CSGameRules()->IsPlayingAnyCompetitiveStrictRuleset() && sv_vote_issue_pause_match_allowed.GetBool();
  858. }
  859. //-----------------------------------------------------------------------------
  860. // Purpose:
  861. //-----------------------------------------------------------------------------
  862. bool CPauseMatchIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  863. {
  864. if( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  865. return false;
  866. if( !IsEnabled() )
  867. {
  868. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  869. return false;
  870. }
  871. if ( !CSGameRules() )
  872. return false;
  873. if ( CSGameRules()->IsMatchWaitingForResume() )
  874. {
  875. nFailCode = VOTE_FAILED_MATCH_PAUSED;
  876. return false;
  877. }
  878. return true;
  879. }
  880. //-----------------------------------------------------------------------------
  881. // Purpose:
  882. //-----------------------------------------------------------------------------
  883. const char *CPauseMatchIssue::GetDisplayString( void )
  884. {
  885. return "#SFUI_vote_pause_match";
  886. }
  887. //-----------------------------------------------------------------------------
  888. // Purpose:
  889. //-----------------------------------------------------------------------------
  890. const char *CPauseMatchIssue::GetVotePassedString( void )
  891. {
  892. return "#SFUI_vote_passed_pause_match";
  893. }
  894. //-----------------------------------------------------------------------------
  895. // Purpose:
  896. //-----------------------------------------------------------------------------
  897. void CPauseMatchIssue::ListIssueDetails( CBasePlayer *pForWhom )
  898. {
  899. if( !sv_vote_issue_pause_match_allowed.GetBool() )
  900. return;
  901. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  902. }
  903. //-----------------------------------------------------------------------------
  904. // Purpose: UnPause Match
  905. //-----------------------------------------------------------------------------
  906. //-----------------------------------------------------------------------------
  907. // Purpose:
  908. //-----------------------------------------------------------------------------
  909. void CUnpauseMatchIssue::ExecuteCommand( void )
  910. {
  911. engine->ServerCommand( CFmtStr( "mp_unpause_match;" ) );
  912. }
  913. //-----------------------------------------------------------------------------
  914. // Purpose:
  915. //-----------------------------------------------------------------------------
  916. bool CUnpauseMatchIssue::IsEnabled( void )
  917. {
  918. return CSGameRules()->IsPlayingAnyCompetitiveStrictRuleset() && sv_vote_issue_pause_match_allowed.GetBool();
  919. }
  920. //-----------------------------------------------------------------------------
  921. // Purpose:
  922. //-----------------------------------------------------------------------------
  923. bool CUnpauseMatchIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  924. {
  925. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  926. return false;
  927. if ( !IsEnabled() )
  928. {
  929. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  930. return false;
  931. }
  932. if (!CSGameRules())
  933. return false;
  934. if ( !CSGameRules()->IsMatchWaitingForResume() )
  935. {
  936. nFailCode = VOTE_FAILED_MATCH_NOT_PAUSED;
  937. return false;
  938. }
  939. return true;
  940. }
  941. //-----------------------------------------------------------------------------
  942. // Purpose:
  943. //-----------------------------------------------------------------------------
  944. const char *CUnpauseMatchIssue::GetDisplayString( void )
  945. {
  946. return "#SFUI_vote_unpause_match";
  947. }
  948. //-----------------------------------------------------------------------------
  949. // Purpose:
  950. //-----------------------------------------------------------------------------
  951. const char *CUnpauseMatchIssue::GetVotePassedString( void )
  952. {
  953. return "#SFUI_vote_passed_unpause_match";
  954. }
  955. //-----------------------------------------------------------------------------
  956. // Purpose:
  957. //-----------------------------------------------------------------------------
  958. void CUnpauseMatchIssue::ListIssueDetails( CBasePlayer *pForWhom )
  959. {
  960. if ( !sv_vote_issue_pause_match_allowed.GetBool() )
  961. return;
  962. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  963. }
  964. //-----------------------------------------------------------------------------
  965. // Purpose: TimeOut
  966. //-----------------------------------------------------------------------------
  967. ConVar sv_vote_issue_timeout_allowed( "sv_vote_issue_timeout_allowed", "1", 0, "Can people hold votes to time out?" );
  968. //-----------------------------------------------------------------------------
  969. // Purpose:
  970. //-----------------------------------------------------------------------------
  971. void CStartTimeOutIssue::ExecuteCommand( void )
  972. {
  973. CBaseEntity *pVoteHolder = UTIL_EntityByIndex( m_pVoteController->GetCallingEntity( ) );
  974. if ( !pVoteHolder )
  975. return;
  976. if ( pVoteHolder->GetTeamNumber() == TEAM_CT )
  977. {
  978. engine->ServerCommand( CFmtStr( "timeout_ct_start;" ) );
  979. }
  980. else if ( pVoteHolder->GetTeamNumber() == TEAM_TERRORIST )
  981. {
  982. engine->ServerCommand( CFmtStr( "timeout_terrorist_start;" ) );
  983. }
  984. }
  985. //-----------------------------------------------------------------------------
  986. // Purpose:
  987. //-----------------------------------------------------------------------------
  988. bool CStartTimeOutIssue::IsEnabled( void )
  989. {
  990. return CSGameRules()->IsPlayingAnyCompetitiveStrictRuleset() && sv_vote_issue_timeout_allowed.GetBool();
  991. }
  992. //-----------------------------------------------------------------------------
  993. // Purpose:
  994. //-----------------------------------------------------------------------------
  995. bool CStartTimeOutIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  996. {
  997. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  998. return false;
  999. if ( !IsEnabled() )
  1000. {
  1001. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1002. return false;
  1003. }
  1004. if ( CSGameRules() && CSGameRules()->IsTimeOutActive() )
  1005. {
  1006. nFailCode = VOTE_FAILED_TIMEOUT_ACTIVE;
  1007. return false;
  1008. }
  1009. if ( CSGameRules() && CSGameRules()->IsMatchWaitingForResume() )
  1010. {
  1011. nFailCode = VOTE_FAILED_MATCH_PAUSED;
  1012. return false;
  1013. }
  1014. return true;
  1015. }
  1016. //-----------------------------------------------------------------------------
  1017. // Purpose:
  1018. //-----------------------------------------------------------------------------
  1019. bool CStartTimeOutIssue::CanTeamCallVote(int iTeam ) const
  1020. {
  1021. if ( !CSGameRules() )
  1022. return false;
  1023. if ( CSGameRules()->IsTimeOutActive() )
  1024. return false;
  1025. if ( iTeam == TEAM_CT )
  1026. {
  1027. return ( CSGameRules()->GetCTTimeOuts() > 0 );
  1028. }
  1029. else if ( iTeam == TEAM_TERRORIST )
  1030. {
  1031. return ( CSGameRules()->GetTerroristTimeOuts() > 0 );
  1032. }
  1033. return false;
  1034. }
  1035. //-----------------------------------------------------------------------------
  1036. // Purpose:
  1037. //-----------------------------------------------------------------------------
  1038. const char *CStartTimeOutIssue::GetDisplayString( void )
  1039. {
  1040. return "#SFUI_vote_start_timeout";
  1041. }
  1042. //-----------------------------------------------------------------------------
  1043. // Purpose:
  1044. //-----------------------------------------------------------------------------
  1045. const char *CStartTimeOutIssue::GetVotePassedString( void )
  1046. {
  1047. return "#SFUI_vote_passed_timeout";
  1048. }
  1049. vote_create_failed_t CStartTimeOutIssue::MakeVoteFailErrorCodeForClients( vote_create_failed_t eDefaultFailCode )
  1050. {
  1051. switch ( eDefaultFailCode )
  1052. {
  1053. case VOTE_FAILED_TEAM_CANT_CALL:
  1054. {
  1055. if ( CSGameRules( ) && CSGameRules( )->IsTimeOutActive( ) )
  1056. return VOTE_FAILED_TIMEOUT_ACTIVE;
  1057. else if ( CSGameRules() && CSGameRules()->IsMatchWaitingForResume() )
  1058. return VOTE_FAILED_MATCH_PAUSED;
  1059. else
  1060. return VOTE_FAILED_TIMEOUT_EXHAUSTED;
  1061. }
  1062. default:
  1063. return eDefaultFailCode;
  1064. }
  1065. }
  1066. //-----------------------------------------------------------------------------
  1067. // Purpose:
  1068. //-----------------------------------------------------------------------------
  1069. void CStartTimeOutIssue::ListIssueDetails( CBasePlayer *pForWhom )
  1070. {
  1071. if ( !sv_vote_issue_pause_match_allowed.GetBool() )
  1072. return;
  1073. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  1074. }
  1075. //-----------------------------------------------------------------------------
  1076. //-----------------------------------------------------------------------------
  1077. ConVar sv_vote_issue_matchready_allowed( "sv_vote_issue_matchready_allowed", "1", 0, "Can people hold votes to ready/unready the match?" );
  1078. //-----------------------------------------------------------------------------
  1079. // Purpose:
  1080. //-----------------------------------------------------------------------------
  1081. void CReadyForMatchIssue::ExecuteCommand( void )
  1082. {
  1083. CSGameRules()->SetWarmupPeriodStartTime( gpGlobals->curtime );
  1084. engine->ServerCommand( CFmtStr( "mp_warmup_pausetimer 0;" ) );
  1085. }
  1086. //-----------------------------------------------------------------------------
  1087. // Purpose:
  1088. //-----------------------------------------------------------------------------
  1089. bool CReadyForMatchIssue::IsEnabled( void )
  1090. {
  1091. return CSGameRules()->IsPlayingAnyCompetitiveStrictRuleset() && sv_vote_issue_matchready_allowed.GetBool();
  1092. }
  1093. //-----------------------------------------------------------------------------
  1094. // Purpose:
  1095. //-----------------------------------------------------------------------------
  1096. bool CReadyForMatchIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  1097. {
  1098. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  1099. return false;
  1100. if ( !IsEnabled() )
  1101. {
  1102. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1103. return false;
  1104. }
  1105. if ( CSGameRules() && !CSGameRules()->IsWarmupPeriod() )
  1106. {
  1107. nFailCode = VOTE_FAILED_NOT_IN_WARMUP;
  1108. return false;
  1109. }
  1110. #if !defined ( _DEBUG )
  1111. if ( UTIL_HumansInGame( true, true ) != 10 )
  1112. {
  1113. nFailCode = VOTE_FAILED_NOT_10_PLAYERS;
  1114. return false;
  1115. }
  1116. #endif
  1117. return true;
  1118. }
  1119. //-----------------------------------------------------------------------------
  1120. // Purpose:
  1121. //-----------------------------------------------------------------------------
  1122. const char *CReadyForMatchIssue::GetDisplayString( void )
  1123. {
  1124. return "#SFUI_vote_ready_for_match";
  1125. }
  1126. //-----------------------------------------------------------------------------
  1127. // Purpose:
  1128. //-----------------------------------------------------------------------------
  1129. const char *CReadyForMatchIssue::GetVotePassedString( void )
  1130. {
  1131. return "#SFUI_vote_passed_ready_for_match";
  1132. }
  1133. //-----------------------------------------------------------------------------
  1134. // Purpose:
  1135. //-----------------------------------------------------------------------------
  1136. void CReadyForMatchIssue::ListIssueDetails( CBasePlayer *pForWhom )
  1137. {
  1138. if ( !sv_vote_issue_matchready_allowed.GetBool() )
  1139. return;
  1140. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  1141. }
  1142. //-----------------------------------------------------------------------------
  1143. // Purpose: Someone wants to abort the ready process
  1144. //-----------------------------------------------------------------------------
  1145. //-----------------------------------------------------------------------------
  1146. // Purpose:
  1147. //-----------------------------------------------------------------------------
  1148. void CNotReadyForMatchIssue::ExecuteCommand( void )
  1149. {
  1150. engine->ServerCommand( CFmtStr( "mp_warmup_pausetimer 1;" ) );
  1151. CBaseEntity *pVoteCaller = UTIL_EntityByIndex( m_pVoteController->GetCallingEntity( ) );
  1152. if ( !pVoteCaller )
  1153. return;
  1154. CCSPlayer *pPlayer = ToCSPlayer( pVoteCaller );
  1155. if ( !pPlayer )
  1156. return;
  1157. CFmtStr fmtEntName;
  1158. if ( pPlayer )
  1159. fmtEntName.AppendFormat( "#ENTNAME[%d]%s", pPlayer->entindex(), pPlayer->GetPlayerName() );
  1160. UTIL_ClientPrintAll( HUD_PRINTTALK, "#SFUI_vote_passed_not_ready_for_match_chat", fmtEntName.Access() );
  1161. }
  1162. //-----------------------------------------------------------------------------
  1163. // Purpose:
  1164. //-----------------------------------------------------------------------------
  1165. bool CNotReadyForMatchIssue::IsEnabled( void )
  1166. {
  1167. return CSGameRules()->IsPlayingAnyCompetitiveStrictRuleset() && sv_vote_issue_matchready_allowed.GetBool();
  1168. }
  1169. //-----------------------------------------------------------------------------
  1170. // Purpose:
  1171. //-----------------------------------------------------------------------------
  1172. bool CNotReadyForMatchIssue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  1173. {
  1174. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  1175. return false;
  1176. if ( !IsEnabled() )
  1177. {
  1178. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1179. return false;
  1180. }
  1181. if ( CSGameRules() && !CSGameRules()->IsWarmupPeriod() )
  1182. {
  1183. nFailCode = VOTE_FAILED_NOT_IN_WARMUP;
  1184. return false;
  1185. }
  1186. return true;
  1187. }
  1188. //-----------------------------------------------------------------------------
  1189. // Purpose:
  1190. //-----------------------------------------------------------------------------
  1191. const char *CNotReadyForMatchIssue::GetDisplayString( void )
  1192. {
  1193. return "#SFUI_vote_not_ready_for_match";
  1194. }
  1195. //-----------------------------------------------------------------------------
  1196. // Purpose:
  1197. //-----------------------------------------------------------------------------
  1198. const char *CNotReadyForMatchIssue::GetVotePassedString( void )
  1199. {
  1200. return "#SFUI_vote_passed_not_ready_for_match";
  1201. }
  1202. //-----------------------------------------------------------------------------
  1203. // Purpose:
  1204. //-----------------------------------------------------------------------------
  1205. void CNotReadyForMatchIssue::ListIssueDetails( CBasePlayer *pForWhom )
  1206. {
  1207. if ( !sv_vote_issue_matchready_allowed.GetBool() )
  1208. return;
  1209. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  1210. }
  1211. //-----------------------------------------------------------------------------
  1212. // Purpose: Swap Teams Issue
  1213. //-----------------------------------------------------------------------------
  1214. ConVar sv_vote_issue_swap_teams_allowed( "sv_vote_issue_swap_teams_allowed", "1", 0, "Can people hold votes to swap the teams?" );
  1215. //-----------------------------------------------------------------------------
  1216. // Purpose:
  1217. //-----------------------------------------------------------------------------
  1218. void CSwapTeams::ExecuteCommand( void )
  1219. {
  1220. engine->ServerCommand( CFmtStr( "mp_swapteams;" ) );
  1221. }
  1222. //-----------------------------------------------------------------------------
  1223. // Purpose:
  1224. //-----------------------------------------------------------------------------
  1225. bool CSwapTeams::IsEnabled( void )
  1226. {
  1227. return sv_vote_issue_swap_teams_allowed.GetBool();
  1228. }
  1229. //-----------------------------------------------------------------------------
  1230. // Purpose:
  1231. //-----------------------------------------------------------------------------
  1232. bool CSwapTeams::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  1233. {
  1234. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  1235. return false;
  1236. if ( !IsEnabled() )
  1237. {
  1238. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1239. return false;
  1240. }
  1241. if ( CSGameRules() && CSGameRules()->GetSwapTeamsOnRestart() )
  1242. {
  1243. nFailCode = VOTE_FAILED_SWAP_IN_PROGRESS;
  1244. return false;
  1245. }
  1246. return true;
  1247. }
  1248. //-----------------------------------------------------------------------------
  1249. // Purpose:
  1250. //-----------------------------------------------------------------------------
  1251. const char *CSwapTeams::GetDisplayString( void )
  1252. {
  1253. return "#SFUI_vote_swap_teams";
  1254. }
  1255. //-----------------------------------------------------------------------------
  1256. // Purpose:
  1257. //-----------------------------------------------------------------------------
  1258. const char *CSwapTeams::GetVotePassedString( void )
  1259. {
  1260. return "#SFUI_vote_passed_swap_teams";
  1261. }
  1262. //-----------------------------------------------------------------------------
  1263. // Purpose:
  1264. //-----------------------------------------------------------------------------
  1265. void CSwapTeams::ListIssueDetails( CBasePlayer *pForWhom )
  1266. {
  1267. if ( !sv_vote_issue_swap_teams_allowed.GetBool() )
  1268. return;
  1269. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  1270. }
  1271. //-----------------------------------------------------------------------------
  1272. // Purpose: Surrender Issue
  1273. //-----------------------------------------------------------------------------
  1274. ConVar sv_vote_issue_surrender_allowed( "sv_vote_issue_surrrender_allowed", "1", 0, "Can people hold votes to surrender?" );
  1275. //-----------------------------------------------------------------------------
  1276. // Purpose:
  1277. //-----------------------------------------------------------------------------
  1278. void CSurrender::ExecuteCommand( void )
  1279. {
  1280. CBaseEntity *pVoteHolder = UTIL_EntityByIndex( m_pVoteController->GetCallingEntity( ) );
  1281. if ( !pVoteHolder )
  1282. return;
  1283. if ( CSGameRules() && CSGameRules()->IsQueuedMatchmaking() )
  1284. {
  1285. if ( CSGameRules()->m_iRoundWinStatus != WINNER_NONE || CSGameRules()->GetGamePhase() == GAMEPHASE_HALFTIME )
  1286. {
  1287. // if the vote succeeds at the round end, just cancel it because we don't handle this in the gamerules round logic
  1288. CBasePlayer *pVoteCaller = dynamic_cast< CBasePlayer* >( pVoteHolder );
  1289. if ( pVoteCaller )
  1290. m_pVoteController->SendVoteFailedMessage( VOTE_FAILED_CANT_ROUND_END, pVoteCaller, 0 );
  1291. }
  1292. else if ( ( CSGameRules()->m_eQueuedMatchmakingRematchState == CSGameRules()->k_EQueuedMatchmakingRematchState_MatchInProgress ) &&
  1293. ( CSGameRules()->GetGamePhase() != GAMEPHASE_MATCH_ENDED ) )
  1294. {
  1295. if ( pVoteHolder->GetTeamNumber() == TEAM_TERRORIST )
  1296. {
  1297. CSGameRules()->GetMatch()->AddCTWins( 1 );
  1298. CSGameRules()->m_eQueuedMatchmakingRematchState = CSGameRules()->k_EQueuedMatchmakingRematchState_VoteToRematch_T_Surrender;
  1299. CSGameRules()->TerminateRound( 0, Terrorists_Surrender );
  1300. }
  1301. if ( pVoteHolder->GetTeamNumber() == TEAM_CT )
  1302. {
  1303. CSGameRules()->GetMatch()->AddTerroristWins( 1 );
  1304. CSGameRules()->m_eQueuedMatchmakingRematchState = CSGameRules()->k_EQueuedMatchmakingRematchState_VoteToRematch_CT_Surrender;
  1305. CSGameRules()->TerminateRound( 0, CTs_Surrender );
  1306. }
  1307. }
  1308. }
  1309. else
  1310. {
  1311. if ( pVoteHolder->GetTeamNumber() == TEAM_TERRORIST )
  1312. {
  1313. CSGameRules()->TerminateRound( 0, Terrorists_Surrender );
  1314. }
  1315. if ( pVoteHolder->GetTeamNumber() == TEAM_CT )
  1316. {
  1317. CSGameRules()->TerminateRound( 0, CTs_Surrender );
  1318. }
  1319. }
  1320. }
  1321. //-----------------------------------------------------------------------------
  1322. // Purpose:
  1323. //-----------------------------------------------------------------------------
  1324. bool CSurrender::IsEnabled( void )
  1325. {
  1326. return sv_vote_issue_surrender_allowed.GetBool();
  1327. }
  1328. //-----------------------------------------------------------------------------
  1329. // Purpose:
  1330. //-----------------------------------------------------------------------------
  1331. bool CSurrender::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  1332. {
  1333. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  1334. return false;
  1335. if ( CSGameRules() && CSGameRules()->IsQueuedMatchmaking() )
  1336. {
  1337. if ( CSGameRules()->IsPlayingCooperativeGametype() )
  1338. {
  1339. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1340. return false;
  1341. }
  1342. if ( CSGameRules()->m_eQueuedMatchmakingRematchState != CSGameRules()->k_EQueuedMatchmakingRematchState_MatchInProgress )
  1343. {
  1344. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1345. return false;
  1346. }
  1347. if ( CSGameRules()->GetGamePhase() == GAMEPHASE_MATCH_ENDED || CSGameRules()->GetGamePhase() == GAMEPHASE_HALFTIME ||
  1348. CSGameRules()->IsLastRoundBeforeHalfTime() )
  1349. {
  1350. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1351. return false;
  1352. }
  1353. if ( CSGameRules()->GetRoundsPlayed() < 1 )
  1354. { // Cannot surrender unless at least one round was played
  1355. nFailCode = VOTE_FAILED_WAITINGFORPLAYERS;
  1356. return false;
  1357. }
  1358. }
  1359. if ( !IsEnabled() )
  1360. {
  1361. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1362. return false;
  1363. }
  1364. return true;
  1365. }
  1366. bool CSurrender::CanTeamCallVote( int iTeam ) const
  1367. {
  1368. if ( !CSGameRules() || !CSGameRules()->IsQueuedMatchmaking() )
  1369. return false;
  1370. bool bTeamsArePlayingSwitchedSides = CSGameRules()->AreTeamsPlayingSwitchedSides();
  1371. FOR_EACH_MAP( CSGameRules()->m_mapQueuedMatchmakingPlayersData, idxQPD )
  1372. {
  1373. CCSGameRules::CQMMPlayerData_t const &qpd = * CSGameRules()->m_mapQueuedMatchmakingPlayersData.Element( idxQPD );
  1374. if ( qpd.m_bAbandonAllowsSurrender )
  1375. {
  1376. bool bSecondTeam = ( qpd.m_iDraftIndex >= 5 );
  1377. int iTeamOfThisQPlayer = ( bSecondTeam == bTeamsArePlayingSwitchedSides ) ? TEAM_CT : TEAM_TERRORIST;
  1378. if ( iTeamOfThisQPlayer == iTeam )
  1379. return true;
  1380. }
  1381. }
  1382. #if 0
  1383. return true; // Allow in debug mode
  1384. #endif
  1385. return false;
  1386. }
  1387. //-----------------------------------------------------------------------------
  1388. // Purpose:
  1389. //-----------------------------------------------------------------------------
  1390. const char *CSurrender::GetDisplayString( void )
  1391. {
  1392. return "#SFUI_vote_surrender";
  1393. }
  1394. //-----------------------------------------------------------------------------
  1395. // Purpose:
  1396. //-----------------------------------------------------------------------------
  1397. const char *CSurrender::GetOtherTeamDisplayString( void )
  1398. {
  1399. return "#SFUI_otherteam_vote_surrender";
  1400. }
  1401. //-----------------------------------------------------------------------------
  1402. // Purpose:
  1403. //-----------------------------------------------------------------------------
  1404. const char *CSurrender::GetVotePassedString( void )
  1405. {
  1406. return ( CSGameRules() && CSGameRules()->IsQueuedMatchmaking() ) ? "#SFUI_vote_passed_surrender_q" : "#SFUI_vote_passed_surrender";
  1407. }
  1408. //-----------------------------------------------------------------------------
  1409. // Purpose:
  1410. //-----------------------------------------------------------------------------
  1411. void CSurrender::ListIssueDetails( CBasePlayer *pForWhom )
  1412. {
  1413. if ( !sv_vote_issue_surrender_allowed.GetBool() )
  1414. return;
  1415. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  1416. }
  1417. //-----------------------------------------------------------------------------
  1418. // Purpose:
  1419. //-----------------------------------------------------------------------------
  1420. void CQueuedMatchmakingRematch::ExecuteCommand( void )
  1421. {
  1422. if ( CSGameRules() )
  1423. {
  1424. CSGameRules()->m_eQueuedMatchmakingRematchState = CSGameRules()->k_EQueuedMatchmakingRematchState_VoteToRematchSucceeded;
  1425. }
  1426. }
  1427. void CQueuedMatchmakingRematch::OnVoteFailed()
  1428. {
  1429. if ( CSGameRules() )
  1430. {
  1431. CSGameRules()->m_eQueuedMatchmakingRematchState = CSGameRules()->k_EQueuedMatchmakingRematchState_VoteToRematchFailed;
  1432. }
  1433. }
  1434. void CQueuedMatchmakingRematch::OnVoteStarted()
  1435. {
  1436. if ( CSGameRules() )
  1437. {
  1438. CSGameRules()->m_eQueuedMatchmakingRematchState = CSGameRules()->k_EQueuedMatchmakingRematchState_VoteToRematchInProgress;
  1439. }
  1440. }
  1441. //-----------------------------------------------------------------------------
  1442. // Purpose:
  1443. //-----------------------------------------------------------------------------
  1444. bool CQueuedMatchmakingRematch::IsEnabled( void )
  1445. {
  1446. return IsTimeForRematchVote();
  1447. }
  1448. //-----------------------------------------------------------------------------
  1449. // Purpose:
  1450. //-----------------------------------------------------------------------------
  1451. bool CQueuedMatchmakingRematch::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  1452. {
  1453. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  1454. return false;
  1455. if ( !IsTimeForRematchVote() )
  1456. return false;
  1457. return true;
  1458. }
  1459. //-----------------------------------------------------------------------------
  1460. // Purpose:
  1461. //-----------------------------------------------------------------------------
  1462. const char *CQueuedMatchmakingRematch::GetDisplayString( void )
  1463. {
  1464. return "#SFUI_vote_rematch";
  1465. }
  1466. //-----------------------------------------------------------------------------
  1467. // Purpose:
  1468. //-----------------------------------------------------------------------------
  1469. const char *CQueuedMatchmakingRematch::GetVotePassedString( void )
  1470. {
  1471. return "#SFUI_vote_passed_rematch";
  1472. }
  1473. //-----------------------------------------------------------------------------
  1474. // Purpose:
  1475. //-----------------------------------------------------------------------------
  1476. void CQueuedMatchmakingRematch::ListIssueDetails( CBasePlayer *pForWhom )
  1477. {
  1478. if ( !IsTimeForRematchVote() )
  1479. return;
  1480. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  1481. }
  1482. bool CQueuedMatchmakingRematch::IsTimeForRematchVote()
  1483. {
  1484. return CSGameRules() && CSGameRules()->IsQueuedMatchmaking() &&
  1485. ( CSGameRules()->GetGamePhase() == GAMEPHASE_MATCH_ENDED ) &&
  1486. ( CSGameRules()->m_eQueuedMatchmakingRematchState == CSGameRules()->k_EQueuedMatchmakingRematchState_VoteStarting );
  1487. }
  1488. //-----------------------------------------------------------------------------
  1489. // Purpose:
  1490. //-----------------------------------------------------------------------------
  1491. void CQueuedMatchmakingContinue::ExecuteCommand( void )
  1492. {
  1493. // By design: successful vote to continue does not disrupt the game
  1494. }
  1495. void CQueuedMatchmakingContinue::OnVoteFailed()
  1496. {
  1497. Msg( "Aborting match...\n" );
  1498. }
  1499. void CQueuedMatchmakingContinue::OnVoteStarted()
  1500. {
  1501. CBaseCSIssue::OnVoteStarted();
  1502. if ( CSGameRules() )
  1503. CSGameRules()->m_bNeedToAskPlayersForContinueVote = false;
  1504. }
  1505. //-----------------------------------------------------------------------------
  1506. // Purpose:
  1507. //-----------------------------------------------------------------------------
  1508. bool CQueuedMatchmakingContinue::IsEnabled( void )
  1509. {
  1510. return ( CSGameRules() && CSGameRules()->IsQueuedMatchmaking() );
  1511. }
  1512. //-----------------------------------------------------------------------------
  1513. // Purpose:
  1514. //-----------------------------------------------------------------------------
  1515. bool CQueuedMatchmakingContinue::CanCallVote( int iEntIndex, const char *pszTypeString, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  1516. {
  1517. if ( !CBaseCSIssue::CanCallVote( iEntIndex, pszTypeString, pszDetails, nFailCode, nTime ) )
  1518. return false;
  1519. if ( !IsEnabled() )
  1520. return false;
  1521. if ( iEntIndex != 99 ) // only game rules on the server can call the vote
  1522. return false;
  1523. return true;
  1524. }
  1525. //-----------------------------------------------------------------------------
  1526. // Purpose:
  1527. //-----------------------------------------------------------------------------
  1528. const char *CQueuedMatchmakingContinue::GetDisplayString( void )
  1529. {
  1530. return "#SFUI_vote_continue";
  1531. }
  1532. //-----------------------------------------------------------------------------
  1533. // Purpose:
  1534. //-----------------------------------------------------------------------------
  1535. const char *CQueuedMatchmakingContinue::GetVotePassedString( void )
  1536. {
  1537. return "#SFUI_vote_passed_continue";
  1538. }
  1539. //-----------------------------------------------------------------------------
  1540. // Purpose:
  1541. //-----------------------------------------------------------------------------
  1542. void CQueuedMatchmakingContinue::ListIssueDetails( CBasePlayer *pForWhom )
  1543. {
  1544. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  1545. }
  1546. #ifdef TF_MVM_MODE
  1547. //-----------------------------------------------------------------------------
  1548. // Purpose:
  1549. //-----------------------------------------------------------------------------
  1550. void CMannVsMachineStartRound::ExecuteCommand( void )
  1551. {
  1552. if ( CSGameRules() && CSGameRules()->InSetup() && CSGameRules()->GetActiveRoundTimer() )
  1553. {
  1554. // need to find the current timer and set the new countdown time to 5
  1555. CTeamRoundTimer *pTimer = CSGameRules()->GetActiveRoundTimer();
  1556. if ( pTimer && pTimer->ShowInHud() && ( pTimer->GetTimerState() == RT_STATE_SETUP ) && ( pTimer->GetTimeRemaining() > 6 ) )
  1557. {
  1558. variant_t sVariant;
  1559. sVariant.SetInt( 6 );
  1560. pTimer->AcceptInput( "SetTime", NULL, NULL, sVariant, 0 );
  1561. }
  1562. }
  1563. }
  1564. //-----------------------------------------------------------------------------
  1565. // Purpose:
  1566. //-----------------------------------------------------------------------------
  1567. bool CMannVsMachineStartRound::IsEnabled( void )
  1568. {
  1569. if ( CSGameRules() )
  1570. {
  1571. if ( !CSGameRules()->IsMannVsMachineMode() )
  1572. return false;
  1573. if ( !CSGameRules()->InSetup() )
  1574. return false;
  1575. }
  1576. return true;
  1577. }
  1578. //-----------------------------------------------------------------------------
  1579. // Purpose:
  1580. //-----------------------------------------------------------------------------
  1581. bool CMannVsMachineStartRound::CanCallVote( int iEntIndex, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime )
  1582. {
  1583. // if( !CBaseCSIssue::CanCallVote( iEntIndex, pszDetails, nFailCode, nTime ) )
  1584. // return false;
  1585. if( !IsEnabled() )
  1586. {
  1587. nFailCode = VOTE_FAILED_ISSUE_DISABLED;
  1588. return false;
  1589. }
  1590. return true;
  1591. }
  1592. //-----------------------------------------------------------------------------
  1593. // Purpose:
  1594. //-----------------------------------------------------------------------------
  1595. const char *CMannVsMachineStartRound::GetDisplayString( void )
  1596. {
  1597. return "#SFUI_vote_td_start_round";
  1598. }
  1599. //-----------------------------------------------------------------------------
  1600. // Purpose:
  1601. //-----------------------------------------------------------------------------
  1602. const char *CMannVsMachineStartRound::GetVotePassedString( void )
  1603. {
  1604. return "#SFUI_vote_passed_td_start_round";
  1605. }
  1606. //-----------------------------------------------------------------------------
  1607. // Purpose:
  1608. //-----------------------------------------------------------------------------
  1609. void CMannVsMachineStartRound::ListIssueDetails( CBasePlayer *pForWhom )
  1610. {
  1611. if( !IsEnabled() )
  1612. return;
  1613. ListStandardNoArgCommand( pForWhom, GetTypeString() );
  1614. }
  1615. #endif // TF_MVM_MODE