This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

191 lines
7.8 KiB
C++

//========= 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
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
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;
};
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; }
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);
protected:
void ResetData(void);
void VoteControllerThink(void);
void CheckForEarlyVoteClose(void); // If everyone has voted (and changing
// votes is not allowed) then end early
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
int m_nVotesCast[MAX_PLAYERS + 1]; // arrays are zero-based and player
// indices are one-based
int m_iEntityHoldingVote;
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