]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_phys.c
fix use of r_main_texturepool (it's a pointer, but this file imported it
[xonotic/darkplaces.git] / sv_phys.c
index 886d640bd816782afee9a819d2b37ca8a2f9b037..6de482673ece7bb62ad654f8c108ec72c450639b 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -756,17 +756,32 @@ Returns the clipflags if the velocity was modified (hit something solid)
 If stepnormal is not NULL, the plane normal of any vertical wall hit will be stored
 ============
 */
+static float SV_Gravity (prvm_edict_t *ent);
 // LordHavoc: increased from 5 to 32
 #define MAX_CLIP_PLANES 32
-int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal, int hitsupercontentsmask)
+static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, float *stepnormal, int hitsupercontentsmask)
 {
        int blocked, bumpcount;
        int i, j, impact, numplanes;
-       float d, time_left;
+       float d, time_left, gravity;
        vec3_t dir, end, planes[MAX_CLIP_PLANES], primal_velocity, original_velocity, new_velocity;
        trace_t trace;
        if (time <= 0)
                return 0;
+       gravity = 0;
+       if (applygravity)
+       {
+               if (sv_gameplayfix_gravityunaffectedbyticrate.integer)
+               {
+                       gravity = SV_Gravity(ent) * 0.5f;
+                       ent->fields.server->velocity[2] -= gravity;
+               }
+               else
+               {
+                       applygravity = false;
+                       ent->fields.server->velocity[2] -= SV_Gravity(ent);
+               }
+       }
        blocked = 0;
        VectorCopy(ent->fields.server->velocity, original_velocity);
        VectorCopy(ent->fields.server->velocity, primal_velocity);
@@ -980,16 +995,18 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal, int hitsuperco
        // LordHavoc: this came from QW and allows you to get out of water more easily
        if (sv_gameplayfix_easierwaterjump.integer && ((int)ent->fields.server->flags & FL_WATERJUMP))
                VectorCopy(primal_velocity, ent->fields.server->velocity);
+       if (applygravity && !((int)ent->fields.server->flags & FL_ONGROUND))
+               ent->fields.server->velocity[2] -= gravity;
        return blocked;
 }
 
 /*
 ============
-SV_AddGravity
+SV_Gravity
 
 ============
 */
-void SV_AddGravity (prvm_edict_t *ent)
+static float SV_Gravity (prvm_edict_t *ent)
 {
        float ent_gravity;
        prvm_eval_t *val;
@@ -999,7 +1016,7 @@ void SV_AddGravity (prvm_edict_t *ent)
                ent_gravity = val->_float;
        else
                ent_gravity = 1.0;
-       ent->fields.server->velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime;
+       return ent_gravity * sv_gravity.value * sv.frametime;
 }
 
 
@@ -1628,12 +1645,17 @@ void SV_WalkMove (prvm_edict_t *ent)
        int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity, hitsupercontentsmask;
        vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity;
        trace_t downtrace;
+       qboolean applygravity;
 
        // if frametime is 0 (due to client sending the same timestamp twice),
        // don't move
        if (sv.frametime <= 0)
                return;
 
+       SV_CheckStuck (ent);
+
+       applygravity = !SV_CheckWater (ent) && ent->fields.server->movetype == MOVETYPE_WALK && ! ((int)ent->fields.server->flags & FL_WATERJUMP);
+
        hitsupercontentsmask = SV_GenericHitSuperContentsMask(ent);
 
        SV_CheckVelocity(ent);
@@ -1644,13 +1666,14 @@ void SV_WalkMove (prvm_edict_t *ent)
        VectorCopy (ent->fields.server->origin, start_origin);
        VectorCopy (ent->fields.server->velocity, start_velocity);
 
-       clip = SV_FlyMove (ent, sv.frametime, NULL, hitsupercontentsmask);
+       clip = SV_FlyMove (ent, sv.frametime, applygravity, NULL, hitsupercontentsmask);
 
        // if the move did not hit the ground at any point, we're not on ground
        if (!(clip & 1))
                ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
 
        SV_CheckVelocity(ent);
+       SV_LinkEdict (ent, true);
 
        VectorCopy(ent->fields.server->origin, originalmove_origin);
        VectorCopy(ent->fields.server->velocity, originalmove_velocity);
@@ -1696,10 +1719,11 @@ void SV_WalkMove (prvm_edict_t *ent)
 
                // move forward
                ent->fields.server->velocity[2] = 0;
-               clip = SV_FlyMove (ent, sv.frametime, stepnormal, hitsupercontentsmask);
+               clip = SV_FlyMove (ent, sv.frametime, applygravity, stepnormal, hitsupercontentsmask);
                ent->fields.server->velocity[2] += start_velocity[2];
 
                SV_CheckVelocity(ent);
+               SV_LinkEdict (ent, true);
 
                // check for stuckness, possibly due to the limited precision of floats
                // in the clipping hulls
@@ -1763,6 +1787,7 @@ void SV_WalkMove (prvm_edict_t *ent)
        }
 
        SV_CheckVelocity(ent);
+       SV_LinkEdict (ent, true);
 }
 
 //============================================================================
@@ -1871,6 +1896,8 @@ void SV_Physics_Toss (prvm_edict_t *ent)
 {
        trace_t trace;
        vec3_t move;
+       vec_t movetime;
+       int bump;
 
 // if onground, return without moving
        if ((int)ent->fields.server->flags & FL_ONGROUND)
@@ -1900,27 +1927,30 @@ void SV_Physics_Toss (prvm_edict_t *ent)
 
 // add gravity
        if (ent->fields.server->movetype == MOVETYPE_TOSS || ent->fields.server->movetype == MOVETYPE_BOUNCE)
-               SV_AddGravity (ent);
+               ent->fields.server->velocity[2] -= SV_Gravity(ent);
 
 // move angles
        VectorMA (ent->fields.server->angles, sv.frametime, ent->fields.server->avelocity, ent->fields.server->angles);
 
-// move origin
-       VectorScale (ent->fields.server->velocity, sv.frametime, move);
-       trace = SV_PushEntity (ent, move, true);
-       if (ent->priv.server->free)
-               return;
-       if (trace.bmodelstartsolid)
+       movetime = sv.frametime;
+       for (bump = 0;bump < MAX_CLIP_PLANES && movetime > 0;bump++)
        {
-               // try to unstick the entity
-               SV_UnstickEntity(ent);
-               trace = SV_PushEntity (ent, move, false);
+       // move origin
+               VectorScale (ent->fields.server->velocity, movetime, move);
+               trace = SV_PushEntity (ent, move, true);
                if (ent->priv.server->free)
                        return;
-       }
-
-       if (trace.fraction < 1)
-       {
+               if (trace.bmodelstartsolid)
+               {
+                       // try to unstick the entity
+                       SV_UnstickEntity(ent);
+                       trace = SV_PushEntity (ent, move, false);
+                       if (ent->priv.server->free)
+                               return;
+               }
+               if (trace.fraction == 1)
+                       break;
+               movetime *= 1 - min(1, trace.fraction);
                if (ent->fields.server->movetype == MOVETYPE_BOUNCEMISSILE)
                {
                        ClipVelocity (ent->fields.server->velocity, trace.plane.normal, ent->fields.server->velocity, 2.0);
@@ -1928,13 +1958,19 @@ void SV_Physics_Toss (prvm_edict_t *ent)
                }
                else if (ent->fields.server->movetype == MOVETYPE_BOUNCE)
                {
-                       float d;
+                       float d, ent_gravity;
+                       prvm_eval_t *val;
                        ClipVelocity (ent->fields.server->velocity, trace.plane.normal, ent->fields.server->velocity, 1.5);
                        // LordHavoc: fixed grenades not bouncing when fired down a slope
+                       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.gravity);
+                       if (val!=0 && val->_float)
+                               ent_gravity = val->_float;
+                       else
+                               ent_gravity = 1.0;
                        if (sv_gameplayfix_grenadebouncedownslopes.integer)
                        {
                                d = DotProduct(trace.plane.normal, ent->fields.server->velocity);
-                               if (trace.plane.normal[2] > 0.7 && fabs(d) < 60)
+                               if (trace.plane.normal[2] > 0.7 && fabs(d) < sv_gravity.value * (60.0 / 800.0) * ent_gravity)
                                {
                                        ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
                                        ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
@@ -1946,7 +1982,7 @@ void SV_Physics_Toss (prvm_edict_t *ent)
                        }
                        else
                        {
-                               if (trace.plane.normal[2] > 0.7 && ent->fields.server->velocity[2] < 60)
+                               if (trace.plane.normal[2] > 0.7 && ent->fields.server->velocity[2] < sv_gravity.value * (60.0 / 800.0) * ent_gravity)
                                {
                                        ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
                                        ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
@@ -1972,6 +2008,8 @@ void SV_Physics_Toss (prvm_edict_t *ent)
                        else
                                ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
                }
+               if (!sv_gameplayfix_slidemoveprojectiles.integer || (ent->fields.server->movetype != MOVETYPE_BOUNCE && ent->fields.server->movetype == MOVETYPE_BOUNCEMISSILE))
+                       break;
        }
 
 // check for in water
@@ -2017,9 +2055,8 @@ void SV_Physics_Step (prvm_edict_t *ent)
                        if ((ent->fields.server->velocity[2] >= (1.0 / 32.0) && sv_gameplayfix_upwardvelocityclearsongroundflag.integer) || ent->fields.server->groundentity)
                        {
                                ent->fields.server->flags -= FL_ONGROUND;
-                               SV_AddGravity(ent);
                                SV_CheckVelocity(ent);
-                               SV_FlyMove(ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent));
+                               SV_FlyMove(ent, sv.frametime, true, NULL, SV_GenericHitSuperContentsMask(ent));
                                SV_LinkEdict(ent, true);
                                ent->priv.server->waterposition_forceupdate = true;
                        }
@@ -2029,9 +2066,8 @@ void SV_Physics_Step (prvm_edict_t *ent)
                        // freefall if not onground
                        int hitsound = ent->fields.server->velocity[2] < sv_gravity.value * -0.1;
 
-                       SV_AddGravity(ent);
                        SV_CheckVelocity(ent);
-                       SV_FlyMove(ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent));
+                       SV_FlyMove(ent, sv.frametime, true, NULL, SV_GenericHitSuperContentsMask(ent));
                        SV_LinkEdict(ent, true);
 
                        // just hit ground
@@ -2077,10 +2113,16 @@ void SV_Physics_Step (prvm_edict_t *ent)
 
 static void SV_Physics_Entity (prvm_edict_t *ent)
 {
-       // don't run a move on newly spawned projectiles as it messes up movement
-       // interpolation and rocket trails
+       // don't run think/move on newly spawned projectiles as it messes up
+       // movement interpolation and rocket trails, and is inconsistent with
+       // respect to entities spawned in the same frame
+       // (if an ent spawns a higher numbered ent, it moves in the same frame,
+       //  but if it spawns a lower numbered ent, it doesn't - this never moves
+       //  ents in the first frame regardless)
        qboolean runmove = ent->priv.server->move;
        ent->priv.server->move = true;
+       if (!runmove && sv_gameplayfix_delayprojectiles.integer)
+               return;
        switch ((int) ent->fields.server->movetype)
        {
        case MOVETYPE_PUSH:
@@ -2109,13 +2151,7 @@ static void SV_Physics_Entity (prvm_edict_t *ent)
                break;
        case MOVETYPE_WALK:
                if (SV_RunThink (ent))
-               {
-                       if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) )
-                               SV_AddGravity (ent);
-                       SV_CheckStuck (ent);
                        SV_WalkMove (ent);
-                       SV_LinkEdict (ent, true);
-               }
                break;
        case MOVETYPE_TOSS:
        case MOVETYPE_BOUNCE:
@@ -2123,7 +2159,7 @@ static void SV_Physics_Entity (prvm_edict_t *ent)
        case MOVETYPE_FLYMISSILE:
        case MOVETYPE_FLY:
                // regular thinking
-               if (SV_RunThink (ent) && (runmove || !sv_gameplayfix_delayprojectiles.integer))
+               if (SV_RunThink (ent))
                        SV_Physics_Toss (ent);
                break;
        default:
@@ -2158,17 +2194,8 @@ void SV_Physics_ClientMove(void)
                VectorClear(ent->fields.server->velocity);
 
        // perform MOVETYPE_WALK behavior
-       if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) )
-               SV_AddGravity (ent);
-       SV_CheckStuck (ent);
        SV_WalkMove (ent);
 
-       SV_CheckVelocity (ent);
-
-       SV_LinkEdict (ent, true);
-
-       SV_CheckVelocity (ent);
-
        // call standard player post-think, with frametime = 0
        prog->globals.server->time = sv.time;
        prog->globals.server->frametime = 0;
@@ -2198,7 +2225,7 @@ void SV_Physics_ClientEntity(prvm_edict_t *ent)
        }
 
        // don't run physics here if running asynchronously
-       if (host_client->clmovement_skipphysicsframes <= 0)
+       if (host_client->clmovement_inputtimeout <= 0)
        {
                SV_ClientThink();
                //host_client->cmd.time = max(host_client->cmd.time, sv.time);
@@ -2245,13 +2272,8 @@ void SV_Physics_ClientEntity(prvm_edict_t *ent)
        case MOVETYPE_WALK:
                SV_RunThink (ent);
                // don't run physics here if running asynchronously
-               if (host_client->clmovement_skipphysicsframes <= 0)
-               {
-                       if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) )
-                               SV_AddGravity (ent);
-                       SV_CheckStuck (ent);
+               if (host_client->clmovement_inputtimeout <= 0)
                        SV_WalkMove (ent);
-               }
                break;
        case MOVETYPE_TOSS:
        case MOVETYPE_BOUNCE:
@@ -2263,7 +2285,6 @@ void SV_Physics_ClientEntity(prvm_edict_t *ent)
                break;
        case MOVETYPE_FLY:
                SV_RunThink (ent);
-               SV_CheckWater (ent);
                SV_WalkMove (ent);
                break;
        default:
@@ -2273,8 +2294,10 @@ void SV_Physics_ClientEntity(prvm_edict_t *ent)
 
        // decrement the countdown variable used to decide when to go back to
        // synchronous physics
-       if (host_client->clmovement_skipphysicsframes > 0)
-               host_client->clmovement_skipphysicsframes--;
+       if (host_client->clmovement_inputtimeout > sv.frametime)
+               host_client->clmovement_inputtimeout -= sv.frametime;
+       else
+               host_client->clmovement_inputtimeout = 0;
 
        SV_CheckVelocity (ent);