/* 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; char ip[128]; 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; //compacted version of the colours, for comparison against caches } 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; qboolean nqexpectingstatusresponse; } 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. #define DLLF_ALLOWWEB (1u<<9) //failed http downloads should retry but from the game server itself 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 //temporary view kick from weapon firing, angles+origins float punchangle_cl; // qw-style angles vec3_t punchangle_sv; // nq-style vec3_t punchorigin; // nq-style 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; enum { CLNQPP_NONE, CLNQPP_PINGS, CLNQPP_STATUS, //"host: *\n" ... "players: *\n\n" CLNQPP_STATUSPLAYER, //#...\n CLNQPP_STATUSPLAYERIP, // foobar\n } nqparseprint; int nqparseprintplayer; float nqplayernamechanged; } 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); typedef struct cin_s cin_t; #ifdef HAVE_MEDIA_DECODER /*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; /*media playing system*/ qboolean Media_PlayingFullScreen(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); //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); #else #define Media_Playing() false #define Media_PlayingFullScreen() false #define Media_PlayFilm(n,e) false #define Media_StopFilm(a) (void)true #endif void Media_Init(void); 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) 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);