quake4-sdk/source/game/mp/GameState.h
2007-06-15 00:00:00 +00:00

483 lines
12 KiB
C++

//----------------------------------------------------------------
// GameState.h
//
// Copyright 2002-2005 Raven Software
//----------------------------------------------------------------
#ifndef __GAMESTATE_H__
#define __GAMESTATE_H__
#include "../Game_local.h"
#include "../MultiplayerGame.h"
#include "Tourney.h"
/*
===============================================================================
rvGameState
Game state info common for all gametypes
===============================================================================
*/
typedef enum {
GS_BASE,
GS_DM,
GS_TEAMDM,
GS_CTF,
GS_TOURNEY,
GS_DZ
} gameStateType_t;
typedef enum {
INACTIVE = 0, // not running
WARMUP, // warming up
COUNTDOWN, // post warmup pre-game
GAMEON, // game is on
SUDDENDEATH, // game is on but in sudden death, first frag wins
GAMEREVIEW, // game is over, scoreboard is up. we wait si_gameReviewPause seconds (which has a min value)
NEXTGAME,
STATE_COUNT
} mpGameState_t;
class rvGameState {
public:
rvGameState( bool allocPrevious = true );
virtual ~rvGameState( void );
// clientNum == -1 except for SendInitialState
// when clientNum >= 0, always send the state
virtual void SendState( int clientNum = -1 );
virtual void ReceiveState( const idBitMsg& msg );
virtual void SendInitialState( int clientNum );
virtual void PackState( idBitMsg& outMsg );
virtual void WriteState( idBitMsg &msg );
virtual void UnpackState( const idBitMsg& inMsg );
virtual void GameStateChanged( void );
virtual void Run( void );
virtual void NewState( mpGameState_t newState );
virtual void ClientDisconnect( idPlayer* player );
virtual void Spectate( idPlayer* player );
virtual void Clear( void );
virtual bool IsType( gameStateType_t type ) const;
static gameStateType_t GetClassType( void );
mpGameState_t GetMPGameState( void ) { return currentState; }
mpGameState_t GetNextMPGameState( void ) { return nextState; }
int GetNextMPGameStateTime( void ) { return nextStateTime; }
void SetNextMPGameState( mpGameState_t newState ) { nextState = newState; }
void SetNextMPGameStateTime( int time ) { nextStateTime = time; }
bool operator==( const rvGameState& rhs ) const;
bool operator!=( const rvGameState& rhs ) const;
rvGameState& operator=( const rvGameState& rhs );
void WriteNetworkInfo( idFile *file, int clientNum );
void ReadNetworkInfo( idFile *file, int clientNum );
void SpawnDeadZonePowerup();
protected:
static gameStateType_t type;
rvGameState* previousGameState;
bool trackPrevious;
mpGameState_t currentState;
mpGameState_t nextState;
int nextStateTime;
int fragLimitTimeout;
};
/*
===============================================================================
rvDMGameState
Game state info for DM
===============================================================================
*/
class rvDMGameState : public rvGameState {
public:
rvDMGameState( bool allocPrevious = true );
virtual void Run( void );
virtual bool IsType( gameStateType_t type ) const;
static gameStateType_t GetClassType( void );
private:
static gameStateType_t type;
};
/*
===============================================================================
rvTeamDMGameState
Game state info for Team DM
===============================================================================
*/
class rvTeamDMGameState : public rvGameState {
public:
rvTeamDMGameState( bool allocPrevious = true );
virtual void Run( void );
virtual bool IsType( gameStateType_t type ) const;
static gameStateType_t GetClassType( void );
private:
static gameStateType_t type;
};
/*
===============================================================================
rvCTFGameState
Game state info for CTF
===============================================================================
*/
// assault point state for CTF
enum apState_t {
AS_MARINE,
AS_STROGG,
AS_NEUTRAL
};
// current flag state for CTF
enum flagState_t {
FS_AT_BASE = 0,
FS_DROPPED,
FS_TAKEN,
// for one flag CTF
FS_TAKEN_STROGG, // taken by strogg team
FS_TAKEN_MARINE // taken by marine team
};
struct flagStatus_t {
flagState_t state;
int clientNum;
};
class rvCTFGameState : public rvGameState {
public:
rvCTFGameState( bool allocPrevious = true );
virtual void Clear( void );
virtual void SendState( int clientNum = -1 );
virtual void ReceiveState( const idBitMsg& msg );
virtual void SendInitialState( int clientNum );
virtual void PackState( idBitMsg& outMsg );
virtual void WriteState( idBitMsg &msg );
virtual void UnpackState( const idBitMsg& inMsg );
virtual void GameStateChanged( void );
virtual void Run( void );
void SetAPOwner( int ap, int owner );
int GetAPOwner( int ap );
void SetFlagState( int flag, flagState_t newState );
flagState_t GetFlagState( int flag );
int GetFlagCarrier( int flag );
void SetFlagCarrier( int flag, int clientNum );
bool operator==( const rvCTFGameState& rhs ) const;
rvCTFGameState& operator=( const rvCTFGameState& rhs );
virtual bool IsType( gameStateType_t type ) const;
static gameStateType_t GetClassType( void );
private:
flagStatus_t flagStatus[ TEAM_MAX ];
apState_t apState[ MAX_AP ];
static gameStateType_t type;
};
ID_INLINE void rvCTFGameState::SetAPOwner( int ap, int owner ) {
assert( (ap >= 0 && ap < MAX_AP) && (owner >= 0 && owner < TEAM_MAX) );
apState[ ap ] = (apState_t)owner;
}
ID_INLINE int rvCTFGameState::GetAPOwner( int ap ) {
return apState[ ap ];
}
ID_INLINE flagState_t rvCTFGameState::GetFlagState( int flag ) {
assert( flag >= 0 && flag < TEAM_MAX );
return flagStatus[ flag ].state;
}
ID_INLINE int rvCTFGameState::GetFlagCarrier( int flag ) {
assert( flag >= 0 && flag < TEAM_MAX );
return flagStatus[ flag ].clientNum;
}
ID_INLINE bool operator==( const flagStatus_t& lhs, const flagStatus_t rhs ) {
return (lhs.state == rhs.state) && (lhs.clientNum == rhs.clientNum);
}
ID_INLINE bool operator!=( const flagStatus_t& lhs, const flagStatus_t rhs ) {
return (lhs.state != rhs.state) || (lhs.clientNum != rhs.clientNum);
}
/*
===============================================================================
rvTourneyGameState
Game state info for tourney
===============================================================================
*/
enum tourneyState_t {
TS_INVALID = 0,
TS_PREMATCH,
TS_MATCH,
TS_END_GAME
};
class rvTourneyGameState : public rvGameState {
public:
rvTourneyGameState( bool allocPrevious = true );
virtual void Clear( void );
virtual void Run( void );
virtual void Reset( void );
virtual void SendState( int clientNum = -1 );
virtual void ReceiveState( const idBitMsg& msg );
virtual void SendInitialState( int clientNum );
virtual void PackState( idBitMsg& outMsg );
virtual void WriteState( idBitMsg &msg );
virtual void UnpackState( const idBitMsg& inMsg );
virtual void GameStateChanged( void );
virtual void NewState( mpGameState_t newState );
virtual void ClientDisconnect( idPlayer* player );
virtual void Spectate( idPlayer* player );
void RemovePlayer( idPlayer* player );
bool operator==( const rvTourneyGameState& rhs ) const;
rvTourneyGameState& operator=( const rvTourneyGameState& rhs );
int GetNumArenas( void ) const;
bool HasBye( idPlayer* player );
int GetMaxRound( void ) const;
int GetRound( void ) const;
int GetStartingRound( void ) const;
idPlayer** GetArenaPlayers( int arena );
rvTourneyArena& GetArena( int arena );
const char* GetRoundDescription( void );
int GetNextActiveArena( int arena );
int GetPrevActiveArena( int arena );
void SpectateCycleNext( idPlayer* player );
void SpectateCyclePrev( idPlayer* player );
int GetTourneyCount( void );
void SetTourneyCount( int count ) { tourneyCount = count; }
void UpdateTourneyBrackets( void );
void UpdateTourneyHistory( int round );
int FirstAvailableArena( void );
arenaOutcome_t* GetArenaOutcome( int arena );
virtual bool IsType( gameStateType_t type ) const;
static gameStateType_t GetClassType( void );
private:
void SetupInitialBrackets( void );
tourneyState_t tourneyState;
// startingRound - The starting round, with the current # of players
int startingRound;
// round - current round ( 1-indexed )
int round;
// maxRound - the most rounds we'll run (based on MAX_ARENAS)
int maxRound;
// arenas - current brackets, an extra arena to serve as the waiting room
rvTourneyArena arenas[ MAX_ARENAS + 1 ];
// tourneyHistory - past winners
arenaOutcome_t tourneyHistory[ MAX_ROUNDS ][ MAX_ARENAS ];
// byeArena - the arena that natural (non disconnection) bye players go in
int byeArena;
// packTourneyHistory - whether or not we should transmit tourney history to one client through SendState
bool packTourneyHistory;
// forceTourneyHistory - if true will sync down tourney history for all clients
bool forceTourneyHistory;
// tourneyCount - how many tourneys to run per map
int tourneyCount;
// roundTimeout - a delay between all arenas finishing and starting the next round
int roundTimeout;
static gameStateType_t type;
};
ID_INLINE int rvTourneyGameState::GetMaxRound( void ) const {
assert( type == GS_TOURNEY );
return maxRound;
}
ID_INLINE int rvTourneyGameState::GetRound( void ) const {
assert( type == GS_TOURNEY );
return round;
}
ID_INLINE int rvTourneyGameState::GetStartingRound( void ) const {
assert( type == GS_TOURNEY );
return startingRound;
}
ID_INLINE idPlayer** rvTourneyGameState::GetArenaPlayers( int arena ) {
assert( type == GS_TOURNEY );
return arenas[ arena ].GetPlayers();
}
ID_INLINE rvTourneyArena& rvTourneyGameState::GetArena( int arena ) {
assert( type == GS_TOURNEY );
return arenas[ arena ];
}
ID_INLINE const char* rvTourneyGameState::GetRoundDescription( void ) {
assert( type == GS_TOURNEY );
if( round == maxRound ) {
return common->GetLocalizedString( "#str_107720" );
} else if( round == maxRound - 1 ) {
return common->GetLocalizedString( "#str_107719" );
} else if( round == maxRound - 2 ) {
return common->GetLocalizedString( "#str_107718" );
} else if( round == maxRound - 3 ) {
return common->GetLocalizedString( "#str_107717" );
} else {
// shouldn't happen in production
return va( "ROUND %d", round );
}
}
ID_INLINE int rvTourneyGameState::GetTourneyCount( void ) {
assert( type == GS_TOURNEY );
return tourneyCount;
}
/*
===============================================================================
riDZGameState
Game state info for Dead Zone
===============================================================================
*/
// current control zone state
enum dzState_t {
DZ_NONE = 0,
DZ_TAKEN,
DZ_LOST,
DZ_DEADLOCK,
DZ_MARINES_TAKEN,
DZ_MARINES_LOST,
DZ_STROGG_TAKEN,
DZ_STROGG_LOST,
DZ_MARINE_TO_STROGG,
DZ_STROGG_TO_MARINE,
DZ_MARINE_DEADLOCK,
DZ_STROGG_DEADLOCK,
DZ_MARINE_REGAIN,
DZ_STROGG_REGAIN
};
struct dzStatus_t {
dzState_t state;
int clientNum;
};
class riDZGameState : public rvGameState {
public:
riDZGameState( bool allocPrevious = true );
~riDZGameState( void );
virtual void Clear( void );
virtual void SendState( int clientNum = -1 );
virtual void ReceiveState( const idBitMsg& msg );
virtual void SendInitialState( int clientNum );
virtual void PackState( idBitMsg& outMsg );
virtual void WriteState( idBitMsg &msg );
virtual void UnpackState( const idBitMsg& inMsg );
virtual void GameStateChanged( void );
virtual void Run( void );
void SetDZState( int dz, dzState_t newState );
dzState_t GetDZState( int dz );
bool operator==( const riDZGameState& rhs ) const;
riDZGameState& operator=( const riDZGameState& rhs );
int dzTriggerEnt;
int dzShaderParm;
private:
dzStatus_t dzStatus[ TEAM_MAX ];
void ControlZoneStateChanged( int team );
};
ID_INLINE dzState_t riDZGameState::GetDZState( int dz ) {
assert( dz >= 0 && dz < TEAM_MAX );
return dzStatus[ dz ].state;
}
ID_INLINE bool operator==( const dzStatus_t& lhs, const dzStatus_t rhs ) {
return (lhs.state == rhs.state) && (lhs.clientNum == rhs.clientNum);
}
ID_INLINE bool operator!=( const dzStatus_t& lhs, const dzStatus_t rhs ) {
return (lhs.state != rhs.state) || (lhs.clientNum != rhs.clientNum);
}
#endif