// LordHavoc: 256 dynamic lights
#define MAX_DLIGHTS 256
+// this is the maximum number of input packets that can be lost without a
+// misprediction
+#define CL_MAX_USERCMDS 16
+
// flags for rtlight rendering
#define LIGHTFLAG_NORMALMODE 1
#define LIGHTFLAG_REALTIMEMODE 2
// note that the world to light matrices are inversely scaled (divided) by lightradius
// core properties
+ // matrix for transforming light filter coordinates to world coordinates
+ matrix4x4_t matrix_lighttoworld;
// matrix for transforming world coordinates to light filter coordinates
matrix4x4_t matrix_worldtolight;
// typically 1 1 1, can be lower (dim) or higher (overbright)
// surfaces seen by light
int static_numsurfaces;
int *static_surfacelist;
+ // flag bits indicating which triangles of the world model should cast
+ // shadows, and which ones should be lit
+ //
+ // this avoids redundantly scanning the triangles in each surface twice
+ // for whether they should cast shadows, once in culling and once in the
+ // actual shadowmarklist production.
+ int static_numshadowtrispvsbytes;
+ unsigned char *static_shadowtrispvs;
+ // this allows the lighting batch code to skip backfaces andother culled
+ // triangles not relevant for lighting
+ // (important on big surfaces such as terrain)
+ int static_numlighttrispvsbytes;
+ unsigned char *static_lighttrispvs;
}
rtlight_t;
// color of light
// (worldlight: saved to .rtlights file)
vec3_t color;
- // cubemap number to use on this light
- // (dlight only)
- int cubemapnum;
// cubemap name to use on this light
- // (worldlight only)
// (worldlight: saved to .rtlights file)
char cubemapname[64];
// make light flash while selected
// (worldlight only)
struct dlight_s *next;
// embedded rtlight struct for renderer
- // (renderer only)
+ // (worldlight only)
rtlight_t rtlight;
}
dlight_t;
model_t *model;
// current uninterpolated animation frame (for things which do not use interpolation)
int frame;
+ // number of the entity represents, or 0 for non-network entities
+ int entitynumber;
// entity shirt and pants colors (-1 if not colormapped)
int colormap;
// literal colors for renderer
vec3_t colormap_shirtcolor;
// light, particles, etc
int effects;
+ // qw CTF flags and other internal-use-only effect bits
+ int internaleffects;
// for Alias models
int skinnum;
// render flags
vec3_t modellight_ambient;
vec3_t modellight_diffuse; // q3bsp
vec3_t modellight_lightdir; // q3bsp
+
+ // last time visible during trace culling
+ double last_trace_visibility;
}
entity_render_t;
// particle trail
float trail_time;
+ qboolean trail_allowed; // set to false by teleports, true by update code, prevents bad lerps
// muzzleflash fading
float muzzleflash;
double time;
double receivetime;
+ int msec; // for qw moves
int buttons;
int impulse;
int sequence;
qboolean applied; // if false we're still accumulating a move
+ qboolean predicted; // if true the sequence should be sent as 0
} usercmd_t;
typedef struct lightstyle_s
// (note: qw_download variables are also used)
cl_downloadack_t dp_downloadack[CL_MAX_DOWNLOADACKS];
+ // input sequence numbers are not reset on level change, only connect
+ int movesequence;
+ int servermovesequence;
+
// quakeworld stuff below
// value of "qport" cvar at time of connection
float move[3];
qboolean jump;
qboolean crouch;
+ qboolean canjump;
}
client_movementqueue_t;
qboolean drawcrosshair;
}csqc_vidvars_t;
-typedef struct qw_usercmd_s
-{
- vec3_t angles;
- short forwardmove, sidemove, upmove;
- unsigned char padding1[2];
- unsigned char msec;
- unsigned char buttons;
- unsigned char impulse;
- unsigned char padding2;
-}
-qw_usercmd_t;
-
typedef enum
{
PARTICLE_BILLBOARD = 0,
model_t *ownermodel; // model the decal is stuck to (used to make sure the entity is still alive)
vec3_t relativeorigin; // decal at this location in entity's coordinate space
vec3_t relativedirection; // decal oriented this way relative to entity's coordinate space
+ float delayedcollisions; // time that p->bounce becomes active
+ float delayedspawn; // time that particle appears and begins moving
+ float die; // time when this particle should be removed, regardless of alpha
}
particle_t;
}
cl_parsingtextmode_t;
+typedef struct cl_locnode_s
+{
+ struct cl_locnode_s *next;
+ char *name;
+ vec3_t mins, maxs;
+}
+cl_locnode_t;
+
//
// the client_state_t structure is wiped completely at every
// server signon
// true if playing in a local game and no one else is connected
int islocalgame;
- // when connecting to the server throw out the first couple move messages
- // so the player doesn't accidentally do something the first frame
- int movemessages;
-
// send a clc_nop periodically until connected
float sendnoptime;
- // current input to send to the server
+ // current input being accumulated by mouse/joystick/etc input
usercmd_t cmd;
+ // latest moves sent to the server that have not been confirmed yet
+ usercmd_t movecmd[CL_MAX_USERCMDS];
// information for local display
// health, etc
int stats[MAX_CL_STATS];
+ float *statsf; // points to stats[] array
// last known inventory bit flags, for blinking
int olditems;
// cl.time of acquiring item, for blinking
// use pain anim frame if cl.time < this
float faceanimtime;
// for stair smoothing
- float stairoffset;
+ float stairsmoothz;
+ double stairsmoothtime;
// color shifts for damage, powerups
cshift_t cshifts[NUM_CSHIFTS];
// these fields are only updated by CL_ClientMovement (called by CL_SendMove after parsing each network packet)
// set by CL_ClientMovement_Replay functions
qboolean movement_predicted;
+ // if true the CL_ClientMovement_Replay function will update origin, etc
+ qboolean movement_replay;
// this is set true by svc_time parsing and causes a new movement to be
// queued for prediction purposes
qboolean movement_needupdate;
- // indicates the queue has been updated and should be replayed
- qboolean movement_replay;
// timestamps of latest two predicted moves for interpolation
- double movement_time[2];
+ double movement_time[4];
// simulated data (this is valid even if cl.movement is false)
vec3_t movement_origin;
vec3_t movement_oldorigin;
// queue of proposed moves
int movement_numqueue;
client_movementqueue_t movement_queue[256];
- int movesequence;
- int servermovesequence;
// whether the replay should allow a jump at the first sequence
qboolean movement_replay_canjump;
// clients view of time, time should be between mtime[0] and mtime[1] to
// generate a lerp point for other data, oldtime is the previous frame's
// value of time, frametime is the difference between time and oldtime
+ // note: cl.time may be beyond cl.mtime[0] if packet loss is occuring, it
+ // is only forcefully limited when a packet is received
double time, oldtime;
// how long it has been since the previous client frame in real time
// (not game time, for that use cl.time - cl.oldtime)
sfx_t *sfx_ric2;
sfx_t *sfx_ric3;
sfx_t *sfx_r_exp3;
+ // indicates that the file "sound/misc/talk2.wav" was found (for use by team chat messages)
+ qboolean foundtalk2wav;
// refresh related state
int downloadsound_current;
int loadsound_total;
qboolean downloadcsqc;
+ qboolean loadbegun;
qboolean loadfinished;
// quakeworld stuff
//qboolean qw_spectator;
// movement parameters for client prediction
- float qw_movevars_gravity;
- float qw_movevars_stopspeed;
- float qw_movevars_maxspeed; // can change during play
- float qw_movevars_spectatormaxspeed;
- float qw_movevars_accelerate;
- float qw_movevars_airaccelerate;
- float qw_movevars_wateraccelerate;
- float qw_movevars_friction;
- float qw_movevars_waterfriction;
- float qw_movevars_entgravity; // can change during play
+ float movevars_wallfriction;
+ float movevars_waterfriction;
+ float movevars_friction;
+ float movevars_ticrate;
+ float movevars_timescale;
+ float movevars_gravity;
+ float movevars_stopspeed;
+ float movevars_maxspeed;
+ float movevars_spectatormaxspeed;
+ float movevars_accelerate;
+ float movevars_airaccelerate;
+ float movevars_wateraccelerate;
+ float movevars_entgravity;
+ float movevars_jumpvelocity;
+ float movevars_edgefriction;
+ float movevars_maxairspeed;
+ float movevars_stepheight;
+ float movevars_airaccel_qw;
+ float movevars_airaccel_sideways_friction;
// models used by qw protocol
int qw_modelindex_spike;
int qw_validsequence;
- qw_usercmd_t qw_moves[QW_UPDATE_BACKUP];
-
int qw_deltasequence[QW_UPDATE_BACKUP];
+
+ // csqc stuff:
+ // server entity number corresponding to a clientside entity
+ unsigned short csqc_server2csqcentitynumber[MAX_EDICTS];
+ qboolean csqc_loaded;
+ vec3_t csqc_origin;
+ vec3_t csqc_angles;
+ qboolean csqc_usecsqclistener;
+ matrix4x4_t csqc_listenermatrix;
+ char csqc_printtextbuf[MAX_INPUTLINE];
+
+ // collision culling data
+ world_t world;
+
+ // loc file stuff (points and boxes describing locations in the level)
+ cl_locnode_t *locnodes;
+ // this is updated to cl.movement_origin whenever health is < 1
+ // used by %d print in say/say_team messages if cl_locs_enable is on
+ vec3_t lastdeathorigin;
+
+ // processing buffer used by R_BuildLightMap, reallocated as needed,
+ // freed on each level change
+ size_t buildlightmapmemorysize;
+ unsigned char *buildlightmapmemory;
}
client_state_t;
extern cvar_t cl_shownet;
extern cvar_t cl_nolerp;
+extern cvar_t cl_nettimesyncfactor;
+extern cvar_t cl_nettimesyncboundmode;
+extern cvar_t cl_nettimesyncboundtolerance;
extern cvar_t cl_pitchdriftspeed;
extern cvar_t lookspring;
extern cvar_t cl_prydoncursor;
+extern cvar_t cl_locs_enable;
+
extern client_state_t cl;
-extern void CL_AllocDlight (entity_render_t *ent, matrix4x4_t *matrix, float radius, float red, float green, float blue, float decay, float lifetime, int cubemapnum, int style, int shadowenable, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags);
+extern void CL_AllocLightFlash (entity_render_t *ent, matrix4x4_t *matrix, float radius, float red, float green, float blue, float decay, float lifetime, int cubemapnum, int style, int shadowenable, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags);
+
+cl_locnode_t *CL_Locs_FindNearest(const vec3_t point);
+void CL_Locs_FindLocationName(char *buffer, size_t buffersize, vec3_t point);
//=============================================================================
void CL_Disconnect_f (void);
void CL_UpdateRenderEntity(entity_render_t *ent);
-void CL_UpdateEntities(void);
+void CL_UpdateViewEntities(void);
//
// cl_input
void CL_NewBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning);
void CL_RelinkBeams (void);
void CL_Beam_CalculatePositions (const beam_t *b, vec3_t start, vec3_t end);
+void CL_ClientMovement_Replay(void);
void CL_ClearTempEntities (void);
entity_t *CL_NewTempEntity (void);
void CL_SetInfo(const char *key, const char *value, qboolean send, qboolean allowstarkey, qboolean allowmodel, qboolean quiet);
-int CL_ReadFromServer (void);
+void CL_UpdateWorld (void);
void CL_WriteToServer (void);
-void CL_Move (void);
+void CL_Input (void);
extern qboolean cl_ignoremousemove;
//
void CL_StopPlayback(void);
void CL_ReadDemoMessage(void);
-void CL_WriteDemoMessage(void);
+void CL_WriteDemoMessage(sizebuf_t *mesage);
void CL_NextDemo(void);
void CL_Stop_f(void);
extern cvar_t cl_particles_blood_alpha;
extern cvar_t cl_particles_blood_bloodhack;
extern cvar_t cl_particles_bulletimpacts;
-extern cvar_t cl_particles_explosions_bubbles;
extern cvar_t cl_particles_explosions_smoke;
extern cvar_t cl_particles_explosions_sparks;
extern cvar_t cl_particles_explosions_shell;
+extern cvar_t cl_particles_rain;
+extern cvar_t cl_particles_snow;
extern cvar_t cl_particles_smoke;
extern cvar_t cl_particles_smoke_alpha;
extern cvar_t cl_particles_smoke_alphafade;
int CL_ParticleEffectIndexForName(const char *name);
const char *CL_ParticleEffectNameForIndex(int i);
void CL_ParticleEffect(int effectindex, float pcount, const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, entity_t *ent, int palettecolor);
+void CL_ParticleTrail(int effectindex, float pcount, const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, entity_t *ent, int palettecolor, qboolean spawndlight, qboolean spawnparticles);
void CL_ParseParticleEffect (void);
void CL_ParticleCube (const vec3_t mins, const vec3_t maxs, const vec3_t dir, int count, int colorbase, vec_t gravity, vec_t randomvel);
void CL_ParticleRain (const vec3_t mins, const vec3_t maxs, const vec3_t dir, int count, int colorbase, int type);
void R_MoveExplosions(void);
void R_NewExplosion(const vec3_t org);
+void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth);
+void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a);
+void Debug_PolygonEnd(void);
+
#include "cl_screen.h"
extern qboolean sb_showscores;
#define NUMCROSSHAIRS 32
extern cachepic_t *r_crosshairs[NUMCROSSHAIRS+1];
-#define FOGTABLEWIDTH 1024
-extern int fogtableindex;
-#define VERTEXFOGTABLE(dist) (fogtableindex = (int)((dist) * r_refdef.fogtabledistmultiplier), r_refdef.fogtable[bound(0, fogtableindex, FOGTABLEWIDTH - 1)])
+float FogPoint_World(const vec3_t p);
+float FogPoint_Model(const vec3_t p);
typedef struct r_refdef_stats_s
{
int maxentities;
// renderable dynamic lights
- dlight_t *lights[MAX_DLIGHTS];
+ rtlight_t lights[MAX_DLIGHTS];
int numlights;
// 8.8bit fixed point intensities for light styles
vec3_t fogcolor;
vec_t fogrange;
vec_t fograngerecip;
- vec_t fogtabledistmultiplier;
- float fogtable[FOGTABLEWIDTH];
+ vec_t fogmasktabledistmultiplier;
+#define FOGMASKTABLEWIDTH 1024
+ float fogmasktable[FOGMASKTABLEWIDTH];
float fog_density;
float fog_red;
float fog_green;
vec3_t up;
mplane_t frustum[5];
float frustum_x, frustum_y;
+ vec3_t frustumcorner[4];
// screen area to render in
int x;