home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GameStar 2006 March
/
Gamestar_82_2006-03_dvd.iso
/
DVDStar
/
Editace
/
quake4_sdkv10.exe
/
source
/
game
/
MultiplayerGame.h
< prev
next >
Wrap
C/C++ Source or Header
|
2005-11-14
|
22KB
|
798 lines
// RAVEN BEGIN
// ddynerman: note that this file is no longer merged with Doom3 updates
//
// MERGE_DATE 09/30/2004
#ifndef __MULTIPLAYERGAME_H__
#define __MULTIPLAYERGAME_H__
/*
===============================================================================
Quake IV multiplayer
===============================================================================
*/
class idPlayer;
class rvCTF_AssaultPoint;
class rvItemCTFFlag;
typedef enum {
GAME_SP,
GAME_DM,
GAME_TOURNEY,
GAME_TDM,
// bdube: added ctf
GAME_CTF,
// ddynerman: new gametypes
GAME_1F_CTF,
GAME_ARENA_CTF,
GAME_ARENA_1F_CTF
} gameType_t;
// ddynerman: teams
typedef enum {
TEAM_MARINE,
TEAM_STROGG,
TEAM_MAX,
} team_t;
// shouchard: server admin command types
typedef enum {
SERVER_ADMIN_KICK,
SERVER_ADMIN_BAN,
SERVER_ADMIN_REMOVE_BAN,
SERVER_ADMIN_FORCE_SWITCH,
} serverAdmin_t;
// shouchard: vote struct for packing up interface values to be handled later
// note that we have two mechanisms for dealing with vote data that
// should be consolidated: this one that handles the interface and
// multi-field votes and the one that handles console commands and
// single line votes.
struct voteStruct_t {
int m_fieldFlags; // flags for which fields are valid
int m_kick; // id of the player
idStr m_map; // name of the map
int m_gameType; // game type enum
int m_timeLimit;
int m_fragLimit;
int m_tourneyLimit;
int m_captureLimit;
int m_minPlayers;
int m_teamBalance;
// restart is a flag only
// nextmap is a flag only but we don't technically support it (but doom had it so it's here)
};
typedef enum {
VOTEFLAG_RESTART = 0x0001,
VOTEFLAG_MIN_PLAYERS = 0x0002,
VOTEFLAG_TEAMBALANCE = 0x0004,
VOTEFLAG_NEXTMAP = 0x0008,
VOTEFLAG_KICK = 0x0010,
VOTEFLAG_MAP = 0x0020,
VOTEFLAG_GAMETYPE = 0x0040,
VOTEFLAG_TIMELIMIT = 0x0080,
VOTEFLAG_TOURNEYLIMIT = 0x0100,
VOTEFLAG_CAPTURELIMIT = 0x0200,
VOTEFLAG_FRAGLIMIT = 0x0400,
} voteFlag_t;
// more compact than a chat line
typedef enum {
MSG_SUICIDE = 0,
MSG_KILLED,
MSG_KILLEDTEAM,
MSG_DIED,
MSG_VOTE,
MSG_VOTEPASSED,
MSG_VOTEFAILED,
MSG_SUDDENDEATH,
MSG_FORCEREADY,
MSG_JOINEDSPEC,
MSG_TIMELIMIT,
MSG_FRAGLIMIT,
MSG_CAPTURELIMIT,
MSG_TELEFRAGGED,
MSG_JOINTEAM,
MSG_HOLYSHIT,
MSG_COUNT
} msg_evt_t;
typedef enum {
PLAYER_VOTE_NONE,
PLAYER_VOTE_NO,
PLAYER_VOTE_YES,
PLAYER_VOTE_WAIT // mark a player allowed to vote
} playerVote_t;
typedef enum {
PRM_AUTO,
PRM_SCORE,
PRM_TEAM_SCORE,
PRM_TEAM_SCORE_PLUS_SCORE,
PRM_WINS
} playerRankMode_t;
enum announcerSound_t {
// General announcements
AS_GENERAL_ONE,
AS_GENERAL_TWO,
AS_GENERAL_THREE,
AS_GENERAL_YOU_WIN,
AS_GENERAL_YOU_LOSE,
AS_GENERAL_FIGHT,
AS_GENERAL_SUDDEN_DEATH,
AS_GENERAL_VOTE_FAILED,
AS_GENERAL_VOTE_PASSED,
AS_GENERAL_VOTE_NOW,
AS_GENERAL_ONE_FRAG,
AS_GENERAL_TWO_FRAGS,
AS_GENERAL_THREE_FRAGS,
AS_GENERAL_ONE_MINUTE,
AS_GENERAL_FIVE_MINUTE,
AS_GENERAL_PREPARE_TO_FIGHT,
AS_GENERAL_QUAD_DAMAGE,
AS_GENERAL_REGENERATION,
AS_GENERAL_HASTE,
AS_GENERAL_INVISIBILITY,
// DM announcements
AS_DM_YOU_TIED_LEAD,
AS_DM_YOU_HAVE_TAKEN_LEAD,
AS_DM_YOU_LOST_LEAD,
// Team announcements
AS_TEAM_ENEMY_SCORES,
AS_TEAM_YOU_SCORE,
AS_TEAM_TEAMS_TIED,
AS_TEAM_STROGG_LEAD,
AS_TEAM_MARINES_LEAD,
AS_TEAM_JOIN_MARINE,
AS_TEAM_JOIN_STROGG,
// CTF announcements
AS_CTF_YOU_HAVE_FLAG,
AS_CTF_YOUR_TEAM_HAS_FLAG,
AS_CTF_ENEMY_HAS_FLAG,
AS_CTF_YOUR_TEAM_DROPS_FLAG,
AS_CTF_ENEMY_DROPS_FLAG,
AS_CTF_YOUR_FLAG_RETURNED,
AS_CTF_ENEMY_RETURNS_FLAG,
// Tourney announcements
AS_TOURNEY_ADVANCE,
AS_TOURNEY_JOIN_ARENA_ONE,
AS_TOURNEY_JOIN_ARENA_TWO,
AS_TOURNEY_JOIN_ARENA_THREE,
AS_TOURNEY_JOIN_ARENA_FOUR,
AS_TOURNEY_JOIN_ARENA_FIVE,
AS_TOURNEY_JOIN_ARENA_SIX,
AS_TOURNEY_JOIN_ARENA_SEVEN,
AS_TOURNEY_JOIN_ARENA_EIGHT,
AS_TOURNEY_JOIN_ARENA_WAITING,
AS_TOURNEY_DONE,
AS_TOURNEY_START,
AS_TOURNEY_ELIMINATED,
AS_TOURNEY_WON,
AS_TOURNEY_PRELIMS,
AS_TOURNEY_QUARTER_FINALS,
AS_TOURNEY_SEMI_FINALS,
AS_TOURNEY_FINAL_MATCH,
AS_NUM_SOUNDS
};
typedef struct mpPlayerState_s {
int ping; // player ping
int fragCount; // kills
int teamFragCount; // teamplay awards
int wins;
playerVote_t vote; // player's vote
bool scoreBoardUp; // toggle based on player scoreboard button, used to activate de-activate the scoreboard gui
bool ingame;
} mpPlayerState_t;
const int MAX_INSTANCES = 8;
const int NUM_CHAT_NOTIFY = 5;
const int CHAT_FADE_TIME = 400;
const int FRAGLIMIT_DELAY = 2000;
const int CAPTURELIMIT_DELAY = 750;
const int MP_PLAYER_MINFRAGS = -100;
const int MP_PLAYER_MAXFRAGS = 999;
const int MP_PLAYER_MAXWINS = 100;
const int MP_PLAYER_MAXPING = 999;
const int MAX_AP = 5;
const int CHAT_HISTORY_SIZE = 2048;
const int RCON_HISTORY_SIZE = 4096;
const int KILL_NOTIFICATION_LEN = 256;
//RAVEN BEGIN
//asalmon: update stats for Xenon
#ifdef _XENON
const int XENON_STAT_UPDATE_INTERVAL = 1000;
#endif
const int ASYNC_PLAYER_FRAG_BITS = -idMath::BitsForInteger( MP_PLAYER_MAXFRAGS - MP_PLAYER_MINFRAGS ); // player can have negative frags
const int ASYNC_PLAYER_WINS_BITS = idMath::BitsForInteger( MP_PLAYER_MAXWINS );
const int ASYNC_PLAYER_PING_BITS = idMath::BitsForInteger( MP_PLAYER_MAXPING );
const int ASYNC_PLAYER_INSTANCE_BITS = idMath::BitsForInteger( MAX_INSTANCES );
//RAVEN END
// ddynerman: game state
#include "mp/GameState.h"
typedef struct mpChatLine_s {
idStr line;
short fade; // starts high and decreases, line is removed once reached 0
} mpChatLine_t;
typedef struct mpBanInfo_s {
idStr name;
char guid[ CLIENT_GUID_LENGTH ];
// unsigned char ip[ 15 ];
} mpBanInfo_t;
class idMultiplayerGame {
// rvGameState manages our state
friend class rvGameState;
public:
idMultiplayerGame();
void Shutdown( void );
// resets everything and prepares for a match
void Reset( void );
// RAVEN BEGIN
// mwhitlock: Dynamic memory consolidation
// Made this public so that level heap can be emptied.
void Clear( void );
// RAVEN END
// setup local data for a new player
void SpawnPlayer( int clientNum );
// Run the MP Game
void Run( void );
// Run the local client
void ClientRun( void );
// Run common code (client & server)
void CommonRun( void );
// draws mp hud, scoredboard, etc..
bool Draw( int clientNum );
// updates a player vote
void PlayerVote( int clientNum, playerVote_t vote );
// updates frag counts and potentially ends the match in sudden death
void PlayerDeath( idPlayer *dead, idPlayer *killer, int methodOfDeath );
void AddChatLine( const char *fmt, ... ) id_attribute((format(printf,2,3)));
void UpdateMainGui( void );
// RAVEN BEGIN
// bdube: global pickup sounds (powerups, etc)
// Global item acquire sounds
void PlayGlobalItemAcquireSound ( int entityDefIndex );
#ifdef _USE_VOICECHAT
// jscott: game side voice comms
bool CanTalk( idPlayer *from, idPlayer *to, bool echo );
void XmitVoiceData( void );
void ReceiveAndForwardVoiceData( int clientNum, const idBitMsg &inMsg, bool echo );
void ReceiveAndPlayVoiceData( const idBitMsg &inMsg );
#endif
// jshepard: selects a map at random that will run with the current game type
bool PickMap( idStr gameType );
void ClearVote( int clientNum = -1 );
void ResetRconGuiStatus( void );
// RAVEN END
idUserInterface* StartMenu( void );
void ClearMenu() { currentMenu = 0; }
const char* HandleGuiCommands( const char *menuCommand );
void WriteToSnapshot( idBitMsgDelta &msg ) const;
void ReadFromSnapshot( const idBitMsgDelta &msg );
void ShuffleTeams( void );
void SetGameType( void );
void SetMatchStartedTime( int time ) { matchStartedTime = time; }
rvGameState* GetGameState( void );
void PrintMessageEvent( int to, msg_evt_t evt, int parm1 = -1, int parm2 = -1 );
void DisconnectClient( int clientNum );
static void ForceReady_f( const idCmdArgs &args );
static void DropWeapon_f( const idCmdArgs &args );
static void MessageMode_f( const idCmdArgs &args );
static void VoiceChat_f( const idCmdArgs &args );
static void VoiceChatTeam_f( const idCmdArgs &args );
// RAVEN BEGIN
// shouchard: added console commands to mute/unmute voice chat
static void VoiceMute_f( const idCmdArgs &args );
static void VoiceUnmute_f( const idCmdArgs &args );
// jshepard: command wrappers
static void ForceTeamChange_f( const idCmdArgs& args );
static void RemoveClientFromBanList_f( const idCmdArgs& args );
// activates the admin console when a rcon password challenge returns.
void ProcessRconReturn( bool success );
// RAVEN END
typedef enum {
VOTE_RESTART = 0,
VOTE_TIMELIMIT,
VOTE_FRAGLIMIT,
VOTE_GAMETYPE,
VOTE_KICK,
VOTE_MAP,
VOTE_MIN_PLAYERS,
VOTE_NEXTMAP,
// RAVEN BEGIN
// shouchard: added capturelimit, round limit, and autobalance to vote flags
VOTE_CAPTURELIMIT,
VOTE_ROUNDLIMIT,
VOTE_AUTOBALANCE,
VOTE_MULTIFIELD, // all the "packed" vote functions
// RAVEN END
VOTE_COUNT,
VOTE_NONE
} vote_flags_t;
typedef enum {
VOTE_UPDATE,
VOTE_FAILED,
VOTE_PASSED, // passed, but no reset yet
VOTE_ABORTED,
VOTE_RESET // tell clients to reset vote state
} vote_result_t;
// RAVEN BEGIN
// shouchard: added enum to remove magic numbers
typedef enum {
VOTE_GAMETYPE_DM = 0,
VOTE_GAMETYPE_TOURNEY,
VOTE_GAMETYPE_TDM,
VOTE_GAMETYPE_CTF,
VOTE_GAMETYPE_ARENA_CTF,
VOTE_GAMETYPE_COUNT
} vote_gametype_t;
// RAVEN END
static void Vote_f( const idCmdArgs &args );
static void CallVote_f( const idCmdArgs &args );
void ClientCallVote( vote_flags_t voteIndex, const char *voteValue );
void ServerCallVote( int clientNum, const idBitMsg &msg );
void ClientStartVote( int clientNum, const char *voteString );
void ServerStartVote( int clientNum, vote_flags_t voteIndex, const char *voteValue );
// RAVEN BEGIN
// shouchard: multiline vote support
void ClientUpdateVote( vote_result_t result, int yesCount, int noCount, const voteStruct_t &voteData );
// RAVEN END
void CastVote( int clientNum, bool vote );
void ExecuteVote( void );
// RAVEN BEGIN
// shouchard: multiline vote handlers
void ClientCallPackedVote( const voteStruct_t &voteData );
void ServerCallPackedVote( int clientNum, const idBitMsg &msg );
void ClientStartPackedVote( int clientNum, const voteStruct_t &voteData );
void ServerStartPackedVote( int clientNum, const voteStruct_t &voteData );
void ExecutePackedVote( void );
// RAVEN END
void WantKilled( int clientNum );
int NumActualClients( bool countSpectators, int *teamcount = NULL );
void DropWeapon( int clientNum );
void MapRestart( void );
void JoinTeam( const char* team );
// called by idPlayer whenever it detects a team change (init or switch)
void SwitchToTeam( int clientNum, int oldteam, int newteam );
bool IsPureReady( void ) const;
void ProcessChatMessage( int clientNum, bool team, const char *name, const char *text, const char *sound );
void ProcessVoiceChat( int clientNum, bool team, int index );
// RAVEN BEGIN
// shouchard: added commands to mute/unmute voice chat
void ClientVoiceMute( int clientNum, bool mute );
int GetClientNumFromPlayerName( const char *playerName );
void ServerHandleVoiceMuting( int clientSrc, int clientDest, bool mute );
// shouchard: fixing a bug in multiplayer where round timer sounds (5 minute
// warning, etc.) don't go away at the end of the round.
void ClearAnnouncerSounds();
// shouchard: server admin stuff
typedef struct
{
bool restartMap;
idStr mapName;
int gameType;
int captureLimit;
int fragLimit;
int tourneyLimit;
int timeLimit;
int minPlayers;
bool autoBalance;
} serverAdminData_t;
void HandleServerAdminBanPlayer( int clientNum );
void HandleServerAdminRemoveBan( const char * info );
void HandleServerAdminKickPlayer( int clientNum );
void HandleServerAdminForceTeamSwitch( int clientNum );
bool HandleServerAdminCommands( serverAdminData_t &data );
// RAVEN END
void Precache( void );
// throttle UI switch rates
void ThrottleUserInfo( void );
void ToggleSpectate( void );
void ToggleReady( void );
void ToggleTeam( void );
void ClearFrags( int clientNum );
void EnterGame( int clientNum );
bool CanPlay( idPlayer *p );
bool IsInGame( int clientNum );
bool WantRespawn( idPlayer *p );
void ServerWriteInitialReliableMessages( int clientNum );
void ClientReadStartState( const idBitMsg &msg );
void ServerClientConnect( int clientNum );
void PlayerStats( int clientNum, char *data, const int len );
void AddTeamScore ( int team, int amount );
void AddPlayerScore( idPlayer* player, int amount );
void AddPlayerTeamScore( idPlayer* player, int amount );
void AddPlayerWin( idPlayer* player, int amount );
void SetPlayerTeamScore( idPlayer* player, int value );
void SetPlayerScore( idPlayer* player, int value );
void SetPlayerWin( idPlayer* player, int value );
void SetHudOverlay( idUserInterface* overlay, int duration );
void ClearMap ( void );
void EnableDamage( bool enable = true );
idPlayer* GetRankedPlayer( int i );
int GetRankedPlayerScore( int i );
int GetNumRankedPlayers( void );
idPlayer* GetUnrankedPlayer( int i );
int GetNumUnrankedPlayers( void );
int GetScore( int i );
int GetScore( idPlayer* player );
int GetTeamScore( int i );
int GetTeamScore( idPlayer* player );
int GetWins( int i );
int GetWins( idPlayer* player );
// asalmon: Get the score for a team.
int GetScoreForTeam( int i );
int GetTeamsTotalFrags( int i );
int GetTeamsTotalScore( int i );
int TeamLeader( void );
int GetPlayerTime( idPlayer* player );
const char* GetLongGametypeName( const char* gametype );
int GameTypeToVote( const char *gameType );
void ReceiveRemoteConsoleOutput( const char* output );
void ClientSetInstance( const idBitMsg& msg );
void ServerSetInstance( int instance );
//RAVEN BEGIN
//asalmon: Xenon scoreboard update
#ifdef _XENON
void UpdateXenonScoreboard( idUserInterface *scoreBoard );
#endif
//RAVEN END
void ScheduleAnnouncerSound ( announcerSound_t sound, float time, int arena = -1, bool allowOverride = false );
void ScheduleTimeAnnouncements( void );
// RAVEN END
void SendDeathMessage( idPlayer *attacker, idPlayer *victim, int methodOfDeath );
void ReceiveDeathMessage( idPlayer *attacker, int attackerScore, idPlayer *victim, int victimScore, int methodOfDeath );
rvCTF_AssaultPoint* NextAP( int team );
int OpposingTeam( int team );
idList<idEntityPtr<rvCTF_AssaultPoint> > assaultPoints;
idVec3 flagBaseLocation[ TEAM_MAX ];
idUserInterface* statSummary; // stat summary
rvTourneyGUI tourneyGUI;
void ShowStatSummary( void );
bool CanCapture( int team );
void FlagCaptured( idPlayer *player );
void UpdatePlayerRanks( playerRankMode_t rankMode = PRM_AUTO );
void UpdateTeamRanks( void );
void UpdateHud( idUserInterface* _mphud );
idPlayer * FragLimitHit( void );
idPlayer * FragLeader( void );
bool TimeLimitHit( void );
int GetCurrentMenu( void ) { return currentMenu; }
void WriteClientNetworkInfo( idFile *file, int clientNum );
void ReadClientNetworkInfo( idFile* file, int clientNum );
static const char* teamNames[ TEAM_MAX ];
private:
static const char *MPGuis[];
static const char *ThrottleVars[];
static const char *ThrottleVarsInEnglish[];
static const int ThrottleDelay[];
char killNotificationMsg[ KILL_NOTIFICATION_LEN ];
int pingUpdateTime; // time to update ping
mpPlayerState_t playerState[ MAX_CLIENTS ];
// game state
rvGameState* gameState;
// vote vars
vote_flags_t vote; // active vote or VOTE_NONE
int voteTimeOut; // when the current vote expires
int voteExecTime; // delay between vote passed msg and execute
float yesVotes; // counter for yes votes
float noVotes; // and for no votes
idStr voteValue; // the data voted upon ( server )
idStr voteString; // the vote string ( client )
bool voted; // hide vote box ( client )
int kickVoteMap[ MAX_CLIENTS ];
// RAVEN BEGIN
// shouchard: names for kickVoteMap
idStr kickVoteMapNames[ MAX_CLIENTS ];
voteStruct_t currentVoteData; // used for multi-field votes
// RAVEN END
// time related
int matchStartedTime; // time current match started
// guis
idUserInterface *scoreBoard; // scoreboard
idUserInterface *mainGui; // ready / nick / votes etc.
idListGUI *mapList;
idUserInterface *msgmodeGui; // message mode
int currentMenu; // 0 - none, 1 - mainGui, 2 - msgmodeGui
int nextMenu; // if 0, will do mainGui
bool bCurrentMenuMsg; // send menu state updates to server
enum {
MPLIGHT_CTF_MARINE,
MPLIGHT_CTF_STROGG,
MPLIGHT_QUAD,
MPLIGHT_HASTE,
MPLIGHT_REGEN,
MPLIGHT_MAX
};
int lightHandles[ MPLIGHT_MAX ];
renderLight_t lights[ MPLIGHT_MAX ];
// chat buffer
idStr chatHistory;
// rcon buffer
idStr rconHistory;
//RAVEN BEGIN
//asalmon: Need to refresh stats periodically if the player is looking at stats
int currentStatClient;
int currentStatTeam;
//RAVEN END
public:
// current player rankings
idList<rvPair<idPlayer*, int> > rankedPlayers;
idList<idPlayer*> unrankedPlayers;
rvPair<int, int> rankedTeams[ TEAM_MAX ];
private:
bool pureReady; // defaults to false, set to true once server game is running with pure checksums
bool currentSoundOverride;
int switchThrottle[ 3 ];
int voiceChatThrottle;
// updates the passed gui with current score information
void UpdateRankColor( idUserInterface *gui, const char *mask, int i, const idVec3 &vec );
// bdube: test scoreboard
void UpdateTestScoreboard( idUserInterface *scoreBoard );
// ddynerman: gametype specific scoreboard
void UpdateScoreboard( idUserInterface *scoreBoard );
void UpdateDMScoreboard( idUserInterface *scoreBoard );
void UpdateTeamScoreboard( idUserInterface *scoreBoard );
void UpdateSummaryBoard( idUserInterface *scoreBoard );
int GetPlayerRank( idPlayer* player, bool& isTied );
int GetAdjustedPlayerRank( idPlayer* player, int adjust, bool& isTied );
char* GetPlayerRankText( idPlayer* player );
char* GetPlayerRankText( int rank, bool tied, int score );
const char* BuildSummaryListString( idPlayer* player, int rankedScore );
typedef struct announcerSoundNode_s {
announcerSound_t soundShader;
float time;
idLinkList<announcerSoundNode_s> announcerSoundNode;
int arena;
bool allowOverride;
} announcerSoundNode_t;
idLinkList<announcerSoundNode_t> announcerSoundQueue;
static const char* announcerSoundDefs[ AS_NUM_SOUNDS ];
float announcerPlayTime;
void PlayAnnouncerSounds ( void );
int teamScore[ TEAM_MAX ];
void ClearTeamScores ( void );
void UpdateLeader( idPlayer* oldLeader );
void ClearGuis( void );
void DrawScoreBoard( idPlayer *player );
void CheckVote( void );
bool AllPlayersReady( idStr* reason = NULL );
const char * GameTime( void );
bool EnoughClientsToPlay( void );
void DrawStatSummary( void );
// go through the clients, and see if they want to be respawned, and if the game allows it
// called during normal gameplay for death -> respawn cycles
// and for a spectator who want back in the game (see param)
void CheckRespawns( idPlayer *spectator = NULL );
void FreeLight ( int lightID );
void UpdateLight ( int lightID, idPlayer *player );
void CheckSpecialLights( void );
void ForceReady();
// when clients disconnect or join spectate during game, check if we need to end the game
void CheckAbortGame( void );
void MessageMode( const idCmdArgs &args );
void DisableMenu( void );
void SetMapShot( void );
// scores in TDM
void VoiceChat( const idCmdArgs &args, bool team );
// RAVEN BEGIN
// mekberg: added
void UpdateMPSettingsModel( idUserInterface* currentGui );
// RAVEN END
void ServerWriteStartState( int clientNum, idBitMsg &msg, bool withLocalClient );
};
ID_INLINE bool idMultiplayerGame::IsPureReady( void ) const {
return pureReady;
}
ID_INLINE void idMultiplayerGame::ClearFrags( int clientNum ) {
playerState[ clientNum ].fragCount = 0;
}
ID_INLINE bool idMultiplayerGame::IsInGame( int clientNum ) {
return playerState[ clientNum ].ingame;
}
ID_INLINE int idMultiplayerGame::OpposingTeam( int team ) {
return (team == TEAM_STROGG ? TEAM_MARINE : TEAM_STROGG);
}
ID_INLINE idPlayer* idMultiplayerGame::GetRankedPlayer( int i ) {
if( i >= 0 && i < rankedPlayers.Num() ) {
return rankedPlayers[ i ].First();
} else {
return NULL;
}
}
ID_INLINE int idMultiplayerGame::GetRankedPlayerScore( int i ) {
if( i >= 0 && i < rankedPlayers.Num() ) {
return rankedPlayers[ i ].Second();
} else {
return 0;
}
}
ID_INLINE int idMultiplayerGame::GetNumUnrankedPlayers( void ) {
return unrankedPlayers.Num();
}
ID_INLINE idPlayer* idMultiplayerGame::GetUnrankedPlayer( int i ) {
if( i >= 0 && i < unrankedPlayers.Num() ) {
return unrankedPlayers[ i ];
} else {
return NULL;
}
}
ID_INLINE int idMultiplayerGame::GetNumRankedPlayers( void ) {
return rankedPlayers.Num();
}
ID_INLINE int idMultiplayerGame::GetTeamScore( int i ) {
return playerState[ i ].teamFragCount;
}
ID_INLINE int idMultiplayerGame::GetScore( int i ) {
return playerState[ i ].fragCount;
}
ID_INLINE int idMultiplayerGame::GetWins( int i ) {
return playerState[ i ].wins;
}
ID_INLINE void idMultiplayerGame::ResetRconGuiStatus( void ) {
if( mainGui) {
mainGui->SetStateInt( "password_valid", 0 );
}
}
// asalmon: needed access team scores for rich presence
ID_INLINE int idMultiplayerGame::GetScoreForTeam( int i ) {
if( i < 0 || i > TEAM_MAX ) {
return 0;
}
return teamScore[ i ];
}
ID_INLINE int idMultiplayerGame::TeamLeader( void ) {
if( teamScore[ TEAM_MARINE ] == teamScore[ TEAM_STROGG ] ) {
return -1;
} else {
return ( teamScore[ TEAM_MARINE ] > teamScore[ TEAM_STROGG ] ? TEAM_MARINE : TEAM_STROGG );
}
}
int ComparePlayersByScore( const void* left, const void* right );
int CompareTeamsByScore( const void* left, const void* right );
#endif /* !__MULTIPLAYERGAME_H__ */
// RAVEN END