Team Fortress 2 Source Code as on 22/4/2020
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.

170 lines
8.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Player-driven Voting System for Multiplayer Source games (currently implemented for TF2)
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef VOTE_CONTROLLER_H
  8. #define VOTE_CONTROLLER_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "shareddefs.h"
  13. #define MAX_COMMAND_LENGTH 64
  14. #define MAX_CREATE_ERROR_STRING 96
  15. struct VoteParams_t
  16. {
  17. VoteParams_t()
  18. {
  19. Reset();
  20. }
  21. int m_iIssueIndex;
  22. int m_iEntIndex;
  23. char m_szTypeString[MAX_COMMAND_LENGTH];
  24. char m_szDetailString[MAX_VOTE_DETAILS_LENGTH];
  25. void Reset( void )
  26. {
  27. m_iIssueIndex = INVALID_ISSUE;
  28. m_iEntIndex = -1;
  29. m_szTypeString[0] = 0;
  30. m_szDetailString[0] = 0;
  31. }
  32. };
  33. class CBaseIssue // Base class concept for vote issues (i.e. Kick Player). Created per level-load and destroyed by CVoteController's dtor.
  34. {
  35. public:
  36. CBaseIssue( const char *typeString );
  37. virtual ~CBaseIssue();
  38. const char *GetTypeString( void ); // Connection between console command and specific type of issue
  39. virtual const char *GetTypeStringLocalized( void ) { return ""; } // When empty, the client uses the classname string and prepends "#Vote_"
  40. virtual const char *GetDetailsString( void );
  41. virtual void SetIssueDetails( const char *pszDetails ); // We need to know the details part of the con command for later
  42. virtual void OnVoteFailed( int iEntityHoldingVote ); // The moment the vote fails, also has some time for feedback before the window goes away
  43. virtual void OnVoteStarted( void ) {} // Called as soon as the vote starts
  44. virtual bool IsEnabled( void ) { return false; } // Query the issue to see if it's enabled
  45. virtual bool CanTeamCallVote( int iTeam ) const; // Can someone on the given team call this vote?
  46. virtual bool CanCallVote( int nEntIndex, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime ); // Can this guy hold a vote on this issue?
  47. virtual bool IsTeamRestrictedVote( void ); // Restrict access and visibility of this vote to a specific team?
  48. virtual const char *GetDisplayString( void ) = 0; // The string that will be passed to the client for display
  49. virtual void ExecuteCommand( void ) = 0; // Where the magic happens. Do your thing.
  50. virtual void ListIssueDetails( CBasePlayer *pForWhom ) = 0; // Someone would like to know all your valid details
  51. virtual const char *GetVotePassedString( void ); // Get the string an issue would like to display when it passes.
  52. virtual int CountPotentialVoters( void );
  53. virtual int GetNumberVoteOptions( void ); // How many choices this vote will have. i.e. Returns 2 on a Yes/No issue (the default).
  54. virtual bool IsYesNoVote( void );
  55. virtual void SetYesNoVoteCount( int iNumYesVotes, int iNumNoVotes, int iNumPotentialVotes );
  56. virtual bool GetVoteOptions( CUtlVector <const char*> &vecNames ); // We use this to generate options for voting
  57. virtual bool BRecordVoteFailureEventForEntity( int iVoteCallingEntityIndex ) const { return iVoteCallingEntityIndex != DEDICATED_SERVER; }
  58. void SetIssueCooldownDuration( float flDuration ) { m_flNextCallTime = gpGlobals->curtime + flDuration; } // The issue can not be raised again for this period of time (in seconds)
  59. virtual float GetQuorumRatio( void ); // Each issue can decide the required ratio of voted-vs-abstained
  60. virtual bool NeedsPermissionFromGC( void ) { return false; } // Per-issue decision to ask a GC if this vote is permitted (see TF's MvM kick vote for an example)
  61. virtual void GCResponseReceived( bool bApproved ); // How to handle the response/verdict from the GC (VoteController also receives a response)
  62. CHandle< CBasePlayer > m_hPlayerTarget; // If the target of the issue is a player, we should store them here
  63. protected:
  64. static void ListStandardNoArgCommand( CBasePlayer *forWhom, const char *issueString ); // List a Yes vote command
  65. struct FailedVote
  66. {
  67. char szFailedVoteParameter[MAX_VOTE_DETAILS_LENGTH];
  68. float flLockoutTime;
  69. };
  70. CUtlVector< FailedVote* > m_FailedVotes;
  71. char m_szTypeString[MAX_COMMAND_LENGTH];
  72. char m_szDetailsString[MAX_VOTE_DETAILS_LENGTH];
  73. int m_iNumYesVotes;
  74. int m_iNumNoVotes;
  75. int m_iNumPotentialVotes;
  76. float m_flNextCallTime;
  77. bool m_bGCNotified;
  78. bool m_bGCApproved;
  79. bool m_bGCResponded;
  80. };
  81. class CVoteController : public CBaseEntity
  82. {
  83. DECLARE_CLASS( CVoteController, CBaseEntity );
  84. public:
  85. DECLARE_SERVERCLASS();
  86. DECLARE_DATADESC();
  87. virtual ~CVoteController();
  88. enum TryCastVoteResult
  89. {
  90. CAST_OK,
  91. CAST_FAIL_SERVER_DISABLE,
  92. CAST_FAIL_NO_ACTIVE_ISSUE,
  93. CAST_FAIL_TEAM_RESTRICTED,
  94. CAST_FAIL_NO_CHANGES,
  95. CAST_FAIL_DUPLICATE,
  96. CAST_FAIL_VOTE_CLOSED,
  97. CAST_FAIL_SYSTEM_ERROR
  98. };
  99. virtual void Spawn( void );
  100. virtual int UpdateTransmitState( void );
  101. virtual bool IsVoteSystemEnabled( void );
  102. bool SetupVote( int iEntIndex ); // This creates a list of issues for the UI
  103. bool CreateVote( int iEntIndex, const char *pszTypeString, const char *pszDetailString ); // This is what the UI passes in
  104. TryCastVoteResult TryCastVote( int iEntIndex, const char *pszVoteString );
  105. void RegisterIssue( CBaseIssue *pNewIssue );
  106. void ListIssues( CBasePlayer *pForWhom );
  107. bool IsValidVoter( CBasePlayer *pWhom );
  108. bool CanTeamCastVote( int iTeam ) const;
  109. void SendVoteCreationFailedMessage( vote_create_failed_t nReason, CBasePlayer *pVoteCaller, int nTime = -1 );
  110. void SendVoteFailedToPassMessage( vote_create_failed_t nReason );
  111. void VoteChoice_Increment( int nVoteChoice );
  112. void VoteChoice_Decrement( int nVoteChoice );
  113. int GetVoteIssueIndexWithHighestCount( void );
  114. void TrackVoteCaller( CBasePlayer *pPlayer );
  115. bool CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown, vote_create_failed_t &nErrorCode );
  116. bool IsVoteActive( void ) { return ( m_iActiveIssueIndex != INVALID_ISSUE || m_pendingVoteParams.m_iIssueIndex != INVALID_ISSUE ); }
  117. int GetNumVotesCast( void );
  118. void AddPlayerToKickWatchList( CSteamID steamID, float flDuration ); // Band-aid until we figure out how player's avoid kick votes
  119. void AddPlayerToNameLockedList( CSteamID steamID, float flDuration, int nUserID );
  120. bool IsPlayerBeingKicked( CBasePlayer *pPlayer );
  121. void GCResponseReceived( bool bVerdict ); // The GC's response when a vote issue requires approval from the GC
  122. protected:
  123. void ResetData( void );
  124. void VoteControllerThink( void );
  125. void CheckForEarlyVoteClose( void ); // If everyone has voted (and changing votes is not allowed) then end early
  126. bool SubmitPendingVote( VoteParams_t params ); // When an issue requires permission from the GC, this is how the pending issue moves forward
  127. CNetworkVar( int, m_iActiveIssueIndex ); // Type of thing being voted on
  128. CNetworkVar( int, m_iOnlyTeamToVote ); // If an Ally restricted vote, the team number that is allowed to vote
  129. CNetworkArray( int, m_nVoteOptionCount, MAX_VOTE_OPTIONS ); // Vote options counter
  130. CNetworkVar( int, m_nPotentialVotes ); // How many votes could come in, so we can close ballot early
  131. CNetworkVar( bool, m_bIsYesNoVote ); // Is the current issue Yes/No?
  132. CountdownTimer m_acceptingVotesTimer; // How long from vote start until we count the ballots
  133. CountdownTimer m_executeCommandTimer; // How long after end of vote time until we execute a passed vote
  134. CountdownTimer m_resetVoteTimer; // when the current vote will end
  135. CountdownTimer m_waitingForGCResponseTimer; // Some votes require approval from the GC - wait this long for a response
  136. int m_nVotesCast[MAX_PLAYERS + 1]; // arrays are zero-based and player indices are one-based
  137. int m_iEntityHoldingVote;
  138. VoteParams_t m_pendingVoteParams; // A pending vote that's waiting for a response from the GC
  139. CUtlVector <CBaseIssue *> m_potentialIssues;
  140. CUtlVector <const char *> m_VoteOptions;
  141. CUtlMap <uint64, float> m_VoteCallers; // History of SteamIDs that have tried to call votes.
  142. friend class CVoteControllerSystem;
  143. };
  144. extern CVoteController *g_voteController;
  145. #endif // VOTE_CONTROLLER_H