14 Aug 2016
This commit is contained in:
parent
f0da5370cf
commit
e9889b21ca
|
@ -476,12 +476,22 @@ void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, floa
|
|||
else VectorCopy( angles, args.angles );
|
||||
|
||||
if( !origin || VectorIsNull( origin ))
|
||||
VectorCopy( cl.frame.client.origin, args.origin );
|
||||
{
|
||||
if( CL_IsPredicted( )) VectorCopy( cl.predicted.origin, args.origin );
|
||||
else VectorCopy( cl.frame.client.origin, args.origin );
|
||||
}
|
||||
else VectorCopy( origin, args.origin );
|
||||
|
||||
VectorCopy( cl.frame.client.velocity, args.velocity );
|
||||
args.ducking = (cl.frame.playerstate[cl.playernum].usehull == 1);
|
||||
// args.ducking = cl.frame.client.bInDuck;
|
||||
if( CL_IsPredicted( ))
|
||||
{
|
||||
VectorCopy( cl.predicted.velocity, args.velocity );
|
||||
args.ducking = (cl.predicted.usehull == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( cl.frame.client.velocity, args.velocity );
|
||||
args.ducking = cl.frame.client.bInDuck;
|
||||
}
|
||||
|
||||
args.fparam1 = fparam1;
|
||||
args.fparam2 = fparam2;
|
||||
|
|
|
@ -123,7 +123,7 @@ qboolean CL_FindInterpolationUpdates( cl_entity_t *ent, float targettime, positi
|
|||
|
||||
int CL_InterpolateModel( cl_entity_t *e )
|
||||
{
|
||||
position_history_t *ph0, *ph1;
|
||||
position_history_t *ph0 = NULL, *ph1 = NULL;
|
||||
vec3_t origin, angles, delta;
|
||||
float t, t1, t2, frac;
|
||||
int i;
|
||||
|
@ -131,13 +131,15 @@ int CL_InterpolateModel( cl_entity_t *e )
|
|||
VectorCopy( e->curstate.origin, e->origin );
|
||||
VectorCopy( e->curstate.angles, e->angles );
|
||||
|
||||
if( e->model == NULL || cl.maxclients <= 1 )
|
||||
if( !e->model || ( e->model->name[0] == '*' && !cl_bmodelinterp->integer ) || RP_LOCALCLIENT( e ) || cl.maxclients <= 1 )
|
||||
return 1;
|
||||
|
||||
if( cl.predicted.moving && cl.predicted.onground == e->index )
|
||||
return 1;
|
||||
|
||||
t = cl.time - cl_interp->value;
|
||||
|
||||
if( !CL_FindInterpolationUpdates( e, t, &ph0, &ph1, NULL ))
|
||||
return 0;
|
||||
CL_FindInterpolationUpdates( e, t, &ph0, &ph1, NULL );
|
||||
|
||||
if( ph0 == NULL || ph1 == NULL )
|
||||
return 0;
|
||||
|
@ -193,6 +195,36 @@ int CL_InterpolateModel( cl_entity_t *e )
|
|||
return 1;
|
||||
}
|
||||
|
||||
void CL_InterpolateMovingEntity( cl_entity_t *ent )
|
||||
{
|
||||
float d, f = 0.0f;
|
||||
int i;
|
||||
|
||||
// don't do it if the goalstarttime hasn't updated in a while.
|
||||
// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
|
||||
// was increased to 1.0 s., which is 2x the max lag we are accounting for.
|
||||
if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime ))
|
||||
f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime );
|
||||
|
||||
f = f - 1.0f;
|
||||
|
||||
ent->origin[0] += ( ent->origin[0] - ent->latched.prevorigin[0] ) * f;
|
||||
ent->origin[1] += ( ent->origin[1] - ent->latched.prevorigin[1] ) * f;
|
||||
ent->origin[2] += ( ent->origin[2] - ent->latched.prevorigin[2] ) * f;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
float ang1, ang2;
|
||||
|
||||
ang1 = ent->angles[i];
|
||||
ang2 = ent->latched.prevangles[i];
|
||||
d = ang1 - ang2;
|
||||
if( d > 180.0f ) d -= 360.0f;
|
||||
else if( d < -180.0f ) d += 360.0f;
|
||||
ent->angles[i] += d * f;
|
||||
}
|
||||
}
|
||||
|
||||
void CL_UpdateEntityFields( cl_entity_t *ent )
|
||||
{
|
||||
// parametric rockets code
|
||||
|
@ -218,7 +250,11 @@ void CL_UpdateEntityFields( cl_entity_t *ent )
|
|||
ent->angles[PITCH] = -ent->angles[PITCH] / 3.0f;
|
||||
|
||||
// make me lerp
|
||||
if( ent->model && ent->model->type == mod_brush && ent->curstate.animtime != 0.0f )
|
||||
if( ent->index == cl.predicted.onground && cl.predicted.moving )
|
||||
{
|
||||
CL_InterpolateMovingEntity( ent );
|
||||
}
|
||||
else if( ent->model && ent->model->type == mod_brush && ent->curstate.animtime != 0.0f)
|
||||
{
|
||||
float d, f = 0.0f;
|
||||
int i;
|
||||
|
@ -324,7 +360,7 @@ void CL_UpdateEntityFields( cl_entity_t *ent )
|
|||
}
|
||||
}
|
||||
|
||||
// move code from StudioSetupTransform here
|
||||
// moved code from StudioSetupTransform here
|
||||
if( host.features & ENGINE_COMPUTE_STUDIO_LERP )
|
||||
{
|
||||
ent->origin[0] += ( ent->curstate.origin[0] - ent->latched.prevorigin[0] ) * f;
|
||||
|
@ -516,10 +552,6 @@ void CL_WeaponAnim( int iAnim, int body )
|
|||
cl.weaponstarttime = 0;
|
||||
cl.weaponsequence = iAnim;
|
||||
|
||||
if( Host_IsLocalClient() || cl_predict->value || !cl_lw->value )
|
||||
view->curstate.modelindex = cl.frame.client.viewmodel;
|
||||
else view->curstate.modelindex = cl.predicted_viewmodel;
|
||||
|
||||
// anim is changed. update latchedvars
|
||||
if( iAnim != view->curstate.sequence )
|
||||
{
|
||||
|
@ -749,6 +781,8 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
|
|||
/*
|
||||
=================
|
||||
CL_FlushEntityPacket
|
||||
|
||||
Read and ignore whole entity packet.
|
||||
=================
|
||||
*/
|
||||
void CL_FlushEntityPacket( sizebuf_t *msg )
|
||||
|
@ -756,7 +790,6 @@ void CL_FlushEntityPacket( sizebuf_t *msg )
|
|||
int newnum;
|
||||
entity_state_t from, to;
|
||||
|
||||
MsgDev( D_INFO, "FlushEntityPacket()\n" );
|
||||
Q_memset( &from, 0, sizeof( from ));
|
||||
|
||||
cl.frames[cl.parsecountmod].valid = false;
|
||||
|
@ -1003,23 +1036,34 @@ CL_SetIdealPitch
|
|||
void CL_SetIdealPitch( void )
|
||||
{
|
||||
float angleval, sinval, cosval;
|
||||
vec3_t top, bottom;
|
||||
float z[MAX_FORWARD];
|
||||
float z[MAX_FORWARD], view_z;
|
||||
vec3_t top, bottom, origin;
|
||||
int i, j;
|
||||
int step, dir, steps;
|
||||
pmtrace_t tr;
|
||||
|
||||
if( !( cl.frame.client.flags & FL_ONGROUND ))
|
||||
return;
|
||||
|
||||
|
||||
if( CL_IsPredicted( ))
|
||||
{
|
||||
VectorCopy( cl.predicted.origin, origin );
|
||||
view_z = cl.predicted.viewofs[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( cl.frame.client.origin, origin );
|
||||
view_z = cl.frame.client.view_ofs[2];
|
||||
}
|
||||
|
||||
angleval = cl.frame.playerstate[cl.playernum].angles[YAW] * M_PI2 / 360.0f;
|
||||
SinCos( angleval, &sinval, &cosval );
|
||||
|
||||
for( i = 0; i < MAX_FORWARD; i++ )
|
||||
{
|
||||
top[0] = cl.frame.client.origin[0] + cosval * (i + 3.0f) * 12.0f;
|
||||
top[1] = cl.frame.client.origin[1] + sinval * (i + 3.0f) * 12.0f;
|
||||
top[2] = cl.frame.client.origin[2] + cl.frame.client.view_ofs[2];
|
||||
top[0] = origin[0] + cosval * (i + 3.0f) * 12.0f;
|
||||
top[1] = origin[1] + sinval * (i + 3.0f) * 12.0f;
|
||||
top[2] = origin[2] + view_z;
|
||||
|
||||
bottom[0] = top[0];
|
||||
bottom[1] = top[1];
|
||||
|
|
|
@ -1226,7 +1226,8 @@ HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags )
|
|||
// load new model
|
||||
if( CL_LoadHudSprite( name, &clgame.sprites[i], false, texFlags ))
|
||||
{
|
||||
clgame.sprites[i].needload = clgame.load_sequence;
|
||||
if( i < ( MAX_IMAGES - 1 ))
|
||||
clgame.sprites[i].needload = clgame.load_sequence;
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
|
@ -2217,6 +2218,8 @@ pfnLocalPlayerDucking
|
|||
*/
|
||||
int pfnLocalPlayerDucking( void )
|
||||
{
|
||||
if( CL_IsPredicted( ))
|
||||
return (cl.predicted.usehull == 1);
|
||||
return cl.frame.client.bInDuck;
|
||||
}
|
||||
|
||||
|
@ -2232,7 +2235,7 @@ void pfnLocalPlayerViewheight( float *view_ofs )
|
|||
if( !view_ofs ) return;
|
||||
|
||||
if( CL_IsPredicted( ))
|
||||
VectorCopy( cl.predicted_viewofs, view_ofs );
|
||||
VectorCopy( cl.predicted.viewofs, view_ofs );
|
||||
else VectorCopy( cl.frame.client.view_ofs, view_ofs );
|
||||
}
|
||||
|
||||
|
@ -2283,94 +2286,6 @@ physent_t *pfnGetPhysent( int idx )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnSetUpPlayerPrediction
|
||||
|
||||
FIXME: finalize
|
||||
=============
|
||||
*/
|
||||
void pfnSetUpPlayerPrediction( int dopred, int bIncludeLocalClient )
|
||||
{
|
||||
#if 0
|
||||
entity_state_t *playerstate = cl.frames[cl.parsecountmod].playerstate;
|
||||
predicted_player_t *player = cls.predicted_players;
|
||||
cl_entity_t *clent;
|
||||
int j, v12;
|
||||
|
||||
for( j = 0; j < MAX_CLIENTS; j++, player++, playerstate++ )
|
||||
{
|
||||
player->active = false;
|
||||
|
||||
if( playerstate->messagenum != cl.parsecount )
|
||||
continue; // not present this frame
|
||||
|
||||
if( !playerstate->modelindex )
|
||||
continue;
|
||||
|
||||
// special for EF_NODRAW and local client?
|
||||
if(( playerstate->effects & EF_NODRAW ) && !bIncludeLocalClient )
|
||||
{
|
||||
// don't include local player?
|
||||
if( cl.playernum != j )
|
||||
{
|
||||
player->active = true;
|
||||
player->movetype = playerstate->movetype;
|
||||
player->solid = playerstate->solid;
|
||||
player->usehull = playerstate->usehull;
|
||||
|
||||
clent = CL_EDICT_NUM( j + 1 );
|
||||
// CL_ComputePlayerOrigin( v9 );
|
||||
VectorCopy( clent->origin, player->origin );
|
||||
VectorCopy( clent->angles, player->angles );
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cl.playernum == j )
|
||||
continue;
|
||||
|
||||
player->active = true;
|
||||
player->movetype = playerstate->movetype;
|
||||
player->solid = playerstate->solid;
|
||||
player->usehull = playerstate->usehull;
|
||||
|
||||
v12 = 17080 * cl.parsecountmod + 340 * j;
|
||||
player->origin[0] = cl.frames[0].playerstate[0].origin[0] + v12;
|
||||
player->origin[1] = cl.frames[0].playerstate[0].origin[1] + v12;
|
||||
player->origin[2] = cl.frames[0].playerstate[0].origin[2] + v12;
|
||||
|
||||
player->angles[0] = cl.frames[0].playerstate[0].angles[0] + v12;
|
||||
player->angles[1] = cl.frames[0].playerstate[0].angles[1] + v12;
|
||||
player->angles[2] = cl.frames[0].playerstate[0].angles[2] + v12;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnPushPMStates
|
||||
|
||||
=============
|
||||
*/
|
||||
void pfnPushPMStates( void )
|
||||
{
|
||||
clgame.oldcount = clgame.pmove->numphysent;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnPopPMStates
|
||||
|
||||
=============
|
||||
*/
|
||||
void pfnPopPMStates( void )
|
||||
{
|
||||
clgame.pmove->numphysent = clgame.oldcount;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnSetTraceHull
|
||||
|
@ -2612,7 +2527,7 @@ const char *PlayerInfo_ValueForKey( int playerNum, const char *key )
|
|||
if(( playerNum > cl.maxclients ) || ( playerNum < 1 ))
|
||||
return NULL;
|
||||
|
||||
if(( cl.players[playerNum-1].name == NULL ) || (*(cl.players[playerNum-1].name) == 0 ))
|
||||
if( !cl.players[playerNum-1].name[0] )
|
||||
return NULL;
|
||||
|
||||
return Info_ValueForKey( cl.players[playerNum-1].userinfo, key );
|
||||
|
@ -3351,7 +3266,8 @@ TriForParams
|
|||
*/
|
||||
void TriFogParams( float flDensity, int iFogSkybox )
|
||||
{
|
||||
// TODO: implement
|
||||
RI.fogDensity = flDensity;
|
||||
RI.fogCustom = iFogSkybox;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3787,9 +3703,9 @@ static event_api_t gEventApi =
|
|||
pfnLocalPlayerBounds,
|
||||
pfnIndexFromTrace,
|
||||
pfnGetPhysent,
|
||||
pfnSetUpPlayerPrediction,
|
||||
pfnPushPMStates,
|
||||
pfnPopPMStates,
|
||||
CL_SetUpPlayerPrediction,
|
||||
CL_PushPMStates,
|
||||
CL_PopPMStates,
|
||||
CL_SetSolidPlayers,
|
||||
CL_SetTraceHull,
|
||||
CL_PlayerTrace,
|
||||
|
|
|
@ -30,7 +30,8 @@ GNU General Public License for more details.
|
|||
convar_t *rcon_client_password;
|
||||
convar_t *rcon_address;
|
||||
|
||||
convar_t *cl_smooth;
|
||||
convar_t *cl_nosmooth;
|
||||
convar_t *cl_smoothtime;
|
||||
convar_t *cl_timeout;
|
||||
convar_t *cl_predict;
|
||||
convar_t *cl_showfps;
|
||||
|
@ -38,6 +39,7 @@ convar_t *cl_nodelta;
|
|||
convar_t *cl_crosshair;
|
||||
convar_t *cl_cmdbackup;
|
||||
convar_t *cl_showerror;
|
||||
convar_t *cl_bmodelinterp;
|
||||
convar_t *cl_draw_particles;
|
||||
convar_t *cl_lightstyle_lerping;
|
||||
convar_t *cl_idealpitchscale;
|
||||
|
@ -305,27 +307,22 @@ void CL_CreateCmd( void )
|
|||
Q_memset( &cmd, 0, sizeof( cmd ));
|
||||
|
||||
// build list of all solid entities per next frame (exclude clients)
|
||||
CL_SetSolidEntities ();
|
||||
CL_SetSolidPlayers ( cl.playernum );
|
||||
CL_SetSolidEntities();
|
||||
CL_PushPMStates();
|
||||
CL_SetSolidPlayers( cl.playernum );
|
||||
|
||||
VectorCopy( cl.refdef.cl_viewangles, angles );
|
||||
VectorCopy( cl.frame.client.origin, cl.data.origin );
|
||||
VectorCopy( cl.refdef.cl_viewangles, cl.data.viewangles );
|
||||
cl.data.iWeaponBits = cl.frame.client.weapons;
|
||||
|
||||
if( cl.scr_fov < 1.0f || cl.scr_fov > 179.0f )
|
||||
cl.scr_fov = 90.0f; // reset to default
|
||||
cl.data.fov = cl.scr_fov;
|
||||
|
||||
clgame.dllFuncs.pfnUpdateClientData( &cl.data, cl.time );
|
||||
|
||||
// grab changes
|
||||
VectorCopy( cl.data.viewangles, cl.refdef.cl_viewangles );
|
||||
cl.frame.client.weapons = cl.data.iWeaponBits;
|
||||
cl.scr_fov = cl.data.fov;
|
||||
|
||||
if( cl.scr_fov < 1.0f || cl.scr_fov > 179.0f )
|
||||
cl.scr_fov = 90.0f; // reset to default
|
||||
if( clgame.dllFuncs.pfnUpdateClientData( &cl.data, cl.time ))
|
||||
{
|
||||
// grab changes if successful
|
||||
VectorCopy( cl.data.viewangles, cl.refdef.cl_viewangles );
|
||||
cl.scr_fov = cl.data.fov;
|
||||
}
|
||||
|
||||
// allways dump the first ten messages,
|
||||
// because it may contain leftover inputs
|
||||
|
@ -337,6 +334,8 @@ void CL_CreateCmd( void )
|
|||
cl.refdef.cmd = &cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].cmd;
|
||||
*cl.refdef.cmd = cmd;
|
||||
}
|
||||
|
||||
CL_PopPMStates();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -354,6 +353,7 @@ void CL_CreateCmd( void )
|
|||
|
||||
active = ( cls.state == ca_active && !cl.refdef.paused && !cls.demoplayback );
|
||||
clgame.dllFuncs.CL_CreateMove( cl.time - cl.oldtime, &pcmd->cmd, active );
|
||||
CL_PopPMStates();
|
||||
|
||||
R_LightForPoint( cl.frame.client.origin, &color, false, false, 128.0f );
|
||||
pcmd->cmd.lightlevel = (color.r + color.g + color.b) / 3;
|
||||
|
@ -523,7 +523,6 @@ void CL_WritePacket( void )
|
|||
for( i = numcmds - 1; i >= 0; i-- )
|
||||
{
|
||||
cmdnumber = ( cls.netchan.outgoing_sequence - i ) & CL_UPDATE_MASK;
|
||||
if( i == 0 ) cl.commands[cmdnumber].processedfuncs = true; // only last cmd allow to run funcs
|
||||
|
||||
to = cmdnumber;
|
||||
CL_WriteUsercmd( &buf, from, to );
|
||||
|
@ -722,7 +721,7 @@ void CL_Connect_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
Q_strncpy( server, Cmd_Argv( 1 ), sizeof( cls.servername ));
|
||||
Q_strncpy( server, Cmd_Argv( 1 ), sizeof( server ));
|
||||
|
||||
if( Host_ServerState())
|
||||
{
|
||||
|
@ -950,7 +949,7 @@ CL_InternetServers_f
|
|||
void CL_InternetServers_f( void )
|
||||
{
|
||||
netadr_t adr;
|
||||
char fullquery[512] = "\x31\xFF" "0.0.0.0:0\0" "\\gamedir\\";
|
||||
char fullquery[512] = "1\xFF" "0.0.0.0:0\0" "\\gamedir\\";
|
||||
|
||||
MsgDev( D_INFO, "Scanning for servers on the internet area...\n" );
|
||||
NET_Config( true ); // allow remote
|
||||
|
@ -958,9 +957,9 @@ void CL_InternetServers_f( void )
|
|||
if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ) )
|
||||
MsgDev( D_INFO, "Can't resolve adr: %s\n", MASTERSERVER_ADR );
|
||||
|
||||
Q_strcpy( &fullquery[21], GI->gamedir );
|
||||
Q_strcpy( &fullquery[22], GI->gamedir );
|
||||
|
||||
NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 22, fullquery, adr );
|
||||
NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 23, fullquery, adr );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1074,9 +1073,10 @@ Handle a reply from a info
|
|||
*/
|
||||
void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
|
||||
{
|
||||
char *s;
|
||||
char *s = BF_ReadString( msg );
|
||||
|
||||
s = BF_ReadString( msg );
|
||||
// more info about servers
|
||||
MsgDev( D_INFO, "Server: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( s, "gamedir" ));
|
||||
UI_AddServerToList( from, s );
|
||||
}
|
||||
|
||||
|
@ -1395,26 +1395,21 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||
// dropped the connection but it is still getting packets from us
|
||||
CL_Disconnect();
|
||||
}
|
||||
else if( msg->pData[0] == 0xFF && msg->pData[1] == 0xFF && msg->pData[2] == 0xFF && msg->pData[3] == 0xFF && msg->pData[4] == 0x66 && msg->pData[5] == 0x0A )
|
||||
else if( !Q_strcmp( c, "f" ))
|
||||
{
|
||||
dataoffset = 6;
|
||||
|
||||
while( 1 )
|
||||
// serverlist got from masterserver
|
||||
while( !msg->bOverflow )
|
||||
{
|
||||
servadr.type = NA_IP;
|
||||
Q_memcpy( servadr.ip, &msg->pData[dataoffset], sizeof(servadr.ip));
|
||||
servadr.port = *(word *)&msg->pData[dataoffset + 4];
|
||||
// 4 bytes for IP
|
||||
BF_ReadBytes( msg, servadr.ip, sizeof( servadr.ip ));
|
||||
// 2 bytes for Port
|
||||
servadr.port = BF_ReadShort( msg );
|
||||
|
||||
if( !servadr.port )
|
||||
break;
|
||||
|
||||
MsgDev( D_INFO, "Found server: %s\n", NET_AdrToString( servadr ));
|
||||
if( !servadr.port ) break;
|
||||
|
||||
NET_Config( true ); // allow remote
|
||||
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
|
||||
|
||||
dataoffset += 6;
|
||||
}
|
||||
}
|
||||
else if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
|
||||
|
@ -1670,13 +1665,15 @@ void CL_InitLocal( void )
|
|||
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_nosmooth = Cvar_Get( "cl_nosmooth", "0", CVAR_ARCHIVE, "disable smooth up stair climbing and interpolate position in multiplayer" );
|
||||
cl_smoothtime = Cvar_Get( "cl_smoothtime", "0.1", CVAR_ARCHIVE, "time to smooth up" );
|
||||
cl_cmdbackup = Cvar_Get( "cl_cmdbackup", "10", CVAR_ARCHIVE, "how many additional history commands are sent" );
|
||||
cl_cmdrate = Cvar_Get( "cl_cmdrate", "30", CVAR_ARCHIVE, "Max number of command packets sent to server per second" );
|
||||
cl_draw_particles = Cvar_Get( "cl_draw_particles", "1", CVAR_ARCHIVE, "Disable any particle effects" );
|
||||
cl_draw_beams = Cvar_Get( "cl_draw_beams", "1", CVAR_ARCHIVE, "Disable view beams" );
|
||||
cl_lightstyle_lerping = Cvar_Get( "cl_lightstyle_lerping", "0", CVAR_ARCHIVE, "enables animated light lerping (perfomance option)" );
|
||||
cl_showerror = Cvar_Get( "cl_showerror", "0", CVAR_ARCHIVE, "show prediction error" );
|
||||
cl_bmodelinterp = Cvar_Get( "cl_bmodelinterp", "1", CVAR_ARCHIVE, "enable bmodel interpolation" );
|
||||
|
||||
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
|
||||
|
|
|
@ -29,6 +29,120 @@ void CL_ClearPhysEnts( void )
|
|||
clgame.pmove->numphysent = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_PushPMStates
|
||||
|
||||
=============
|
||||
*/
|
||||
void CL_PushPMStates( void )
|
||||
{
|
||||
if( clgame.pushed )
|
||||
{
|
||||
MsgDev( D_ERROR, "PushPMStates called with pushed stack\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
clgame.oldphyscount = clgame.pmove->numphysent;
|
||||
clgame.oldviscount = clgame.pmove->numvisent;
|
||||
clgame.pushed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_PopPMStates
|
||||
|
||||
=============
|
||||
*/
|
||||
void CL_PopPMStates( void )
|
||||
{
|
||||
if( clgame.pushed )
|
||||
{
|
||||
clgame.pmove->numphysent = clgame.oldphyscount;
|
||||
clgame.pmove->numvisent = clgame.oldviscount;
|
||||
clgame.pushed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
MsgDev( D_ERROR, "PopPMStates called without stack\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_ComputePlayerOrigin
|
||||
|
||||
FIXME: implement
|
||||
=============
|
||||
*/
|
||||
void CL_ComputePlayerOrigin( cl_entity_t *clent )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_SetUpPlayerPrediction
|
||||
|
||||
=============
|
||||
*/
|
||||
void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient )
|
||||
{
|
||||
entity_state_t *state;
|
||||
predicted_player_t *player;
|
||||
cl_entity_t *clent;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < MAX_CLIENTS; i++ )
|
||||
{
|
||||
state = &cl.frames[cl.parsecountmod].playerstate[i];
|
||||
player = &cls.predicted_players[i];
|
||||
|
||||
player->active = false;
|
||||
|
||||
if( state->messagenum != cl.parsecount )
|
||||
continue; // not present this frame
|
||||
|
||||
if( !state->modelindex )
|
||||
continue;
|
||||
|
||||
clent = CL_GetEntityByIndex( i + 1 );
|
||||
|
||||
// special for EF_NODRAW and local client?
|
||||
if(( state->effects & EF_NODRAW ) && !bIncludeLocalClient )
|
||||
{
|
||||
// don't include local player?
|
||||
if( cl.playernum == i )
|
||||
continue;
|
||||
|
||||
player->active = true;
|
||||
player->movetype = state->movetype;
|
||||
player->solid = state->solid;
|
||||
player->usehull = state->usehull;
|
||||
|
||||
CL_ComputePlayerOrigin( clent );
|
||||
|
||||
VectorCopy( clent->origin, player->origin );
|
||||
VectorCopy( clent->angles, player->angles );
|
||||
}
|
||||
else
|
||||
{
|
||||
player->active = true;
|
||||
player->movetype = state->movetype;
|
||||
player->solid = state->solid;
|
||||
player->usehull = state->usehull;
|
||||
|
||||
// don't rewrite origin and angles of local client
|
||||
if( cl.playernum == i )
|
||||
continue;
|
||||
|
||||
VectorCopy( state->origin, player->origin );
|
||||
VectorCopy( state->angles, player->angles );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CL_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr )
|
||||
{
|
||||
ASSERT( tr != NULL );
|
||||
|
@ -211,25 +325,32 @@ pmove must be setup with world and solid entity hulls before calling
|
|||
*/
|
||||
void CL_SetSolidPlayers( int playernum )
|
||||
{
|
||||
int j;
|
||||
extern vec3_t player_mins;
|
||||
extern vec3_t player_maxs;
|
||||
entity_state_t *state;
|
||||
cl_entity_t *ent;
|
||||
physent_t *pe;
|
||||
int i;
|
||||
|
||||
if( !cl_solid_players->integer )
|
||||
return;
|
||||
|
||||
for( j = 0; j < cl.maxclients; j++ )
|
||||
for( i = 0; i < cl.maxclients; i++ )
|
||||
{
|
||||
// the player object never gets added
|
||||
if( j == playernum ) continue;
|
||||
if( i == playernum ) continue;
|
||||
|
||||
ent = CL_GetEntityByIndex( j + 1 );
|
||||
ent = CL_GetEntityByIndex( i + 1 );
|
||||
|
||||
if( !ent || !ent->player )
|
||||
continue; // not present this frame
|
||||
|
||||
state = cl.frames[cl.parsecountmod].playerstate + i;
|
||||
|
||||
if( state->effects & EF_NODRAW )
|
||||
continue; // skip invisible
|
||||
|
||||
if( !state->solid )
|
||||
continue; // not solid
|
||||
|
||||
pe = &clgame.pmove->physents[clgame.pmove->numphysent];
|
||||
if( CL_CopyEntityToPhysEnt( pe, ent ))
|
||||
clgame.pmove->numphysent++;
|
||||
|
@ -858,6 +979,10 @@ void CL_RunUsercmd( local_state_t *from, local_state_t *to, usercmd_t *u, qboole
|
|||
// copy results back to client
|
||||
CL_FinishPMove( clgame.pmove, to );
|
||||
|
||||
cl.predicted.lastground = clgame.pmove->onground;
|
||||
if( cl.predicted.lastground > 0 && cl.predicted.lastground < clgame.pmove->numphysent )
|
||||
cl.predicted.lastground = clgame.pmove->physents[cl.predicted.lastground].info;
|
||||
|
||||
clgame.dllFuncs.pfnPostRunCmd( from, to, &cmd, runfuncs, *time, random_seed );
|
||||
*time += (double)cmd.msec / 1000.0;
|
||||
}
|
||||
|
@ -879,26 +1004,30 @@ void CL_CheckPredictionError( void )
|
|||
frame = ( cls.netchan.incoming_acknowledged ) & CL_UPDATE_MASK;
|
||||
|
||||
// compare what the server returned with what we had predicted it to be
|
||||
VectorSubtract( cl.frame.playerstate[cl.playernum].origin, cl.predicted_origins[frame], delta );
|
||||
VectorSubtract( cl.frame.playerstate[cl.playernum].origin, cl.predicted.origins[frame], delta );
|
||||
|
||||
maxspd = ( clgame.movevars.maxvelocity * host.frametime );
|
||||
len = VectorLength( delta );
|
||||
|
||||
// save the prediction error for interpolation
|
||||
if(( cl.frame.client.flags & EF_NOINTERP ) || len > maxspd )
|
||||
// if(( cl.frame.client.flags & EF_NOINTERP ) || len > maxspd )
|
||||
if( len > 64.0f )
|
||||
{
|
||||
// a teleport or something or gamepaused
|
||||
VectorClear( cl.prediction_error );
|
||||
VectorClear( cl.predicted.error );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cl_showerror->value && len > 0.5f )
|
||||
MsgDev( D_ERROR, "prediction error on %i: %g\n", cl.parsecount, len );
|
||||
|
||||
VectorCopy( cl.frame.playerstate[cl.playernum].origin, cl.predicted_origins[frame] );
|
||||
VectorCopy( cl.frame.playerstate[cl.playernum].origin, cl.predicted.origins[frame] );
|
||||
|
||||
// save for error itnerpolation
|
||||
VectorCopy( delta, cl.prediction_error );
|
||||
// save for error interpolation
|
||||
VectorCopy( delta, cl.predicted.error );
|
||||
|
||||
if(( len > 0.25f ) && ( cl.maxclients > 1 ))
|
||||
cl.predicted.correction_time = cl_smoothtime->value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,7 +1042,9 @@ void CL_PostRunCmd( usercmd_t *ucmd, int random_seed )
|
|||
{
|
||||
local_state_t from, to;
|
||||
|
||||
memcpy( from.weapondata, cl.frame.weapondata, sizeof( from.weapondata ));
|
||||
Q_memset( &from, 0, sizeof( local_state_t ));
|
||||
Q_memset( &to, 0, sizeof( local_state_t ));
|
||||
Q_memcpy( from.weapondata, cl.frame.weapondata, sizeof( from.weapondata ));
|
||||
from.playerstate = cl.frame.playerstate[cl.playernum];
|
||||
from.client = cl.frame.client;
|
||||
to = from;
|
||||
|
@ -921,6 +1052,35 @@ void CL_PostRunCmd( usercmd_t *ucmd, int random_seed )
|
|||
clgame.dllFuncs.pfnPostRunCmd( &from, &to, ucmd, true, cl.time, random_seed );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_FakeUsercmd
|
||||
|
||||
Runs client weapons prediction code
|
||||
=================
|
||||
*/
|
||||
void CL_FakeUsercmd( local_state_t *from, local_state_t *to, usercmd_t *u, qboolean runfuncs, double *pfElapsed, unsigned int random_seed )
|
||||
{
|
||||
usercmd_t cmd;
|
||||
local_state_t temp;
|
||||
usercmd_t split;
|
||||
|
||||
while( u->msec > 50 )
|
||||
{
|
||||
split = *u;
|
||||
split.msec /= 2;
|
||||
CL_FakeUsercmd( from, &temp, &split, runfuncs, pfElapsed, random_seed );
|
||||
from = &temp;
|
||||
u = &split;
|
||||
}
|
||||
|
||||
cmd = *u;
|
||||
*to = *from;
|
||||
|
||||
clgame.dllFuncs.pfnPostRunCmd( from, to, &cmd, runfuncs, *pfElapsed, random_seed );
|
||||
*pfElapsed += cmd.msec / 1000.0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_PredictMovement
|
||||
|
@ -949,15 +1109,62 @@ void CL_PredictMovement( void )
|
|||
|
||||
if( !CL_IsInGame( )) return;
|
||||
|
||||
CL_SetUpPlayerPrediction( false, false );
|
||||
|
||||
// unpredicted pure angled values converted into axis
|
||||
AngleVectors( cl.refdef.cl_viewangles, cl.refdef.forward, cl.refdef.right, cl.refdef.up );
|
||||
|
||||
ASSERT( cl.refdef.cmd != NULL );
|
||||
|
||||
if( !CL_IsPredicted( ))
|
||||
{
|
||||
// run commands even if client predicting is disabled - client expected it
|
||||
CL_PostRunCmd( cl.refdef.cmd, cls.lastoutgoingcommand );
|
||||
{
|
||||
// fake prediction code
|
||||
// we need to perform cl_lw prediction while cl_predict is disabled
|
||||
// because cl_lw is enabled by default in Half-Life
|
||||
if( !cl_lw->integer )
|
||||
{
|
||||
cl.predicted.viewmodel = cl.frame.client.viewmodel;
|
||||
return;
|
||||
}
|
||||
|
||||
ack = cls.netchan.incoming_acknowledged;
|
||||
outgoing_command = cls.netchan.outgoing_sequence;
|
||||
|
||||
from = &cl.predict[cl.parsecountmod];
|
||||
from->playerstate = cl.frame.playerstate[cl.playernum];
|
||||
from->client = cl.frame.client;
|
||||
Q_memcpy( from->weapondata, cl.frame.weapondata, sizeof( from->weapondata ));
|
||||
|
||||
time = cl.frame.time;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
// we've run too far forward
|
||||
if( frame >= ( CL_UPDATE_BACKUP - 1 ))
|
||||
break;
|
||||
|
||||
// Incoming_acknowledged is the last usercmd the server acknowledged having acted upon
|
||||
current_command = ack + frame;
|
||||
current_command_mod = current_command & CL_UPDATE_MASK;
|
||||
|
||||
// we've caught up to the current command.
|
||||
if( current_command >= outgoing_command )
|
||||
break;
|
||||
|
||||
to = &cl.predict[( cl.parsecountmod + frame ) & CL_UPDATE_MASK];
|
||||
|
||||
CL_FakeUsercmd( from, to, &cl.commands[current_command_mod].cmd,
|
||||
!cl.commands[current_command_mod].processedfuncs,
|
||||
&time, cls.netchan.incoming_acknowledged + frame );
|
||||
|
||||
cl.commands[current_command_mod].processedfuncs = true;
|
||||
|
||||
from = to;
|
||||
frame++;
|
||||
}
|
||||
|
||||
if( to )
|
||||
cl.predicted.viewmodel = to->client.viewmodel;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -965,7 +1172,7 @@ void CL_PredictMovement( void )
|
|||
outgoing_command = cls.netchan.outgoing_sequence;
|
||||
|
||||
from = &cl.predict[cl.parsecountmod];
|
||||
memcpy( from->weapondata, cl.frame.weapondata, sizeof( from->weapondata ));
|
||||
Q_memcpy( from->weapondata, cl.frame.weapondata, sizeof( from->weapondata ));
|
||||
from->playerstate = cl.frame.playerstate[cl.playernum];
|
||||
from->client = cl.frame.client;
|
||||
|
||||
|
@ -996,7 +1203,7 @@ void CL_PredictMovement( void )
|
|||
cl.commands[current_command_mod].processedfuncs = true;
|
||||
|
||||
// save for debug checking
|
||||
VectorCopy( to->playerstate.origin, cl.predicted_origins[current_command_mod] );
|
||||
VectorCopy( to->playerstate.origin, cl.predicted.origins[current_command_mod] );
|
||||
|
||||
from = to;
|
||||
frame++;
|
||||
|
@ -1004,15 +1211,109 @@ void CL_PredictMovement( void )
|
|||
|
||||
if( to )
|
||||
{
|
||||
VectorCopy( to->playerstate.origin, cl.predicted_origin );
|
||||
VectorCopy( to->client.velocity, cl.predicted_velocity );
|
||||
VectorCopy( to->client.view_ofs, cl.predicted_viewofs );
|
||||
VectorCopy( to->client.punchangle, cl.predicted_punchangle );
|
||||
float t0 = cl.commands[( cl.parsecountmod + frame - 1) & CL_UPDATE_MASK].senttime;
|
||||
float t1 = cl.commands[( cl.parsecountmod + frame ) & CL_UPDATE_MASK].senttime;
|
||||
float t;
|
||||
|
||||
cl.predicted_viewmodel = to->client.viewmodel;
|
||||
cl.scr_fov = to->client.fov;
|
||||
if( t0 == t1 )
|
||||
{
|
||||
t = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (host.realtime - t0) / (t1 - t0);
|
||||
t = bound( 0.0f, t, 1.0f );
|
||||
}
|
||||
|
||||
if( cl.scr_fov < 1.0f || cl.scr_fov > 179.0f )
|
||||
cl.scr_fov = 90.0f;
|
||||
// was teleported
|
||||
if( fabs( to->playerstate.origin[0] - from->playerstate.origin[0] ) > 128.0f ||
|
||||
fabs( to->playerstate.origin[1] - from->playerstate.origin[1] ) > 128.0f ||
|
||||
fabs( to->playerstate.origin[2] - from->playerstate.origin[2] ) > 128.0f )
|
||||
{
|
||||
VectorCopy( to->playerstate.origin, cl.predicted.origin );
|
||||
VectorCopy( to->client.velocity, cl.predicted.velocity );
|
||||
VectorCopy( to->client.punchangle, cl.predicted.punchangle );
|
||||
VectorCopy( to->client.view_ofs, cl.predicted.viewofs );
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3_t delta_origin, delta_punch, delta_vel;
|
||||
|
||||
VectorSubtract( to->playerstate.origin, from->playerstate.origin, delta_origin );
|
||||
VectorSubtract( to->client.velocity, from->client.velocity, delta_vel );
|
||||
VectorSubtract( to->client.punchangle, from->client.punchangle, delta_punch );
|
||||
|
||||
VectorMA( from->playerstate.origin, t, delta_origin, cl.predicted.origin );
|
||||
VectorMA( from->client.velocity, t, delta_vel, cl.predicted.velocity );
|
||||
VectorMA( from->client.punchangle, t, delta_punch, cl.predicted.punchangle );
|
||||
|
||||
if( from->playerstate.usehull == to->playerstate.usehull )
|
||||
{
|
||||
vec3_t delta_viewofs;
|
||||
|
||||
VectorSubtract( to->client.view_ofs, from->client.view_ofs, delta_viewofs );
|
||||
VectorMA( from->client.view_ofs, t, delta_viewofs, cl.predicted.viewofs );
|
||||
}
|
||||
}
|
||||
|
||||
cl.predicted.waterlevel = to->client.waterlevel;
|
||||
cl.predicted.viewmodel = to->client.viewmodel;
|
||||
cl.predicted.usehull = to->playerstate.usehull;
|
||||
|
||||
if( to->client.flags & FL_ONGROUND )
|
||||
{
|
||||
cl_entity_t *ent = CL_GetEntityByIndex( cl.predicted.lastground );
|
||||
|
||||
cl.predicted.onground = cl.predicted.lastground;
|
||||
cl.predicted.moving = 0;
|
||||
|
||||
if( ent )
|
||||
{
|
||||
vec3_t delta;
|
||||
delta[0] = ent->curstate.origin[0] - ent->prevstate.origin[0];
|
||||
delta[1] = ent->curstate.origin[1] - ent->prevstate.origin[1];
|
||||
delta[2] = 0.0f;
|
||||
|
||||
if( VectorLength( delta ) > 0.0f )
|
||||
{
|
||||
cl.predicted.correction_time = 0;
|
||||
cl.predicted.moving = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cl.predicted.onground = -1;
|
||||
cl.predicted.moving = 0;
|
||||
}
|
||||
|
||||
if ( cl.predicted.correction_time > 0.0 && !cl_nosmooth->value && cl_smoothtime->value )
|
||||
{
|
||||
float d;
|
||||
int i;
|
||||
|
||||
cl.predicted.correction_time = cl.predicted.correction_time - host.frametime;
|
||||
|
||||
if( cl_smoothtime->value <= 0 )
|
||||
Cvar_SetFloat( "cl_smoothtime", 0.1 );
|
||||
|
||||
if( cl.predicted.correction_time < 0 )
|
||||
cl.predicted.correction_time = 0;
|
||||
|
||||
if( cl_smoothtime->value <= cl.predicted.correction_time )
|
||||
cl.predicted.correction_time = cl_smoothtime->value;
|
||||
|
||||
d = cl.predicted.correction_time / cl_smoothtime->value;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
cl.predicted.origin[i] = cl.predicted.lastorigin[i] + ( cl.predicted.origin[i] - cl.predicted.lastorigin[i] ) * (1.0 - d);
|
||||
}
|
||||
}
|
||||
|
||||
VectorCopy( cl.predicted.origin, cl.predicted.lastorigin );
|
||||
CL_SetIdealPitch();
|
||||
}
|
||||
|
||||
CL_CheckPredictionError();
|
||||
}
|
|
@ -527,7 +527,7 @@ void CL_Bubbles( const vec3_t mins, const vec3_t maxs, float height, int modelIn
|
|||
|
||||
pTemp->x = origin[0];
|
||||
pTemp->y = origin[1];
|
||||
angle = Com_RandomLong( -M_PI, M_PI );
|
||||
angle = Com_RandomFloat( -M_PI, M_PI );
|
||||
SinCos( angle, &sine, &cosine );
|
||||
|
||||
zspeed = Com_RandomLong( 80, 140 );
|
||||
|
@ -572,7 +572,7 @@ void CL_BubbleTrail( const vec3_t start, const vec3_t end, float flWaterZ, int m
|
|||
|
||||
pTemp->x = origin[0];
|
||||
pTemp->y = origin[1];
|
||||
angle = Com_RandomLong( -M_PI, M_PI );
|
||||
angle = Com_RandomFloat( -M_PI, M_PI );
|
||||
|
||||
zspeed = Com_RandomLong( 80, 140 );
|
||||
VectorSet( pTemp->entity.baseline.origin, speed * cos( angle ), speed * sin( angle ), zspeed );
|
||||
|
@ -2653,7 +2653,7 @@ int CL_DecalIndexFromName( const char *name )
|
|||
return 0;
|
||||
|
||||
// look through the loaded sprite name list for SpriteName
|
||||
for( i = 0; i < MAX_DECALS && host.draw_decals[i+1][0]; i++ )
|
||||
for( i = 0; i < (MAX_DECALS - 1) && host.draw_decals[i+1][0]; i++ )
|
||||
{
|
||||
if( !Q_stricmp( name, host.draw_decals[i+1] ))
|
||||
return i+1;
|
||||
|
|
|
@ -36,14 +36,14 @@ void V_SetupRefDef( void )
|
|||
clent = CL_GetLocalPlayer ();
|
||||
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
clgame.viewent.curstate.modelindex = cl.frame.client.viewmodel;
|
||||
if( cl_lw->value ) clgame.viewent.curstate.modelindex = cl.predicted.viewmodel;
|
||||
else clgame.viewent.curstate.modelindex = cl.frame.client.viewmodel;
|
||||
clgame.viewent.model = Mod_Handle( clgame.viewent.curstate.modelindex );
|
||||
clgame.viewent.curstate.number = cl.playernum + 1;
|
||||
clgame.viewent.curstate.entityType = ET_NORMAL;
|
||||
clgame.viewent.index = cl.playernum + 1;
|
||||
|
||||
cl.refdef.movevars = &clgame.movevars;
|
||||
cl.refdef.onground = ( cl.frame.client.flags & FL_ONGROUND ) ? 1 : 0;
|
||||
cl.refdef.health = cl.frame.client.health;
|
||||
cl.refdef.playernum = cl.playernum;
|
||||
cl.refdef.max_entities = clgame.maxEntities;
|
||||
|
@ -51,12 +51,11 @@ void V_SetupRefDef( void )
|
|||
cl.refdef.time = cl.time;
|
||||
cl.refdef.frametime = cl.time - cl.oldtime;
|
||||
cl.refdef.demoplayback = cls.demoplayback;
|
||||
cl.refdef.smoothing = cl_smooth->integer;
|
||||
cl.refdef.viewsize = scr_viewsize->integer;
|
||||
cl.refdef.waterlevel = cl.frame.client.waterlevel;
|
||||
cl.refdef.onlyClientDraw = 0; // reset clientdraw
|
||||
cl.refdef.hardware = true; // always true
|
||||
cl.refdef.spectator = (clent->curstate.spectator != 0);
|
||||
cl.refdef.smoothing = false; // old stuff to smooth multiplayer view
|
||||
cl.refdef.nextView = 0;
|
||||
|
||||
SCR_AddDirtyPoint( 0, 0 );
|
||||
|
@ -81,8 +80,7 @@ void V_SetupRefDef( void )
|
|||
cl.refdef.viewport[0] = (scr_width->integer - cl.refdef.viewport[2]) / 2;
|
||||
cl.refdef.viewport[1] = (scr_height->integer - sb_lines - cl.refdef.viewport[3]) / 2;
|
||||
|
||||
if( cl.scr_fov < 1.0f || cl.scr_fov > 179.0f )
|
||||
cl.scr_fov = 90.0f;
|
||||
cl.scr_fov = bound( 1.0f, cl.scr_fov, 179.0f );
|
||||
|
||||
// calc FOV
|
||||
cl.refdef.fov_x = cl.scr_fov; // this is a final fov value
|
||||
|
@ -94,11 +92,12 @@ void V_SetupRefDef( void )
|
|||
|
||||
if( CL_IsPredicted( ) && !cl.refdef.demoplayback )
|
||||
{
|
||||
VectorMA( cl.predicted_origin, -cl.lerpBack, cl.prediction_error, cl.refdef.simorg );
|
||||
VectorCopy( cl.predicted_origin, cl.refdef.simorg );
|
||||
VectorCopy( cl.predicted_velocity, cl.refdef.simvel );
|
||||
VectorCopy( cl.predicted_viewofs, cl.refdef.viewheight );
|
||||
VectorCopy( cl.predicted_punchangle, cl.refdef.punchangle );
|
||||
VectorCopy( cl.predicted.origin, cl.refdef.simorg );
|
||||
VectorCopy( cl.predicted.velocity, cl.refdef.simvel );
|
||||
VectorCopy( cl.predicted.viewofs, cl.refdef.viewheight );
|
||||
VectorCopy( cl.predicted.punchangle, cl.refdef.punchangle );
|
||||
cl.refdef.onground = ( cl.predicted.onground == -1 ) ? false : true;
|
||||
cl.refdef.waterlevel = cl.predicted.waterlevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -106,6 +105,8 @@ void V_SetupRefDef( void )
|
|||
VectorCopy( cl.frame.client.view_ofs, cl.refdef.viewheight );
|
||||
VectorCopy( cl.frame.client.velocity, cl.refdef.simvel );
|
||||
VectorCopy( cl.frame.client.punchangle, cl.refdef.punchangle );
|
||||
cl.refdef.onground = (cl.frame.client.flags & FL_ONGROUND) ? 1 : 0;
|
||||
cl.refdef.waterlevel = cl.frame.client.waterlevel;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,24 @@ extern int CL_UPDATE_BACKUP;
|
|||
|
||||
#define INVALID_HANDLE 0xFFFF // for XashXT cache system
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t origin; // generated by CL_PredictMovement
|
||||
vec3_t viewofs;
|
||||
vec3_t velocity;
|
||||
vec3_t punchangle;
|
||||
vec3_t origins[CMD_BACKUP];
|
||||
vec3_t error;
|
||||
vec3_t lastorigin;
|
||||
double correction_time;
|
||||
int viewmodel;
|
||||
int onground;
|
||||
int waterlevel;
|
||||
int usehull;
|
||||
int moving;
|
||||
int lastground;
|
||||
} cl_predicted_data_t; // data we got from prediction system
|
||||
|
||||
// the client_t structure is wiped completely at every
|
||||
// server map change
|
||||
typedef struct
|
||||
|
@ -140,12 +158,7 @@ typedef struct
|
|||
event_state_t events;
|
||||
|
||||
// predicting stuff
|
||||
vec3_t predicted_origin; // generated by CL_PredictMovement
|
||||
vec3_t predicted_viewofs;
|
||||
vec3_t predicted_velocity;
|
||||
vec3_t predicted_punchangle;
|
||||
vec3_t predicted_origins[CMD_BACKUP];
|
||||
vec3_t prediction_error;
|
||||
cl_predicted_data_t predicted; // generated from CL_PredictMovement
|
||||
|
||||
// server state information
|
||||
int playernum;
|
||||
|
@ -166,7 +179,6 @@ typedef struct
|
|||
|
||||
// weapon predict stuff
|
||||
float scr_fov;
|
||||
int predicted_viewmodel;
|
||||
float weaponstarttime;
|
||||
int weaponsequence;
|
||||
} client_t;
|
||||
|
@ -357,8 +369,10 @@ typedef struct
|
|||
movevars_t oldmovevars;
|
||||
playermove_t *pmove; // pmove state
|
||||
|
||||
int old_trace_hull; // used by PM_Push\Pop state
|
||||
int oldcount; // used by PM_Push\Pop state
|
||||
int old_trace_hull; // used by PM_Push\Pop state
|
||||
qboolean pushed; // used by PM_Push\Pop state
|
||||
int oldviscount; // used by PM_Push\Pop state
|
||||
int oldphyscount; // used by PM_Push\Pop state
|
||||
|
||||
vec3_t player_mins[MAX_MAP_HULLS]; // 4 hulls allowed
|
||||
vec3_t player_maxs[MAX_MAP_HULLS]; // 4 hulls allowed
|
||||
|
@ -518,13 +532,14 @@ extern menu_static_t menu;
|
|||
// cvars
|
||||
//
|
||||
extern convar_t *cl_predict;
|
||||
extern convar_t *cl_smooth;
|
||||
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_showerror;
|
||||
extern convar_t *cl_nosmooth;
|
||||
extern convar_t *cl_smoothtime;
|
||||
extern convar_t *cl_crosshair;
|
||||
extern convar_t *cl_testlights;
|
||||
extern convar_t *cl_solid_players;
|
||||
|
@ -534,6 +549,7 @@ extern convar_t *cl_lightstyle_lerping;
|
|||
extern convar_t *cl_draw_particles;
|
||||
extern convar_t *cl_levelshot_name;
|
||||
extern convar_t *cl_draw_beams;
|
||||
extern convar_t *cl_bmodelinterp;
|
||||
extern convar_t *cl_lw; // local weapons
|
||||
extern convar_t *scr_centertime;
|
||||
extern convar_t *scr_viewsize;
|
||||
|
@ -712,6 +728,9 @@ cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
|
|||
void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, qboolean runfuncs, double time );
|
||||
pmtrace_t CL_TraceLine( vec3_t start, vec3_t end, int flags );
|
||||
void CL_ClearPhysEnts( void );
|
||||
void CL_PushPMStates( void );
|
||||
void CL_PopPMStates( void );
|
||||
void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient );
|
||||
|
||||
//
|
||||
// cl_studio.c
|
||||
|
@ -727,6 +746,7 @@ void CL_UpdateStudioVars( cl_entity_t *ent, entity_state_t *newstate, qboolean n
|
|||
qboolean CL_GetEntitySpatialization( int entnum, vec3_t origin, float *pradius );
|
||||
void CL_UpdateEntityFields( cl_entity_t *ent );
|
||||
qboolean CL_IsPlayerIndex( int idx );
|
||||
void CL_SetIdealPitch( void );
|
||||
|
||||
//
|
||||
// cl_remap.c
|
||||
|
|
|
@ -1232,7 +1232,11 @@ void R_DecalRemoveAll( int textureIndex )
|
|||
{
|
||||
pdecal = &gDecalPool[i];
|
||||
|
||||
if( !textureIndex || pdecal->texture == textureIndex )
|
||||
// don't remove permanent decals
|
||||
if( pdecal->flags & FDECAL_PERMANENT )
|
||||
continue;
|
||||
|
||||
if( !textureIndex || ( pdecal->texture == textureIndex ))
|
||||
R_DecalUnlink( pdecal );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1191,5 +1191,6 @@ BOOL ( WINAPI * pwglRealizeLayerPalette)(HDC, int, BOOL);
|
|||
BOOL ( WINAPI * pwglSwapLayerBuffers)(HDC, UINT);
|
||||
BOOL ( WINAPI * pwglSwapIntervalEXT)( int interval );
|
||||
HGLRC ( WINAPI * pwglCreateContextAttribsARB)( HDC hDC, HGLRC hShareContext, const int *attribList );
|
||||
const char *( WINAPI * pwglGetExtensionsStringEXT)( void );
|
||||
|
||||
#endif//GL_EXPORT_H
|
|
@ -492,6 +492,7 @@ void R_NewMap( void );
|
|||
enum
|
||||
{
|
||||
GL_OPENGL_110 = 0, // base
|
||||
GL_WGL_EXTENSIONS,
|
||||
GL_WGL_SWAPCONTROL,
|
||||
GL_WGL_PROCADDRESS,
|
||||
GL_HARDWARE_GAMMA_CONTROL,
|
||||
|
@ -548,6 +549,7 @@ typedef struct
|
|||
|
||||
// list of supported extensions
|
||||
const char *extensions_string;
|
||||
const char *wgl_extensions_string;
|
||||
byte extension[GL_EXTCOUNT];
|
||||
|
||||
int max_texture_units;
|
||||
|
|
|
@ -370,16 +370,16 @@ int R_ComputeFxBlend( cl_entity_t *e )
|
|||
break;
|
||||
}
|
||||
|
||||
if( e->model->type != mod_brush )
|
||||
if( e->model && e->model->type != mod_brush )
|
||||
{
|
||||
// NOTE: never pass sprites with rendercolor '0 0 0' it's a stupid Valve Hammer Editor bug
|
||||
if( !e->curstate.rendercolor.r && !e->curstate.rendercolor.g && !e->curstate.rendercolor.b )
|
||||
e->curstate.rendercolor.r = e->curstate.rendercolor.g = e->curstate.rendercolor.b = 255;
|
||||
}
|
||||
|
||||
// apply scale to studiomodels and sprites only
|
||||
if( e->model && e->model->type != mod_brush && !e->curstate.scale )
|
||||
e->curstate.scale = 1.0f;
|
||||
// apply scale to studiomodels and sprites only
|
||||
if( !e->curstate.scale )
|
||||
e->curstate.scale = 1.0f;
|
||||
}
|
||||
|
||||
blend = bound( 0, blend, 255 );
|
||||
|
||||
|
|
|
@ -843,20 +843,64 @@ void CL_BloodStream( const vec3_t org, const vec3_t dir, int pcolor, int speed )
|
|||
{
|
||||
particle_t *p;
|
||||
int i, j;
|
||||
float arc;
|
||||
|
||||
for( i = 0; i < speed * 20; i++ )
|
||||
for( arc = 0.05f, i = 0; i < 100; i++, arc -= 0.005f )
|
||||
{
|
||||
p = CL_AllocParticle( NULL );
|
||||
|
||||
if( !p ) return;
|
||||
|
||||
p->die += 2.0f;
|
||||
p->type = pt_vox_grav;
|
||||
p->color = pcolor + Com_RandomLong( 0, 9 );
|
||||
|
||||
VectorCopy( org, p->org );
|
||||
VectorCopy( dir, p->vel );
|
||||
|
||||
p->vel[2] -= arc;
|
||||
arc -= 0.005f;
|
||||
|
||||
VectorScale( p->vel, speed, p->vel );
|
||||
}
|
||||
|
||||
for( arc = 0.075f, i = 0; i < speed / 2; i++, arc -= 0.005f )
|
||||
{
|
||||
float num;
|
||||
|
||||
p = CL_AllocParticle( NULL );
|
||||
if( !p ) return;
|
||||
|
||||
p->die += Com_RandomFloat( 0.2f, 0.8f );
|
||||
p->type = pt_vox_grav;
|
||||
p->color = pcolor;
|
||||
p->die += 3.0f;
|
||||
p->color = pcolor + Com_RandomLong( 0, 9 );
|
||||
p->type = pt_vox_slowgrav;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
VectorCopy( org, p->org );
|
||||
VectorCopy( dir, p->vel );
|
||||
|
||||
p->vel[2] -= arc;
|
||||
|
||||
num = Com_RandomFloat( 0.0f, 1.0f );
|
||||
num = 1.7f * num * (int)(num * speed);
|
||||
VectorScale( p->vel, num, p->vel );
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
p->org[j] = org[j];
|
||||
p->vel[j] = dir[j] * speed;
|
||||
p = CL_AllocParticle( NULL );
|
||||
if( !p ) return;
|
||||
|
||||
p->die += 3.0f;
|
||||
p->color = pcolor + Com_RandomLong( 0, 9 );
|
||||
p->type = pt_vox_slowgrav;
|
||||
|
||||
p->org[0] = org[0] + Com_RandomFloat( -1.0f, 1.0f );
|
||||
p->org[1] = org[1] + Com_RandomFloat( -1.0f, 1.0f );
|
||||
p->org[2] = org[2] + Com_RandomFloat( -1.0f, 1.0f );
|
||||
|
||||
VectorCopy( dir, p->vel );
|
||||
p->vel[2] -= arc;
|
||||
|
||||
VectorScale( p->vel, num, p->vel );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3302,9 +3302,6 @@ void R_RunViewmodelEvents( void )
|
|||
if( !Mod_Extradata( clgame.viewent.model ))
|
||||
return;
|
||||
|
||||
if( cl_lw->value && cl.frame.client.viewmodel != cl.predicted_viewmodel )
|
||||
return;
|
||||
|
||||
RI.currententity = &clgame.viewent;
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
if( !RI.currentmodel ) return;
|
||||
|
@ -3339,9 +3336,6 @@ void R_DrawViewModel( void )
|
|||
if( !Mod_Extradata( clgame.viewent.model ))
|
||||
return;
|
||||
|
||||
if( cl_lw->value && cl.frame.client.viewmodel != cl.predicted_viewmodel )
|
||||
return;
|
||||
|
||||
RI.currententity = &clgame.viewent;
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
if( !RI.currentmodel ) return;
|
||||
|
|
|
@ -27,11 +27,6 @@ GNU General Public License for more details.
|
|||
#define WINDOW_EX_STYLE (0)
|
||||
#define WINDOW_NAME "Xash Window" // Half-Life
|
||||
|
||||
#ifdef WIN32
|
||||
// Enable NVIDIA High Performance Graphics while using Integrated Graphics.
|
||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
#endif
|
||||
|
||||
convar_t *renderinfo;
|
||||
convar_t *gl_allow_software;
|
||||
convar_t *gl_extensions;
|
||||
|
@ -465,6 +460,12 @@ static dllfunc_t wglswapintervalfuncs[] =
|
|||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static dllfunc_t wglgetextensionsstring[] =
|
||||
{
|
||||
{ "wglGetExtensionsStringEXT" , (void **)&pwglGetExtensionsStringEXT },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
dll_info_t opengl_dll = { "opengl32.dll", wgl_funcs, true };
|
||||
|
||||
/*
|
||||
|
@ -530,6 +531,7 @@ void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cv
|
|||
{
|
||||
const dllfunc_t *func;
|
||||
convar_t *parm;
|
||||
const char *extensions_string;
|
||||
|
||||
MsgDev( D_NOTE, "GL_CheckExtension: %s ", name );
|
||||
|
||||
|
@ -547,7 +549,12 @@ void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cv
|
|||
GL_SetExtension( r_ext, 1 );
|
||||
}
|
||||
|
||||
if(( name[2] == '_' || name[3] == '_' ) && !Q_strstr( glConfig.extensions_string, name ))
|
||||
extensions_string = glConfig.extensions_string;
|
||||
|
||||
if( name[0] == 'W' && name[1] == 'G' && name[2] == 'L' && glConfig.wgl_extensions_string != NULL )
|
||||
extensions_string = glConfig.wgl_extensions_string;
|
||||
|
||||
if(( name[2] == '_' || name[3] == '_' ) && !Q_strstr( extensions_string, name ))
|
||||
{
|
||||
GL_SetExtension( r_ext, false ); // update render info
|
||||
MsgDev( D_NOTE, "- ^1failed\n" );
|
||||
|
@ -1577,8 +1584,13 @@ void R_RenderInfo_f( void )
|
|||
|
||||
// don't spam about extensions
|
||||
if( host.developer >= 4 )
|
||||
{
|
||||
Msg( "GL_EXTENSIONS: %s\n", glConfig.extensions_string );
|
||||
|
||||
if( glConfig.wgl_extensions_string != NULL )
|
||||
Msg( "\nWGL_EXTENSIONS: %s\n", glConfig.wgl_extensions_string );
|
||||
}
|
||||
|
||||
Msg( "GL_MAX_TEXTURE_SIZE: %i\n", glConfig.max_2d_texture_size );
|
||||
|
||||
if( GL_Support( GL_ARB_MULTITEXTURE ))
|
||||
|
@ -1705,6 +1717,13 @@ void GL_InitExtensions( void )
|
|||
glConfig.extensions_string = pglGetString( GL_EXTENSIONS );
|
||||
MsgDev( D_INFO, "Video: %s\n", glConfig.renderer_string );
|
||||
|
||||
// windows-specific extensions
|
||||
GL_CheckExtension( "WGL Extensions String", wglgetextensionsstring, NULL, GL_WGL_EXTENSIONS );
|
||||
|
||||
if( pwglGetExtensionsStringEXT != NULL )
|
||||
glConfig.wgl_extensions_string = pwglGetExtensionsStringEXT();
|
||||
else glConfig.wgl_extensions_string = NULL;
|
||||
|
||||
// initalize until base opengl functions loaded
|
||||
GL_CheckExtension( "WGL_EXT_swap_control", wglswapintervalfuncs, NULL, GL_WGL_SWAPCONTROL );
|
||||
|
||||
|
|
|
@ -828,7 +828,7 @@ void CheckNewDspPresets( void )
|
|||
if( dsp_off->value != 0.0f )
|
||||
return;
|
||||
|
||||
if( cl.frame.client.waterlevel > 2 )
|
||||
if( s_listener.waterlevel > 2 )
|
||||
idsp_room = roomwater_type->value;
|
||||
else idsp_room = room_type->value;
|
||||
|
||||
|
|
|
@ -355,20 +355,8 @@ already playing.
|
|||
channel_t *SND_PickStaticChannel( int entnum, sfx_t *sfx, const vec3_t pos )
|
||||
{
|
||||
channel_t *ch = NULL;
|
||||
int i, dupe = 0;
|
||||
#if 0
|
||||
// TODO: remove this code when predicting is will be done
|
||||
// check for duplicate sounds
|
||||
for( i = 0; i < total_channels; i++ )
|
||||
{
|
||||
if( channels[i].sfx == sfx && VectorCompare( channels[i].origin, pos ))
|
||||
dupe++;
|
||||
}
|
||||
int i;
|
||||
|
||||
// check for duplicated static channels (same origin and same sfx)
|
||||
if( dupe > MAX_DUPLICATED_CHANNELS )
|
||||
return NULL;
|
||||
#endif
|
||||
// check for replacement sound, or find the best one to replace
|
||||
for( i = MAX_DYNAMIC_CHANNELS; i < total_channels; i++ )
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@ void VGUI_EnableTexture( qboolean enable );
|
|||
void VGUI_CreateTexture( int id, int width, int height );
|
||||
void VGUI_UploadTexture( int id, const char *buffer, int width, int height );
|
||||
void VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight );
|
||||
long VGUI_SurfaceWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
LONG VGUI_SurfaceWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
void VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr );
|
||||
void VGUI_GetTextureSizes( int *width, int *height );
|
||||
int VGUI_GenerateTexture( void );
|
||||
|
|
|
@ -228,7 +228,7 @@ KeyCode VGUI_MapKey( int keyCode )
|
|||
}
|
||||
}
|
||||
|
||||
long VGUI_SurfaceWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
LONG VGUI_SurfaceWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
SurfaceBase *surface = NULL;
|
||||
CEnginePanel *panel = NULL;
|
||||
|
|
|
@ -48,6 +48,6 @@ int Q_buildnum( void )
|
|||
|
||||
return b;
|
||||
#else
|
||||
return 3387;
|
||||
return 3477;
|
||||
#endif
|
||||
}
|
|
@ -304,8 +304,8 @@ qboolean Cmd_GetMusicList( const char *s, char *completedname, int length )
|
|||
{
|
||||
const char *ext = FS_FileExtension( t->filenames[i] );
|
||||
|
||||
if( !Q_stricmp( ext, "wav" ) || !Q_stricmp( ext, "mp3" ));
|
||||
else continue;
|
||||
if( Q_stricmp( ext, "wav" ) && Q_stricmp( ext, "mp3" ))
|
||||
continue;
|
||||
|
||||
FS_FileBase( t->filenames[i], matchbuf );
|
||||
Msg( "%16s\n", matchbuf );
|
||||
|
@ -568,7 +568,7 @@ Cmd_GetTexturemodes
|
|||
Prints or complete sound filename
|
||||
=====================================
|
||||
*/
|
||||
qboolean Cmd_GetTexturemodes( const char *s, char *completedname, int length )
|
||||
qboolean Cmd_GetTextureModes( const char *s, char *completedname, int length )
|
||||
{
|
||||
int i, numtexturemodes;
|
||||
string texturemodes[6]; // keep an actual ( sizeof( gl_texturemode) / sizeof( gl_texturemode[0] ))
|
||||
|
@ -584,7 +584,7 @@ qboolean Cmd_GetTexturemodes( const char *s, char *completedname, int length )
|
|||
"GL_NEAREST_MIPMAP_NEAREST",
|
||||
};
|
||||
|
||||
// compare gamelist with current keyword
|
||||
// compare texture filtering mode list with current keyword
|
||||
for( i = 0, numtexturemodes = 0; i < 6; i++ )
|
||||
{
|
||||
if(( *s == '*' ) || !Q_strnicmp( gl_texturemode[i], s, Q_strlen( s )))
|
||||
|
@ -592,7 +592,7 @@ qboolean Cmd_GetTexturemodes( const char *s, char *completedname, int length )
|
|||
}
|
||||
|
||||
if( !numtexturemodes ) return false;
|
||||
Q_strncpy( matchbuf, gl_texturemode[0], MAX_STRING );
|
||||
Q_strncpy( matchbuf, texturemodes[0], MAX_STRING );
|
||||
if( completedname && length ) Q_strncpy( completedname, matchbuf, length );
|
||||
if( numtexturemodes == 1 ) return true;
|
||||
|
||||
|
@ -665,6 +665,63 @@ qboolean Cmd_GetGamesList( const char *s, char *completedname, int length )
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetCDList
|
||||
|
||||
Prints or complete CD command name
|
||||
=====================================
|
||||
*/
|
||||
qboolean Cmd_GetCDList( const char *s, char *completedname, int length )
|
||||
{
|
||||
int i, numcdcommands;
|
||||
string cdcommands[8];
|
||||
string matchbuf;
|
||||
|
||||
const char *cd_command[] =
|
||||
{
|
||||
"info",
|
||||
"loop",
|
||||
"off",
|
||||
"on",
|
||||
"pause",
|
||||
"play",
|
||||
"resume",
|
||||
"stop",
|
||||
};
|
||||
|
||||
// compare CD command list with current keyword
|
||||
for( i = 0, numcdcommands = 0; i < 8; i++ )
|
||||
{
|
||||
if(( *s == '*' ) || !Q_strnicmp( cd_command[i], s, Q_strlen( s )))
|
||||
Q_strcpy( cdcommands[numcdcommands++], cd_command[i] );
|
||||
}
|
||||
|
||||
if( !numcdcommands ) return false;
|
||||
Q_strncpy( matchbuf, cdcommands[0], MAX_STRING );
|
||||
if( completedname && length ) Q_strncpy( completedname, matchbuf, length );
|
||||
if( numcdcommands == 1 ) return true;
|
||||
|
||||
for( i = 0; i < numcdcommands; i++ )
|
||||
{
|
||||
Q_strncpy( matchbuf, cdcommands[i], MAX_STRING );
|
||||
Msg( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
Msg( "\n^3 %i commands found.\n", numcdcommands );
|
||||
|
||||
// cut shortestMatch to the amount common with s
|
||||
if( completedname && length )
|
||||
{
|
||||
for( i = 0; matchbuf[i]; i++ )
|
||||
{
|
||||
if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] ))
|
||||
completedname[i] = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
||||
{
|
||||
byte buf[MAX_SYSPATH];
|
||||
|
@ -815,7 +872,7 @@ qboolean Cmd_CheckMapsList( qboolean fRefresh )
|
|||
|
||||
autocomplete_list_t cmd_list[] =
|
||||
{
|
||||
{ "gl_texturemode", Cmd_GetTexturemodes },
|
||||
{ "gl_texturemode", Cmd_GetTextureModes },
|
||||
{ "map_background", Cmd_GetMapList },
|
||||
{ "changelevel", Cmd_GetMapList },
|
||||
{ "playdemo", Cmd_GetDemoList, },
|
||||
|
@ -832,6 +889,7 @@ autocomplete_list_t cmd_list[] =
|
|||
{ "load", Cmd_GetSavesList },
|
||||
{ "play", Cmd_GetSoundList },
|
||||
{ "map", Cmd_GetMapList },
|
||||
{ "cd", Cmd_GetCDList },
|
||||
{ NULL }, // termiantor
|
||||
};
|
||||
|
||||
|
|
|
@ -755,12 +755,6 @@ void Con_Print( const char *txt )
|
|||
if( txt[l] <= ' ')
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
// g-cont. experiment from SDLash3D
|
||||
// word wrap
|
||||
if( l != con.linewidth && ( con.x + l >= con.linewidth ))
|
||||
Con_Linefeed();
|
||||
#endif
|
||||
txt++;
|
||||
|
||||
switch( c )
|
||||
|
|
|
@ -462,6 +462,8 @@ void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end )
|
|||
|
||||
maxcol = max( max( r, g ), b ) / 255.0f;
|
||||
mincol = min( min( r, g ), b ) / 255.0f;
|
||||
|
||||
if( maxcol == 0 ) continue;
|
||||
|
||||
val = maxcol;
|
||||
sat = (maxcol - mincol) / maxcol;
|
||||
|
@ -567,7 +569,7 @@ qboolean Image_Copy8bitRGBA( const byte *in, byte *out, int pixels )
|
|||
// check for color
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
col = (rgba_t *)image.d_currentpal[i];
|
||||
col = (rgba_t *)&image.d_currentpal[i];
|
||||
if( col[0] != col[1] || col[1] != col[2] )
|
||||
{
|
||||
image.flags |= IMAGE_HAS_COLOR;
|
||||
|
@ -1114,7 +1116,7 @@ byte *Image_FloodInternal( const byte *indata, int inwidth, int inheight, int ou
|
|||
{
|
||||
if( x < inwidth )
|
||||
*out++ = *in++;
|
||||
else *out++;
|
||||
else out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,7 +435,7 @@ IN_WndProc
|
|||
main window procedure
|
||||
====================
|
||||
*/
|
||||
long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
|
||||
LONG IN_WndProc( HWND hWnd, UINT uMsg, UINT wParam, LONG lParam )
|
||||
{
|
||||
int i, temp = 0;
|
||||
qboolean fActivate;
|
||||
|
|
|
@ -45,7 +45,7 @@ void IN_MouseEvent( int mstate );
|
|||
void IN_ActivateMouse( qboolean force );
|
||||
void IN_DeactivateMouse( void );
|
||||
void IN_ToggleClientMouse( int newstate, int oldstate );
|
||||
long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam );
|
||||
LONG IN_WndProc( HWND hWnd, UINT uMsg, UINT wParam, LONG lParam );
|
||||
void IN_SetCursor( HICON hCursor );
|
||||
|
||||
#endif//INPUT_H
|
|
@ -63,7 +63,7 @@ GNU General Public License for more details.
|
|||
#define PORT_MASTER 27010
|
||||
#define PORT_CLIENT 27005
|
||||
#define PORT_SERVER 27015
|
||||
#define MULTIPLAYER_BACKUP 64 // how many data slots to use when in multiplayer (must be power of 2)
|
||||
#define MULTIPLAYER_BACKUP 128 // how many data slots to use when in multiplayer (must be power of 2)
|
||||
#define SINGLEPLAYER_BACKUP 16 // same for single player
|
||||
|
||||
/*
|
||||
|
|
|
@ -76,7 +76,8 @@ static void FindNextChunk( const char *name )
|
|||
iff_dataPtr += 4;
|
||||
iff_chunkLen = GetLittleLong();
|
||||
|
||||
if( iff_chunkLen < 0 )
|
||||
// limit chunk size to 1 mb
|
||||
if( iff_chunkLen < 0 || iff_chunkLen > ( 1024 * 1024 ))
|
||||
{
|
||||
iff_dataPtr = NULL;
|
||||
return;
|
||||
|
|
|
@ -165,9 +165,16 @@ static const char *Mem_CheckFilename( const char *filename )
|
|||
int i;
|
||||
|
||||
if( !out ) return dummy;
|
||||
|
||||
for( i = 0; i < 128; i++, out++ )
|
||||
if( out == '\0' ) break; // valid name
|
||||
if( i == 128 ) return dummy;
|
||||
{
|
||||
if( *out == '\0' )
|
||||
break; // valid name
|
||||
}
|
||||
|
||||
if( i == 128 )
|
||||
return dummy;
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
|
|
@ -447,6 +447,7 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg );
|
|||
void SV_PrepWorldFrame( void );
|
||||
void SV_ProcessFile( sv_client_t *cl, char *filename );
|
||||
void SV_SendResourceList( sv_client_t *cl );
|
||||
void SV_AddToMaster( netadr_t from, sizebuf_t *msg );
|
||||
void Master_Add( void );
|
||||
void Master_Heartbeat( void );
|
||||
void Master_Packet( void );
|
||||
|
|
|
@ -548,7 +548,7 @@ char *SV_StatusString( void )
|
|||
cl = &svs.clients[i];
|
||||
if( cl->state == cs_connected || cl->state == cs_spawned )
|
||||
{
|
||||
Q_sprintf( player, "%i %i \"%s\"\n", (int)cl->edict->v.frags, cl->ping, cl->name );
|
||||
Q_sprintf( player, "%i %i \"%s\"\n", (int)cl->edict->v.frags, (int)cl->ping, cl->name );
|
||||
playerLength = Q_strlen( player );
|
||||
if( statusLength + playerLength >= sizeof( status ))
|
||||
break; // can't hold any more
|
||||
|
@ -642,7 +642,7 @@ void SV_Info( netadr_t from )
|
|||
int version;
|
||||
|
||||
// ignore in single player
|
||||
if( sv_maxclients->integer == 1 )
|
||||
if( sv_maxclients->integer == 1 || !svs.initialized )
|
||||
return;
|
||||
|
||||
version = Q_atoi( Cmd_Argv( 1 ));
|
||||
|
@ -660,9 +660,9 @@ void SV_Info( netadr_t from )
|
|||
|
||||
Info_SetValueForKey( string, "host", hostname->string );
|
||||
Info_SetValueForKey( string, "map", sv.name );
|
||||
Info_SetValueForKey( string, "dm", va( "%i", svgame.globals->deathmatch ));
|
||||
Info_SetValueForKey( string, "team", va( "%i", svgame.globals->teamplay ));
|
||||
Info_SetValueForKey( string, "coop", va( "%i", svgame.globals->coop ));
|
||||
Info_SetValueForKey( string, "dm", va( "%i", (int)svgame.globals->deathmatch ));
|
||||
Info_SetValueForKey( string, "team", va( "%i", (int)svgame.globals->teamplay ));
|
||||
Info_SetValueForKey( string, "coop", va( "%i", (int)svgame.globals->coop ));
|
||||
Info_SetValueForKey( string, "numcl", va( "%i", count ));
|
||||
Info_SetValueForKey( string, "maxcl", va( "%i", sv_maxclients->integer ));
|
||||
Info_SetValueForKey( string, "gamedir", GI->gamefolder );
|
||||
|
@ -685,7 +685,7 @@ void SV_BuildNetAnswer( netadr_t from )
|
|||
int i, count = 0;
|
||||
|
||||
// ignore in single player
|
||||
if( sv_maxclients->integer == 1 )
|
||||
if( sv_maxclients->integer == 1 || !svs.initialized )
|
||||
return;
|
||||
|
||||
version = Q_atoi( Cmd_Argv( 1 ));
|
||||
|
@ -716,7 +716,7 @@ void SV_BuildNetAnswer( netadr_t from )
|
|||
{
|
||||
edict_t *ed = svs.clients[i].edict;
|
||||
float time = host.realtime - svs.clients[i].lastconnect;
|
||||
Q_strncat( string, va( "%c\\%s\\%i\\%f\\", count, svs.clients[i].name, ed->v.frags, time ), sizeof( string ));
|
||||
Q_strncat( string, va( "%c\\%s\\%i\\%f\\", count, svs.clients[i].name, (int)ed->v.frags, time ), sizeof( string ));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -1802,6 +1802,14 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
|
|||
val = Info_ValueForKey( cl->userinfo, "name" );
|
||||
}
|
||||
|
||||
if( !Q_strlen( temp1 ) )
|
||||
{
|
||||
Info_SetValueForKey( cl->userinfo, "name", "unnamed" );
|
||||
val = Info_ValueForKey( cl->userinfo, "name" );
|
||||
Q_strncpy( temp2, "unnamed", sizeof( temp2 ));
|
||||
Q_strncpy( temp1, "unnamed", sizeof( temp1 ));
|
||||
}
|
||||
|
||||
// check to see if another user by the same name exists
|
||||
while( 1 )
|
||||
{
|
||||
|
@ -1871,6 +1879,14 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
|
|||
}
|
||||
else cl->modelindex = 0;
|
||||
|
||||
// force reset player model to "player"
|
||||
if( cl->modelindex == 0 )
|
||||
{
|
||||
Info_SetValueForKey( cl->userinfo, "model", "player" );
|
||||
Mod_RegisterModel( "models/player.mdl", SV_ModelIndex( "models/player.mdl" ));
|
||||
SV_SetModel( ent, "models/player.mdl" );
|
||||
}
|
||||
|
||||
// call prog code to allow overrides
|
||||
svgame.dllFuncs.pfnClientUserInfoChanged( cl->edict, cl->userinfo );
|
||||
ent->v.netname = MAKE_STRING( cl->name );
|
||||
|
@ -2038,6 +2054,70 @@ void SV_ExecuteClientCommand( sv_client_t *cl, char *s )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_TSourceEngineQuery
|
||||
==================
|
||||
*/
|
||||
void SV_TSourceEngineQuery( netadr_t from )
|
||||
{
|
||||
// A2S_INFO
|
||||
char answer[1024] = "";
|
||||
int count = 0, bots = 0, index;
|
||||
sizebuf_t buf;
|
||||
|
||||
if( svs.clients )
|
||||
{
|
||||
for( index = 0; index < sv_maxclients->integer; index++ )
|
||||
{
|
||||
if( svs.clients[index].state >= cs_connected )
|
||||
{
|
||||
if( svs.clients[index].fakeclient )
|
||||
bots++;
|
||||
else count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BF_Init( &buf, "TSourceEngineQuery", answer, sizeof( answer ));
|
||||
|
||||
BF_WriteByte( &buf, 'm' );
|
||||
BF_WriteString( &buf, NET_AdrToString( net_local ) );
|
||||
BF_WriteString( &buf, hostname->string );
|
||||
BF_WriteString( &buf, sv.name );
|
||||
BF_WriteString( &buf, GI->gamefolder );
|
||||
BF_WriteString( &buf, GI->title );
|
||||
BF_WriteByte( &buf, count );
|
||||
BF_WriteByte( &buf, sv_maxclients->integer );
|
||||
BF_WriteByte( &buf, PROTOCOL_VERSION );
|
||||
BF_WriteByte( &buf, host.type == HOST_DEDICATED ? 'D' : 'L');
|
||||
BF_WriteByte( &buf, 'W' );
|
||||
|
||||
if( Q_stricmp( GI->gamedir, "valve" ))
|
||||
{
|
||||
BF_WriteByte( &buf, 1 ); // mod
|
||||
BF_WriteString( &buf, GI->game_url );
|
||||
BF_WriteString( &buf, GI->update_url );
|
||||
BF_WriteByte( &buf, 0 );
|
||||
BF_WriteLong( &buf, (long)GI->version );
|
||||
BF_WriteLong( &buf, GI->size );
|
||||
|
||||
if( GI->gamemode == 2 )
|
||||
BF_WriteByte( &buf, 1 ); // multiplayer_only
|
||||
else BF_WriteByte( &buf, 0 );
|
||||
|
||||
if( Q_strstr( GI->game_dll, "hl." ))
|
||||
BF_WriteByte( &buf, 0 ); // Half-Life DLL
|
||||
else BF_WriteByte( &buf, 1 ); // Own DLL
|
||||
}
|
||||
else BF_WriteByte( &buf, 0 ); // Half-Life
|
||||
|
||||
BF_WriteByte( &buf, GI->secure ); // unsecure
|
||||
BF_WriteByte( &buf, bots );
|
||||
|
||||
NET_SendPacket( NS_SERVER, BF_GetNumBytesWritten( &buf ), BF_GetData( &buf ), from );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_ConnectionlessPacket
|
||||
|
@ -2053,9 +2133,6 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||
char *args;
|
||||
char *c, buf[MAX_SYSPATH];
|
||||
int len = sizeof( buf );
|
||||
uint challenge;
|
||||
int index, count = 0;
|
||||
char query[512], ostype = 'w';
|
||||
|
||||
BF_Clear( msg );
|
||||
BF_ReadLong( msg );// skip the -1 marker
|
||||
|
@ -2074,46 +2151,9 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||
else if( !Q_strcmp( c, "connect" )) SV_DirectConnect( from );
|
||||
else if( !Q_strcmp( c, "rcon" )) SV_RemoteCommand( from, msg );
|
||||
else if( !Q_strcmp( c, "netinfo" )) SV_BuildNetAnswer( from );
|
||||
else if( msg->pData[0] == 0xFF && msg->pData[1] == 0xFF && msg->pData[2] == 0xFF && msg->pData[3] == 0xFF && msg->pData[4] == 0x73 && msg->pData[5] == 0x0A )
|
||||
{
|
||||
Q_memcpy(&challenge, &msg->pData[6], sizeof(int));
|
||||
|
||||
for( index = 0; index < sv_maxclients->integer; index++ )
|
||||
{
|
||||
if( svs.clients[index].state >= cs_connected )
|
||||
count++;
|
||||
}
|
||||
|
||||
Q_snprintf( query, sizeof( query ),
|
||||
"0\n"
|
||||
"\\protocol\\%d" // protocol version
|
||||
"\\challenge\\%u" // challenge number that got after FF FF FF FF 73 0A
|
||||
"\\players\\%d" // current player number
|
||||
"\\max\\%d" // max_players
|
||||
"\\bots\\0" // bot number?
|
||||
"\\gamedir\\%s" // gamedir. _xash appended, because Xash3D is not compatible with GS in multiplayer
|
||||
"\\map\\%s" // current map
|
||||
"\\type\\d" // server type
|
||||
"\\password\\0" // is password set
|
||||
"\\os\\%c" // server OS?
|
||||
"\\secure\\0" // server anti-cheat? VAC?
|
||||
"\\lan\\0" // is LAN server?
|
||||
"\\version\\%f" // server version
|
||||
"\\region\\255" // server region
|
||||
"\\product\\%s\n", // product? Where is the difference with gamedir?
|
||||
PROTOCOL_VERSION,
|
||||
challenge,
|
||||
count,
|
||||
sv_maxclients->integer,
|
||||
GI->gamefolder,
|
||||
sv.name,
|
||||
ostype,
|
||||
XASH_VERSION,
|
||||
GI->gamefolder
|
||||
);
|
||||
|
||||
NET_SendPacket( NS_SERVER, Q_strlen( query ), query, from );
|
||||
}
|
||||
else if( !Q_strcmp( c, "s")) SV_AddToMaster( from, msg );
|
||||
else if( !Q_strcmp( c, "T" "Source" )) SV_TSourceEngineQuery( from );
|
||||
else if( !Q_strcmp( c, "i" )) NET_SendPacket( NS_SERVER, 5, "\xFF\xFF\xFF\xFFj", from ); // A2A_PING
|
||||
else if( svgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
|
||||
{
|
||||
// user out of band message (must be handled in CL_ConnectionlessPacket)
|
||||
|
@ -2143,7 +2183,6 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
|
|||
usercmd_t cmds[32], *to;
|
||||
edict_t *player;
|
||||
|
||||
numbackup = 2;
|
||||
player = cl->edict;
|
||||
|
||||
frame = &cl->frames[cl->netchan.incoming_acknowledged & SV_UPDATE_MASK];
|
||||
|
|
|
@ -561,6 +561,16 @@ void SV_WriteEntitiesToClient( sv_client_t *cl, sizebuf_t *msg )
|
|||
|
||||
// copy the entity states out
|
||||
frame->num_entities = 0;
|
||||
|
||||
// It will break all connected clients, but it takes more than one week to overflow it
|
||||
if(( (uint)svs.next_client_entities ) + frame_ents.num_entities >= 0x7FFFFFFE )
|
||||
{
|
||||
// just reset counter
|
||||
svs.next_client_entities = 0;
|
||||
// delta is broken now, cannot keep connected clients
|
||||
SV_FinalMessage( "Server is running to long, reconnecting!", true );
|
||||
}
|
||||
|
||||
frame->first_entity = svs.next_client_entities;
|
||||
|
||||
for( i = 0; i < frame_ents.num_entities; i++ )
|
||||
|
@ -569,10 +579,6 @@ void SV_WriteEntitiesToClient( sv_client_t *cl, sizebuf_t *msg )
|
|||
state = &svs.packet_entities[svs.next_client_entities % svs.num_client_entities];
|
||||
*state = frame_ents.entities[i];
|
||||
svs.next_client_entities++;
|
||||
|
||||
// this should never hit, map should always be restarted first in SV_Frame
|
||||
if( svs.next_client_entities >= 0x7FFFFFFE )
|
||||
Host_Error( "svs.next_client_entities wrapped\n" );
|
||||
frame->num_entities++;
|
||||
}
|
||||
|
||||
|
@ -601,6 +607,7 @@ void SV_SendClientDatagram( sv_client_t *cl )
|
|||
svs.currentPlayer = cl;
|
||||
svs.currentPlayerNum = (cl - svs.clients);
|
||||
|
||||
Q_memset( msg_buf, 0, NET_MAX_PAYLOAD );
|
||||
BF_Init( &msg, "Datagram", msg_buf, sizeof( msg_buf ));
|
||||
|
||||
// always send servertime at new frame
|
||||
|
|
|
@ -3185,7 +3185,7 @@ void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg )
|
|||
if( sv.state != ss_active )
|
||||
{
|
||||
// send message into console during loading
|
||||
MsgDev( D_INFO, szMsg );
|
||||
MsgDev( D_INFO, "%s\n", szMsg );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3198,7 +3198,7 @@ void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg )
|
|||
switch( ptype )
|
||||
{
|
||||
case print_console:
|
||||
if( client->fakeclient ) MsgDev( D_INFO, szMsg );
|
||||
if( client->fakeclient ) MsgDev( D_INFO, "%s", szMsg );
|
||||
else SV_ClientPrintf( client, PRINT_HIGH, "%s", szMsg );
|
||||
break;
|
||||
case print_chat:
|
||||
|
@ -3222,7 +3222,7 @@ pfnServerPrint
|
|||
void pfnServerPrint( const char *szMsg )
|
||||
{
|
||||
// while loading in-progress we can sending message only for local client
|
||||
if( sv.state != ss_active ) MsgDev( D_INFO, szMsg );
|
||||
if( sv.state != ss_active ) MsgDev( D_INFO, "%s", szMsg );
|
||||
else SV_BroadcastPrintf( PRINT_HIGH, "%s", szMsg );
|
||||
}
|
||||
|
||||
|
@ -4362,15 +4362,16 @@ pfnCheckParm
|
|||
*/
|
||||
static int pfnCheckParm( char *parm, char **ppnext )
|
||||
{
|
||||
static char str[64];
|
||||
int i = Sys_CheckParm( parm );
|
||||
|
||||
if( Sys_GetParmFromCmdLine( parm, str ))
|
||||
if( ppnext != NULL )
|
||||
{
|
||||
// get the pointer on cmdline param
|
||||
if( ppnext ) *ppnext = str;
|
||||
return 1;
|
||||
if( i > 0 && i < host.argc - 1 )
|
||||
*ppnext = (char*)host.argv[i + 1];
|
||||
else *ppnext = NULL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// engine callbacks
|
||||
|
|
|
@ -403,6 +403,9 @@ void SV_DeactivateServer( void )
|
|||
|
||||
svgame.dllFuncs.pfnServerDeactivate();
|
||||
|
||||
if( sv_maxclients->integer > 32 )
|
||||
Cvar_SetFloat( "maxplayers", 32.0f );
|
||||
|
||||
for( i = 0; i < sv_maxclients->integer; i++ )
|
||||
{
|
||||
// release client frames
|
||||
|
@ -677,7 +680,7 @@ void SV_InitGame( void )
|
|||
// copy gamemode into svgame.globals
|
||||
svgame.globals->deathmatch = Cvar_VariableInteger( "deathmatch" );
|
||||
svgame.globals->teamplay = Cvar_VariableInteger( "teamplay" );
|
||||
svgame.globals->coop = Cvar_VariableInteger( "coop" );
|
||||
svgame.globals->coop = ( sv_maxclients->integer > 1 ) ? Cvar_VariableInteger( "coop" ) : 0;
|
||||
|
||||
// heartbeats will always be sent to the id master
|
||||
svs.last_heartbeat = MAX_HEARTBEAT; // send immediately
|
||||
|
|
|
@ -320,7 +320,8 @@ SV_ReadPackets
|
|||
void SV_ReadPackets( void )
|
||||
{
|
||||
sv_client_t *cl;
|
||||
int i, qport, curSize;
|
||||
int i, qport;
|
||||
size_t curSize;
|
||||
|
||||
while( NET_GetPacket( NS_SERVER, &net_from, net_message_buffer, &curSize ))
|
||||
{
|
||||
|
@ -548,7 +549,12 @@ Host_ServerFrame
|
|||
void Host_ServerFrame( void )
|
||||
{
|
||||
// if server is not active, do nothing
|
||||
if( !svs.initialized ) return;
|
||||
if( !svs.initialized )
|
||||
{
|
||||
// but allow rcon
|
||||
SV_ReadPackets ();
|
||||
return;
|
||||
}
|
||||
|
||||
svgame.globals->frametime = host.frametime;
|
||||
|
||||
|
@ -599,7 +605,7 @@ void Master_Add( void )
|
|||
if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ))
|
||||
MsgDev( D_INFO, "Can't resolve adr: %s\n", MASTERSERVER_ADR );
|
||||
|
||||
NET_SendPacket( NS_SERVER, 1, "q", adr );
|
||||
NET_SendPacket( NS_SERVER, 2, "q\xFF", adr );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -646,6 +652,54 @@ void Master_Shutdown( void )
|
|||
NET_SendPacket( NS_SERVER, 2, "\x62\x0A", adr );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_AddToMaster
|
||||
|
||||
A server info answer to master server.
|
||||
Master will validate challenge and this server to public list
|
||||
=================
|
||||
*/
|
||||
void SV_AddToMaster( netadr_t from, sizebuf_t *msg )
|
||||
{
|
||||
uint challenge;
|
||||
char s[MAX_INFO_STRING] = "0\n"; // skip 2 bytes of header
|
||||
int clients = 0, bots = 0, index;
|
||||
|
||||
if( svs.clients )
|
||||
{
|
||||
for( index = 0; index < sv_maxclients->integer; index++ )
|
||||
{
|
||||
if( svs.clients[index].state >= cs_connected )
|
||||
{
|
||||
if( svs.clients[index].fakeclient )
|
||||
bots++;
|
||||
else clients++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
challenge = BF_ReadUBitLong( msg, sizeof( uint ) << 3 );
|
||||
|
||||
Info_SetValueForKey( s, "protocol", va( "%d", PROTOCOL_VERSION ) ); // protocol version
|
||||
Info_SetValueForKey( s, "challenge", va( "%u", challenge ) ); // challenge number
|
||||
Info_SetValueForKey( s, "players", va( "%d", clients ) ); // current player number, without bots
|
||||
Info_SetValueForKey( s, "max", sv_maxclients->string ); // max_players
|
||||
Info_SetValueForKey( s, "bots", va( "%d", bots ) ); // bot count
|
||||
Info_SetValueForKey( s, "gamedir", GI->gamedir ); // gamedir
|
||||
Info_SetValueForKey( s, "map", sv.name ); // current map
|
||||
Info_SetValueForKey( s, "type", (host.type == HOST_DEDICATED) ? "d" : "l" ); // dedicated or local
|
||||
Info_SetValueForKey( s, "password", "0" ); // is password set
|
||||
Info_SetValueForKey( s, "os", "w" ); // Windows
|
||||
Info_SetValueForKey( s, "secure", "0" ); // server anti-cheat
|
||||
Info_SetValueForKey( s, "lan", "0" ); // LAN servers doesn't send info to master
|
||||
Info_SetValueForKey( s, "version", va( "%g", XASH_VERSION )); // server region. 255 -- all regions
|
||||
Info_SetValueForKey( s, "region", "255" ); // server region. 255 -- all regions
|
||||
Info_SetValueForKey( s, "product", GI->gamefolder ); // product? Where is the difference with gamedir?
|
||||
|
||||
NET_SendPacket( NS_SERVER, Q_strlen( s ), s, from );
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
|
|
|
@ -540,7 +540,7 @@ void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
|
|||
int sides, leafnum;
|
||||
mleaf_t *leaf;
|
||||
|
||||
if( node->contents == CONTENTS_SOLID )
|
||||
if( !node || node->contents == CONTENTS_SOLID )
|
||||
return;
|
||||
|
||||
// add an efrag if the node is a leaf
|
||||
|
|
|
@ -17,6 +17,11 @@ GNU General Public License for more details.
|
|||
|
||||
#define GAME_PATH "valve" // default dir to start from
|
||||
|
||||
#ifdef WIN32
|
||||
// enable NVIDIA High Performance Graphics while using Integrated Graphics.
|
||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
#endif
|
||||
|
||||
typedef void (*pfnChangeGame)( const char *progname );
|
||||
typedef int (*pfnInit)( const char *progname, int bChangeGame, pfnChangeGame func );
|
||||
typedef void (*pfnShutdown)( void );
|
||||
|
|
Reference in New Issue