summaryrefslogtreecommitdiff
path: root/game/server/vote_controller.h
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/vote_controller.h
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/server/vote_controller.h')
-rw-r--r--game/server/vote_controller.h170
1 files changed, 170 insertions, 0 deletions
diff --git a/game/server/vote_controller.h b/game/server/vote_controller.h
new file mode 100644
index 0000000..6382dea
--- /dev/null
+++ b/game/server/vote_controller.h
@@ -0,0 +1,170 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Player-driven Voting System for Multiplayer Source games (currently implemented for TF2)
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef VOTE_CONTROLLER_H
+#define VOTE_CONTROLLER_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "shareddefs.h"
+
+#define MAX_COMMAND_LENGTH 64
+#define MAX_CREATE_ERROR_STRING 96
+
+struct VoteParams_t
+{
+ VoteParams_t()
+ {
+ Reset();
+ }
+
+ int m_iIssueIndex;
+ int m_iEntIndex;
+ char m_szTypeString[MAX_COMMAND_LENGTH];
+ char m_szDetailString[MAX_VOTE_DETAILS_LENGTH];
+
+ void Reset( void )
+ {
+ m_iIssueIndex = INVALID_ISSUE;
+ m_iEntIndex = -1;
+ m_szTypeString[0] = 0;
+ m_szDetailString[0] = 0;
+ }
+};
+
+class CBaseIssue // Base class concept for vote issues (i.e. Kick Player). Created per level-load and destroyed by CVoteController's dtor.
+{
+public:
+ CBaseIssue( const char *typeString );
+ virtual ~CBaseIssue();
+ const char *GetTypeString( void ); // Connection between console command and specific type of issue
+ virtual const char *GetTypeStringLocalized( void ) { return ""; } // When empty, the client uses the classname string and prepends "#Vote_"
+ virtual const char *GetDetailsString( void );
+ virtual void SetIssueDetails( const char *pszDetails ); // We need to know the details part of the con command for later
+ virtual void OnVoteFailed( int iEntityHoldingVote ); // The moment the vote fails, also has some time for feedback before the window goes away
+ virtual void OnVoteStarted( void ) {} // Called as soon as the vote starts
+ virtual bool IsEnabled( void ) { return false; } // Query the issue to see if it's enabled
+ virtual bool CanTeamCallVote( int iTeam ) const; // Can someone on the given team call this vote?
+ virtual bool CanCallVote( int nEntIndex, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime ); // Can this guy hold a vote on this issue?
+ virtual bool IsTeamRestrictedVote( void ); // Restrict access and visibility of this vote to a specific team?
+ virtual const char *GetDisplayString( void ) = 0; // The string that will be passed to the client for display
+ virtual void ExecuteCommand( void ) = 0; // Where the magic happens. Do your thing.
+ virtual void ListIssueDetails( CBasePlayer *pForWhom ) = 0; // Someone would like to know all your valid details
+ virtual const char *GetVotePassedString( void ); // Get the string an issue would like to display when it passes.
+ virtual int CountPotentialVoters( void );
+ virtual int GetNumberVoteOptions( void ); // How many choices this vote will have. i.e. Returns 2 on a Yes/No issue (the default).
+ virtual bool IsYesNoVote( void );
+ virtual void SetYesNoVoteCount( int iNumYesVotes, int iNumNoVotes, int iNumPotentialVotes );
+ virtual bool GetVoteOptions( CUtlVector <const char*> &vecNames ); // We use this to generate options for voting
+ virtual bool BRecordVoteFailureEventForEntity( int iVoteCallingEntityIndex ) const { return iVoteCallingEntityIndex != DEDICATED_SERVER; }
+ void SetIssueCooldownDuration( float flDuration ) { m_flNextCallTime = gpGlobals->curtime + flDuration; } // The issue can not be raised again for this period of time (in seconds)
+ virtual float GetQuorumRatio( void ); // Each issue can decide the required ratio of voted-vs-abstained
+ 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)
+ virtual void GCResponseReceived( bool bApproved ); // How to handle the response/verdict from the GC (VoteController also receives a response)
+
+ CHandle< CBasePlayer > m_hPlayerTarget; // If the target of the issue is a player, we should store them here
+
+protected:
+ static void ListStandardNoArgCommand( CBasePlayer *forWhom, const char *issueString ); // List a Yes vote command
+
+ struct FailedVote
+ {
+ char szFailedVoteParameter[MAX_VOTE_DETAILS_LENGTH];
+ float flLockoutTime;
+ };
+
+ CUtlVector< FailedVote* > m_FailedVotes;
+ char m_szTypeString[MAX_COMMAND_LENGTH];
+ char m_szDetailsString[MAX_VOTE_DETAILS_LENGTH];
+ int m_iNumYesVotes;
+ int m_iNumNoVotes;
+ int m_iNumPotentialVotes;
+ float m_flNextCallTime;
+ bool m_bGCNotified;
+ bool m_bGCApproved;
+ bool m_bGCResponded;
+};
+
+class CVoteController : public CBaseEntity
+{
+ DECLARE_CLASS( CVoteController, CBaseEntity );
+
+public:
+ DECLARE_SERVERCLASS();
+ DECLARE_DATADESC();
+
+ virtual ~CVoteController();
+
+ enum TryCastVoteResult
+ {
+ CAST_OK,
+ CAST_FAIL_SERVER_DISABLE,
+ CAST_FAIL_NO_ACTIVE_ISSUE,
+ CAST_FAIL_TEAM_RESTRICTED,
+ CAST_FAIL_NO_CHANGES,
+ CAST_FAIL_DUPLICATE,
+ CAST_FAIL_VOTE_CLOSED,
+ CAST_FAIL_SYSTEM_ERROR
+ };
+
+ virtual void Spawn( void );
+ virtual int UpdateTransmitState( void );
+ virtual bool IsVoteSystemEnabled( void );
+
+ bool SetupVote( int iEntIndex ); // This creates a list of issues for the UI
+ bool CreateVote( int iEntIndex, const char *pszTypeString, const char *pszDetailString ); // This is what the UI passes in
+ TryCastVoteResult TryCastVote( int iEntIndex, const char *pszVoteString );
+ void RegisterIssue( CBaseIssue *pNewIssue );
+ void ListIssues( CBasePlayer *pForWhom );
+ bool IsValidVoter( CBasePlayer *pWhom );
+ bool CanTeamCastVote( int iTeam ) const;
+ void SendVoteCreationFailedMessage( vote_create_failed_t nReason, CBasePlayer *pVoteCaller, int nTime = -1 );
+ void SendVoteFailedToPassMessage( vote_create_failed_t nReason );
+ void VoteChoice_Increment( int nVoteChoice );
+ void VoteChoice_Decrement( int nVoteChoice );
+ int GetVoteIssueIndexWithHighestCount( void );
+ void TrackVoteCaller( CBasePlayer *pPlayer );
+ bool CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown, vote_create_failed_t &nErrorCode );
+ bool IsVoteActive( void ) { return ( m_iActiveIssueIndex != INVALID_ISSUE || m_pendingVoteParams.m_iIssueIndex != INVALID_ISSUE ); }
+ int GetNumVotesCast( void );
+
+ void AddPlayerToKickWatchList( CSteamID steamID, float flDuration ); // Band-aid until we figure out how player's avoid kick votes
+ void AddPlayerToNameLockedList( CSteamID steamID, float flDuration, int nUserID );
+ bool IsPlayerBeingKicked( CBasePlayer *pPlayer );
+ void GCResponseReceived( bool bVerdict ); // The GC's response when a vote issue requires approval from the GC
+
+protected:
+ void ResetData( void );
+ void VoteControllerThink( void );
+ void CheckForEarlyVoteClose( void ); // If everyone has voted (and changing votes is not allowed) then end early
+ bool SubmitPendingVote( VoteParams_t params ); // When an issue requires permission from the GC, this is how the pending issue moves forward
+
+ CNetworkVar( int, m_iActiveIssueIndex ); // Type of thing being voted on
+ CNetworkVar( int, m_iOnlyTeamToVote ); // If an Ally restricted vote, the team number that is allowed to vote
+ CNetworkArray( int, m_nVoteOptionCount, MAX_VOTE_OPTIONS ); // Vote options counter
+ CNetworkVar( int, m_nPotentialVotes ); // How many votes could come in, so we can close ballot early
+ CNetworkVar( bool, m_bIsYesNoVote ); // Is the current issue Yes/No?
+ CountdownTimer m_acceptingVotesTimer; // How long from vote start until we count the ballots
+ CountdownTimer m_executeCommandTimer; // How long after end of vote time until we execute a passed vote
+ CountdownTimer m_resetVoteTimer; // when the current vote will end
+ CountdownTimer m_waitingForGCResponseTimer; // Some votes require approval from the GC - wait this long for a response
+ int m_nVotesCast[MAX_PLAYERS + 1]; // arrays are zero-based and player indices are one-based
+ int m_iEntityHoldingVote;
+ VoteParams_t m_pendingVoteParams; // A pending vote that's waiting for a response from the GC
+
+ CUtlVector <CBaseIssue *> m_potentialIssues;
+ CUtlVector <const char *> m_VoteOptions;
+ CUtlMap <uint64, float> m_VoteCallers; // History of SteamIDs that have tried to call votes.
+
+ friend class CVoteControllerSystem;
+};
+
+extern CVoteController *g_voteController;
+
+#endif // VOTE_CONTROLLER_H