diff options
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/bg_misc.c | 112 | ||||
| -rw-r--r-- | src/game/bg_public.h | 1 | ||||
| -rw-r--r-- | src/game/g_active.c | 113 | ||||
| -rw-r--r-- | src/game/g_local.h | 12 | ||||
| -rw-r--r-- | src/game/g_main.c | 2 | 
5 files changed, 118 insertions, 122 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 4b0d56f..8810c12 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -3416,118 +3416,6 @@ void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean    s->otherEntityNum = ps->otherEntityNum;  } - -/* -======================== -BG_PlayerStateToEntityStateExtraPolate - -This is done after each set of usercmd_t on the server, -and after local prediction on the client -======================== -*/ -void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap ) -{ -  int     i; - -  if( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR || ps->pm_type == PM_FREEZE ) -    s->eType = ET_INVISIBLE; -  else if( ps->persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) -    s->eType = ET_INVISIBLE; -  else -    s->eType = ET_PLAYER; - -  s->number = ps->clientNum; - -  s->pos.trType = TR_LINEAR_STOP; -  VectorCopy( ps->origin, s->pos.trBase ); - -  if( snap ) -    SnapVector( s->pos.trBase ); - -  // set the trDelta for flag direction and linear prediction -  VectorCopy( ps->velocity, s->pos.trDelta ); -  // set the time for linear prediction -  s->pos.trTime = time; -  // set maximum extra polation time -  s->pos.trDuration = 50; // 1000 / sv_fps (default = 20) - -  s->apos.trType = TR_INTERPOLATE; -  VectorCopy( ps->viewangles, s->apos.trBase ); -  if( snap ) -    SnapVector( s->apos.trBase ); - -  //TA: i need for other things :) -  //s->angles2[YAW] = ps->movementDir; -  s->time2 = ps->movementDir; -  s->legsAnim = ps->legsAnim; -  s->torsoAnim = ps->torsoAnim; -  s->clientNum = ps->clientNum;   // ET_PLAYER looks here instead of at number -                    // so corpses can also reference the proper config -  s->eFlags = ps->eFlags; - -  if( ps->stats[STAT_HEALTH] <= 0 ) -    s->eFlags |= EF_DEAD; -  else -    s->eFlags &= ~EF_DEAD; - -  if( ps->stats[ STAT_STATE ] & SS_BLOBLOCKED ) -    s->eFlags |= EF_BLOBLOCKED; -  else -    s->eFlags &= ~EF_BLOBLOCKED; - -  if( ps->externalEvent ) -  { -    s->event = ps->externalEvent; -    s->eventParm = ps->externalEventParm; -  } -  else if( ps->entityEventSequence < ps->eventSequence ) -  { -    int   seq; - -    if( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS ) -      ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS; - -    seq = ps->entityEventSequence & ( MAX_PS_EVENTS - 1 ); -    s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 ); -    s->eventParm = ps->eventParms[ seq ]; -    ps->entityEventSequence++; -  } - -  s->weapon = ps->weapon; -  s->groundEntityNum = ps->groundEntityNum; - -  //store items held and active items in modelindex and modelindex2 -  s->modelindex = 0; -  s->modelindex2 = 0; - -  for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) -  { -    if( BG_InventoryContainsUpgrade( i, ps->stats ) ) -    { -      s->modelindex |= 1 << i; - -      if( BG_UpgradeIsActive( i, ps->stats ) ) -        s->modelindex2 |= 1 << i; -    } -  } - -  // use misc field to store team/class info: -  s->misc = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); - -  //TA: have to get the surfNormal thru somehow... -  VectorCopy( ps->grapplePoint, s->angles2 ); -  if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) -    s->eFlags |= EF_WALLCLIMBCEILING; - -  s->loopSound = ps->loopSound; -  s->generic1 = ps->generic1; - -  if( s->generic1 <= WPM_NONE || s->generic1 >= WPM_NUM_WEAPONMODES ) -    s->generic1 = WPM_PRIMARY; - -  s->otherEntityNum = ps->otherEntityNum; -} -  /*  ========================  BG_WeaponIsFull diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 790e206..98c0755 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -1258,7 +1258,6 @@ void  BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t res  void  BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps );  void  BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap ); -void  BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap );  qboolean  BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime ); diff --git a/src/game/g_active.c b/src/game/g_active.c index 5bee472..c1cc9f0 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -1568,6 +1568,98 @@ static void ClientGradualFunds( gentity_t *ent )  /*  ============== +ClientSavePosition +============== +*/ +static void ClientSavePosition(gentity_t *ent, int client_time) +{ +	savedPosition_t *pos; + +	pos = ent->client->savedPositions + +	      (ent->client->savedPositionsCount + 1) % MAX_SAVED_POSITIONS; +	ent->client->savedPositionsCount++; + +	VectorCopy(ent->s.pos.trBase, pos->origin); +	pos->time = level.time; +	pos->client_time = client_time; +} + +/* +============== +ClientExtrapolate +============== +*/ +static void ClientExtrapolate(gentity_t *ent) +{ +	savedPosition_t *pos1, *pos2; +	vec3_t dxdt; +	int flags, time_delta, time_since; + +	flags = g_smoothClients.integer; +	if (!flags) +		return; + +	// Don't bother if the player is lagging too hard. +	if (ent->s.eFlags & EF_CONNECTION) +		return; + +	// Need at least 2 samples for linear extrapolation. +	if (ent->client->savedPositionsCount < 2) +		return; + +	pos1 = ent->client->savedPositions + +	       ent->client->savedPositionsCount % MAX_SAVED_POSITIONS; +	pos2 = ent->client->savedPositions + +	       (ent->client->savedPositionsCount + MAX_SAVED_POSITIONS - 1) +	        % MAX_SAVED_POSITIONS; + +	switch ((flags & (2 | 4 | 8)) >> 1) { +	default: +		Com_Printf("^3warning: g_smoothClients has a bad value\n"); +	case 0: +		time_delta = pos2->time - pos1->time; +		break; +	case 1: +		time_delta = pos2->client_time - pos1->client_time; +		break; +	case 2: +		time_delta = 50; +		break; +	case 3: +		time_delta = 25; +		break; +	case 4: +		time_delta = 16; +		break; +	} + +	VectorSubtract(pos2->origin, pos1->origin, dxdt); +	VectorScale(dxdt, pos2->time - pos1->time, dxdt); + +	if (flags & 16) +		time_since = level.time - pos2->client_time; +	else +		time_since = level.time - pos2->time; + +	VectorMA(pos1->origin, time_delta, dxdt, ent->s.pos.trBase); + +	if (g_debugExtrapolation.integer) { +		Com_Printf("Extrapolated player %i:\n", (int)(ent - g_entities)); +		Com_Printf("  pos1=(%f, %f, %f) at t=%i, t'=%i\n", +		           pos1->origin[0], pos1->origin[1], pos1->origin[2], +		           pos1->time, pos1->client_time); +		Com_Printf("  pos2=(%f, %f, %f) at t=%i, t'=%i\n", +		           pos2->origin[0], pos2->origin[1], pos2->origin[2], +		           pos2->time, pos2->client_time); +		Com_Printf("  dxdt=(%f, %f, %f), td=%i, ts=%i\n", +		           dxdt[0], dxdt[1], dxdt[2], time_delta, time_since); +		Com_Printf("  out=(%f, %f, %f)\n", ent->s.pos.trBase[0], +		           ent->s.pos.trBase[1], ent->s.pos.trBase[2]); +	} +} + +/* +==============  ClientThink  This will be called once for each client frame, which will @@ -1882,10 +1974,7 @@ void ClientThink_real( gentity_t *ent )    if ( level.paused ) client->ps.pm_type = real_pm_type; -  if( g_smoothClients.integer ) -    BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qtrue ); -  else -    BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue ); +  BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue );    SendPendingPredictableEvents( &ent->client->ps ); @@ -2036,6 +2125,8 @@ void ClientThink_real( gentity_t *ent )      ent->suicideTime = 0;    } + +  ClientSavePosition( ent, ucmd->serverTime );  }  /* @@ -2170,7 +2261,7 @@ void ClientEndFrame( gentity_t *ent )    P_DamageFeedback( ent );    // add the EF_CONNECTION flag if we haven't gotten commands recently -  if( level.time - ent->client->lastCmdTime > 1000 ) +  if( level.time - ent->client->lastCmdTime > 500 )      ent->s.eFlags |= EF_CONNECTION;    else      ent->s.eFlags &= ~EF_CONNECTION; @@ -2184,10 +2275,14 @@ void ClientEndFrame( gentity_t *ent )    G_SetClientSound( ent );    // set the latest infor -  if( g_smoothClients.integer ) -    BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qtrue ); -  else -    BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue ); +  BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue ); + +  if( ent->client->extrapolate ) +    ClientExtrapolate( ent ); + +  // This flag will go down as soon as a client frame is received. +  // If a frame isn't received then it'll stay up and trigger extrapolation. +  ent->client->extrapolate = qtrue;    SendPendingPredictableEvents( &ent->client->ps );  } diff --git a/src/game/g_local.h b/src/game/g_local.h index a3c02c8..28bd059 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -450,6 +450,13 @@ typedef struct unlagged_s {    qboolean    used;  } unlagged_t; +#define MAX_SAVED_POSITIONS 3 +typedef struct { +  vec3_t      origin; +  int         time; +  int         client_time; +} savedPosition_t; +  // this structure is cleared on each ClientSpawn(),  // except for 'client->pers' and 'client->sess'  struct gclient_s @@ -550,6 +557,10 @@ struct gclient_s    int               tkcredits[ MAX_CLIENTS ];    int                 revertCookie; + +  qboolean            extrapolate; +  savedPosition_t     savedPositions[MAX_SAVED_POSITIONS]; +  int                 savedPositionsCount;  }; @@ -1391,6 +1402,7 @@ extern  vmCvar_t  g_popularMapsVotePercent;  extern  vmCvar_t  g_banIPs;  extern  vmCvar_t  g_filterBan;  extern  vmCvar_t  g_smoothClients; +extern  vmCvar_t  g_debugExtrapolation;  extern  vmCvar_t  g_outdatedClientMessage;  extern  vmCvar_t  pmove_fixed;  extern  vmCvar_t  pmove_msec; diff --git a/src/game/g_main.c b/src/game/g_main.c index 55508be..1c6d84e 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -122,6 +122,7 @@ vmCvar_t  g_popularMapsVotePercent;  vmCvar_t  g_banIPs;  vmCvar_t  g_filterBan;  vmCvar_t  g_smoothClients; +vmCvar_t  g_debugExtrapolation;  vmCvar_t  g_outdatedClientMessage;  vmCvar_t  pmove_fixed;  vmCvar_t  pmove_msec; @@ -416,6 +417,7 @@ static cvarTable_t   gameCvarTable[ ] =      "Set a name by pressing Escape and choosing Options", CVAR_ARCHIVE, 0, qfalse},    { &g_smoothClients, "g_smoothClients", "1", 0, 0, qfalse}, +  { &g_debugExtrapolation, "g_debugExtrapolation", "0", 0, 0, qfalse},     { &g_outdatedClientMessage, "g_outdatedClientMessage", "", CVAR_ARCHIVE, 0, qfalse},    { &pmove_fixed, "pmove_fixed", "0", CVAR_SYSTEMINFO, 0, qfalse},    { &pmove_msec, "pmove_msec", "8", CVAR_SYSTEMINFO, 0, qfalse},  | 
