@@ -395,24 +395,34 @@ static int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
395395 return blocked ;
396396}
397397
398+ static float SV_EntGravity (edict_t * ent )
399+ {
400+ eval_t * val = GetEdictFieldValue (ent , ED_FindFieldOffset ("gravity" ));
401+ return (val && val -> _float ) ? val -> _float : 1.0f ;
402+ }
403+
398404/*
399405============
400406SV_AddGravity
401407
408+ Gravity is applied in two phases: the move runs with velocity biased to the
409+ average of this frame's 72Hz gravity steps, which lands positions exactly on
410+ the canonical 72Hz trajectory for any frame duration. SV_FinishGravity removes
411+ the bias after the move; both phases sum to gravity*frametime and the bias is
412+ zero when frametime == 1/72.
402413============
403414*/
404415static void SV_AddGravity (edict_t * ent )
405416{
406- float ent_gravity ;
407- eval_t * val ;
408-
409- val = GetEdictFieldValue (ent , ED_FindFieldOffset ("gravity" ));
410- if (val && val -> _float )
411- ent_gravity = val -> _float ;
412- else
413- ent_gravity = 1.0 ;
417+ ent -> v .velocity [2 ] -= SV_EntGravity (ent ) * sv_gravity .value * (host_frametime + 1.0 / MAX_PHYSICS_FREQ ) * 0.5 ;
418+ }
414419
415- ent -> v .velocity [2 ] -= ent_gravity * sv_gravity .value * host_frametime ;
420+ static void SV_FinishGravity (edict_t * ent )
421+ {
422+ // entities that landed during the move keep their clipped velocity, like at 72fps
423+ if ((int )ent -> v .flags & FL_ONGROUND )
424+ return ;
425+ ent -> v .velocity [2 ] -= SV_EntGravity (ent ) * sv_gravity .value * (host_frametime - 1.0 / MAX_PHYSICS_FREQ ) * 0.5 ;
416426}
417427
418428/*
@@ -1029,10 +1039,20 @@ static void SV_Physics_Client (edict_t *ent, int num)
10291039 if (!SV_RunThink (ent ))
10301040 return ;
10311041 if (!SV_CheckWater (ent ) && !((int )ent -> v .flags & FL_WATERJUMP ))
1042+ {
10321043 SV_AddGravity (ent );
1033- SV_CheckStuck (ent );
1034- assert_always (!ent -> free );
1035- SV_WalkMove (ent );
1044+ SV_CheckStuck (ent );
1045+ assert_always (!ent -> free );
1046+ SV_WalkMove (ent );
1047+ if (!ent -> free )
1048+ SV_FinishGravity (ent );
1049+ }
1050+ else
1051+ {
1052+ SV_CheckStuck (ent );
1053+ assert_always (!ent -> free );
1054+ SV_WalkMove (ent );
1055+ }
10361056 break ;
10371057
10381058 case MOVETYPE_TOSS :
@@ -1184,11 +1204,15 @@ static void SV_Physics_Toss (edict_t *ent)
11841204 VectorScale (ent -> v .velocity , host_frametime , move );
11851205 trace = SV_PushEntity (ent , move );
11861206
1187- if (trace .fraction == 1 )
1188- return ;
11891207 if (ent -> free )
11901208 return ;
11911209
1210+ if (ent -> v .movetype != MOVETYPE_FLY && ent -> v .movetype != MOVETYPE_FLYMISSILE )
1211+ SV_FinishGravity (ent );
1212+
1213+ if (trace .fraction == 1 )
1214+ return ;
1215+
11921216 if (ent -> v .movetype == MOVETYPE_BOUNCE )
11931217 backoff = 1.5 ;
11941218 else
@@ -1256,6 +1280,8 @@ static void SV_Physics_Step (edict_t *ent)
12561280 if (ent -> free )
12571281 return ;
12581282
1283+ SV_FinishGravity (ent );
1284+
12591285 if ((int )ent -> v .flags & FL_ONGROUND ) // just hit ground
12601286 {
12611287 if (hitsound )
0 commit comments