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.

465 lines
16 KiB

  1. //====== Copyright � 1996-2006, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: Teamplay game rules that manage a round based structure for you
  4. //
  5. //=============================================================================
  6. #ifndef TEAMPLAYROUNDBASED_GAMERULES_H
  7. #define TEAMPLAYROUNDBASED_GAMERULES_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "teamplay_gamerules.h"
  12. #include "teamplay_round_timer.h"
  13. extern ConVar mp_respawnwavetime;
  14. #ifdef GAME_DLL
  15. #include "team_control_point.h"
  16. extern ConVar mp_showroundtransitions;
  17. extern ConVar mp_enableroundwaittime;
  18. extern ConVar mp_showcleanedupents;
  19. extern ConVar mp_bonusroundtime;
  20. extern ConVar mp_restartround;
  21. extern ConVar mp_winlimit;
  22. extern ConVar mp_stalemate_timelimit;
  23. extern ConVar mp_stalemate_enable;
  24. #else
  25. #define CTeamplayRoundBasedRules C_TeamplayRoundBasedRules
  26. #define CTeamplayRoundBasedRulesProxy C_TeamplayRoundBasedRulesProxy
  27. #endif
  28. class CTeamplayRoundBasedRules;
  29. //-----------------------------------------------------------------------------
  30. // Round states
  31. //-----------------------------------------------------------------------------
  32. enum gamerules_roundstate_t
  33. {
  34. // initialize the game, create teams
  35. GR_STATE_INIT = 0,
  36. //Before players have joined the game. Periodically checks to see if enough players are ready
  37. //to start a game. Also reverts to this when there are no active players
  38. GR_STATE_PREGAME,
  39. //The game is about to start, wait a bit and spawn everyone
  40. GR_STATE_STARTGAME,
  41. //All players are respawned, frozen in place
  42. GR_STATE_PREROUND,
  43. //Round is on, playing normally
  44. GR_STATE_RND_RUNNING,
  45. //Someone has won the round
  46. GR_STATE_TEAM_WIN,
  47. //Noone has won, manually restart the game, reset scores
  48. GR_STATE_RESTART,
  49. //Noone has won, restart the game
  50. GR_STATE_STALEMATE,
  51. //Game is over, showing the scoreboard etc
  52. GR_STATE_GAME_OVER,
  53. GR_NUM_ROUND_STATES
  54. };
  55. enum {
  56. WINREASON_NONE =0,
  57. WINREASON_ALL_POINTS_CAPTURED,
  58. WINREASON_OPPONENTS_DEAD,
  59. WINREASON_FLAG_CAPTURE_LIMIT,
  60. WINREASON_DEFEND_UNTIL_TIME_LIMIT,
  61. WINREASON_STALEMATE,
  62. WINREASON_TIMELIMIT,
  63. WINREASON_WINLIMIT,
  64. WINREASON_HUNTED_DEAD,
  65. WINREASON_HUNTED_ESCAPED,
  66. };
  67. enum stalemate_reasons_t
  68. {
  69. STALEMATE_JOIN_MID,
  70. STALEMATE_TIMER,
  71. STALEMATE_SERVER_TIMELIMIT,
  72. NUM_STALEMATE_REASONS,
  73. };
  74. //-----------------------------------------------------------------------------
  75. // Purpose: Per-state data
  76. //-----------------------------------------------------------------------------
  77. class CGameRulesRoundStateInfo
  78. {
  79. public:
  80. gamerules_roundstate_t m_iRoundState;
  81. const char *m_pStateName;
  82. void (CTeamplayRoundBasedRules::*pfnEnterState)(); // Init and deinit the state.
  83. void (CTeamplayRoundBasedRules::*pfnLeaveState)();
  84. void (CTeamplayRoundBasedRules::*pfnThink)(); // Do a PreThink() in this state.
  85. };
  86. //-----------------------------------------------------------------------------
  87. // Purpose:
  88. //-----------------------------------------------------------------------------
  89. class CTeamplayRoundBasedRulesProxy : public CGameRulesProxy
  90. {
  91. public:
  92. DECLARE_CLASS( CTeamplayRoundBasedRulesProxy, CGameRulesProxy );
  93. DECLARE_NETWORKCLASS();
  94. #ifdef GAME_DLL
  95. DECLARE_DATADESC();
  96. void InputSetStalemateOnTimelimit( inputdata_t &inputdata );
  97. #endif
  98. //----------------------------------------------------------------------------------
  99. // Client specific
  100. #ifdef CLIENT_DLL
  101. void OnPreDataChanged( DataUpdateType_t updateType );
  102. void OnDataChanged( DataUpdateType_t updateType );
  103. #endif // CLIENT_DLL
  104. };
  105. //-----------------------------------------------------------------------------
  106. // Purpose: Teamplay game rules that manage a round based structure for you
  107. //-----------------------------------------------------------------------------
  108. class CTeamplayRoundBasedRules : public CTeamplayRules
  109. {
  110. DECLARE_CLASS( CTeamplayRoundBasedRules, CTeamplayRules );
  111. public:
  112. CTeamplayRoundBasedRules();
  113. #ifdef CLIENT_DLL
  114. DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars.
  115. void SetRoundState( int iRoundState );
  116. float m_flLastRoundStateChangeTime;
  117. #else
  118. DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars.
  119. #endif
  120. // Data accessors
  121. inline gamerules_roundstate_t State_Get( void ) { return m_iRoundState; }
  122. bool IsInWaitingForPlayers( void ) { return m_bInWaitingForPlayers; }
  123. virtual bool InRoundRestart( void ) { return State_Get() == GR_STATE_PREROUND; }
  124. bool InStalemate( void ) { return State_Get() == GR_STATE_STALEMATE; }
  125. bool RoundHasBeenWon( void ) { return State_Get() == GR_STATE_TEAM_WIN; }
  126. virtual float GetNextRespawnWave( int iTeam, CBasePlayer *pPlayer );
  127. virtual bool HasPassedMinRespawnTime( CBasePlayer *pPlayer );
  128. float GetRespawnTimeScalar( int iTeam );
  129. float GetRespawnWaveMaxLength( int iTeam, bool bScaleWithNumPlayers = true );
  130. float GetMinTimeWhenPlayerMaySpawn( CBasePlayer *pPlayer );
  131. // Return false if players aren't allowed to cap points at this time (i.e. in WaitingForPlayers)
  132. virtual bool PointsMayBeCaptured( void ) { return ((State_Get() == GR_STATE_RND_RUNNING || State_Get() == GR_STATE_STALEMATE) && !IsInWaitingForPlayers()); }
  133. virtual void SetLastCapPointChanged( int iIndex ) { m_iLastCapPointChanged = iIndex; }
  134. int GetLastCapPointChanged( void ) { return m_iLastCapPointChanged; }
  135. virtual int GetWinningTeam( void ){ return m_iWinningTeam; }
  136. int GetWinReason() { return m_iWinReason; }
  137. bool InOvertime( void ){ return m_bInOvertime; }
  138. void SetOvertime( bool bOvertime );
  139. bool InSetup( void ){ return m_bInSetup; }
  140. void BalanceTeams( bool bRequireSwitcheesToBeDead );
  141. bool SwitchedTeamsThisRound( void ) { return m_bSwitchedTeamsThisRound; }
  142. bool ShouldBalanceTeams( void );
  143. bool IsInTournamentMode( void );
  144. bool IsInPreMatch( void ) { return (IsInTournamentMode() && IsInWaitingForPlayers()); }
  145. bool IsWaitingForTeams( void ) { return m_bAwaitingReadyRestart; }
  146. bool IsInStopWatch( void ) { return m_bStopWatch; }
  147. void SetInStopWatch( bool bState ) { m_bStopWatch = bState; }
  148. virtual void StopWatchModeThink( void ) { };
  149. bool IsTeamReady( int iTeamNumber )
  150. {
  151. return m_bTeamReady[iTeamNumber];
  152. }
  153. virtual void HandleTeamScoreModify( int iTeam, int iScore) { };
  154. float GetRoundRestartTime( void ) { return m_flRestartRoundTime; }
  155. //Arena Mode
  156. virtual bool IsInArenaMode( void ) { return false; }
  157. //----------------------------------------------------------------------------------
  158. // Server specific
  159. #ifdef GAME_DLL
  160. // Derived game rules class should override these
  161. public:
  162. // Override this to prevent removal of game specific entities that need to persist
  163. virtual bool RoundCleanupShouldIgnore( CBaseEntity *pEnt );
  164. virtual bool ShouldCreateEntity( const char *pszClassName );
  165. // Called when a new round is being initialized
  166. virtual void SetupOnRoundStart( void ) { return; }
  167. // Called when a new round is off and running
  168. virtual void SetupOnRoundRunning( void ) { return; }
  169. // Called before a new round is started (so the previous round can end)
  170. virtual void PreviousRoundEnd( void ) { return; }
  171. // Send the team scores down to the client
  172. virtual void SendTeamScoresEvent( void ) { return; }
  173. // Send the end of round info displayed in the win panel
  174. virtual void SendWinPanelInfo( void ) { return; }
  175. // Setup spawn points for the current round before it starts
  176. virtual void SetupSpawnPointsForRound( void ) { return; }
  177. // Called when a round has entered stalemate mode (timer has run out)
  178. virtual void SetupOnStalemateStart( void ) { return; }
  179. virtual void SetupOnStalemateEnd( void ) { return; }
  180. virtual void SetSetup( bool bSetup );
  181. bool PrevRoundWasWaitingForPlayers() { return m_bPrevRoundWasWaitingForPlayers; }
  182. virtual bool ShouldScorePerRound( void ){ return true; }
  183. bool CheckNextLevelCvar( void );
  184. virtual bool TimerMayExpire( void );
  185. virtual bool IsValveMap( void ){ return false; }
  186. virtual void RestartTournament( void );
  187. public:
  188. void State_Transition( gamerules_roundstate_t newState );
  189. void RespawnPlayers( bool bForceRespawn, bool bTeam = false, int iTeam = TEAM_UNASSIGNED );
  190. void SetForceMapReset( bool reset );
  191. void SetRoundToPlayNext( string_t strName ){ m_iszRoundToPlayNext = strName; }
  192. string_t GetRoundToPlayNext( void ){ return m_iszRoundToPlayNext; }
  193. void AddPlayedRound( string_t strName );
  194. bool IsPreviouslyPlayedRound ( string_t strName );
  195. string_t GetLastPlayedRound( void );
  196. virtual void SetWinningTeam( int team, int iWinReason, bool bForceMapReset = true, bool bSwitchTeams = false, bool bDontAddScore = false );
  197. virtual void SetStalemate( int iReason, bool bForceMapReset = true, bool bSwitchTeams = false );
  198. virtual void SetRoundOverlayDetails( void ){ return; }
  199. virtual float GetWaitingForPlayersTime( void ) { return mp_waitingforplayers_time.GetFloat(); }
  200. void ShouldResetScores( bool bResetTeam, bool bResetPlayer ){ m_bResetTeamScores = bResetTeam; m_bResetPlayerScores = bResetPlayer; }
  201. void ShouldResetRoundsPlayed( bool bResetRoundsPlayed ){ m_bResetRoundsPlayed = bResetRoundsPlayed; }
  202. void SetFirstRoundPlayed( string_t strName ){ m_iszFirstRoundPlayed = strName ; }
  203. string_t GetFirstRoundPlayed(){ return m_iszFirstRoundPlayed; }
  204. void SetTeamRespawnWaveTime( int iTeam, float flValue );
  205. void AddTeamRespawnWaveTime( int iTeam, float flValue );
  206. virtual void FillOutTeamplayRoundWinEvent( IGameEvent *event ) {} // derived classes may implement to add fields to this event
  207. void SetStalemateOnTimelimit( bool bStalemate ) { m_bAllowStalemateAtTimelimit = bStalemate; }
  208. bool IsGameUnderTimeLimit( void );
  209. CTeamRoundTimer *GetActiveRoundTimer( void );
  210. void HandleTimeLimitChange( void );
  211. void SetTeamReadyState( bool bState, int iTeam )
  212. {
  213. m_bTeamReady.Set( iTeam, bState );
  214. }
  215. virtual void PlayTrainCaptureAlert( CTeamControlPoint *pPoint, bool bFinalPointInMap ){ return; }
  216. protected:
  217. virtual void Think( void );
  218. virtual void CheckChatText( CBasePlayer *pPlayer, char *pText );
  219. void CheckChatForReadySignal( CBasePlayer *pPlayer, const char *chatmsg );
  220. // Game beginning / end handling
  221. virtual void GoToIntermission( void );
  222. void SetInWaitingForPlayers( bool bWaitingForPlayers );
  223. void CheckWaitingForPlayers( void );
  224. void CheckRestartRound( void );
  225. bool CheckTimeLimit( void );
  226. int GetTimeLeft( void );
  227. virtual bool CheckWinLimit( void );
  228. bool CheckMaxRounds( void );
  229. void CheckReadyRestart( void );
  230. virtual bool CanChangelevelBecauseOfTimeLimit( void ) { return true; }
  231. virtual bool CanGoToStalemate( void ) { return true; }
  232. // State machine handling
  233. void State_Enter( gamerules_roundstate_t newState ); // Initialize the new state.
  234. void State_Leave(); // Cleanup the previous state.
  235. void State_Think(); // Update the current state.
  236. static CGameRulesRoundStateInfo* State_LookupInfo( gamerules_roundstate_t state ); // Find the state info for the specified state.
  237. // State Functions
  238. void State_Enter_INIT( void );
  239. void State_Think_INIT( void );
  240. void State_Enter_PREGAME( void );
  241. void State_Think_PREGAME( void );
  242. void State_Enter_STARTGAME( void );
  243. void State_Think_STARTGAME( void );
  244. void State_Enter_PREROUND( void );
  245. void State_Think_PREROUND( void );
  246. void State_Enter_RND_RUNNING( void );
  247. void State_Think_RND_RUNNING( void );
  248. void State_Enter_TEAM_WIN( void );
  249. void State_Think_TEAM_WIN( void );
  250. void State_Enter_RESTART( void );
  251. void State_Think_RESTART( void );
  252. void State_Enter_STALEMATE( void );
  253. void State_Think_STALEMATE( void );
  254. void State_Leave_STALEMATE( void );
  255. protected:
  256. virtual void InitTeams( void );
  257. virtual int CountActivePlayers( void );
  258. virtual void RoundRespawn( void );
  259. virtual void CleanUpMap( void );
  260. void CheckRespawnWaves( void );
  261. void ResetScores( void );
  262. void ResetMapTime( void );
  263. void PlayStartRoundVoice( void );
  264. void PlayWinSong( int team );
  265. void PlayStalemateSong( void );
  266. void PlaySuddenDeathSong( void );
  267. void BroadcastSound( int iTeam, const char *sound );
  268. inline void RespawnTeam( int iTeam ) { RespawnPlayers( false, true, iTeam ); }
  269. void HideActiveTimer( void );
  270. void RestoreActiveTimer( void );
  271. virtual void InternalHandleTeamWin( int iWinningTeam ){ return; }
  272. bool MapHasActiveTimer( void );
  273. void CreateTimeLimitTimer( void );
  274. protected:
  275. CGameRulesRoundStateInfo *m_pCurStateInfo; // Per-state data
  276. float m_flStateTransitionTime; // Timer for round states
  277. float m_flWaitingForPlayersTimeEnds;
  278. CHandle<CTeamRoundTimer> m_hWaitingForPlayersTimer;
  279. float m_flNextPeriodicThink;
  280. bool m_bChangeLevelOnRoundEnd;
  281. bool m_bResetTeamScores;
  282. bool m_bResetPlayerScores;
  283. bool m_bResetRoundsPlayed;
  284. // Stalemate
  285. EHANDLE m_hPreviousActiveTimer;
  286. CHandle<CTeamRoundTimer> m_hStalemateTimer;
  287. float m_flStalemateStartTime;
  288. CHandle<CTeamRoundTimer> m_hTimeLimitTimer;
  289. bool m_bForceMapReset; // should the map be reset when a team wins and the round is restarted?
  290. bool m_bPrevRoundWasWaitingForPlayers; // was the previous map reset after a waiting for players period
  291. bool m_bInitialSpawn;
  292. string_t m_iszRoundToPlayNext;
  293. CUtlVector<string_t> m_iszPreviousRounds; // we'll store the two previous rounds so we won't play them again right away if there are other rounds that can be played first
  294. string_t m_iszFirstRoundPlayed; // store the first round played after a full restart so we can pick a different one next time if we have other options
  295. float m_flOriginalTeamRespawnWaveTime[ MAX_TEAMS ];
  296. bool m_bAllowStalemateAtTimelimit;
  297. bool m_bChangelevelAfterStalemate;
  298. float m_flRoundStartTime; // time the current round started
  299. int m_nRoundsPlayed;
  300. bool m_bUseAddScoreAnim;
  301. #endif
  302. // End server specific
  303. //----------------------------------------------------------------------------------
  304. //----------------------------------------------------------------------------------
  305. // Client specific
  306. #ifdef CLIENT_DLL
  307. public:
  308. virtual void OnPreDataChanged( DataUpdateType_t updateType );
  309. virtual void OnDataChanged( DataUpdateType_t updateType );
  310. virtual void HandleOvertimeBegin(){}
  311. private:
  312. bool m_bOldInWaitingForPlayers;
  313. bool m_bOldInOvertime;
  314. bool m_bOldInSetup;
  315. #endif // CLIENT_DLL
  316. public:
  317. bool WouldChangeUnbalanceTeams( int iNumPlayersToMove, int iNewTeam, int iCurrentTeam );
  318. bool AreTeamsUnbalanced( int &iHeaviestTeam, int &iLightestTeam );
  319. protected:
  320. CNetworkVar( gamerules_roundstate_t, m_iRoundState );
  321. CNetworkVar( bool, m_bInOvertime ); // Are we currently in overtime?
  322. CNetworkVar( bool, m_bInSetup ); // Are we currently in setup?
  323. CNetworkVar( bool, m_bSwitchedTeamsThisRound );
  324. protected:
  325. CNetworkVar( int, m_iWinningTeam ); // Set before entering GR_STATE_TEAM_WIN
  326. CNetworkVar( int, m_iWinReason );
  327. CNetworkVar( bool, m_bInWaitingForPlayers );
  328. CNetworkVar( bool, m_bAwaitingReadyRestart );
  329. CNetworkVar( float, m_flRestartRoundTime );
  330. CNetworkVar( float, m_flMapResetTime ); // Time that the map was reset
  331. CNetworkArray( float, m_flNextRespawnWave, MAX_TEAMS ); // Minor waste, but cleaner code
  332. CNetworkArray( bool, m_bTeamReady, MAX_TEAMS );
  333. CNetworkVar( bool, m_bStopWatch );
  334. public:
  335. CNetworkArray( float, m_TeamRespawnWaveTimes, MAX_TEAMS ); // Time between each team's respawn wave
  336. private:
  337. float m_flStartBalancingTeamsAt;
  338. float m_flNextBalanceTeamsTime;
  339. bool m_bPrintedUnbalanceWarning;
  340. float m_flFoundUnbalancedTeamsTime;
  341. public:
  342. float m_flStopWatchTotalTime;
  343. int m_iLastCapPointChanged;
  344. };
  345. // Utility function
  346. bool FindInList( const char **pStrings, const char *pToFind );
  347. inline CTeamplayRoundBasedRules* TeamplayRoundBasedRules()
  348. {
  349. return static_cast<CTeamplayRoundBasedRules*>(g_pGameRules);
  350. }
  351. #endif // TEAMPLAYROUNDBASED_GAMERULES_H