1
0
Fork 0
forked from fte/fteqw
fteqw/engine/client/client.h
Spoike 5ded3710b4 networked entity editing now kinda working. still needs much more work before its usable.
try to use microsoft's poor-man's eax stuff with directsound. snd_eax is disabled by default still thankfully.
some hlmdl fixes

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5029 fc73d0e0-1445-4013-8a0c-d673dee63da5
2016-12-07 18:45:25 +00:00

1666 lines
50 KiB
C

/*
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 the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// client.h
#include "particles.h"
enum
{
SKIN_NOTLOADED, //not trying to load it. shouldn't really happen, but can.
SKIN_LOADING, //still loading. just do something else for now...
SKIN_LOADED,
SKIN_FAILED
};
typedef struct qwskin_s
{
char name[64];
int loadstate; // the name isn't a valid skin
//qw skin info
int width;
int height;
void *skindata;
//for hardware 32bit texture overrides
texnums_t textures;
} qwskin_t;
// player_state_t is the information needed by a player entity
// to do move prediction and to generate a drawable entity
typedef struct
{
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
usercmd_t command; // last command for prediction
vec3_t origin;
vec3_t predorigin; // pre-predicted pos
vec3_t viewangles; // only for demos, not from server
vec3_t velocity;
int weaponframe;
unsigned int modelindex;
int frame;
int skinnum;
int effects;
#ifdef PEXT_SCALE
float scale;
#endif
qbyte colourmod[3];
qbyte alpha;
#ifdef PEXT_FATNESS
float fatness;
#endif
int flags; // dead, gib, etc
int pm_type;
float waterjumptime;
qboolean onground;
qboolean jump_held;
int jump_msec; // hack for fixing bunny-hop flickering on non-ZQuake servers
vec3_t szmins, szmaxs;
vec3_t gravitydir;
float lerpstarttime;
int oldframe;
} player_state_t;
#if defined(Q2CLIENT) || defined(Q2SERVER)
typedef enum
{
// can accelerate and turn
Q2PM_NORMAL,
Q2PM_SPECTATOR,
// no acceleration or turning
Q2PM_DEAD,
Q2PM_GIB, // different bounding box
Q2PM_FREEZE
} q2pmtype_t;
typedef struct
{ //shared with q2 dll
q2pmtype_t pm_type;
#if 0
int origin[3]; // 12.3
#else
short origin[3]; // 20.3
#endif
short velocity[3]; // 12.3
qbyte pm_flags; // ducked, jump_held, etc
qbyte pm_time; // each unit = 8 ms
short gravity;
short delta_angles[3]; // add to command angles to get view direction
// changed by spawns, rotating objects, and teleporters
// short pad;
} q2pmove_state_t;
typedef struct
{ //shared with q2 dll so cannot be changed
q2pmove_state_t pmove; // for prediction
// these fields do not need to be communicated bit-precise
vec3_t viewangles; // for fixed views
vec3_t viewoffset; // add to pmovestate->origin
vec3_t kick_angles; // add to view direction to get render angles
// set by weapon kicks, pain effects, etc
vec3_t gunangles;
vec3_t gunoffset;
int gunindex;
int gunframe;
float blend[4]; // rgba full screen effect
float fov; // horizontal field of view
int rdflags; // refdef flags
short stats[Q2MAX_STATS]; // fast status bar updates
} q2player_state_t;
#endif
typedef struct colourised_s {
char name[64];
unsigned int topcolour;
unsigned int bottomcolour;
char skin[64];
struct colourised_s *next;
} colourised_t;
#define MAX_SCOREBOARDNAME 64
#define MAX_DISPLAYEDNAME 16
typedef struct player_info_s
{
int userid;
char userinfo[EXTENDED_INFO_STRING];
char teamstatus[128];
float teamstatustime;
// scoreboard information
char name[MAX_SCOREBOARDNAME];
char team[MAX_INFO_KEY];
float realentertime; //pegged against realtime, to cope with potentially not knowing the server's time when we first receive this message
int frags;
int ping;
qbyte pl;
struct
{
float time; //invalid if too old.
int health;
int armour;
unsigned int items;
vec3_t org;
char nick[8]; //kinda short, yes.
} tinfo;
qboolean ignored;
qboolean vignored;
colourised_t *colourised;
// skin information
unsigned int rtopcolor; //real, according to their userinfo
unsigned int rbottomcolor;
unsigned int ttopcolor; //team, according to colour forcing
unsigned int tbottomcolor;
int spectator;
qwskin_t *qwskin;
qwskin_t *lastskin; //last-known-good skin
skinid_t skinid;
struct model_s *model;
// unsigned short vweapindex;
#ifdef HEXEN2
unsigned char h2playerclass;
#endif
int prevcount;
#ifdef QUAKEHUD
struct wstats_s
{
char wname[16];
unsigned int hit;
unsigned int total;
} weaponstats[16];
#endif
int stats[MAX_CL_STATS];
float statsf[MAX_CL_STATS];
} player_info_t;
typedef struct
{
double senttime; // time cmd was sent off
float latency; // the time the packet was acked. -1=choked, -2=dropped, -3=never sent, -4=reply came back invalid
// generated on client side
usercmd_t cmd[MAX_SPLITS]; // cmd that generated the frame
int cmd_sequence; //the outgoing move sequence. if not equal to expected, that index was stale and is no longer valid
int server_message_num; //the inbound frame that was valid when this command was generated
int server_time;
int client_time;
} outframe_t;
typedef struct
{
//this is the sequence we requested for this frame.
int delta_sequence; // sequence number to delta from, -1 = full update
// received from server
int frameid; //the sequence number of the frame, so we can easily detect which frames are valid without poking all in advance, etc
int ackframe; //the outgoing sequence this frame acked (for prediction backlerping).
double receivedtime; // time message was received, or -1
player_state_t playerstate[MAX_CLIENTS+MAX_SPLITS]; // message received that reflects performing
// the usercmd
packet_entities_t packet_entities;
qboolean invalid; // true if the packet_entities delta was invalid
} inframe_t;
#ifdef Q2CLIENT
typedef struct
{
qboolean valid; // cleared if delta parsing was invalid
int serverframe;
int servertime; // server time the message is valid for (in msec)
int deltaframe;
qbyte areabits[MAX_Q2MAP_AREAS/8]; // portalarea visibility bits
q2player_state_t playerstate[MAX_SPLITS];
int clientnum[MAX_SPLITS];
int num_entities;
int parse_entities; // non-masked index into cl_parse_entities array
} q2frame_t;
#endif
typedef struct
{
int destcolor[3];
float percent; // 0-256
} cshift_t;
#define CSHIFT_CONTENTS 0
#define CSHIFT_DAMAGE 1
#define CSHIFT_BONUS 2
#define CSHIFT_POWERUP 3
#define CSHIFT_SERVER 4
#define NUM_CSHIFTS 5
//
// client_state_t should hold all pieces of the client state
//
//the light array works thusly:
//dlights are allocated DL_LAST downwards to 0, static wlights are allocated DL_LAST+1 to MAX_RTLIGHTS.
//thus to clear the dlights but not rtlights, set the first light to RTL_FIRST
#define DL_LAST (sizeof(unsigned int)*8-1)
#define RTL_FIRST (sizeof(unsigned int)*8)
#define LFLAG_NORMALMODE (1<<0) /*ppl with r_shadow_realtime_dlight*/
#define LFLAG_REALTIMEMODE (1<<1) /*ppl with r_shadow_realtime_world*/
#define LFLAG_LIGHTMAP (1<<2)
#define LFLAG_FLASHBLEND (1<<3)
#define LFLAG_NOSHADOWS (1<<8)
#define LFLAG_SHADOWMAP (1<<9)
#define LFLAG_CREPUSCULAR (1<<10)
#define LFLAG_DYNAMIC (LFLAG_LIGHTMAP | LFLAG_FLASHBLEND | LFLAG_NORMALMODE | LFLAG_REALTIMEMODE)
typedef struct dlight_s
{
int key; // so entities can reuse same entry
vec3_t origin;
vec3_t axis[3];
vec3_t rotation; //cubemap/spotlight rotation
float radius;
float die; // stop lighting after this time
float decay; // drop this each second
float minlight; // don't add when contributing less
float color[3];
float channelfade[3];
#ifdef RTLIGHTS
vec3_t lightcolourscales; //ambient, diffuse, specular
#endif
float corona;
float coronascale;
unsigned int flags;
char cubemapname[64];
int coronaocclusionquery;
unsigned int coronaocclusionresult;
//the following are used for rendering (client code should clear on create)
qboolean rebuildcache;
struct shadowmesh_s *worldshadowmesh;
texid_t cubetexture;
struct {
float updatetime;
} face [6];
int style; //multiply by style values if > 0
float fov; //spotlight
struct dlight_s *next;
} dlight_t;
typedef struct
{
int length;
char map[MAX_STYLESTRING];
vec3_t colours;
int colourkey;
} lightstyle_t;
#define MAX_EFRAGS 512
#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, // netchan_t established, waiting for svc_serverdata
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_wad,
dl_single,
dl_singlestuffed
} dltype_t; // download type
typedef struct qdownload_s
{
enum {DL_QW, DL_QWCHUNKS, DL_Q3, DL_DARKPLACES, DL_QWPENDING, DL_HTTP, DL_FTP} method;
vfsfile_t *file; // file transfer from server
char dclname[MAX_OSPATH]; //file to read/write the chunklist from, for download resumption.
char tempname[MAX_OSPATH]; //file its currently writing to.
char localname[MAX_OSPATH]; //file its going to be renamed to.
int prefixbytes; //number of bytes that prefix the above names (ie: package/ or nothing).
char remotename[MAX_OSPATH]; //file its coming from.
float percent; //for progress indicator.
float starttime; //for speed info
qofs_t completedbytes; //number of bytes downloaded, for progress/speed info
qofs_t size; //total size (may be a guess)
qboolean sizeunknown; //says that size is a guess
unsigned int filesequence; //unique file id.
enum fs_relative fsroot; //where the local+temp file is meant to be relative to.
double ratetime;
int rate;
int ratebytes;
unsigned int flags;
//chunked downloads uses this
struct dlblock_s
{
qofs_t start;
qofs_t end;
enum
{
DLB_MISSING,
DLB_PENDING,
DLB_RECEIVED
} state:16;
unsigned int sequence; //sequence is only valid on pending blocks.
struct dlblock_s *next;
} *dlblocks;
} qdownload_t;
enum qdlabort
{
QDL_FAILED, //delete file, tell server.
QDL_DISCONNECT, //delete file, don't tell server.
QDL_COMPLETED, //rename file, tell server.
};
qboolean DL_Begun(qdownload_t *dl);
void DL_Completed(qdownload_t *dl, qofs_t start, qofs_t end); //notifies the download logic that a chunk of the file is no longer needed.
void DL_Abort(qdownload_t *dl, enum qdlabort aborttype); //just frees the download's resources. does not delete the temp file.
//chunked downloads
void DLC_Poll(qdownload_t *dl);
//
// the client_static_t structure is persistant through an arbitrary number
// of server connections
//
typedef struct
{
// connection information
cactive_t state;
/*Specifies which protocol family we're speaking*/
enum {
CP_UNKNOWN,
CP_QUAKEWORLD,
CP_NETQUAKE,
CP_QUAKE2,
CP_QUAKE3,
CP_PLUGIN
} protocol;
/*QuakeWorld protocol flags*/
#ifdef PROTOCOLEXTENSIONS
unsigned long fteprotocolextensions;
unsigned long fteprotocolextensions2;
#endif
unsigned long z_ext;
/*NQ Protocol flags*/
enum
{
CPNQ_ID,
CPNQ_BJP1, //16bit models, strict 8bit sounds
CPNQ_BJP2, //16bit models, strict 16bit sounds
CPNQ_BJP3, //16bit models, flagged 16bit sounds
CPNQ_FITZ666, /*and rmqe999 protocol*/
CPNQ_DP5,
CPNQ_DP6,
CPNQ_DP7
} protocol_nq;
#define CPNQ_IS_DP (cls.protocol_nq >= CPNQ_DP5)
#define CPNQ_IS_BJP (cls.protocol_nq >= CPNQ_BJP1 && cls.protocol_nq <= CPNQ_BJP3)
qboolean proquake_angles_hack; //angles are always 16bit
int protocol_q2;
qboolean resendinfo;
qboolean findtrack;
int framecount;
int realip_ident;
netadr_t realserverip;
// network stuff
netchan_t netchan;
float lastarbiatarypackettime; //used to mark when packets were sent to prevent mvdsv servers from causing us to disconnect.
// private userinfo for sending to masterless servers
char userinfo[MAX_SPLITS][EXTENDED_INFO_STRING];
char servername[MAX_OSPATH]; // name of server from original connect
struct ftenet_connections_s *sockets;
qdownload_t *download;
// demo loop control
int demonum; // -1 = don't play demos
char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing
// demo recording info must be here, because record is started before
// entering a map (and clearing client_state_t)
vfsfile_t *demooutfile;
enum{DPB_NONE,DPB_QUAKEWORLD,DPB_MVD,DPB_EZTV,
#ifdef NQPROT
DPB_NETQUAKE,
#endif
#ifdef Q2CLIENT
DPB_QUAKE2
#endif
} demoplayback, demorecording;
qboolean demohadkeyframe; //q2 needs to wait for a packet with a key frame, supposedly.
qboolean demoseeking;
float demoseektime;
qboolean timedemo;
vfsfile_t *demoinfile;
struct dl_download *demoindownload;
float td_lastframe; // to meter out one message a frame
int td_startframe; // host_framecount at start
float td_starttime; // realtime at second frame of timedemo
float demostarttime; // the time of the first frame, so we don't get weird results with qw demos
int challenge;
float latency; // rolling average
qboolean allow_anyparticles;
qboolean allow_skyboxes;
qboolean allow_watervis; //fixme: not checked any more
float allow_fbskins; //fraction of allowance
qboolean allow_cheats;
qboolean allow_semicheats; //defaults to true, but this allows a server to enforce a strict ruleset (smackdown type rules).
qboolean allow_csqc; //disables some legacy/compat things, like proquake parsing.
float maxfps; //server capped
int deathmatch;
#ifdef NQPROT
int signon;
#endif
int language;
colourised_t *colourised;
} client_static_t;
extern client_static_t cls;
typedef struct downloadlist_s {
char rname[128];
char localname[128];
unsigned int size;
unsigned int flags;
#define DLLF_VERBOSE (1u<<0) //tell the user that its downloading
#define DLLF_REQUIRED (1u<<1) //means that it won't load models etc until its downloaded (ie: requiredownloads 0 makes no difference)
#define DLLF_OVERWRITE (1u<<2) //overwrite it even if it already exists
#define DLLF_SIZEUNKNOWN (1u<<3) //download's size isn't known
#define DLLF_IGNOREFAILED (1u<<4) //
#define DLLF_NONGAME (1u<<5) //means the requested download filename+localname is gamedir explicit (so id1/foo.txt is distinct from qw/foo.txt)
#define DLLF_TEMPORARY (1u<<6) //download it, but don't actually save it (DLLF_OVERWRITE doesn't actually overwrite, but does ignore any local files)
#define DLLF_USEREXPLICIT (1u<<7) //use explicitly requested it, ignore the cl_downloads cvar.
#define DLLF_BEGUN (1u<<8) //server has confirmed that the file exists, is readable, and we've opened a file. should not be set on new requests.
struct downloadlist_s *next;
} downloadlist_t;
typedef struct {
//current persistant state
trailstate_t *trailstate; //when to next throw out a trail
trailstate_t *emitstate; //when to next emit
//current origin
vec3_t origin; //current render position
vec3_t angles;
//previous rendering frame (for trails)
vec3_t lastorigin;
qboolean isnew;
qboolean isplayer;
//intermediate values for frame lerping
//separate upper+lower lerps
float framelerpdeltatime[FS_COUNT];
float newframestarttime[FS_COUNT];
int newframe[FS_COUNT];
float oldframestarttime[FS_COUNT];
int oldframe[FS_COUNT];
qbyte basebone;
//intermediate values for origin lerping of stepping things
int newsequence;
float orglerpdeltatime;
float orglerpstarttime;
vec3_t neworigin; /*origin that we're lerping towards*/
vec3_t oldorigin; /*origin that we're lerping away from*/
vec3_t newangle;
vec3_t oldangle;
//for further info
int skeletalobject;
int sequence; /*so we know if the ent is still valid*/
entity_state_t *entstate;
} lerpents_t;
//state associated with each player 'seat' (one for each splitscreen client)
//note that this doesn't include networking inputlog info.
struct playerview_s
{
int playernum; //cl.players index for this player.
qboolean nolocalplayer; //inhibit use of qw-style players, predict based on entities.
#ifdef PEXT_SETVIEW
int viewentity; //view is attached to this entity.
#endif
// information for local display
int stats[MAX_CL_STATS]; // health, etc
float statsf[MAX_CL_STATS]; // health, etc
char *statsstr[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
#ifdef HEXEN2
int sb_hexen2_cur_item;//hexen2 hud
float sb_hexen2_item_time;
qboolean sb_hexen2_extra_info;//show the extra stuff
qboolean sb_hexen2_infoplaque;
#endif
// the client maintains its own idea of view angles, which are
// sent to the server each frame. And only reset at level change
// and teleport times
vec3_t viewangles; //current angles
vec3_t viewanglechange; //angles set by input code this frame
vec3_t intermissionangles; //absolute angles for intermission
vec3_t gravitydir;
// pitch drifting vars
float pitchvel;
qboolean nodrift;
float driftmove;
double laststop;
int gamerectknown; //equals cls.framecount if valid
vrect_t gamerect; //position the player's main view was drawn at this frame.
//prediction state
int pmovetype;
float entgravity;
float maxspeed;
vec3_t simorg;
vec3_t simvel;
vec3_t simangles;
float rollangle;
float hdr_last;
int chatstate; //1=talking, 2=afk
float crouch; // local amount for smoothing stepups
vec3_t oldorigin; // to track step smoothing
float oldz, extracrouch, crouchspeed; // to track step smoothing
qboolean onground;
float viewheight;
int waterlevel; //for smartjump
#ifdef Q2CLIENT
vec3_t predicted_origin;
vec3_t predicted_angles;
vec3_t prediction_error;
float predicted_step_time;
float predicted_step;
#endif
float punchangle; // temporary view kick from weapon firing
float v_dmg_time; //various view knockbacks.
float v_dmg_roll;
float v_dmg_pitch;
double bobtime; //sine wave
double bobcltime; //for tracking time increments
float bob; //bob height
vec3_t cam_desired_position; // where the camera wants to be
int cam_oldbuttons; //
vec3_t cam_viewangles; //
double cam_lastviewtime; // timer for wallcam
float cam_reautotrack; // timer to throttle tracking changes.
int cam_spec_track; // player# of who we are tracking / want to track / might want to track
enum
{
CAM_FREECAM = 0, //not attached to another player. we are our own thing (or actually playing).
CAM_PENDING = 1, //we want to lock on to cam_spec_track, but we don't have their position / stats yet. still freecamming
CAM_WALLCAM = 2, //locked, cl_chasecam=0. we're watching them from a wall.
CAM_EYECAM = 3 //locked, cl_chasecam=1. we know where they are, we're in their eyes.
#define CAM_ISLOCKED(pv) ((pv)->cam_state > CAM_PENDING)
} cam_state;
cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups and content types
vec4_t screentint;
vec3_t vw_axis[3]; //weapons should be positioned relative to this
vec3_t vw_origin; //weapons should be positioned relative to this
// entity_t viewent; // is this not utterly redundant yet?
struct
{
struct model_s *oldmodel;
float lerptime;
float oldlerptime;
float frameduration;
int prevframe;
int oldframe;
} vm;
struct
{
qboolean defaulted;
int entnum;
vec3_t origin;
vec3_t forward;
vec3_t right;
vec3_t up;
size_t reverbtype;
vec3_t velocity;
} audio;
};
//
// the client_state_t structure is wiped completely at every
// server signon
//
typedef struct
{
int fpd;
int servercount; // server identification for prespawns
float gamespeed;
qboolean csqcdebug;
qboolean allowsendpacket;
qboolean stillloading; // set when doing something slow, and the game is still loading.
char serverinfo[MAX_SERVERINFO_STRING];
char serverpaknames[1024];
char serverpakcrcs[1024];
qboolean serverpakschanged;
int parsecount; // server message counter
int oldparsecount;
int oldvalidsequence;
int ackedmovesequence; //in quakeworld/q2 this is always equal to validsequence. nq can differ. may only be updated when validsequence is updated.
int lastackedmovesequence; //can be higher than ackedmovesequence when the received frame was unusable.
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
int movesequence; // client->server frames
int spectator;
int autotrack_hint; //the latest hint from the mod, might be negative for invalid.
int autotrack_killer; //if someone kills the guy we're tracking, this is the guy we should switch to.
double last_ping_request; // while showing scoreboard
double last_servermessage;
//list of ent frames that still need to be acked.
int numackframes;
int ackframes[64];
#ifdef Q2CLIENT
q2frame_t q2frame;
q2frame_t q2frames[Q2UPDATE_BACKUP];
#endif
// sentcmds[cl.netchan.outgoing_sequence & UPDATE_MASK] = cmd
outframe_t outframes[UPDATE_BACKUP]; //user inputs (cl.ackedmovesequence+1 to cl.movesequence are still pending)
inframe_t inframes[UPDATE_BACKUP]; //server state (cl.validsequence is the most recent set)
lerpents_t *lerpents;
int maxlerpents; //number of slots allocated.
int lerpentssequence;
lerpents_t lerpplayers[MAX_CLIENTS];
//when running splitscreen, we have multiple viewports all active at once
int splitclients; //we are running this many clients split screen.
playerview_t playerview[MAX_SPLITS];
int defaultnetsplit;//which multiview splitscreen to parse the message for (set by mvd playback code)
// localized movement vars
float bunnyspeedcap;
// 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
float servertime; //current server time, bound between gametime and gametimemark
float mtime; //server time as on the server when we last received a packet. not allowed to decrease.
float oldmtime; //server time as on the server for the previously received packet.
float gametime;
float gametimemark;
float oldgametime; //used as the old time to lerp cl.time from.
float oldgametimemark; //if it's 0, cl.time will casually increase.
float demogametimebias; //mvd timings are weird.
float minpitch;
float maxpitch;
qboolean paused; // send over by server
enum
{
IM_NONE, //off.
IM_NQSCORES, //+showscores forced, view still attached to regular view
IM_NQFINALE, //slow centerprint text etc, view still attached to regular view. no hud
IM_NQCUTSCENE, //IM_NQFINALE, but without the 'finale' header on centerprints.
IM_H2FINALE, //IM_NQFINALE, but with the view offset by the player's viewheight.
IM_QWSCORES //intermission, view locked at a specific point
} intermissionmode; // don't change view angle, full screen, etc
float completed_time; // latched ffrom time at intermission start
#define Q2MAX_VISIBLE_WEAPONS 32 //q2 has about 20.
int numq2visibleweapons; //q2 sends out visible-on-model weapons in a wierd gender-nutral way.
char *q2visibleweapons[Q2MAX_VISIBLE_WEAPONS];//model names beginning with a # are considered 'sexed', and are loaded on a per-client basis. yay. :(
//
// information that is static for the entire time connected to a server
//
char model_name_vwep[MAX_VWEP_MODELS][MAX_QPATH];
char model_name[MAX_PRECACHE_MODELS][MAX_QPATH];
char sound_name[MAX_PRECACHE_SOUNDS][MAX_QPATH];
char *particle_ssname[MAX_SSPARTICLESPRE];
#ifdef Q2CLIENT
char *configstring_general[Q2MAX_CLIENTS|Q2MAX_GENERAL];
char *image_name[Q2MAX_IMAGES];
char *item_name[Q2MAX_ITEMS];
short inventory[MAX_SPLITS][Q2MAX_ITEMS];
#endif
struct model_s *model_precache_vwep[MAX_VWEP_MODELS];
struct model_s *model_precache[MAX_PRECACHE_MODELS];
struct sfx_s *sound_precache[MAX_PRECACHE_SOUNDS];
int particle_ssprecache[MAX_SSPARTICLESPRE]; //these are actually 1-based, so 0 can be used to lazy-init them. I cheat.
char model_csqcname[MAX_CSMODELS][MAX_QPATH];
struct model_s *model_csqcprecache[MAX_CSMODELS];
char *particle_csname[MAX_CSPARTICLESPRE];
int particle_csprecache[MAX_CSPARTICLESPRE]; //these are actually 1-based, so we can be lazy and do a simple negate.
qboolean model_precaches_added;
qboolean particle_ssprecaches; //says to not try to do any dp-compat hacks.
qboolean particle_csprecaches; //says to not try to do any dp-compat hacks.
//used for q2 sky/configstrings
char skyname[MAX_QPATH];
float skyrotate;
vec3_t skyaxis;
qboolean fog_locked;
fogstate_t fog[2]; //0 = air, 1 = water. if water has no density fall back on air.
fogstate_t oldfog[2];
char levelname[40]; // for display on solo scoreboard
char *windowtitle; // fully overrides the window caption.
// refresh related state
struct model_s *worldmodel; // cl_entitites[0].model
int num_entities; // stored bottom up in cl_entities array
int num_statics; // stored top down in cl_entitiers
// all player information
unsigned int allocated_client_slots;
player_info_t players[MAX_CLIENTS];
downloadlist_t *downloadlist;
downloadlist_t *faileddownloads;
qboolean gamedirchanged;
#ifdef Q2CLIENT
char q2statusbar[1024];
char q2layout[MAX_SPLITS][1024];
int parse_entities;
float lerpfrac;
float q2svnetrate; //number of frames we expect to receive per second (required to calculate the server time correctly).
#endif
char lastcenterprint[1024]; //prevents too much spam with console centerprint logging.
struct itemtimer_s
{
float end;
int entnum;
float start;
float duration;
vec3_t origin;
float radius;
struct itemtimer_s *next;
} *itemtimers;
//interpolation+snapshots
float packfrac;
packet_entities_t *currentpackentities;
packet_entities_t *previouspackentities;
float currentpacktime;
qboolean do_lerp_players;
int teamplay;
int deathmatch;
qboolean teamfortress; // *sigh*. This is used for teamplay stuff. This sucks.
qboolean hexen2pickups;
qboolean sendprespawn;
int contentstage;
double matchgametimestart;
enum {
MATCH_DONTKNOW, //assumed to be in progress.
MATCH_COUNTDOWN,
MATCH_STANDBY,
MATCH_INPROGRESS
} matchstate;
} client_state_t;
extern unsigned int cl_teamtopcolor;
extern unsigned int cl_teambottomcolor;
extern unsigned int cl_enemytopcolor;
extern unsigned int cl_enemybottomcolor;
//FPD values
//(commented out ones are ones that we don't support)
#define FPD_NO_FORCE_SKIN 256
#define FPD_NO_FORCE_COLOR 512
#define FPD_LIMIT_PITCH (1 << 14) //limit scripted pitch changes
#define FPD_LIMIT_YAW (1 << 15) //limit scripted yaw changes
//
// cvars
//
extern cvar_t cl_warncmd;
extern cvar_t cl_upspeed;
extern cvar_t cl_forwardspeed;
extern cvar_t cl_backspeed;
extern cvar_t cl_sidespeed;
extern cvar_t cl_movespeedkey;
extern cvar_t cl_yawspeed;
extern cvar_t cl_pitchspeed;
extern cvar_t cl_anglespeedkey;
extern cvar_t cl_shownet;
extern cvar_t cl_sbar;
extern cvar_t cl_hudswap;
extern cvar_t cl_pitchdriftspeed;
extern cvar_t lookspring;
extern cvar_t lookstrafe;
extern cvar_t sensitivity;
extern cvar_t m_pitch;
extern cvar_t m_yaw;
extern cvar_t m_forward;
extern cvar_t m_side;
extern cvar_t _windowed_mouse;
#ifndef SERVERONLY
extern cvar_t name;
#endif
extern cvar_t ruleset_allow_playercount;
extern cvar_t ruleset_allow_frj;
extern cvar_t ruleset_allow_semicheats;
extern cvar_t ruleset_allow_packet;
extern cvar_t ruleset_allow_particle_lightning;
extern cvar_t ruleset_allow_overlongsounds;
extern cvar_t ruleset_allow_larger_models;
extern cvar_t ruleset_allow_modified_eyes;
extern cvar_t ruleset_allow_sensitive_texture_replacements;
extern cvar_t ruleset_allow_localvolume;
extern cvar_t ruleset_allow_shaders;
extern cvar_t ruleset_allow_watervis;
#ifndef SERVERONLY
extern client_state_t cl;
#endif
typedef struct
{
entity_t ent;
entity_state_t state;
trailstate_t *emit;
int mdlidx; /*negative are csqc indexes*/
pvscache_t pvscache;
} static_entity_t;
// FIXME, allocate dynamically
extern entity_state_t *cl_baselines;
extern static_entity_t *cl_static_entities;
extern unsigned int cl_max_static_entities;
extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
extern dlight_t *cl_dlights;
extern unsigned int cl_maxdlights;
extern int rtlights_first, rtlights_max;
extern int cl_baselines_count;
extern qboolean nomaster;
extern float server_version; // version of server we connected to
//=============================================================================
//
// cl_main
//
void CL_InitDlights(void);
void CL_FreeDlights(void);
dlight_t *CL_AllocDlight (int key);
dlight_t *CL_AllocSlight (void); //allocates a static light
dlight_t *CL_NewDlight (int key, const vec3_t origin, float radius, float time, float r, float g, float b);
dlight_t *CL_NewDlightCube (int key, const vec3_t origin, vec3_t angles, float radius, float time, vec3_t colours);
void CL_DecayLights (void);
void CLQW_ParseDelta (struct entity_state_s *from, struct entity_state_s *to, int bits);
void CL_Init (void);
void Host_WriteConfiguration (void);
void CL_CheckServerInfo(void);
void CL_CheckServerPacks(void);
void CL_EstablishConnection (char *host);
void CL_Disconnect (void);
void CL_Disconnect_f (void);
void CL_Reconnect_f (void);
void CL_NextDemo (void);
void CL_Startdemos_f (void);
void CL_Demos_f (void);
void CL_Stopdemo_f (void);
void CL_Changing_f (void);
void CL_Reconnect_f (void);
void CL_ConnectionlessPacket (void);
qboolean CL_DemoBehind(void);
void CL_SaveInfo(vfsfile_t *f);
void CL_SetInfo (int pnum, char *key, char *value);
void CL_BeginServerConnect(const char *host, int port, qboolean noproxy);
char *CL_TryingToConnect(void);
void CL_ExecInitialConfigs(char *defaultexec);
extern int cl_framecount; //number of times the entity lists have been cleared+reset.
extern int cl_numvisedicts;
extern int cl_maxvisedicts;
extern entity_t *cl_visedicts;
/*these are for q3 really*/
typedef struct {
struct shader_s *shader;
int firstvert;
int firstidx;
int numvert;
int numidx;
unsigned int flags;
} scenetris_t;
extern scenetris_t *cl_stris;
extern vecV_t *fte_restrict cl_strisvertv;
extern vec4_t *fte_restrict cl_strisvertc;
extern vec2_t *fte_restrict cl_strisvertt;
extern index_t *fte_restrict cl_strisidx;
extern unsigned int cl_numstrisidx;
extern unsigned int cl_maxstrisidx;
extern unsigned int cl_numstrisvert;
extern unsigned int cl_maxstrisvert;
extern unsigned int cl_numstris;
extern unsigned int cl_maxstris;
extern char emodel_name[], pmodel_name[], prespawn_name[], modellist_name[], soundlist_name[];
//CL_TraceLine traces against network(positive)+csqc(negative) ents. returns frac(1 on failure), and impact, normal, ent values
float CL_TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int *ent);
entity_t *TraceLineR (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
//
// cl_input
//
typedef struct
{
int down[MAX_SPLITS][2]; // key nums holding it down
int state[MAX_SPLITS]; // low bit is down state
} kbutton_t;
extern kbutton_t in_mlook, in_klook;
extern kbutton_t in_strafe;
extern kbutton_t in_speed;
extern float in_sensitivityscale;
void CL_MakeActive(char *gamename);
void CL_UpdateWindowTitle(void);
void CL_InitInput (void);
void CL_SendCmd (double frametime, qboolean mainloop);
void CL_SendMove (usercmd_t *cmd);
#ifdef NQPROT
void CL_ParseTEnt (qboolean nqprot);
#else
void CL_ParseTEnt (void);
#endif
void CL_UpdateTEnts (void);
enum beamtype_e
{ //these are internal ids, matching the beam table
BT_Q1LIGHTNING1,
BT_Q1LIGHTNING2,
BT_Q1LIGHTNING3,
BT_Q1BEAM,
BT_Q2PARASITE,
BT_Q2GRAPPLE,
BT_Q2HEATBEAM,
BT_Q2LIGHTNING,
BT_H2LIGHTNING_SMALL,
BT_H2CHAIN,
BT_H2SUNSTAFF1,
BT_H2SUNSTAFF1_SUB, //inner beam hack
BT_H2SUNSTAFF2, //same model as 1, but different particle effect
BT_H2LIGHTNING,
BT_H2COLORBEAM,
BT_H2ICECHUNKS,
BT_H2GAZE,
BT_H2FAMINE,
};
typedef struct beam_s beam_t;
beam_t *CL_AddBeam (enum beamtype_e tent, int ent, vec3_t start, vec3_t end);
void CL_ClearState (void);
void CLQ2_ClearState(void);
void CL_ReadPackets (void);
void CL_ClampPitch (int pnum);
int CL_ReadFromServer (void);
void CL_WriteToServer (usercmd_t *cmd);
void CL_BaseMove (usercmd_t *cmd, int pnum, float extra, float wantfps);
int Master_FindBestRoute(char *server, char *out, size_t outsize, int *directcost, int *chainedcost);
float CL_KeyState (kbutton_t *key, int pnum, qboolean noslowstart);
char *Key_KeynumToString (int keynum, int modifier);
int Key_StringToKeynum (const char *str, int *modifier);
char *Key_GetBinding(int keynum, int bindmap, int modifier);
void Key_GetBindMap(int *bindmaps);
void Key_SetBindMap(int *bindmaps);
void CL_UseIndepPhysics(qboolean allow);
void CL_FlushClientCommands(void);
void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...) LIKEPRINTF(2);
float CL_FilterTime (double time, float wantfps, qboolean ignoreserver);
int CL_RemoveClientCommands(char *command);
void CL_AllowIndependantSendCmd(qboolean allow);
//
// cl_demo.c
//
void CL_StopPlayback (void);
qboolean CL_GetMessage (void);
void CL_WriteDemoCmd (usercmd_t *pcmd);
void CL_Demo_ClientCommand(char *commandtext); //for QTV.
void CL_WriteSetDemoMessage (void); //'restarts' a qwd, when we have reloads/map changes in them
void CL_WriteRecordQ2DemoMessage(sizebuf_t *msg);
void CL_Stop_f (void);
void CL_Record_f (void);
void CL_ReRecord_f (void);
void CL_PlayDemo_f (void);
void CL_QTVPlay_f (void);
void CL_QTVPoll (void);
void CL_QTVList_f (void);
void CL_QTVDemos_f (void);
void CL_DemoJump_f(void);
void CL_ProgressDemoTime(void);
void CL_TimeDemo_f (void);
typedef struct
{
enum
{
QTVCT_NONE,
QTVCT_STREAM,
QTVCT_CONNECT,
QTVCT_JOIN,
QTVCT_OBSERVE,
QTVCT_MAP
} connectiontype;
enum
{
QTVCT_NETQUAKE,
QTVCT_QUAKEWORLD,
QTVCT_QUAKE2,
QTVCT_QUAKE3
} protocol;
char server[256];
char splashscreen[256];
//char *datafiles;
} qtvfile_t;
void CL_ParseQTVFile(vfsfile_t *f, const char *fname, qtvfile_t *result);
//
// cl_parse.c
//
#define NET_TIMINGS 256
#define NET_TIMINGSMASK 255
extern int packet_latency[NET_TIMINGS];
int CL_CalcNet (float scale);
void CL_CalcNet2 (float *pings, float *pings_min, float *pings_max, float *pingms_stddev, float *pingfr, int *pingfr_min, int *pingfr_max, float *dropped, float *choked, float *invalid);
void CL_ClearParseState(void);
void CL_Parse_Disconnected(void);
void CL_DumpPacket(void);
void CL_ParseEstablished(void);
void CLQW_ParseServerMessage (void);
void CLNQ_ParseServerMessage (void);
#ifdef Q2CLIENT
void CLQ2_ParseServerMessage (void);
#endif
void CL_NewTranslation (int slot);
int CL_IsDownloading(const char *localname);
qboolean CL_CheckOrEnqueDownloadFile (const char *filename, const char *localname, unsigned int flags);
qboolean CL_EnqueDownload(const char *filename, const char *localname, unsigned int flags);
downloadlist_t *CL_DownloadFailed(const char *name, qdownload_t *qdl);
int CL_DownloadRate(void);
void CL_GetDownloadSizes(unsigned int *filecount, qofs_t *totalsize, qboolean *somesizesunknown);
qboolean CL_ParseOOBDownload(void);
void CL_DownloadFinished(qdownload_t *dl);
void CL_RequestNextDownload (void);
void CL_SendDownloadReq(sizebuf_t *msg);
void Sound_CheckDownload(const char *s); /*checkorenqueue a sound file*/
qboolean CL_IsUploading(void);
void CL_NextUpload(void);
void CL_StartUpload (qbyte *data, int size);
void CL_StopUpload(void);
qboolean CL_CheckBaselines (int size);
//
// view.c
//
void V_StartPitchDrift (playerview_t *pv);
void V_StopPitchDrift (playerview_t *pv);
void V_RenderView (void);
void V_Register (void);
void V_ParseDamage (playerview_t *pv);
void V_SetContentsColor (int contents);
//used directly by csqc
void V_CalcRefdef (playerview_t *pv);
void V_ClearRefdef(playerview_t *pv);
void V_ApplyRefdef(void);
void V_CalcGunPositionAngle (playerview_t *pv, float bob);
float V_CalcBob (playerview_t *pv, qboolean queryold);
void DropPunchAngle (playerview_t *pv);
int V_EditExternalModels(int newviewentity, entity_t *viewentities, int maxviewenties);
void V_DepthSortEntities(float *vieworg);
//
// cl_tent
//
void CL_RegisterParticles(void);
void CL_InitTEnts (void);
void CL_InitTEntSounds (void);
void CL_ClearTEnts (void);
void CL_ClearTEntParticleState (void);
void CL_ClearCustomTEnts(void);
void CL_ParseCustomTEnt(void);
qboolean CL_WriteCustomTEnt(sizebuf_t *buf, int id);
void CL_ParseEffect (qboolean effect2);
void CLNQ_ParseParticleEffect (void);
void CL_ParseParticleEffect2 (void);
void CL_ParseParticleEffect3 (void);
void CL_ParseParticleEffect4 (void);
int CL_TranslateParticleFromServer(int sveffect);
void CL_ParseTrailParticles(void);
void CL_ParsePointParticles(qboolean compact);
void CL_SpawnSpriteEffect(vec3_t org, vec3_t dir, vec3_t orientationup, struct model_s *model, int startframe, int framecount, float framerate, float alpha, float scale, float randspin, float gravity, int traileffect, unsigned int renderflags, int skinnum); /*called from the particlesystem*/
//
// cl_ents.c
//
void CL_SetSolidPlayers (void);
void CL_SetUpPlayerPrediction(qboolean dopred);
void CL_LinkStaticEntities(void *pvs);
void CL_TransitionEntities (void); /*call at the start of the frame*/
void CL_EmitEntities (void);
void CL_ClearProjectiles (void);
void CL_ParseProjectiles (int modelindex, qboolean nails2);
void CLQW_ParsePacketEntities (qboolean delta);
void CLFTE_ParseEntities (void);
void CLFTE_ParseBaseline(entity_state_t *es, qboolean numberisimportant);
void CL_SetSolidEntities (void);
void CL_ParsePlayerinfo (void);
void CL_ParseClientPersist(void);
//these last ones are needed for csqc handling of engine-bound ents.
void CL_ClearEntityLists(void);
void CL_FreeVisEdicts(void);
void CL_LinkViewModel(void);
void CL_LinkPlayers (void);
void CL_LinkPacketEntities (void);
void CL_LinkProjectiles (void);
void CL_ClearLerpEntsParticleState (void);
qboolean CL_MayLerp(void);
//
//clq3_parse.c
//
#ifdef Q3CLIENT
void VARGS CLQ3_SendClientCommand(const char *fmt, ...) LIKEPRINTF(1);
void CLQ3_SendAuthPacket(netadr_t *gameserver);
void CLQ3_SendConnectPacket(netadr_t *to, int challenge, int qport);
void CLQ3_SendCmd(usercmd_t *cmd);
qboolean CLQ3_Netchan_Process(void);
void CLQ3_ParseServerMessage (void);
struct snapshot_s;
qboolean CG_FillQ3Snapshot(int snapnum, struct snapshot_s *snapshot);
void CG_InsertIntoGameState(int num, char *str);
void CG_Restart_f(void);
char *CG_GetConfigString(int num);
#endif
//
//pr_csqc.c
//
#ifdef CSQC_DAT
qboolean CSQC_Inited(void);
void CSQC_RendererRestarted(void);
qboolean CSQC_UnconnectedOkay(qboolean inprinciple);
qboolean CSQC_UnconnectedInit(void);
qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checksum);
qboolean CSQC_ConsoleLink(char *text, char *info);
void CSQC_RegisterCvarsAndThings(void);
qboolean CSQC_SetupToRenderPortal(int entnum);
qboolean CSQC_DrawView(void);
qboolean CSQC_UseGamecodeLoadingScreen(void);
void CSQC_Shutdown(void);
qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend);
void CSQC_MapEntityEdited(int idx, const char *newe);
qboolean CSQC_LoadResource(char *resname, char *restype);
qboolean CSQC_ParsePrint(char *message, int printlevel);
qboolean CSQC_ParseGamePacket(void);
qboolean CSQC_CenterPrint(int lplayernum, char *cmd);
qboolean CSQC_Parse_Damage(float save, float take, vec3_t source);
void CSQC_Input_Frame(int lplayernum, usercmd_t *cmd);
void CSQC_WorldLoaded(void);
qboolean CSQC_ParseTempEntity(void);
qboolean CSQC_ConsoleCommand(char *cmd);
qboolean CSQC_KeyPress(int key, int unicode, qboolean down, unsigned int devid);
qboolean CSQC_MouseMove(float xdelta, float ydelta, unsigned int devid);
qboolean CSQC_MousePosition(float xabs, float yabs, unsigned int devid);
qboolean CSQC_JoystickAxis(int axis, float value, unsigned int devid);
qboolean CSQC_Accelerometer(float x, float y, float z);
qboolean CSQC_Gyroscope(float x, float y, float z);
int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation, float pitchmod, float timeofs, unsigned int flags);
void CSQC_ParseEntities(void);
void CSQC_ResetTrails(void);
qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state);
void CSQC_DeltaStart(float time);
qboolean CSQC_DeltaUpdate(entity_state_t *src);
void CSQC_DeltaEnd(void);
void CSQC_CvarChanged(cvar_t *var);
#else
#define CSQC_UnconnectedOkay(inprinciple) false
#define CSQC_UnconnectedInit() false
#define CSQC_UseGamecodeLoadingScreen() false
#endif
//
// cl_pred.c
//
void CL_InitPrediction (void);
void CL_PredictMove (void);
void CL_PredictUsercmd (int seat, int entnum, player_state_t *from, player_state_t *to, usercmd_t *u);
#ifdef Q2CLIENT
void CLQ2_CheckPredictionError (void);
#endif
void CL_CalcClientTime(void);
//
// cl_cam.c
//
qboolean Cam_DrawViewModel(playerview_t *pv);
int Cam_TrackNum(playerview_t *pv);
void Cam_Unlock(playerview_t *pv); //revert to freecam or so, because that entity failed.
void Cam_Lock(playerview_t *pv, int playernum); //attempt to lock on to the given player.
void Cam_NowLocked(playerview_t *pv); //player was located, track them now
void Cam_SelfTrack(playerview_t *pv);
void Cam_Track(playerview_t *pv, usercmd_t *cmd);
void Cam_TrackCrosshairedPlayer(playerview_t *pv);
void Cam_SetModAutoTrack(int userid);
void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd);
void Cam_Reset(void);
void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg);
void CL_InitCam(void);
void Cam_AutoTrack_Update(const char *mode); //reset autotrack setting (because we started a new map or whatever)
void QDECL vectoangles(vec3_t fwd, vec3_t ang);
//
//zqtp.c
//
#define TPM_UNKNOWN 0
#define TPM_NORMAL 1
#define TPM_TEAM 2
#define TPM_SPECTATOR 4
#define TPM_FAKED 16
#define TPM_OBSERVEDTEAM 32
#define TPM_QTV 64 //should only be qtv_say_game/qtv_say_team_game
void CL_Say (qboolean team, char *extra);
int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr);
void TP_CheckPickupSound(char *s, vec3_t org, int seat);
qboolean TP_CheckSoundTrigger (char *str);
int TP_CountPlayers (void);
char* TP_EnemyName (void);
char* TP_EnemyTeam (void);
void TP_ExecTrigger (char *s, qboolean indemos);
qboolean TP_FilterMessage (char *s);
void TP_Init(void);
char* TP_LocationName (vec3_t location);
char* TP_MapName (void);
void TP_NewMap (void);
void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_info_t *info);
qboolean TP_IsPlayerVisible(vec3_t origin);
char* TP_PlayerName (void);
char* TP_PlayerTeam (void);
void TP_SearchForMsgTriggers (char *s, int level);
qboolean TP_SoundTrigger(char *message);
void TP_StatChanged (int stat, int value);
qboolean TP_SuppressMessage(char *buf);
colourised_t *TP_FindColours(char *name);
void TP_UpdateAutoStatus(void);
//
// skin.c
//
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
// unsigned char data; // unbounded
} pcx_t;
qbyte *ReadPCXData(qbyte *buf, int length, int width, int height, qbyte *result);
qwskin_t *Skin_Lookup (char *fullname);
char *Skin_FindName (player_info_t *sc);
void Skin_Find (player_info_t *sc);
qbyte *Skin_Cache8 (qwskin_t *skin);
void Skin_Skins_f (void);
void Skin_FlushSkin(char *name);
void Skin_AllSkins_f (void);
void Skin_NextDownload (void);
void Skin_FlushPlayers(void);
void Skin_FlushAll(void);
#define RSSHOT_WIDTH 320
#define RSSHOT_HEIGHT 200
//valid.c
void RulesetLatch(cvar_t *cvar);
void Validation_Apply_Ruleset(void);
void Validation_FlushFileList(void);
void Validation_CheckIfResponse(char *text);
void Validation_DelatchRulesets(void);
void InitValidation(void);
void Validation_IncludeFile(char *filename, char *file, int filelen);
void Validation_Auto_Response(int playernum, char *s);
extern qboolean f_modified_particles;
extern qboolean care_f_modified;
//random files (fixme: clean up)
#ifdef Q2CLIENT
unsigned int CLQ2_GatherSounds(vec3_t *positions, unsigned int *entnums, sfx_t **sounds, unsigned int max);
void CLQ2_ParseTEnt (void);
void CLQ2_AddEntities (void);
void CLQ2_ParseBaseline (void);
void CLQ2_ClearParticleState(void);
void CLR1Q2_ParsePlayerUpdate(void);
void CLQ2_ParseFrame (int extrabits);
void CLQ2_RunMuzzleFlash2 (int ent, int flash_number);
int CLQ2_RegisterTEntModels (void);
void CLQ2_WriteDemoBaselines(sizebuf_t *buf);
#endif
#ifdef HLCLIENT
//networking
void CLHL_LoadClientGame(void);
int CLHL_ParseGamePacket(void);
int CLHL_AnimateViewEntity(entity_t *ent);
//screen
int CLHL_DrawHud(void);
//inputs
int CLHL_GamecodeDoesMouse(void);
int CLHL_MouseEvent(unsigned int buttonmask);
void CLHL_SetMouseActive(int activate);
int CLHL_BuildUserInput(int msecs, usercmd_t *cmd);
#endif
#ifdef NQPROT
void CLNQ_ParseEntity(unsigned int bits);
void NQ_P_ParseParticleEffect (void);
void CLNQ_SignonReply (void);
void NQ_BeginConnect(char *to);
void NQ_ContinueConnect(char *to);
int CLNQ_GetMessage (void);
#endif
void CL_BeginServerReconnect(void);
void SV_User_f (void); //called by client version of the function
void SV_Serverinfo_f (void);
void SV_ConSay_f(void);
#ifdef TEXTEDITOR
extern console_t *editormodal;
void Editor_Draw(void);
void Editor_Init(void);
struct pubprogfuncs_s;
void Editor_ProgsKilled(struct pubprogfuncs_s *dead);
#endif
void SCR_StringToRGB (char *rgbstring, float *rgb, float rgbinputscale);
struct model_s;
void CL_AddVWeapModel(entity_t *player, struct model_s *model);
/*q2 cinematics*/
struct cinematics_s;
void CIN_StopCinematic (struct cinematics_s *cin);
struct cinematics_s *CIN_PlayCinematic (char *arg);
int CIN_RunCinematic (struct cinematics_s *cin, float playbacktime, qbyte **outdata, int *outwidth, int *outheight, qbyte **outpalette);
void CIN_Rewind(struct cinematics_s *cin);
typedef enum
{
CINSTATE_INVALID, //also reported for not playing
CINSTATE_PLAY,
CINSTATE_LOOP,
CINSTATE_PAUSE,
CINSTATE_ENDED,
CINSTATE_FLUSHED, //video will restart from beginning
} cinstates_t;
typedef struct cin_s cin_t;
#ifdef NOMEDIA
#define Media_Playing() false
#define Media_Init() (void)0
#define Media_PlayingFullScreen() false
#define Media_PlayFilm(n,e) false
#define Media_StopFilm(a) (void)true
#else
/*media playing system*/
qboolean Media_PlayingFullScreen(void);
void Media_Init(void);
qboolean Media_PlayFilm(char *name, qboolean enqueue);
qboolean Media_StopFilm(qboolean all);
struct cin_s *Media_StartCin(char *name);
texid_tf Media_UpdateForShader(cin_t *cin);
void Media_ShutdownCin(cin_t *cin);
#endif
qboolean Media_NamedTrack(const char *initialtrack, const char *looptrack); //new background music interface
void Media_NumberedTrack(unsigned int initialtrack, unsigned int looptrack); //legacy cd interface for protocols that only support numbered tracks.
void Media_EndedTrack(void); //cd is no longer running, media code needs to pick a new track (cd track or faketrack)
//these accept NULL for cin to mean the current fullscreen video
void Media_Send_Command(cin_t *cin, const char *command);
void Media_Send_MouseMove(cin_t *cin, float x, float y);
void Media_Send_Resize(cin_t *cin, int x, int y);
void Media_Send_GetSize(cin_t *cin, int *x, int *y, float *aspect);
void Media_Send_KeyEvent(cin_t *cin, int button, int unicode, int event);
void Media_Send_Reset(cin_t *cin);
void Media_SetState(cin_t *cin, cinstates_t newstate);
cinstates_t Media_GetState(cin_t *cin);
const char *Media_Send_GetProperty(cin_t *cin, const char *key);
void MVD_Interpolate(void);
int Stats_GetKills(int playernum);
int Stats_GetTKills(int playernum);
int Stats_GetDeaths(int playernum);
int Stats_GetTouches(int playernum);
int Stats_GetCaptures(int playernum);
qboolean Stats_HaveFlags(int mode);
qboolean Stats_HaveKills(void);
float Stats_GetLastOwnFrag(int seat, char *res, int reslen);
void VARGS Stats_Message(char *msg, ...) LIKEPRINTF(1);
qboolean Stats_ParsePrintLine(const char *line);
qboolean Stats_ParsePickups(const char *line);
void Stats_NewMap(void);
void Stats_Clear(void);
void Stats_Init(void);
enum uploadfmt;
typedef struct
{
size_t structsize;
const char *drivername;
void *(VARGS *createdecoder)(const char *name);
qboolean (VARGS *decodeframe)(void *ctx, qboolean nosound, qboolean forcevideo, double mediatime, void (QDECL *uploadtexture)(void *ectx, uploadfmt_t fmt, int width, int height, void *data, void *palette), void *ectx);
void (VARGS *shutdown)(void *ctx);
void (VARGS *rewind)(void *ctx);
//these are any interactivity functions you might want...
void (VARGS *cursormove) (void *ctx, float posx, float posy); //pos is 0-1
void (VARGS *key) (void *ctx, int code, int unicode, int event);
qboolean (VARGS *setsize) (void *ctx, int width, int height);
void (VARGS *getsize) (void *ctx, int *width, int *height);
void (VARGS *changestream) (void *ctx, const char *streamname);
qboolean (VARGS *getproperty) (void *ctx, const char *field, char *out, size_t *outsize); //if out is null, returns required buffer size. returns 0 on failure / buffer too small
} media_decoder_funcs_t;
typedef struct
{
size_t structsize;
const char *drivername;
const char *description;
const char *defaultextension;
void *(VARGS *capture_begin) (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits);
void (VARGS *capture_video) (void *ctx, void *data, int frame, int width, int height, enum uploadfmt fmt);
void (VARGS *capture_audio) (void *ctx, void *data, int bytes);
void (VARGS *capture_end) (void *ctx);
} media_encoder_funcs_t;
extern struct plugin_s *currentplug;
qboolean Media_RegisterDecoder(struct plugin_s *plug, media_decoder_funcs_t *funcs);
qboolean Media_UnregisterDecoder(struct plugin_s *plug, media_decoder_funcs_t *funcs);
qboolean Media_RegisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *funcs);
qboolean Media_UnregisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *funcs);