25 Mar 2012

This commit is contained in:
g-cont 2012-03-25 00:00:00 +04:00 committed by Alibek Omarov
parent 48f7021630
commit c7644f243c
29 changed files with 606 additions and 348 deletions

View File

@ -1,6 +1,15 @@
build ????
Physic: fix trace bug when model is missing
Client: implement function TriScreenToWorld
Server: add local times for all the clients
Server: implement unlag system
Client: added ex_interp variable
GameUI: added support for playermodel images (preview thumbnails)
Engine: fix potentially crash in menu after calling Host_Error
Engine: fix crash on Cry Of Fear modification (memory corrupts)
Engine: first implementation of HLTV
Render: fix a little bug with engine mirrors
build 1850

View File

@ -1091,6 +1091,16 @@ void CL_FreeEdicts( void )
clgame.numStatics = 0;
}
void CL_ClearEdicts( void )
{
if( clgame.entities != NULL )
return;
// in case we stopped with error
clgame.maxEntities = 2;
CL_InitEdicts();
}
/*
===============================================================================
CGame Builtin Functions
@ -1958,8 +1968,8 @@ pfnIsSpectateOnly
*/
static int pfnIsSpectateOnly( void )
{
// TODO: check for proxie
return 0;
cl_entity_t *pPlayer = CL_GetLocalPlayer();
return (pPlayer->curstate.spectator != 0);
}
/*

View File

@ -43,6 +43,7 @@ convar_t *cl_idealpitchscale;
convar_t *cl_solid_players;
convar_t *cl_draw_beams;
convar_t *cl_cmdrate;
convar_t *cl_interp;
//
// userinfo
@ -52,6 +53,7 @@ convar_t *model;
convar_t *topcolor;
convar_t *bottomcolor;
convar_t *rate;
convar_t *hltv;
client_t cl;
client_static_t cls;
@ -275,6 +277,8 @@ void CL_CreateCmd( void )
// never let client.dll calc frametime for player
// because is potential backdoor for cheating
cmd.msec = ms;
cmd.lerp_msec = cl_interp->value * 1000;
cmd.lerp_msec = bound( 0, cmd.lerp_msec, 250 );
V_ProcessOverviewCmds( &cmd );
@ -1551,6 +1555,7 @@ void CL_InitLocal( void )
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0, "disable delta-compression for usercommnds" );
cl_idealpitchscale = Cvar_Get( "cl_idealpitchscale", "0.8", 0, "how much to look up/down slopes and stairs when not using freelook" );
cl_solid_players = Cvar_Get( "cl_solid_players", "1", 0, "Make all players not solid (can't traceline them)" );
cl_interp = Cvar_Get( "ex_interp", "0.1", 0, "Interpolate object positions starting this many seconds in past" );
cl_timeout = Cvar_Get( "cl_timeout", "60", 0, "connect timeout (in-seconds)" );
rcon_client_password = Cvar_Get( "rcon_password", "", 0, "remote control client password" );
@ -1563,6 +1568,7 @@ void CL_InitLocal( void )
topcolor = Cvar_Get( "topcolor", "0", CVAR_USERINFO|CVAR_ARCHIVE, "player top color" );
bottomcolor = Cvar_Get( "bottomcolor", "0", CVAR_USERINFO|CVAR_ARCHIVE, "player bottom color" );
rate = Cvar_Get( "rate", "25000", CVAR_USERINFO|CVAR_ARCHIVE, "player network rate" );
hltv = Cvar_Get( "hltv", "0", CVAR_USERINFO|CVAR_LATCH, "HLTV mode" );
cl_showfps = Cvar_Get( "cl_showfps", "1", CVAR_ARCHIVE, "show client fps" );
cl_smooth = Cvar_Get ("cl_smooth", "0", CVAR_ARCHIVE, "smooth up stair climbing and interpolate position in multiplayer" );
cl_cmdbackup = Cvar_Get( "cl_cmdbackup", "10", CVAR_ARCHIVE, "how many additional history commands are sent" );
@ -1573,7 +1579,6 @@ void CL_InitLocal( void )
Cvar_Get( "hud_scale", "0", CVAR_ARCHIVE|CVAR_LATCH, "scale hud at current resolution" );
Cvar_Get( "skin", "", CVAR_USERINFO, "player skin" ); // XDM 3.3 want this cvar
Cvar_Get( "spectator", "0", CVAR_USERINFO|CVAR_ARCHIVE, "1 is enable spectator mode" );
Cvar_Get( "cl_updaterate", "60", CVAR_USERINFO|CVAR_ARCHIVE, "refresh rate of server messages" );
// these two added to shut up CS 1.5 about 'unknown' commands

View File

@ -518,13 +518,6 @@ void CL_ParseServerData( sizebuf_t *msg )
#endif
UI_SetActiveMenu( cl.background );
if( cl.playernum & 128 )
{
cl.spectator = true;
cl.playernum &= ~128;
}
else cl.spectator = false;
cl.refdef.viewentity = cl.playernum + 1; // always keep viewent an actual
menu.globals->maxClients = cl.maxclients;
@ -619,6 +612,8 @@ void CL_ParseClientData( sizebuf_t *msg )
// do this after all packets read for this frame?
cl.last_incoming_sequence = cls.netchan.incoming_sequence;
if( hltv->integer ) return; // clientdata for spectators ends here
to_cd = &frame->local.client;
to_wd = frame->local.weapondata;

View File

@ -702,7 +702,7 @@ void CL_SetupPMove( playermove_t *pmove, clientdata_t *cd, entity_state_t *state
pmove->waterjumptime = cd->waterjumptime;
pmove->dead = (cd->health <= 0.0f ) ? true : false;
pmove->deadflag = cd->deadflag;
pmove->spectator = cl.spectator;
pmove->spectator = (state->spectator != 0);
pmove->movetype = state->movetype;
pmove->onground = -1; // will be set by PM_ code
pmove->waterlevel = cd->waterlevel;

View File

@ -18,78 +18,6 @@ GNU General Public License for more details.
#include "gl_local.h"
#include "studio.h"
static void CL_PaletteHueReplace( byte *palSrc, int newHue, int start, int end )
{
float r, g, b;
float maxcol, mincol;
float hue, val, sat;
int i;
hue = (float)(newHue * ( 360.0f / 255 ));
for( i = start; i <= end; i++ )
{
r = palSrc[i*3+0];
g = palSrc[i*3+1];
b = palSrc[i*3+2];
maxcol = max( max( r, g ), b ) / 255.0f;
mincol = min( min( r, g ), b ) / 255.0f;
val = maxcol;
sat = (maxcol - mincol) / maxcol;
mincol = val * (1.0f - sat);
if( hue <= 120.0f )
{
b = mincol;
if( hue < 60 )
{
r = val;
g = mincol + hue * (val - mincol) / (120.0f - hue);
}
else
{
g = val;
r = mincol + (120.0f - hue) * (val - mincol) / hue;
}
}
else if( hue <= 240.0f )
{
r = mincol;
if( hue < 180.0f )
{
g = val;
b = mincol + (hue - 120.0f) * (val - mincol) / (240.0f - hue);
}
else
{
b = val;
g = mincol + (240.0f - hue) * (val - mincol) / (hue - 120.0f);
}
}
else
{
g = mincol;
if( hue < 300.0f )
{
b = val;
r = mincol + (hue - 240.0f) * (val - mincol) / (360.0f - hue);
}
else
{
r = val;
b = mincol + (360.0f - hue) * (val - mincol) / (hue - 240.0f);
}
}
palSrc[i*3+0] = (byte)(r * 255);
palSrc[i*3+1] = (byte)(g * 255);
palSrc[i*3+2] = (byte)(b * 255);
}
}
/*
====================
CL_GetRemapInfoForEntity
@ -156,8 +84,8 @@ byte *CL_CreateRawTextureFromPixels( texture_t *tx, size_t *size, int topcolor,
// update palette
pal = (byte *)(tx + 1) + (tx->width * tx->height);
CL_PaletteHueReplace( pal, topcolor, tx->anim_min, tx->anim_max );
CL_PaletteHueReplace( pal, bottomcolor, tx->anim_max + 1, tx->anim_total );
Image_PaletteHueReplace( pal, topcolor, tx->anim_min, tx->anim_max );
Image_PaletteHueReplace( pal, bottomcolor, tx->anim_max + 1, tx->anim_total );
return (byte *)&pin;
}

View File

@ -57,7 +57,7 @@ void V_SetupRefDef( void )
cl.refdef.waterlevel = cl.frame.local.client.waterlevel;
cl.refdef.onlyClientDraw = 0; // reset clientdraw
cl.refdef.hardware = true; // always true
cl.refdef.spectator = cl.spectator;
cl.refdef.spectator = (clent->curstate.spectator != 0);
cl.refdef.nextView = 0;
SCR_AddDirtyPoint( 0, 0 );

View File

@ -96,7 +96,6 @@ typedef struct
qboolean force_send_usercmd;
qboolean thirdperson;
qboolean spectator; // true for spectators
qboolean background; // not real game, just a background
uint checksum; // for catching cheater maps
@ -534,6 +533,7 @@ extern convar_t *cl_showfps;
extern convar_t *cl_envshot_size;
extern convar_t *cl_timeout;
extern convar_t *cl_nodelta;
extern convar_t *cl_interp;
extern convar_t *cl_crosshair;
extern convar_t *cl_testlights;
extern convar_t *cl_solid_players;
@ -549,6 +549,7 @@ extern convar_t *scr_download;
extern convar_t *scr_loading;
extern convar_t *scr_dark; // start from dark
extern convar_t *userinfo;
extern convar_t *hltv;
//=============================================================================

View File

@ -905,10 +905,10 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag
tex->flags &= ~TF_MAKELUMA;
}
if( tex->flags & TF_KEEP_8BIT )
if( !subImage && tex->flags & TF_KEEP_8BIT )
tex->original = FS_CopyImage( pic ); // because current pic will be expanded to rgba
if( tex->flags & TF_KEEP_RGBDATA )
if( !subImage && tex->flags & TF_KEEP_RGBDATA )
tex->original = pic; // no need to copy
// we need to expand image into RGBA buffer
@ -1250,30 +1250,40 @@ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor )
{
gltexture_t *image;
rgbdata_t *pic;
byte *buf;
int flags = 0;
ASSERT( texnum > 0 && texnum < MAX_TEXTURES );
image = &r_textures[texnum];
// select mode
if( gamma != -1.0f )
{
flags = IMAGE_LIGHTGAMMA;
}
else if( topColor != -1 && bottomColor != -1 )
{
flags = IMAGE_REMAP;
}
else
{
MsgDev( D_ERROR, "GL_ProcessTexture: bad operation for %s\n", image->name );
return;
}
if(!( image->flags & (TF_KEEP_RGBDATA|TF_KEEP_8BIT)) || !image->original )
{
MsgDev( D_ERROR, "GL_ProcessTexture: no input data for %s\n", image->name );
return;
}
pic = image->original;
buf = Mem_Alloc( r_temppool, pic->size );
Q_memcpy( buf, pic->buffer, pic->size );
// UNDONE: topColor and bottomColor just for future expansions
Image_Process( &pic, topColor, bottomColor, gamma, IMAGE_LIGHTGAMMA );
// all the operations makes over the image copy not an original
pic = FS_CopyImage( image->original );
Image_Process( &pic, topColor, bottomColor, gamma, flags );
GL_UploadTexture( pic, image, true );
GL_TexFilter( image, true ); // update texture filter, wrap etc
// restore original image
Q_memcpy( pic->buffer, buf, pic->size );
Mem_Free( buf );
FS_FreeImage( pic );
}
/*

View File

@ -245,13 +245,21 @@ void R_DrawMirrors( void )
RI.refdef.viewangles[1] = anglemod( angles[1] );
RI.refdef.viewangles[2] = anglemod( angles[2] );
VectorCopy( origin, RI.refdef.vieworg );
#if 0
// put pvsorigin before the mirror plane to avoid get full visibility on world mirrors
if( RI.currententity == clgame.entities ) VectorMA( es->origin, 5.0f, plane.normal, origin );
#endif
VectorCopy( origin, RI.pvsorigin );
VectorCopy( origin, RI.cullorigin );
// put pvsorigin before the mirror plane to avoid get full visibility on world mirrors
if( RI.currententity == clgame.entities )
{
VectorMA( es->origin, 1.0f, plane.normal, origin );
}
else
{
Matrix4x4_VectorTransform( mirrormatrix, es->origin, origin );
VectorMA( origin, 1.0f, plane.normal, origin );
}
VectorCopy( origin, RI.pvsorigin );
// combine two leafs from client and mirror views
r_viewleaf = Mod_PointInLeaf( oldRI.pvsorigin, cl.worldmodel->nodes );
r_viewleaf2 = Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes );

View File

@ -1183,6 +1183,9 @@ void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld )
tr.realframecount++;
if( RI.drawOrtho != gl_overview->integer )
tr.fResetVis = true;
// completely override rendering
if( clgame.drawFuncs.GL_RenderFrame != NULL )
{

View File

@ -457,7 +457,9 @@ StudioPlayerBlend
void R_StudioPlayerBlend( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch )
{
// calc up/down pointing
*pBlend = (*pPitch * 3);
if( RI.params & RP_MIRRORVIEW )
*pBlend = (*pPitch * -6);
else *pBlend = (*pPitch * 3);
if( *pBlend < pseqdesc->blendstart[0] )
{
@ -2795,8 +2797,9 @@ R_StudioDrawPlayer
static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
{
int m_nPlayerIndex;
float gaitframe, gaityaw;
vec3_t dir, prevgaitorigin;
alight_t lighting;
vec3_t dir;
m_nPlayerIndex = pplayer->number - 1;
@ -2809,6 +2812,15 @@ static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
R_StudioSetHeader((studiohdr_t *)Mod_Extradata( RI.currentmodel ));
if( !RP_NORMALPASS() )
{
m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex );
VectorCopy( m_pPlayerInfo->prevgaitorigin, prevgaitorigin );
gaitframe = m_pPlayerInfo->gaitframe;
gaityaw = m_pPlayerInfo->gaityaw;
m_pPlayerInfo = NULL;
}
if( pplayer->gaitsequence )
{
vec3_t orig_angles;
@ -2845,7 +2857,18 @@ static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
{
// see if the bounding box lets us trivially reject, also sets
if( !R_StudioCheckBBox( ))
{
if( !RP_NORMALPASS() )
{
m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex );
VectorCopy( prevgaitorigin, m_pPlayerInfo->prevgaitorigin );
m_pPlayerInfo->gaitframe = gaitframe;
m_pPlayerInfo->gaityaw = gaityaw;
m_pPlayerInfo = NULL;
}
return 0;
}
r_stats.c_studio_models_drawn++;
g_nStudioCount++; // render data cache cookie
@ -2926,6 +2949,16 @@ static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
*RI.currententity = saveent;
}
}
if( !RP_NORMALPASS() )
{
m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex );
VectorCopy( prevgaitorigin, m_pPlayerInfo->prevgaitorigin );
m_pPlayerInfo->gaitframe = gaitframe;
m_pPlayerInfo->gaityaw = gaityaw;
m_pPlayerInfo = NULL;
}
return 1;
}

View File

@ -465,6 +465,7 @@ typedef enum
IMAGE_MAKE_LUMA = BIT(24), // create luma texture from indexed
IMAGE_QUANTIZE = BIT(25), // make indexed image from 24 or 32- bit image
IMAGE_LIGHTGAMMA = BIT(26), // apply gamma for image
IMAGE_REMAP = BIT(27), // interpret width and height as top and bottom color
} imgFlags_t;
typedef struct rgbdata_s
@ -491,6 +492,7 @@ rgbdata_t *FS_CopyImage( rgbdata_t *in );
void FS_FreeImage( rgbdata_t *pack );
extern const bpc_desc_t PFDesc[]; // image get pixelformat
qboolean Image_Process( rgbdata_t **pix, int width, int height, float gamma, uint flags );
void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end );
void Image_SetForceFlags( uint flags ); // set image force flags on loading
/*
@ -731,6 +733,7 @@ void SV_ForceError( void );
void CL_WriteMessageHistory( void );
void CL_SendCmd( void );
void CL_Disconnect( void );
void CL_ClearEdicts( void );
void CL_Crashed( void );
qboolean CL_NextDemo( void );
void CL_Drop( void );

View File

@ -535,6 +535,9 @@ void Host_Error( const char *error, ... )
SV_Shutdown( false );
CL_Drop(); // drop clients
// recreate world if needs
CL_ClearEdicts ();
// release all models
Mod_ClearAll();

View File

@ -236,6 +236,7 @@ extern imglib_t image;
void Image_RoundDimensions( int *scaled_width, int *scaled_height );
byte *Image_ResampleInternal( const void *indata, int in_w, int in_h, int out_w, int out_h, int intype, qboolean *done );
byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int type, int flags );
void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end );
void Image_FreeImage( rgbdata_t *pack );
void Image_Save( const char *filename, rgbdata_t *pix );
rgbdata_t *Image_Load(const char *filename, const byte *buffer, size_t buffsize );

View File

@ -352,7 +352,7 @@ qboolean Image_SaveBMP( const char *name, rgbdata_t *pix )
if( host.write_to_clipboard )
{
// NOTE: the cbPalyBytes may be 0
// NOTE: the cbPalBytes may be 0
total_size = sizeof( bmih ) + cbPalBytes + cbBmpBits;
clipbuf = Z_Malloc( total_size );
cur_size = 0;

View File

@ -15,6 +15,7 @@ GNU General Public License for more details.
#include "imagelib.h"
#include "mathlib.h"
#include "mod_local.h"
convar_t *gl_round_down;
@ -397,6 +398,78 @@ void Image_CopyPalette32bit( void )
Q_memcpy( image.palette, image.d_currentpal, 1024 );
}
void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end )
{
float r, g, b;
float maxcol, mincol;
float hue, val, sat;
int i;
hue = (float)(newHue * ( 360.0f / 255 ));
for( i = start; i <= end; i++ )
{
r = palSrc[i*3+0];
g = palSrc[i*3+1];
b = palSrc[i*3+2];
maxcol = max( max( r, g ), b ) / 255.0f;
mincol = min( min( r, g ), b ) / 255.0f;
val = maxcol;
sat = (maxcol - mincol) / maxcol;
mincol = val * (1.0f - sat);
if( hue <= 120.0f )
{
b = mincol;
if( hue < 60 )
{
r = val;
g = mincol + hue * (val - mincol) / (120.0f - hue);
}
else
{
g = val;
r = mincol + (120.0f - hue) * (val - mincol) / hue;
}
}
else if( hue <= 240.0f )
{
r = mincol;
if( hue < 180.0f )
{
g = val;
b = mincol + (hue - 120.0f) * (val - mincol) / (240.0f - hue);
}
else
{
b = val;
g = mincol + (240.0f - hue) * (val - mincol) / (hue - 120.0f);
}
}
else
{
g = mincol;
if( hue < 300.0f )
{
b = val;
r = mincol + (hue - 240.0f) * (val - mincol) / (360.0f - hue);
}
else
{
r = val;
b = mincol + (360.0f - hue) * (val - mincol) / (hue - 240.0f);
}
}
palSrc[i*3+0] = (byte)(r * 255);
palSrc[i*3+1] = (byte)(g * 255);
palSrc[i*3+2] = (byte)(b * 255);
}
}
void Image_CopyParms( rgbdata_t *src )
{
Image_Reset();
@ -1245,6 +1318,34 @@ rgbdata_t *Image_LightGamma( rgbdata_t *pic, float texGamma )
return pic;
}
qboolean Image_RemapInternal( rgbdata_t *pic, int topColor, int bottomColor )
{
switch( pic->type )
{
case PF_INDEXED_24:
break;
case PF_INDEXED_32:
Image_ConvertPalTo24bit( pic );
break;
default:
MsgDev( D_ERROR, "Image_Remap: unsupported format %s\n", PFDesc[pic->type].name );
return false;
}
if( !pic->palette )
{
MsgDev( D_ERROR, "Image_Remap: palette is missed\n" );
return false;
}
// just change palette and decompress to RGBA buffer
// g-cont. preview images has a swapped top and bottom colors. I don't know why.
Image_PaletteHueReplace( pic->palette, topColor, SUIT_HUE_START, SUIT_HUE_END );
Image_PaletteHueReplace( pic->palette, bottomColor, PLATE_HUE_START, PLATE_HUE_END );
return true;
}
qboolean Image_Process( rgbdata_t **pix, int width, int height, float gamma, uint flags )
{
rgbdata_t *pic = *pix;
@ -1273,6 +1374,13 @@ qboolean Image_Process( rgbdata_t **pix, int width, int height, float gamma, uin
pic->flags &= ~IMAGE_HAS_LUMA;
}
if( flags & IMAGE_REMAP )
{
// NOTE: user should keep copy of indexed image manually for new changes
if( Image_RemapInternal( pic, width, height ))
pic = Image_DecompressInternal( pic );
}
// update format to RGBA if any
if( flags & IMAGE_FORCE_RGBA ) pic = Image_DecompressInternal( pic );
if( flags & IMAGE_LIGHTGAMMA ) pic = Image_LightGamma( pic, gamma );

View File

@ -153,6 +153,7 @@ typedef struct
clientdata_t clientdata;
weapon_data_t weapondata[MAX_WEAPONS];
byte sentinel[128]; // g-cont. The fucking Cry Of Fear a corrupt memory after the weapondata!!!
int num_entities;
int first_entity; // into the circular sv_packet_entities[]
} client_frame_t;
@ -170,7 +171,6 @@ typedef struct sv_client_s
qboolean local_weapons; // enable weapon predicting
qboolean lag_compensation; // enable lag compensation
qboolean hltv_proxy; // this is spectator proxy (hltv)
qboolean spectator; // this is spectator (not a real client)
netchan_t netchan;
int chokecount; // number of messages rate supressed
@ -309,7 +309,7 @@ typedef struct
movevars_t movevars; // curstate
movevars_t oldmovevars; // oldstate
playermove_t *pmove; // pmove state
sv_interp_t interp[32]; // interpolate clients
sv_interp_t interp[MAX_CLIENTS]; // interpolate clients
sv_pushed_t pushed[MAX_PUSHED_ENTS]; // no reason to keep array for all edicts
// 256 it should be enough for any game situation
@ -438,10 +438,11 @@ qboolean SV_InitPhysicsAPI( void );
void SV_CheckVelocity( edict_t *ent );
qboolean SV_CheckWater( edict_t *ent );
qboolean SV_RunThink( edict_t *ent );
void SV_FreeOldEntities( void );
qboolean SV_PlayerRunThink( edict_t *ent, float frametime, double time );
qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker ); // for EntityInSolid checks
void SV_Impact( edict_t *e1, trace_t *trace );
void SV_Impact( edict_t *e1, edict_t *e2, trace_t *trace );
qboolean SV_CanPushed( edict_t *ent );
void SV_FreeOldEntities( void );
void SV_CheckAllEnts( void );
//
@ -481,9 +482,7 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg );
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg );
edict_t *SV_FakeConnect( const char *netname );
void SV_ExecuteClientCommand( sv_client_t *cl, char *s );
void SV_PreRunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed );
void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed );
void SV_PostRunCmd( sv_client_t *cl );
qboolean SV_IsPlayerIndex( int idx );
void SV_InitClientMove( void );
void SV_UpdateServerInfo( void );
@ -564,6 +563,12 @@ int SV_LoadGameState( char const *level, qboolean createPlayers );
void SV_LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName );
void SV_InitSaveRestore( void );
//
// sv_pmove.c
//
void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin );
void SV_GetTrueMinMax( sv_client_t *cl, int edictnum, vec3_t mins, vec3_t maxs );
//
// sv_world.c
//

View File

@ -92,15 +92,14 @@ A connection request that did not come from the master
*/
void SV_DirectConnect( netadr_t from )
{
char *s, physinfo[512];
char physinfo[512];
char userinfo[MAX_INFO_STRING];
sv_client_t temp, *cl, *newcl;
edict_t *ent;
qboolean spectator = false;
int i, edictnum;
int qport, version;
int count = 0;
int challenge;
edict_t *ent;
version = Q_atoi( Cmd_Argv( 1 ));
if( version != PROTOCOL_VERSION )
@ -158,12 +157,6 @@ void SV_DirectConnect( netadr_t from )
newcl = &temp;
Q_memset( newcl, 0, sizeof( sv_client_t ));
// check for spectators
s = Info_ValueForKey( userinfo, "spectator" );
if( s && Q_strcmp( s, "0" ) && sv_maxclients->integer > 1 )
spectator = true;
// if there is already a slot for this ip, reuse it
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
@ -216,10 +209,7 @@ gotnewcl:
newcl->frames = (client_frame_t *)Z_Malloc( sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
newcl->userid = g_userid++; // create unique userid
newcl->authentication_method = 2;
#if 0
// g-cont. i'm don't know how spectators interact with server. disabled
newcl->spectator = spectator;
#endif
// get the game a chance to reject this connection or modify the userinfo
if( !( SV_ClientConnect( ent, userinfo )))
{
@ -390,9 +380,7 @@ void SV_DropClient( sv_client_t *drop )
}
// let the game known about client state
if( drop->spectator )
svgame.dllFuncs.pfnSpectatorDisconnect( drop->edict );
else svgame.dllFuncs.pfnClientDisconnect( drop->edict );
svgame.dllFuncs.pfnClientDisconnect( drop->edict );
// don't send to other clients
drop->edict->v.modelindex = 0;
@ -967,26 +955,20 @@ void SV_PutClientInServer( edict_t *ent )
if( !sv.loadgame )
{
client->hltv_proxy = Q_atoi( Info_ValueForKey( client->userinfo, "hltv" )) ? true : false;
if( client->hltv_proxy )
ent->v.flags |= FL_PROXY;
ent->v.flags |= FL_PROXY;
else ent->v.flags = 0;
if( client->spectator )
{
svgame.globals->time = sv.time;
svgame.dllFuncs.pfnSpectatorConnect( ent );
}
else
{
ent->v.netname = MAKE_STRING( client->name );
ent->v.netname = MAKE_STRING( client->name );
// fisrt entering
svgame.globals->time = sv.time;
svgame.dllFuncs.pfnClientPutInServer( ent );
// fisrt entering
svgame.globals->time = sv.time;
svgame.dllFuncs.pfnClientPutInServer( ent );
if( sv.background ) // don't attack player in background mode
ent->v.flags |= (FL_GODMODE|FL_NOTARGET);
}
if( sv.background ) // don't attack player in background mode
ent->v.flags |= (FL_GODMODE|FL_NOTARGET);
client->pViewEntity = NULL; // reset pViewEntity
@ -999,12 +981,6 @@ void SV_PutClientInServer( edict_t *ent )
}
else
{
if( client->hltv_proxy )
{
MsgDev( D_ERROR, "spectator mode doesn't work with saved game\n" );
return;
}
// enable dev-mode to prevent crash cheat-protecting from Invasion mod
if( ent->v.flags & (FL_GODMODE|FL_NOTARGET) && !Q_stricmp( GI->gamefolder, "invasion" ))
SV_ExecuteClientCommand( client, "test\n" );
@ -1110,7 +1086,7 @@ void SV_New_f( sv_client_t *cl )
BF_WriteLong( &cl->netchan.message, PROTOCOL_VERSION );
BF_WriteLong( &cl->netchan.message, svs.spawncount );
BF_WriteLong( &cl->netchan.message, sv.checksum );
BF_WriteByte( &cl->netchan.message, playernum|( cl->spectator ? 128 : 0 ));
BF_WriteByte( &cl->netchan.message, playernum );
BF_WriteByte( &cl->netchan.message, svgame.globals->maxClients );
BF_WriteWord( &cl->netchan.message, svgame.globals->maxEntities );
BF_WriteString( &cl->netchan.message, sv.name );
@ -1653,7 +1629,7 @@ void SV_Pause_f( sv_client_t *cl )
return;
}
if( cl->spectator )
if( cl->hltv_proxy )
{
SV_ClientPrintf( cl, PRINT_HIGH, "Spectators can not pause.\n" );
return;
@ -1741,7 +1717,6 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
cl->local_weapons = Q_atoi( Info_ValueForKey( cl->userinfo, "cl_lw" )) ? true : false;
cl->lag_compensation = Q_atoi( Info_ValueForKey( cl->userinfo, "cl_lc" )) ? true : false;
cl->hltv_proxy = Q_atoi( Info_ValueForKey( cl->userinfo, "hltv" )) ? true : false;
val = Info_ValueForKey( cl->userinfo, "cl_updaterate" );
@ -2066,27 +2041,21 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
{
while( net_drop > numbackup )
{
SV_PreRunCmd( cl, &cl->lastcmd, 0 );
SV_RunCmd( cl, &cl->lastcmd, 0 );
SV_PostRunCmd( cl );
net_drop--;
}
while( net_drop > 0 )
{
i = net_drop + newcmds - 1;
SV_PreRunCmd( cl, &cmds[i], cl->netchan.incoming_sequence - i );
SV_RunCmd( cl, &cmds[i], cl->netchan.incoming_sequence - i );
SV_PostRunCmd( cl );
net_drop--;
}
}
for( i = newcmds - 1; i >= 0; i-- )
{
SV_PreRunCmd( cl, &cmds[i], cl->netchan.incoming_sequence - i );
SV_RunCmd( cl, &cmds[i], cl->netchan.incoming_sequence - i );
SV_PostRunCmd( cl );
}
cl->lastcmd = cmds[0];

View File

@ -1386,6 +1386,7 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
edict_t *pClient;
vec3_t view;
float delta;
model_t *mod;
int i;
if( !SV_IsValidEdict( pEdict ))
@ -1405,7 +1406,17 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
if( !SV_ClientFromEdict( pClient, true ))
return svgame.edicts;
VectorAdd( pEdict->v.origin, pEdict->v.view_ofs, view );
mod = Mod_Handle( pEdict->v.modelindex );
if( mod && mod->type == mod_brush && !( mod->flags & MODEL_HAS_ORIGIN ))
{
// handle PVS origin for bmodels
VectorAverage( pEdict->v.mins, pEdict->v.maxs, view );
VectorAdd( view, pEdict->v.origin, view );
}
else
{
VectorAdd( pEdict->v.origin, pEdict->v.view_ofs, view );
}
if( pEdict->v.effects & EF_INVLIGHT )
view[2] -= 1.0f; // HACK for barnacle
@ -3304,6 +3315,7 @@ void pfnRunPlayerMove( edict_t *pClient, const float *v_angle, float fmove, floa
svs.currentPlayer = SV_ClientFromEdict( pClient, true );
svs.currentPlayerNum = (svs.currentPlayer - svs.clients);
svs.currentPlayer->timebase = (sv.time + host.frametime) - (msec / 1000.0f);
Q_memset( &cmd, 0, sizeof( cmd ));
if( v_angle ) VectorCopy( v_angle, cmd.viewangles );
@ -3316,9 +3328,7 @@ void pfnRunPlayerMove( edict_t *pClient, const float *v_angle, float fmove, floa
seed = Com_RandomLong( 0, 0x7fffffff ); // full range
SV_PreRunCmd( cl, &cmd, seed );
SV_RunCmd( cl, &cmd, seed );
SV_PostRunCmd( cl );
cl->lastcmd = cmd;
cl->lastcmd.buttons = 0; // avoid multiple fires on lag
@ -4047,12 +4057,11 @@ const char *pfnGetPlayerAuthId( edict_t *e )
=============
pfnSequenceGet
used by CS:CZ
used by CS:CZ (client stub)
=============
*/
void *pfnSequenceGet( const char *fileName, const char *entryName )
{
// UNDONE: no description
return NULL;
}
@ -4060,12 +4069,11 @@ void *pfnSequenceGet( const char *fileName, const char *entryName )
=============
pfnSequencePickSentence
used by CS:CZ
used by CS:CZ (client stub)
=============
*/
void *pfnSequencePickSentence( const char *groupName, int pickMethod, int *picked )
{
// UNDONE: no description
return NULL;
}
@ -4085,12 +4093,11 @@ int pfnGetFileSize( char *filename )
=============
pfnIsCareerMatch
used by CS:CZ
used by CS:CZ (client stub)
=============
*/
int pfnIsCareerMatch( void )
{
// UNDONE: no description
return 0;
}
@ -4098,11 +4105,11 @@ int pfnIsCareerMatch( void )
=============
pfnGetLocalizedStringLength
used by CS:CZ (client stub)
=============
*/
int pfnGetLocalizedStringLength( const char *label )
{
// UNDONE: no description
return 0;
}

View File

@ -380,7 +380,7 @@ void SV_DeactivateServer( void )
svgame.dllFuncs.pfnServerDeactivate();
for( i = 0; i < svgame.globals->maxClients; i++ )
for( i = 0; i < sv_maxclients->integer; i++ )
{
// release client frames
if( svs.clients[i].frames )

View File

@ -179,8 +179,42 @@ qboolean SV_RunThink( edict_t *ent )
svgame.dllFuncs.pfnThink( ent );
}
// if( ent->v.flags & FL_SPECTATOR )
// SV_FreeEdict( ent );
if( ent->v.flags & FL_SPECTATOR )
SV_FreeEdict( ent );
return !ent->free;
}
/*
=============
SV_PlayerRunThink
Runs thinking code if player time. There is some play in the exact time the think
function will be called, because it is called before any movement is done
in a frame. Not used for pushmove objects, because they must be exact.
Returns false if the entity removed itself.
=============
*/
qboolean SV_PlayerRunThink( edict_t *ent, float frametime, double time )
{
float thinktime;
if(!( ent->v.flags & (FL_KILLME|FL_DORMANT )))
{
thinktime = ent->v.nextthink;
if( thinktime <= 0.0f || thinktime > time + frametime )
return true;
if( thinktime > time )
thinktime = time;
ent->v.nextthink = 0.0f;
svgame.globals->time = thinktime;
svgame.dllFuncs.pfnThink( ent );
}
if( ent->v.flags & FL_KILLME )
SV_FreeEdict( ent );
return !ent->free;
}
@ -192,10 +226,8 @@ SV_Impact
Two entities have touched, so run their touch functions
==================
*/
void SV_Impact( edict_t *e1, trace_t *trace )
void SV_Impact( edict_t *e1, edict_t *e2, trace_t *trace )
{
edict_t *e2 = trace->ent;
svgame.globals->time = sv.time;
if(( e1->v.flags|e2->v.flags ) & FL_SPECTATOR )
@ -466,7 +498,7 @@ int SV_FlyMove( edict_t *ent, float time, trace_t *steptrace )
}
// run the impact function
SV_Impact( ent, &trace );
SV_Impact( ent, trace.ent, &trace );
// break if removed by the impact function
if( ent->free ) break;
@ -662,7 +694,8 @@ trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int
if( blocked ) *blocked = !VectorCompare( ent->v.origin, end ); // can't move full distance
// so we can run impact function afterwards.
if( SV_IsValidEdict( trace.ent )) SV_Impact( ent, &trace );
if( SV_IsValidEdict( trace.ent ))
SV_Impact( ent, trace.ent, &trace );
return trace;
}
@ -1500,7 +1533,7 @@ void SV_Physics_Step( edict_t *ent )
{
trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent );
if(( trace.fraction < 1.0f || trace.startsolid ) && SV_IsValidEdict( trace.ent ))
SV_Impact( ent, &trace );
SV_Impact( ent, trace.ent, &trace );
}
}
@ -1582,7 +1615,9 @@ static void SV_Physics_Entity( edict_t *ent )
break;
}
if( ent->v.flags & FL_KILLME )
// g-cont. don't alow free entities during loading because
// this produce a corrupted baselines
if( sv.state == ss_active && ent->v.flags & FL_KILLME )
SV_FreeEdict( ent );
}

View File

@ -30,20 +30,11 @@ void SV_ClearPhysEnts( void )
svgame.pmove->numphysent = 0;
}
void SV_CopyPmtraceToGlobal( pmtrace_t *trace )
void SV_ConvertPMTrace( trace_t *out, pmtrace_t *in, edict_t *ent )
{
svgame.globals->trace_allsolid = trace->allsolid;
svgame.globals->trace_startsolid = trace->startsolid;
svgame.globals->trace_fraction = trace->fraction;
svgame.globals->trace_plane_dist = trace->plane.dist;
svgame.globals->trace_flags = 0;
svgame.globals->trace_inopen = trace->inopen;
svgame.globals->trace_inwater = trace->inwater;
VectorCopy( trace->endpos, svgame.globals->trace_endpos );
VectorCopy( trace->plane.normal, svgame.globals->trace_plane_normal );
svgame.globals->trace_hitgroup = trace->hitgroup;
if( trace->ent == -1 ) svgame.globals->trace_ent = svgame.edicts;
else svgame.globals->trace_ent = EDICT_NUM( svgame.pmove->physents[trace->ent].info );
Q_memcpy( out, in, 48 ); // matched
out->hitgroup = in->hitgroup;
out->ent = ent;
}
qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
@ -53,11 +44,16 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
if( !mod ) return false;
pe->player = false;
pe->info = NUM_FOR_EDICT( ed );
VectorCopy( ed->v.origin, pe->origin );
VectorCopy( ed->v.angles, pe->angles );
if( ed->v.flags & ( FL_CLIENT|FL_FAKECLIENT ))
{
// client or bot
SV_GetTrueOrigin( svs.currentPlayer, (pe->info - 1), pe->origin );
Q_strncpy( pe->name, "player", sizeof( pe->name ));
pe->player = NUM_FOR_EDICT( ed );
pe->player = pe->info;
}
else
{
@ -90,10 +86,6 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
break;
}
pe->info = NUM_FOR_EDICT( ed );
VectorCopy( ed->v.origin, pe->origin );
VectorCopy( ed->v.angles, pe->angles );
pe->solid = ed->v.solid;
pe->rendermode = ed->v.rendermode;
pe->skin = ed->v.skin;
@ -127,6 +119,41 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
return true;
}
void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin )
{
if( !cl->local_weapons || !cl->lag_compensation || !sv_unlag->integer )
return;
// don't allow unlag in singleplayer
if( sv_maxclients->integer <= 1 ) return;
if( cl->state < cs_connected || edictnum < 0 || edictnum >= sv_maxclients->integer )
return;
if( !svgame.interp[edictnum].active || !svgame.interp[edictnum].moving )
return;
VectorCopy( svgame.interp[edictnum].newpos, origin );
}
void SV_GetTrueMinMax( sv_client_t *cl, int edictnum, vec3_t mins, vec3_t maxs )
{
if( !cl->local_weapons || !cl->lag_compensation || !sv_unlag->integer )
return;
// don't allow unlag in singleplayer
if( sv_maxclients->integer <= 1 ) return;
if( cl->state < cs_connected || edictnum < 0 || edictnum >= sv_maxclients->integer )
return;
if( !svgame.interp[edictnum].active || !svgame.interp[edictnum].moving )
return;
VectorCopy( svgame.interp[edictnum].mins, mins );
VectorCopy( svgame.interp[edictnum].maxs, maxs );
}
/*
====================
SV_AddLinksToPmove
@ -138,6 +165,7 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
{
link_t *l, *next;
edict_t *check, *pl;
vec3_t mins, maxs;
physent_t *pe;
pl = EDICT_NUM( svgame.pmove->player_index + 1 );
@ -180,7 +208,13 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
if( VectorIsNull( check->v.size )) continue;
if( !BoundsIntersect( pmove_mins, pmove_maxs, check->v.absmin, check->v.absmax ))
VectorCopy( check->v.absmin, mins );
VectorCopy( check->v.absmax, maxs );
if( check->v.flags & FL_CLIENT )
SV_GetTrueMinMax( svs.currentPlayer, ( NUM_FOR_EDICT( check ) - 1), mins, maxs ); // try to get interpolated values
if( !BoundsIntersect( pmove_mins, pmove_maxs, mins, maxs ))
continue;
if( svgame.pmove->numphysent < MAX_PHYSENTS )
@ -552,16 +586,17 @@ static void PM_CheckMovingGround( edict_t *ent, float frametime )
ent->v.flags &= ~FL_BASEVELOCITY;
}
static void SV_SetupPMove( playermove_t *pmove, edict_t *clent, usercmd_t *ucmd, const char *physinfo )
static void SV_SetupPMove( playermove_t *pmove, sv_client_t *cl, usercmd_t *ucmd, const char *physinfo )
{
vec3_t absmin, absmax;
edict_t *clent = cl->edict;
int i;
svgame.globals->frametime = (ucmd->msec * 0.001f);
pmove->player_index = NUM_FOR_EDICT( clent ) - 1;
pmove->multiplayer = (sv_maxclients->integer > 1) ? true : false;
pmove->time = sv.time; // probably never used
pmove->time = cl->timebase; // probably never used
VectorCopy( clent->v.origin, pmove->origin );
VectorCopy( clent->v.v_angle, pmove->angles );
VectorCopy( clent->v.v_angle, pmove->oldangles );
@ -607,7 +642,8 @@ static void SV_SetupPMove( playermove_t *pmove, edict_t *clent, usercmd_t *ucmd,
VectorCopy( clent->v.vuser3, pmove->vuser3 );
VectorCopy( clent->v.vuser4, pmove->vuser4 );
pmove->cmd = *ucmd; // setup current cmds
pmove->runfuncs = true;
Q_strncpy( pmove->physinfo, physinfo, MAX_INFO_STRING );
// setup physents
@ -630,8 +666,10 @@ static void SV_SetupPMove( playermove_t *pmove, edict_t *clent, usercmd_t *ucmd,
SV_AddLaddersToPmove( sv_areanodes, absmin, absmax );
}
static void SV_FinishPMove( playermove_t *pmove, edict_t *clent )
static void SV_FinishPMove( playermove_t *pmove, sv_client_t *cl )
{
edict_t *clent = cl->edict;
clent->v.teleport_time = pmove->waterjumptime;
VectorCopy( pmove->origin, clent->v.origin );
VectorCopy( pmove->view_ofs, clent->v.view_ofs );
@ -667,7 +705,9 @@ static void SV_FinishPMove( playermove_t *pmove, edict_t *clent )
VectorCopy( pmove->vuser4, clent->v.vuser4 );
if( svgame.pmove->onground == -1 )
{
clent->v.flags &= ~FL_ONGROUND;
}
else if( pmove->onground >= 0 && pmove->onground < pmove->numphysent )
{
clent->v.flags |= FL_ONGROUND;
@ -683,6 +723,11 @@ static void SV_FinishPMove( playermove_t *pmove, edict_t *clent )
clent->v.angles[ROLL] = clent->v.v_angle[ROLL];
clent->v.angles[YAW] = clent->v.v_angle[YAW];
}
SV_SetMinMaxSize( clent, pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull] );
// all next calls ignore footstep sounds
pmove->runfuncs = false;
}
entity_state_t *SV_FindEntInPack( int index, client_frame_t *frame )
@ -700,16 +745,16 @@ entity_state_t *SV_FindEntInPack( int index, client_frame_t *frame )
return NULL;
}
int SV_UnlagCheckTeleport( vec3_t old_pos, vec3_t new_pos )
qboolean SV_UnlagCheckTeleport( vec3_t old_pos, vec3_t new_pos )
{
int i;
for( i = 0; i < 3; i++ )
{
if( fabs( old_pos[i] - new_pos[i] ) > 50 )
return 1;
return true;
}
return 0;
return false;
}
void SV_SetupMoveInterpolant( sv_client_t *cl )
@ -719,7 +764,7 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
float latency, temp, lerpFrac;
client_frame_t *frame, *frame2;
entity_state_t *state, *lerpstate;
vec3_t tempvec, tempvec2;
vec3_t curpos, newpos;
sv_client_t *check;
sv_interp_t *lerp;
@ -727,19 +772,20 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
has_update = false;
// don't allow unlag in singleplayer
if( sv_maxclients->integer <= 1 ) return;
if( sv_maxclients->integer <= 1 || cl->state != cs_spawned )
return;
// unlag disabled by game request
if( !svgame.dllFuncs.pfnAllowLagCompensation() || !sv_unlag->integer )
return;
// unlag disabled for current client
if( cl->state != cs_spawned || !cl->lag_compensation )
if( !cl->local_weapons || !cl->lag_compensation )
return;
has_update = true;
for( i = 0, check = svs.clients; i < sv_maxclients->integer; i++, cl++ )
for( i = 0, check = svs.clients; i < sv_maxclients->integer; i++, check++ )
{
if( check->state != cs_spawned || check == cl )
continue;
@ -855,35 +901,69 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
if( !lerpstate )
{
tempvec[0] = state->origin[0];
tempvec[1] = state->origin[1];
tempvec[2] = state->origin[2];
VectorCopy( state->origin, curpos );
}
else
{
tempvec2[0] = lerpstate->origin[0] - state->origin[0];
tempvec2[1] = lerpstate->origin[1] - state->origin[1];
tempvec2[2] = lerpstate->origin[2] - state->origin[2];
VectorMA( state->origin, lerpFrac, tempvec2, tempvec );
VectorSubtract( lerpstate->origin, state->origin, newpos );
VectorMA( state->origin, lerpFrac, newpos, curpos );
}
VectorCopy( tempvec, lerp->curpos );
VectorCopy( tempvec, lerp->newpos );
VectorCopy( curpos, lerp->curpos );
VectorCopy( curpos, lerp->newpos );
if( !VectorCompare( tempvec, check->edict->v.origin ))
if( !VectorCompare( curpos, check->edict->v.origin ))
{
VectorCopy( tempvec, check->edict->v.origin );
VectorCopy( curpos, check->edict->v.origin );
SV_LinkEdict( check->edict, false );
lerp->moving = true;
}
}
}
void SV_PreRunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
void SV_RestoreMoveInterpolant( sv_client_t *cl )
{
svgame.pmove->runfuncs = true;
svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, random_seed );
sv_client_t *check;
sv_interp_t *oldlerp;
int i;
if( !has_update )
{
has_update = true;
return;
}
// don't allow unlag in singleplayer
if( sv_maxclients->integer <= 1 || cl->state != cs_spawned )
return;
// unlag disabled by game request
if( !svgame.dllFuncs.pfnAllowLagCompensation() || !sv_unlag->integer )
return;
// unlag disabled for current client
if( !cl->local_weapons || !cl->lag_compensation )
return;
for( i = 0, check = svs.clients; i < sv_maxclients->integer; i++, check++ )
{
if( check->state != cs_spawned || check == cl )
continue;
oldlerp = &svgame.interp[i];
if( VectorCompare( oldlerp->oldpos, oldlerp->newpos ))
continue; // they didn't actually move.
if( !oldlerp->moving || !oldlerp->active )
return;
if( VectorCompare( oldlerp->curpos, check->edict->v.origin ))
{
VectorCopy( oldlerp->oldpos, check->edict->v.origin );
SV_LinkEdict( check->edict, false );
}
}
}
/*
@ -893,10 +973,13 @@ SV_RunCmd
*/
void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
{
usercmd_t cmd;
edict_t *clent;
usercmd_t lastcmd;
edict_t *clent, *touch;
double frametime;
int i, oldmsec;
pmtrace_t *pmtrace;
trace_t trace;
vec3_t oldvel;
int oldmsec;
clent = cl->edict;
@ -911,23 +994,37 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
// chop up very long commands
if( ucmd->msec > 50 )
{
cmd = *ucmd;
lastcmd = *ucmd;
oldmsec = ucmd->msec;
cmd.msec = oldmsec / 2;
lastcmd.msec = oldmsec / 2;
SV_RunCmd( cl, &cmd, random_seed );
SV_RunCmd( cl, &lastcmd, random_seed );
cmd.msec = oldmsec / 2 + (oldmsec & 1); // give them back thier msec.
cmd.impulse = 0;
SV_RunCmd( cl, &cmd, random_seed );
lastcmd.msec = oldmsec / 2 + (oldmsec & 1); // give them back thier msec.
lastcmd.impulse = 0;
SV_RunCmd( cl, &lastcmd, random_seed );
return;
}
PM_CheckMovingGround( clent, ucmd->msec * 0.001f );
if( !cl->fakeclient )
{
SV_SetupMoveInterpolant( cl );
}
lastcmd = *ucmd;
svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, random_seed );
frametime = ucmd->msec * 0.001;
cl->timebase += frametime;
cl->last_movetime += frametime;
PM_CheckMovingGround( clent, frametime );
VectorCopy( clent->v.v_angle, svgame.pmove->oldangles ); // save oldangles
if( !clent->v.fixangle ) VectorCopy( ucmd->viewangles, clent->v.v_angle );
VectorClear( clent->v.clbasevelocity );
// copy player buttons
clent->v.button = ucmd->buttons;
if( ucmd->impulse ) clent->v.impulse = ucmd->impulse;
@ -938,101 +1035,54 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
SV_RefreshUserinfo();
}
if( clent->v.flags & FL_DUCKING )
SV_SetMinMaxSize( clent, svgame.pmove->player_mins[1], svgame.pmove->player_maxs[1] );
else SV_SetMinMaxSize( clent, svgame.pmove->player_mins[0], svgame.pmove->player_maxs[0] );
svgame.globals->time = cl->timebase;
svgame.dllFuncs.pfnPlayerPreThink( clent );
SV_PlayerRunThink( clent, frametime, cl->timebase );
if( !cl->spectator )
{
svgame.globals->time = sv.time + host.frametime;
svgame.dllFuncs.pfnPlayerPreThink( clent );
SV_RunThink( clent ); // clients cannot be deleted from map
// If conveyor, or think, set basevelocity, then send to client asap too.
if( !VectorIsNull( clent->v.basevelocity ))
VectorCopy( clent->v.basevelocity, clent->v.clbasevelocity );
}
if(( sv_maxclients->integer <= 1 ) && !CL_IsInGame( ) || ( clent->v.flags & FL_FROZEN ))
ucmd->msec = 0; // pause
// If conveyor, or think, set basevelocity, then send to client asap too.
if( !VectorIsNull( clent->v.basevelocity ))
VectorCopy( clent->v.basevelocity, clent->v.clbasevelocity );
// setup playermove state
SV_SetupPMove( svgame.pmove, clent, ucmd, cl->physinfo );
SV_SetupPMove( svgame.pmove, cl, ucmd, cl->physinfo );
// motor!
svgame.dllFuncs.pfnPM_Move( svgame.pmove, true );
// copy results back to client
SV_FinishPMove( svgame.pmove, clent );
if( !cl->spectator )
{
int i;
edict_t *touch;
SV_FinishPMove( svgame.pmove, cl );
// link into place and touch triggers
SV_LinkEdict( clent, true );
VectorCopy( clent->v.velocity, oldvel ); // save velocity
// link into place and touch triggers
SV_LinkEdict( clent, true );
VectorCopy( clent->v.velocity, oldvel ); // save velocity
svgame.globals->time = sv.time + host.frametime;
// touch other objects
for( i = 0; i < svgame.pmove->numtouch; i++ )
{
if( i == MAX_PHYSENTS ) break;
// touch other objects
for( i = 0; i < svgame.pmove->numtouch; i++ )
{
if( i == MAX_PHYSENTS ) break;
touch = EDICT_NUM( svgame.pmove->physents[svgame.pmove->touchindex[i].ent].info );
if( touch == clent ) continue;
pmtrace = &svgame.pmove->touchindex[i];
touch = EDICT_NUM( svgame.pmove->physents[pmtrace->ent].info );
if( touch == clent ) continue;
VectorCopy( svgame.pmove->touchindex[i].deltavelocity, clent->v.velocity );
if( touch->v.groupinfo && clent->v.groupinfo )
{
if(( svs.groupop == 0 && ( touch->v.groupinfo & clent->v.groupinfo )) == 0 ||
(svs.groupop == 1 && (touch->v.groupinfo & clent->v.groupinfo) != 0 ))
continue;
}
if( touch->v.solid != SOLID_NOT )
{
SV_CopyPmtraceToGlobal( &svgame.pmove->touchindex[i] );
svgame.dllFuncs.pfnTouch( touch, clent );
}
if( clent->v.solid != SOLID_NOT )
{
SV_CopyPmtraceToGlobal( &svgame.pmove->touchindex[i] );
svgame.dllFuncs.pfnTouch( clent, touch );
}
}
// restore velocity
VectorCopy( oldvel, clent->v.velocity );
VectorCopy( pmtrace->deltavelocity, clent->v.velocity );
SV_ConvertPMTrace( &trace, pmtrace, touch );
SV_Impact( touch, clent, &trace );
}
// restore velocity
VectorCopy( oldvel, clent->v.velocity );
svgame.pmove->numtouch = 0;
}
svgame.globals->time = cl->timebase;
svgame.globals->frametime = frametime;
/*
===========
SV_PostRunCmd
Done after running a player command.
===========
*/
void SV_PostRunCmd( sv_client_t *cl )
{
edict_t *clent;
clent = cl->edict;
if( !clent || clent->free ) return;
svgame.pmove->runfuncs = false; // all next calls ignore footstep sounds
// run post-think
if( cl->spectator )
svgame.dllFuncs.pfnSpectatorThink( clent );
else svgame.dllFuncs.pfnPlayerPostThink( clent );
svgame.dllFuncs.pfnPlayerPostThink( clent );
svgame.dllFuncs.pfnCmdEnd( clent );
svgame.globals->time = sv.time + host.frametime;
svgame.dllFuncs.pfnCmdEnd( cl->edict );
}
if( !cl->fakeclient )
{
SV_RestoreMoveInterpolant( cl );
}
}

View File

@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "ui_title_anim.h"
cvar_t *ui_precache;
cvar_t *ui_showmodels;
uiStatic_t uiStatic;
@ -1497,6 +1498,7 @@ void UI_Init( void )
{
// register our cvars and commands
ui_precache = CVAR_REGISTER( "ui_precache", "0", FCVAR_ARCHIVE );
ui_showmodels = CVAR_REGISTER( "ui_showmodels", "0", FCVAR_ARCHIVE );
Cmd_AddCommand( "menu_main", UI_Main_Menu );
Cmd_AddCommand( "menu_newgame", UI_NewGame_Menu );

View File

@ -313,6 +313,7 @@ void UI_PicButton_Draw( menuPicButton_s *item );
// Main menu interface
extern cvar_t *ui_precache;
extern cvar_t *ui_showmodels;
#define BACKGROUND_ROWS 3
#define BACKGROUND_COLUMNS 4

View File

@ -31,7 +31,8 @@ GNU General Public License for more details.
#define GetGameInfo (*g_engfuncs.pfnGetGameInfo)
#define CheckGameDll (*g_engfuncs.pfnCheckGameDll)
#define PIC_SetGamma( x, y ) (*g_engfuncs.pfnProcessImage)( x, y, 0, 0 )
#define PIC_SetGamma( x, y ) (*g_engfuncs.pfnProcessImage)( x, y, -1, -1 )
#define PIC_Remap( x, y, z ) (*g_engfuncs.pfnProcessImage)( x, -1.0f, y, z )
#define DRAW_LOGO (*g_engfuncs.pfnDrawLogo)
#define PRECACHE_LOGO( x ) (*g_engfuncs.pfnDrawLogo)( x, 0, 0, 0, 0 )
@ -87,6 +88,7 @@ inline HIMAGE PIC_Load( const char *szPicName, const byte *ucRawImage, long ulRa
#define CMD_ARGC (*g_engfuncs.pfnCmdArgc)
#define CMD_ARGV (*g_engfuncs.pfnCmdArgv)
#define Con_Printf (*g_engfuncs.Con_Printf)
#define Con_NPrintf (*g_engfuncs.Con_NPrintf)
#define GET_GAMES_LIST (*g_engfuncs.pfnGetGamesList)
#define BACKGROUND_TRACK (*g_engfuncs.pfnPlayBackgroundTrack)

View File

@ -36,10 +36,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ID_MAXCLIENTS 7
#define ID_HOSTNAME 8
#define ID_PASSWORD 9
#define ID_DEDICATED 10
#define ID_HLTV 10
#define ID_DEDICATED 11
#define ID_MSGBOX 11
#define ID_MSGTEXT 12
#define ID_MSGBOX 12
#define ID_MSGTEXT 13
#define ID_YES 130
#define ID_NO 131
@ -63,6 +64,7 @@ typedef struct
menuField_s maxClients;
menuField_s hostName;
menuField_s password;
menuCheckBox_s hltv;
menuCheckBox_s dedicatedServer;
// newgame prompt dialog
@ -96,6 +98,7 @@ static void UI_CreateGame_Begin( void )
CVAR_SET_FLOAT( "maxplayers", atoi( uiCreateGame.maxClients.buffer ));
CVAR_SET_STRING( "hostname", uiCreateGame.hostName.buffer );
CVAR_SET_STRING( "defaultmap", uiCreateGame.mapName[uiCreateGame.mapsList.curItem] );
CVAR_SET_FLOAT( "hltv", uiCreateGame.hltv.enabled );
// all done, start server
if( uiCreateGame.dedicatedServer.enabled )
@ -137,6 +140,7 @@ static void UI_PromptDialog( void )
uiCreateGame.hostName.generic.flags ^= QMF_INACTIVE;
uiCreateGame.password.generic.flags ^= QMF_INACTIVE;
uiCreateGame.dedicatedServer.generic.flags ^= QMF_INACTIVE;
uiCreateGame.hltv.generic.flags ^= QMF_INACTIVE;
uiCreateGame.mapsList.generic.flags ^= QMF_INACTIVE;
uiCreateGame.msgBox.generic.flags ^= QMF_HIDDEN;
@ -226,6 +230,7 @@ static void UI_CreateGame_Callback( void *self, int event )
switch( item->id )
{
case ID_HLTV:
case ID_DEDICATED:
if( event == QM_PRESSED )
((menuCheckBox_s *)self)->focusPic = UI_CHECKBOX_PRESSED;
@ -333,6 +338,15 @@ static void UI_CreateGame_Init( void )
uiCreateGame.dedicatedServer.generic.callback = UI_CreateGame_Callback;
uiCreateGame.dedicatedServer.generic.statusText = "faster, but you can't join the server from this machine";
uiCreateGame.hltv.generic.id = ID_HLTV;
uiCreateGame.hltv.generic.type = QMTYPE_CHECKBOX;
uiCreateGame.hltv.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW;
uiCreateGame.hltv.generic.name = "HLTV";
uiCreateGame.hltv.generic.x = 72;
uiCreateGame.hltv.generic.y = 635;
uiCreateGame.hltv.generic.callback = UI_CreateGame_Callback;
uiCreateGame.hltv.generic.statusText = "enable hltv mode in multiplayer";
uiCreateGame.hintMessage.generic.id = ID_TABLEHINT;
uiCreateGame.hintMessage.generic.type = QMTYPE_ACTION;
uiCreateGame.hintMessage.generic.flags = QMF_INACTIVE|QMF_SMALLFONT;
@ -441,6 +455,7 @@ static void UI_CreateGame_Init( void )
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.hostName );
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.password );
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.dedicatedServer );
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.hltv );
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.hintMessage );
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.mapsList );
UI_AddItem( &uiCreateGame.menu, (void *)&uiCreateGame.msgBox );

View File

@ -41,7 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ID_TOPCOLOR 7
#define ID_BOTTOMCOLOR 8
#define ID_HIMODELS 9
#define ID_SPECTATOR 10
#define ID_SHOWMODELS 10
#define MAX_PLAYERMODELS 100
@ -63,16 +63,18 @@ typedef struct
menuPicButton_s AdvOptions;
menuBitmap_s view;
menuCheckBox_s showModels;
menuCheckBox_s hiModels;
menuSlider_s topColor;
menuSlider_s bottomColor;
menuCheckBox_s spectator;
menuField_s name;
menuSpinControl_s model;
} uiPlayerSetup_t;
static uiPlayerSetup_t uiPlayerSetup;
static HIMAGE playerImage = 0; // keep actual
static char lastImage[256];
/*
=================
@ -154,8 +156,8 @@ static void UI_PlayerSetup_GetConfig( void )
if( CVAR_GET_FLOAT( "cl_himodels" ))
uiPlayerSetup.hiModels.enabled = 1;
if( CVAR_GET_FLOAT( "spectator" ))
uiPlayerSetup.spectator.enabled = 1;
if( CVAR_GET_FLOAT( "ui_showmodels" ))
uiPlayerSetup.showModels.enabled = 1;
}
/*
@ -170,7 +172,7 @@ static void UI_PlayerSetup_SetConfig( void )
CVAR_SET_FLOAT( "topcolor", (int)(uiPlayerSetup.topColor.curValue * 255 ));
CVAR_SET_FLOAT( "bottomcolor", (int)(uiPlayerSetup.bottomColor.curValue * 255 ));
CVAR_SET_FLOAT( "cl_himodels", uiPlayerSetup.hiModels.enabled );
CVAR_SET_FLOAT( "spectator", uiPlayerSetup.spectator.enabled );
CVAR_SET_FLOAT( "ui_showmodels", uiPlayerSetup.showModels.enabled );
}
/*
@ -181,6 +183,8 @@ UI_PlayerSetup_UpdateConfig
static void UI_PlayerSetup_UpdateConfig( void )
{
char path[256], name[256];
char newImage[256];
int topColor, bottomColor;
// see if the model has changed
if( stricmp( uiPlayerSetup.currentModel, uiPlayerSetup.models[(int)uiPlayerSetup.model.curValue] ))
@ -192,19 +196,62 @@ static void UI_PlayerSetup_UpdateConfig( void )
strcpy( name, uiPlayerSetup.models[(int)uiPlayerSetup.model.curValue] );
if( !stricmp( name, "player" ))
{
strcpy( path, "models/player.mdl" );
else sprintf( path, "models/player/%s/%s.mdl", name, name );
newImage[0] = '\0';
}
else
{
sprintf( path, "models/player/%s/%s.mdl", name, name );
sprintf( newImage, "models/player/%s/%s.bmp", name, name );
}
topColor = (int)(uiPlayerSetup.topColor.curValue * 255 );
bottomColor = (int)(uiPlayerSetup.bottomColor.curValue * 255 );
CVAR_SET_STRING( "model", uiPlayerSetup.currentModel );
CVAR_SET_FLOAT( "cl_himodels", uiPlayerSetup.hiModels.enabled );
CVAR_SET_FLOAT( "spectator", uiPlayerSetup.spectator.enabled );
CVAR_SET_FLOAT( "topcolor", (int)(uiPlayerSetup.topColor.curValue * 255 ));
CVAR_SET_FLOAT( "bottomcolor", (int)(uiPlayerSetup.bottomColor.curValue * 255 ));
CVAR_SET_FLOAT( "ui_showmodels", uiPlayerSetup.showModels.enabled );
CVAR_SET_FLOAT( "topcolor", topColor );
CVAR_SET_FLOAT( "bottomcolor", bottomColor );
// IMPORTANT: always set default model becuase we need to have something valid here
// if you wish draw your playermodel as normal studiomodel please change "models/player.mdl" to path
if( uiPlayerSetup.ent )
ENGINE_SET_MODEL( uiPlayerSetup.ent, "models/player.mdl" );
if( !ui_showmodels->value )
{
if( stricmp( lastImage, newImage ))
{
if( lastImage[0] && playerImage )
{
// release old image
// Con_NPrintf( 1, "release %s\n", lastImage );
PIC_Free( lastImage );
lastImage[0] = '\0';
playerImage = 0;
}
if( stricmp( name, "player" ))
{
sprintf( lastImage, "models/player/%s/%s.bmp", name, name );
playerImage = PIC_Load( lastImage, PIC_KEEP_8BIT ); // if present of course
// Con_NPrintf( 2, "loading %s[%i]\n", lastImage, playerImage );
}
else if( lastImage[0] && playerImage )
{
// Con_NPrintf( 1, "release %s\n", lastImage );
// release old image
PIC_Free( lastImage );
lastImage[0] = '\0';
playerImage = 0;
}
}
if( playerImage != 0 ) // update remap colors
PIC_Remap( playerImage, topColor, bottomColor );
}
}
/*
@ -219,7 +266,7 @@ static void UI_PlayerSetup_Callback( void *self, int event )
switch( item->id )
{
case ID_HIMODELS:
case ID_SPECTATOR:
case ID_SHOWMODELS:
if( event == QM_PRESSED )
((menuCheckBox_s *)self)->focusPic = UI_CHECKBOX_PRESSED;
else ((menuCheckBox_s *)self)->focusPic = UI_CHECKBOX_FOCUS;
@ -263,16 +310,24 @@ static void UI_PlayerSetup_Ownerdraw( void *self )
// draw the rectangle
UI_DrawRectangle( item->x, item->y, item->width, item->height, uiInputFgColor );
R_ClearScene ();
if( !ui_showmodels->value && playerImage != 0 )
{
PIC_Set( playerImage, 255, 255, 255, 255 );
PIC_Draw( item->x, item->y, item->width, item->height );
}
else
{
R_ClearScene ();
// update renderer timings
uiPlayerSetup.refdef.time = gpGlobals->time;
uiPlayerSetup.refdef.frametime = gpGlobals->frametime;
uiPlayerSetup.ent->curstate.body = 0; // clearing body each frame
// update renderer timings
uiPlayerSetup.refdef.time = gpGlobals->time;
uiPlayerSetup.refdef.frametime = gpGlobals->frametime;
uiPlayerSetup.ent->curstate.body = 0; // clearing body each frame
// draw the player model
R_AddEntity( ET_NORMAL, uiPlayerSetup.ent );
R_RenderFrame( &uiPlayerSetup.refdef );
// draw the player model
R_AddEntity( ET_NORMAL, uiPlayerSetup.ent );
R_RenderFrame( &uiPlayerSetup.refdef );
}
}
/*
@ -391,24 +446,24 @@ static void UI_PlayerSetup_Init( void )
uiPlayerSetup.bottomColor.maxValue = 1.0;
uiPlayerSetup.bottomColor.range = 0.05f;
uiPlayerSetup.showModels.generic.id = ID_SHOWMODELS;
uiPlayerSetup.showModels.generic.type = QMTYPE_CHECKBOX;
uiPlayerSetup.showModels.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW;
uiPlayerSetup.showModels.generic.name = "Show Player Models";
uiPlayerSetup.showModels.generic.x = 72;
uiPlayerSetup.showModels.generic.y = 380;
uiPlayerSetup.showModels.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.showModels.generic.statusText = "show 3D player models instead of preview thumbnails";
uiPlayerSetup.hiModels.generic.id = ID_HIMODELS;
uiPlayerSetup.hiModels.generic.type = QMTYPE_CHECKBOX;
uiPlayerSetup.hiModels.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW;
uiPlayerSetup.hiModels.generic.name = "High quality models";
uiPlayerSetup.hiModels.generic.x = 72;
uiPlayerSetup.hiModels.generic.y = 380;
uiPlayerSetup.hiModels.generic.y = 430;
uiPlayerSetup.hiModels.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.hiModels.generic.statusText = "show hi-res models in multiplayer";
uiPlayerSetup.spectator.generic.id = ID_SPECTATOR;
uiPlayerSetup.spectator.generic.type = QMTYPE_CHECKBOX;
uiPlayerSetup.spectator.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW;
uiPlayerSetup.spectator.generic.name = "Play as a spectator";
uiPlayerSetup.spectator.generic.x = 72;
uiPlayerSetup.spectator.generic.y = 430;
uiPlayerSetup.spectator.generic.callback = UI_PlayerSetup_Callback;
uiPlayerSetup.spectator.generic.statusText = "enable spectator mode in multiplayer";
UI_PlayerSetup_GetConfig();
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.background );
@ -422,8 +477,8 @@ static void UI_PlayerSetup_Init( void )
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.model );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.topColor );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.bottomColor );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.showModels );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.hiModels );
UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.spectator );
// setup render and actor
uiPlayerSetup.refdef.fov_x = 40;

View File

@ -73,7 +73,7 @@ static void UI_VidOptions_GetConfig( void )
uiVidOptions.gammaIntensity.curValue = RemapVal( CVAR_GET_FLOAT( "gamma" ), 1.8f, 3.0f, 0.0f, 1.0f );
PIC_SetGamma( uiVidOptions.hTestImage, CVAR_GET_FLOAT( "gamma" ));
}
else uiVidOptions.gammaIntensity.curValue = RemapVal( CVAR_GET_FLOAT( "gamma" ), 0.5f, 3.0f, 0.0f, 1.0f );
else uiVidOptions.gammaIntensity.curValue = RemapVal( CVAR_GET_FLOAT( "gamma" ), 0.5f, 2.3f, 0.0f, 1.0f );
if( CVAR_GET_FLOAT( "r_fastsky" ))
uiVidOptions.fastSky.enabled = 1;