/*
	client.h

	Client definitions

	Copyright (C) 1996-1997  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:

		Free Software Foundation, Inc.
		59 Temple Place - Suite 330
		Boston, MA  02111-1307, USA

*/

#ifndef _CLIENT_H
#define _CLIENT_H

#include "QF/info.h"
#include "QF/quakefs.h"
#include "QF/vid.h"
#include "QF/zone.h"

#include "QF/plugin/vid_render.h"

#include "client/entities.h"

#include "netchan.h"
#include "qw/bothdefs.h"
#include "qw/protocol.h"


/*
  player_state_t is the information needed by a player entity
  to do move prediction and to generate a drawable entity
*/
typedef struct player_state_s {
	int         messagenum;		// all player's won't be updated each frame

	double      state_time;		// not the same as the packet time,
								// because player commands come asyncronously
	vec3_t      viewangles;		// only for demos, not from server

	plent_state_t pls;

	float       waterjumptime;
	int         onground;		// -1 = in air, else pmove entity number
	int         oldbuttons;
	int         oldonground;

} player_state_t;

typedef struct player_info_s {
	int         userid;
	struct info_s *userinfo;

	// scoreboard information
	struct info_key_s *name;
	struct info_key_s *team;
	struct info_key_s *chat;
	float       entertime;
	int         frags;
	int         ping;
	byte        pl;

	// skin information
	int         topcolor;
	int         bottomcolor;
	struct info_key_s *skinname;
	struct skin_s *skin;

	int         spectator;
	int         stats[MAX_CL_STATS];	// health, etc
	int         prevcount;
} player_info_t;


typedef struct {
	// generated on client side
	usercmd_t   cmd;		// cmd that generated the frame
	double      senttime;	// time cmd was sent off
	int         delta_sequence;		// sequence number to delta from, -1 = full update

	// received from server
	double      receivedtime;	// time message was received, or -1
	player_state_t playerstate[MAX_CLIENTS];	// message received that
												// reflects performing the
												// usercmd
	packet_entities_t packet_entities;
	qboolean    invalid;		// true if the packet_entities delta was invalid
} frame_t;

#define	MAX_DEMOS		8
#define	MAX_DEMONAME	16

typedef enum {
	ca_disconnected, 	// full screen console with no connection
	ca_demostart,		// starting up a demo
	ca_connected,		// talking to a server
	ca_onserver,		// processing data lists, donwloading, etc
	ca_active,			// everything is in, so frames can be rendered
} cactive_t;

typedef enum {
	dl_none,
	dl_model,
	dl_sound,
	dl_skin,
	dl_single
} dltype_t;		// download type

/*
  the client_static_t structure is persistant through an arbitrary number
  of server connections
*/
typedef struct {
// connection information
	cactive_t   state;

// network stuff
	netchan_t   netchan;
	int         qport;
	int         challenge;
	float       latency;				// rolling average
	struct dstring_s *servername;		// name of server from original connect
	netadr_t    server_addr;			// address of server

// private userinfo for sending to masterless servers
	struct info_s	*userinfo;
	int         chat;

// file transfer from server
	QFile      *download;
	struct dstring_s *downloadtempname;
	struct dstring_s *downloadname;
	struct dstring_s *downloadurl;
	int         downloadnumber;
	dltype_t    downloadtype;
	int         downloadpercent;

// demo loop control
	int         demonum;		// -1 = don't play demos
	char        demos[MAX_DEMOS][MAX_DEMONAME];		// when not playing

	QFile      *demofile;
	qboolean    demorecording;
	qboolean    demo_capture;
	qboolean    demoplayback;
	qboolean    demoplayback2;
	qboolean    findtrack;
	int         lastto;
	int         lasttype;
	int         prevtime;
	double      basetime;
	qboolean    timedemo;
	double      td_lastframe;		// to meter out one message a frame
	int         td_startframe;		// host_framecount at start
	double      td_starttime;		// realtime at second frame of timedemo
} client_static_t;

extern client_static_t	cls;

#define FPD_NO_MACROS		0x0001	// Many clients ignore this, and it isn't used, but let's honor it
#define FPD_NO_TIMERS		0x0002	// We never allow timers anyway
#define FPD_NO_STRIGGER		0x0004	// Don't have soundtrigger yet, but this disables it
#define FPD_HIDE_PERCENTE	0x0020	// Ditto
#define FPD_HIDE_POINT		0x0080	// Can ignore if we do visibility checking for point
#define FPD_NO_TEAMSKIN		0x0100	// Disable skin force
#define FPD_NO_TEAMCOLOR	0x0200	// Disable color force
#define FPD_HIDE_ITEM		0x0400	// No idea what this does
#define FPD_LIMIT_PITCH		0x4000	// Limit pitchspeed
#define FPD_LIMIT_YAW		0x8000	// Limit yawspeed

#define FPD_DEFAULT			(FPD_HIDE_PERCENTE | FPD_NO_TEAMSKIN)

// These limits prevent a usable RJ script, requiring > 0.1 sec of turning time.
#define FPD_MAXPITCH		1000
#define FPD_MAXYAW			2000

// Default fbskins value. This should really be different for different gamedirs, but eh
#define FBSKINS_DEFAULT		0.0

/*
  the client_state_t structure is wiped completely at every server signon
*/
typedef struct {
	qboolean    loading;

	int         movemessages;	// Since connecting to this server throw out
								// the first couple, so the player doesn't
								// accidentally do something the first frame
	// sentcmds[cl.netchan.outgoing_sequence & UPDATE_MASK] = cmd
	frame_t     frames[UPDATE_BACKUP];
	int         link_sequence;
	int         prev_sequence;

// information for local display
	int         stats[MAX_CL_STATS];	// health, etc
	float       item_gettime[32];	// cl.time of aquiring item, for blinking
	float       faceanimtime;			// Use anim frame if cl.time < this

	cshift_t    cshifts[NUM_CSHIFTS];	// Color shifts for damage, powerups
	cshift_t    prev_cshifts[NUM_CSHIFTS];	// and content types

// the client maintains its own idea of view angles, which are sent to the
// server each frame.  And reset only at level change and teleport times
	vec3_t      viewangles;

// the client simulates or interpolates movement to get these values
	double      time;			// this is the time value that the client
								// is rendering at.  always <= realtime
	vec3_t      simorg;
	vec3_t      simvel;
	vec3_t      simangles;

	vec3_t      punchangle;		// temporary view kick from weapon firing

// pitch drifting vars
	float       idealpitch;
	float       pitchvel;
	qboolean    nodrift;
	float       driftmove;
	double      laststop;

	qboolean    paused;			// Sent over by server
	int         onground;		// -1 when in air
	float       viewheight;
	float       crouch;			// local amount for smoothing stepups

	int         intermission;	// don't change view angle, full screen, etc
	int         completed_time;	// latched from time at intermission start

	int         servercount;	// server identification for prespawns
	struct info_s *serverinfo;
	int         parsecount;		// server message counter
	int         validsequence;	// this is the sequence number of the last good
								// packetentity_t we got.  If this is 0, we
								// can't render a frame yet

	double      last_ping_request;	// while showing scoreboard
	double      last_servermessage;

/* information that is static for the entire time connected to a server */

	char        model_name[MAX_MODELS][MAX_QPATH];
	char        sound_name[MAX_SOUNDS][MAX_QPATH];

	struct model_s *model_precache[MAX_MODELS];
	struct sfx_s *sound_precache[MAX_SOUNDS];
	int         nummodels;
	int         numsounds;

	struct plitem_s *edicts;
	struct plitem_s *worldspawn;

	char        levelname[40];	// for display on solo scoreboard
	int         spectator;
	int         playernum;
	int         viewentity;
	float       stdver;
	int         maxclients;
	// serverinfo mirrors
	int         chase;
	int         sv_cshifts;
	int         no_pogo_stick;
	int         teamplay;
	int         watervis;
	int         fpd;
	int         fbskins;

// refresh related state
	struct model_s *worldmodel;	// cl_entitites[0].model
	int         num_entities;	// stored bottom up in cl_entities array
	entity_t    viewent;		// the weapon model

	int         cdtrack;		// cd audio

// all player information
	player_info_t players[MAX_CLIENTS];

	lightstyle_t lightstyle[MAX_LIGHTSTYLES];
} client_state_t;


/*
  cvars
*/
extern	struct cvar_s	*r_netgraph;
extern	struct cvar_s	*r_netgraph_alpha;
extern	struct cvar_s	*r_netgraph_box;
extern	struct cvar_s	*cl_upspeed;
extern	struct cvar_s	*cl_forwardspeed;
extern	struct cvar_s	*cl_backspeed;
extern	struct cvar_s	*cl_sidespeed;

extern	struct cvar_s	*cl_movespeedkey;

extern	struct cvar_s	*cl_yawspeed;
extern	struct cvar_s	*cl_pitchspeed;

extern	struct cvar_s	*cl_anglespeedkey;

extern	struct cvar_s	*cl_draw_locs;
extern	struct cvar_s	*cl_shownet;
extern	struct cvar_s	*hud_sbar;
extern	struct cvar_s	*hud_sbar_separator;
extern	struct cvar_s	*hud_swap;

extern	struct cvar_s	*cl_pitchdriftspeed;
extern	struct cvar_s	*lookspring;

extern	struct cvar_s	*m_pitch;
extern	struct cvar_s	*m_yaw;
extern	struct cvar_s	*m_forward;
extern	struct cvar_s	*m_side;

extern	struct cvar_s	*cl_name;

extern	struct cvar_s	*cl_model_crcs;

extern	struct cvar_s	*rate;

extern	struct cvar_s	*hud_ping;
extern	struct cvar_s	*hud_pl;

extern	struct cvar_s	*skin;

extern	struct cvar_s	*cl_fb_players;

extern	client_state_t	cl;

extern	entity_t		*cl_static_entities;
extern	entity_t		cl_entities[512];
extern	byte			cl_entity_valid[2][512];

extern	qboolean	nomaster;
extern char	*server_version;	// version of server we connected to

extern	double		realtime;
extern	int			fps_count;

extern struct cbuf_s *cl_cbuf;
extern struct cbuf_s *cl_stbuf;

void Cvar_Info (struct cvar_s *var);

void CL_NetGraph (void);
void CL_UpdateScreen (double realtime);

void CL_SetState (cactive_t state);

void V_ParseDamage (void);

void V_PrepBlend (void);

void CL_Cmd_ForwardToServer (void);
void CL_Cmd_Init (void);

void CL_RSShot_f (void);

#define RSSHOT_WIDTH 320
#define RSSHOT_HEIGHT 200

extern struct dstring_s *centerprint;

#endif // _CLIENT_H