/*
   Copyright (C) 1997-2001 Id Software, Inc.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

   See the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 */

//g_gametypes.c
extern cvar_t *g_warmup_enabled;
extern cvar_t *g_warmup_timelimit;
extern cvar_t *g_countdown_time;
extern cvar_t *g_match_extendedtime;
extern cvar_t *g_votable_gametypes;
extern cvar_t *g_gametype; // only for use in function that deal with changing gametype, use game.gametype

// some game settings
cvar_t *g_allow_falldamage;

// g_gameteams.c
extern cvar_t *g_teams_teamdamage;

#define G_CHALLENGERS_MIN_JOINTEAM_MAPTIME  9000 // must wait 10 seconds before joining
#define G_POSTMATCH_TIMELIMIT		4000 // postmatch will finish after 4 seconds

typedef struct
{
	void ( *initGametype )( void );
	void ( *newMap )( void );
	void ( *checkRules )( void );
	qboolean ( *respawn )( edict_t *ent );
	void ( *clientbegin )( edict_t *ent );
	char *( *scoreboardMessage )( void );

	//time blocks start funcs
	void ( *warmupMatch )( void );
	void ( *countdownMatch )( void );
	void ( *startMatch )( void );
	void ( *endMatch )( void );

	int maxPlayersPerTeam;
	qboolean hasChallengersQueue;

	// default item respwan time
	int ammo_respawn;
	int armor_respawn;
	int weapon_respawn;
	int health_respawn;
	int powerup_respawn;
	int megahealth_respawn;

	// few default settings
	int timelimit;
	int extended_time;
	int scorelimit;
	int spawnpoint_radius;
} gametype_t;

extern gametype_t gametypes[];

typedef struct
{
	int playerIndices[MAX_CLIENTS];
	int numplayers;
	int teamplayerscores;
	int teamscore;
	qboolean locked;
	int invited[MAX_CLIENTS];
	qboolean has_coach;
} g_teamlist_t;

g_teamlist_t teamlist[GS_MAX_TEAMS];

typedef struct
{
	int score;
	int deaths;
	int kills;
	int suicides;
	int teamfrags;
} client_scores_t;

typedef struct matchgame_s
{
	int state;
	unsigned int starttime;
	unsigned int endtime;
	int pickableItemsMask;

	qboolean forceStart;    // force starting the game, when warmup timelimit is up
	qboolean forceExit;     // just exit, ignore extended time checks
	int extendedTime;       // are we in extended time period and if so is it first, second or ...

	qboolean ready[MAX_CLIENTS];
	client_scores_t scores[MAX_CLIENTS];

	int roundstate;
	unsigned int roundstarttime;
	unsigned int roundendtime;

} matchgame_t;

extern matchgame_t match;

//clock
char clockstring[16];

//
//	matches management
//
qboolean G_Match_Tied( void );
void G_Match_RespawnAllItems( void );
void G_Match_SetUpDelayedItems( void );
void G_Match_RemoveAllClientLasers( void );
void G_Match_RemoveAllProjectiles( void );
void G_Match_RespawnAllClients( void );
void G_Match_CleanUpPlayerStats( edict_t *ent );
void G_Match_FreeBodyQueue( void );
void G_Match_SetUpNextState( void );

void G_ServerSettings_ConfigString( void );
//
//	teams
//
void G_Teams_NewMap( void );
void G_Teams_Init( void );
void G_Teams_UpdateTeamInfoMessages( void );

void G_GameType_ClientHealthRule( void );
void G_GameType_BeginPostMatch( void );
qboolean G_Match_GenericCountDownAnnounces( void );

qboolean G_Gametype_hasChallengersQueue( int type );
void G_Teams_ExecuteChallengersQueue( void );
void G_Teams_AdvanceChallengersQueue( void );

void G_GameType_ClientArmorDecayRule( void );

void G_Gametype_GENERIC_SetUpMatch( void );
void G_Gametype_GENERIC_SetUpCountdown( void );
void G_Gametype_GENERIC_SetUpEndMatch( void );

// gametype specific functions
void G_Gametype_CTF_CheckRules( void );

void G_Gametype_DM_CheckRules( void );
char *G_Gametype_DM_ScoreboardMessage( void );

void G_Gametype_TDM_PreEntSpawn( void );
void G_Gametype_TDM_NewMap( void );
void G_Gametype_TDM_CheckRules( void );
void G_Gametype_TDM_SetUpMatch( void );
char *G_Gametype_TDM_ScoreboardMessage( void );
void G_Gametype_TDM_FragBonuses( edict_t *targ, edict_t *inflictor, edict_t *attacker, int mod );
short G_Gametype_TDM_AreaStatus( void );
short G_Gametype_TDM_AreaCapturing( int stat );

void G_Gametype_CTF_Init( void );
void G_Gametype_CTF_NewMap( void );
void G_Gametype_CTF_ClientBegin( edict_t *ent );
void G_Gametype_CTF_SetUpMatch( void );
void G_Gametype_CTF_SetUpEndMatch( void );
char *G_Gametype_CTF_ScoreboardMessage( void );
int G_Gametype_CTF_CapturedFlagTimer( int team );
int G_Gametype_CTF_FlagStatus( int team, int playernr );
void G_Gametype_CTF_FragBonuses( edict_t *targ, edict_t *inflictor, edict_t *attacker, int mod );

char *G_Gametype_DUEL_ScoreboardMessage( void );
void G_Gametype_DUEL_CheckRules( void );

void G_Gametype_RACE_CheckRules( void );
void G_Gametype_RACE_ClientBegin( edict_t *ent );
char *G_Gametype_RACE_ScoreboardMessage( void );
void G_Gametype_RACE_SetUpWarmup( void );
void G_Gametype_RACE_SetUpMatch( void );
qboolean G_Gametype_RACE_ClientRespawn( edict_t *self );

void G_Gametype_CA_NewMap( void );
void G_Gametype_CA_SetUpCountdown( void );
void G_Gametype_CA_SetUpMatch( void );
qboolean G_Gametype_CA_ClientRespawn( edict_t *ent );
void G_Gametype_CA_CheckRules( void );
char *G_Gametype_CA_ScoreboardMessage( void );
void G_Gametype_CA_FragBonuses( edict_t *targ, edict_t *inflictor, edict_t *attacker, int mod );
void G_Gametype_CA_PlayerClass_Cmd( edict_t *ent );
qboolean G_Gametype_CA_SetWeaponFlag( char *weaponflaginfo, int *normal, int *grunt, int *camper, int *spammer );
qboolean G_Gametype_CA_SetAmmo( char *ammoinfo, int *gb, int *rg, int *gl, int *rl, int *pg, int *lg, int *eb );

#ifdef DUEL_ARENA
void G_Gametype_DA_CheckRules( void );
qboolean G_Gametype_DA_ClientRespawn( edict_t *ent );
void G_Gametype_DA_FragBonuses( edict_t *targ, edict_t *inflictor, edict_t *attacker, int mod );
char *G_Gametype_DA_ScoreboardMessage( void );
void G_Gametype_DA_SetUpEndMatch( void );
#endif

void G_Match_Autorecord_Start( void );
void G_Match_Autorecord_Stop( void );
void G_Match_Autorecord_Cancel( void );

//coach
void G_Teams_Coach( edict_t *ent );
void G_Teams_CoachLockTeam( edict_t *ent );
void G_Teams_CoachUnLockTeam( edict_t *ent );
void G_Teams_CoachRemovePlayer( edict_t *ent );
