]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_phys.c
newline change?
[xonotic/darkplaces.git] / sv_phys.c
index afe020c9a22037e655d88e07d74cdbea34b40160..09ec4653e5b7df58d5965028270fd3a8cfeb55e4 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
 
 See the GNU General Public License for more details.
 
@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
 
 
 pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
 
-onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects 
+onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects
 
 doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
 bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
 
 doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
 bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
@@ -39,11 +39,11 @@ solid_edge items only clip against bsp models.
 
 */
 
 
 */
 
-cvar_t sv_friction = {"sv_friction","4",false,true};
-cvar_t sv_stopspeed = {"sv_stopspeed","100"};
-cvar_t sv_gravity = {"sv_gravity","800",false,true};
-cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"};
-cvar_t sv_nostep = {"sv_nostep","0"};
+cvar_t sv_friction = {CVAR_NOTIFY, "sv_friction","4"};
+cvar_t sv_stopspeed = {0, "sv_stopspeed","100"};
+cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800"};
+cvar_t sv_maxvelocity = {0, "sv_maxvelocity","2000"};
+cvar_t sv_nostep = {0, "sv_nostep","0"};
 
 #define        MOVE_EPSILON    0.01
 
 
 #define        MOVE_EPSILON    0.01
 
@@ -118,7 +118,6 @@ void SV_CheckVelocity (edict_t *ent)
                ent->v.velocity[0] *= wishspeed;
                ent->v.velocity[1] *= wishspeed;
                ent->v.velocity[2] *= wishspeed;
                ent->v.velocity[0] *= wishspeed;
                ent->v.velocity[1] *= wishspeed;
                ent->v.velocity[2] *= wishspeed;
-               wishspeed = sv_maxvelocity.value;
        }
 }
 
        }
 }
 
@@ -137,7 +136,7 @@ qboolean SV_RunThink (edict_t *ent)
        float   thinktime;
 
        thinktime = ent->v.nextthink;
        float   thinktime;
 
        thinktime = ent->v.nextthink;
-       if (thinktime <= 0 || thinktime > sv.time + host_frametime)
+       if (thinktime <= 0 || thinktime > sv.time + sv.frametime)
                return true;
                
        if (thinktime < sv.time)
                return true;
                
        if (thinktime < sv.time)
@@ -162,10 +161,10 @@ Two entities have touched, so run their touch functions
 void SV_Impact (edict_t *e1, edict_t *e2)
 {
        int             old_self, old_other;
 void SV_Impact (edict_t *e1, edict_t *e2)
 {
        int             old_self, old_other;
-       
+
        old_self = pr_global_struct->self;
        old_other = pr_global_struct->other;
        old_self = pr_global_struct->self;
        old_other = pr_global_struct->other;
-       
+
        pr_global_struct->time = sv.time;
        if (e1->v.touch && e1->v.solid != SOLID_NOT)
        {
        pr_global_struct->time = sv.time;
        if (e1->v.touch && e1->v.solid != SOLID_NOT)
        {
@@ -173,7 +172,7 @@ void SV_Impact (edict_t *e1, edict_t *e2)
                pr_global_struct->other = EDICT_TO_PROG(e2);
                PR_ExecuteProgram (e1->v.touch, "");
        }
                pr_global_struct->other = EDICT_TO_PROG(e2);
                PR_ExecuteProgram (e1->v.touch, "");
        }
-       
+
        if (e2->v.touch && e2->v.solid != SOLID_NOT)
        {
                pr_global_struct->self = EDICT_TO_PROG(e2);
        if (e2->v.touch && e2->v.solid != SOLID_NOT)
        {
                pr_global_struct->self = EDICT_TO_PROG(e2);
@@ -201,13 +200,13 @@ int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
        float   backoff;
        float   change;
        int             i, blocked;
        float   backoff;
        float   change;
        int             i, blocked;
-       
+
        blocked = 0;
        if (normal[2] > 0)
                blocked |= 1;           // floor
        if (!normal[2])
                blocked |= 2;           // step
        blocked = 0;
        if (normal[2] > 0)
                blocked |= 1;           // floor
        if (!normal[2])
                blocked |= 2;           // step
-       
+
        backoff = DotProduct (in, normal) * overbounce;
 
        for (i=0 ; i<3 ; i++)
        backoff = DotProduct (in, normal) * overbounce;
 
        for (i=0 ; i<3 ; i++)
@@ -217,7 +216,7 @@ int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
                if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
                        out[i] = 0;
        }
                if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
                        out[i] = 0;
        }
-       
+
        return blocked;
 }
 
        return blocked;
 }
 
@@ -234,10 +233,7 @@ Returns the clipflags if the velocity was modified (hit something solid)
 If steptrace is not NULL, the trace of any vertical wall hit will be stored
 ============
 */
 If steptrace is not NULL, the trace of any vertical wall hit will be stored
 ============
 */
-// LordHavoc: increased from 5 to 20, to partially fix angled corner sticking
-// (example - start.bsp hall to e1m4, leading to the pool there are two
-//  angled corners, which you could get stuck on, now they are just a one
-//  frame hiccup)
+// LordHavoc: increased from 5 to 20
 #define        MAX_CLIP_PLANES 20
 int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
 {
 #define        MAX_CLIP_PLANES 20
 int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
 {
@@ -251,15 +247,15 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
        trace_t         trace;
        vec3_t          end;
        float           time_left;
        trace_t         trace;
        vec3_t          end;
        float           time_left;
-       int                     blocked;
-       
+       int                     blocked, impact;
+
        numbumps = 4;
        numbumps = 4;
-       
+
        blocked = 0;
        VectorCopy (ent->v.velocity, original_velocity);
        VectorCopy (ent->v.velocity, primal_velocity);
        numplanes = 0;
        blocked = 0;
        VectorCopy (ent->v.velocity, original_velocity);
        VectorCopy (ent->v.velocity, primal_velocity);
        numplanes = 0;
-       
+
        time_left = time;
 
        for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
        time_left = time;
 
        for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
@@ -270,13 +266,15 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
                for (i=0 ; i<3 ; i++)
                        end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
 
                for (i=0 ; i<3 ; i++)
                        end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
 
-               trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
+               trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
 
 
+               /*
                if (trace.allsolid)
                {       // entity is trapped in another solid
                        VectorClear(ent->v.velocity);
                        return 3;
                }
                if (trace.allsolid)
                {       // entity is trapped in another solid
                        VectorClear(ent->v.velocity);
                        return 3;
                }
+               */
 
                if (trace.fraction > 0)
                {       // actually covered some distance
 
                if (trace.fraction > 0)
                {       // actually covered some distance
@@ -291,10 +289,23 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
                if (!trace.ent)
                        Host_Error ("SV_FlyMove: !trace.ent");
 
                if (!trace.ent)
                        Host_Error ("SV_FlyMove: !trace.ent");
 
+               if ((int) ent->v.flags & FL_ONGROUND)
+               {
+                       if (ent->v.groundentity == EDICT_TO_PROG(trace.ent))
+                               impact = false;
+                       else
+                       {
+                               ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
+                               impact = true;
+                       }
+               }
+               else
+                       impact = true;
+
                if (trace.plane.normal[2] > 0.7)
                {
                        blocked |= 1;           // floor
                if (trace.plane.normal[2] > 0.7)
                {
                        blocked |= 1;           // floor
-                       if (trace.ent->v.solid == SOLID_BSP)
+                       //if (trace.ent->v.solid == SOLID_BSP)
                        {
                                ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
                                ent->v.groundentity = EDICT_TO_PROG(trace.ent);
                        {
                                ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
                                ent->v.groundentity = EDICT_TO_PROG(trace.ent);
@@ -310,13 +321,14 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
 //
 // run the impact function
 //
 //
 // run the impact function
 //
-               SV_Impact (ent, trace.ent);
+               if (impact)
+                       SV_Impact (ent, trace.ent);
                if (ent->free)
                        break;          // removed by the impact function
 
                if (ent->free)
                        break;          // removed by the impact function
 
-               
+
                time_left -= time_left * trace.fraction;
                time_left -= time_left * trace.fraction;
-               
+
        // cliped to another plane
                if (numplanes >= MAX_CLIP_PLANES)
                {       // this shouldn't really happen
        // cliped to another plane
                if (numplanes >= MAX_CLIP_PLANES)
                {       // this shouldn't really happen
@@ -342,7 +354,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
                        if (j == numplanes)
                                break;
                }
                        if (j == numplanes)
                                break;
                }
-               
+
                if (i != numplanes)
                {       // go along this plane
                        VectorCopy (new_velocity, ent->v.velocity);
                if (i != numplanes)
                {       // go along this plane
                        VectorCopy (new_velocity, ent->v.velocity);
@@ -356,6 +368,8 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
                                return 7;
                        }
                        CrossProduct (planes[0], planes[1], dir);
                                return 7;
                        }
                        CrossProduct (planes[0], planes[1], dir);
+                       // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
+                       VectorNormalize(dir);
                        d = DotProduct (dir, ent->v.velocity);
                        VectorScale (dir, d, ent->v.velocity);
                }
                        d = DotProduct (dir, ent->v.velocity);
                        VectorScale (dir, d, ent->v.velocity);
                }
@@ -392,7 +406,7 @@ void SV_AddGravity (edict_t *ent)
                ent_gravity = val->_float;
        else
                ent_gravity = 1.0;
                ent_gravity = val->_float;
        else
                ent_gravity = 1.0;
-       ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;
+       ent->v.velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime;
 }
 
 
 }
 
 
@@ -411,11 +425,11 @@ SV_PushEntity
 Does not change the entities velocity at all
 ============
 */
 Does not change the entities velocity at all
 ============
 */
-trace_t SV_PushEntity (edict_t *ent, vec3_t push)
+trace_t SV_PushEntity (edict_t *ent, vec3_t push, vec3_t pushangles)
 {
        trace_t trace;
        vec3_t  end;
 {
        trace_t trace;
        vec3_t  end;
-               
+
        VectorAdd (ent->v.origin, push, end);
 
        if (ent->v.movetype == MOVETYPE_FLYMISSILE)
        VectorAdd (ent->v.origin, push, end);
 
        if (ent->v.movetype == MOVETYPE_FLYMISSILE)
@@ -424,16 +438,17 @@ trace_t SV_PushEntity (edict_t *ent, vec3_t push)
        // only clip against bmodels
                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
        else
        // only clip against bmodels
                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
        else
-               trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);       
-       
+               trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
+
        VectorCopy (trace.endpos, ent->v.origin);
        VectorCopy (trace.endpos, ent->v.origin);
+       // FIXME: turn players specially
+       ent->v.angles[1] += trace.fraction * pushangles[1];
        SV_LinkEdict (ent, true);
 
        SV_LinkEdict (ent, true);
 
-       if (trace.ent)
-               SV_Impact (ent, trace.ent);             
-
+       if (trace.ent && (!((int)ent->v.flags & FL_ONGROUND) || ent->v.groundentity != EDICT_TO_PROG(trace.ent)))
+               SV_Impact (ent, trace.ent);
        return trace;
        return trace;
-}                                      
+}
 
 
 /*
 
 
 /*
@@ -442,16 +457,18 @@ SV_PushMove
 
 ============
 */
 
 ============
 */
+trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end);
 void SV_PushMove (edict_t *pusher, float movetime)
 {
 void SV_PushMove (edict_t *pusher, float movetime)
 {
-       int                     i, e;
+       int                     i, e, index;
        edict_t         *check;
        edict_t         *check;
-       vec3_t          mins, maxs, move;
-       vec3_t          entorig, pushorig;
+       float           savesolid, movetime2, pushltime;
+       vec3_t          mins, maxs, move, move1, moveangle, /*entorig, entang, */pushorig, pushang, a, forward, left, up, org, org2;
        int                     num_moved;
        edict_t         *moved_edict[MAX_EDICTS];
        int                     num_moved;
        edict_t         *moved_edict[MAX_EDICTS];
-       vec3_t          moved_from[MAX_EDICTS];
-       float           savesolid;
+       vec3_t          moved_from[MAX_EDICTS], moved_fromangles[MAX_EDICTS];
+       model_t         *pushermodel;
+       trace_t         trace;
 
        switch ((int) pusher->v.solid)
        {
 
        switch ((int) pusher->v.solid)
        {
@@ -465,33 +482,91 @@ void SV_PushMove (edict_t *pusher, float movetime)
        case SOLID_NOT:
        case SOLID_TRIGGER:
                VectorMA (pusher->v.origin, movetime, pusher->v.velocity, pusher->v.origin);
        case SOLID_NOT:
        case SOLID_TRIGGER:
                VectorMA (pusher->v.origin, movetime, pusher->v.velocity, pusher->v.origin);
+               VectorMA (pusher->v.angles, movetime, pusher->v.avelocity, pusher->v.angles);
                pusher->v.ltime += movetime;
                SV_LinkEdict (pusher, false);
                return;
        default:
                Host_Error("SV_PushMove: unrecognized solid type %f\n", pusher->v.solid);
        }
                pusher->v.ltime += movetime;
                SV_LinkEdict (pusher, false);
                return;
        default:
                Host_Error("SV_PushMove: unrecognized solid type %f\n", pusher->v.solid);
        }
-       if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
+       if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2] && !pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
        {
                pusher->v.ltime += movetime;
                return;
        }
        {
                pusher->v.ltime += movetime;
                return;
        }
-
-       for (i=0 ; i<3 ; i++)
+       index = (int) pusher->v.modelindex;
+       if (index < 1 || index >= MAX_MODELS)
+               Host_Error("SV_PushMove: invalid modelindex %f\n", pusher->v.modelindex);
+       pushermodel = sv.models[index];
+
+       // LordHavoc: round up by a small epsilon
+       movetime2 = movetime; // + (1.0 / 256.0);
+       VectorScale(pusher->v.velocity, movetime2, move1);
+       VectorScale(pusher->v.avelocity, movetime2, moveangle);
+       if (moveangle[0] || moveangle[2])
        {
        {
-               move[i] = pusher->v.velocity[i] * movetime;
-               mins[i] = pusher->v.absmin[i] + move[i];
-               maxs[i] = pusher->v.absmax[i] + move[i];
+               for (i = 0;i < 3;i++)
+               {
+                       if (move1[i] > 0)
+                       {
+                               mins[i] = pushermodel->rotatedmins[i] + pusher->v.origin[i] - 1;
+                               maxs[i] = pushermodel->rotatedmaxs[i] + move1[i] + pusher->v.origin[i] + 1;
+                       }
+                       else
+                       {
+                               mins[i] = pushermodel->rotatedmins[i] + move1[i] + pusher->v.origin[i] - 1;
+                               maxs[i] = pushermodel->rotatedmaxs[i] + pusher->v.origin[i] + 1;
+                       }
+               }
        }
        }
+       else if (moveangle[1])
+       {
+               for (i = 0;i < 3;i++)
+               {
+                       if (move1[i] > 0)
+                       {
+                               mins[i] = pushermodel->yawmins[i] + pusher->v.origin[i] - 1;
+                               maxs[i] = pushermodel->yawmaxs[i] + move1[i] + pusher->v.origin[i] + 1;
+                       }
+                       else
+                       {
+                               mins[i] = pushermodel->yawmins[i] + move1[i] + pusher->v.origin[i] - 1;
+                               maxs[i] = pushermodel->yawmaxs[i] + pusher->v.origin[i] + 1;
+                       }
+               }
+       }
+       else
+       {
+               for (i = 0;i < 3;i++)
+               {
+                       if (move1[i] > 0)
+                       {
+                               mins[i] = pushermodel->normalmins[i] + pusher->v.origin[i] - 1;
+                               maxs[i] = pushermodel->normalmaxs[i] + move1[i] + pusher->v.origin[i] + 1;
+                       }
+                       else
+                       {
+                               mins[i] = pushermodel->normalmins[i] + move1[i] + pusher->v.origin[i] - 1;
+                               maxs[i] = pushermodel->normalmaxs[i] + pusher->v.origin[i] + 1;
+                       }
+               }
+       }
+
+       VectorNegate (moveangle, a);
+       AngleVectorsFLU (a, forward, left, up);
 
        VectorCopy (pusher->v.origin, pushorig);
 
        VectorCopy (pusher->v.origin, pushorig);
-       
+       VectorCopy (pusher->v.angles, pushang);
+       pushltime = pusher->v.ltime;
+
 // move the pusher to it's final position
 
 // move the pusher to it's final position
 
-       VectorAdd (pusher->v.origin, move, pusher->v.origin);
+       VectorMA (pusher->v.origin, movetime, pusher->v.velocity, pusher->v.origin);
+       VectorMA (pusher->v.angles, movetime, pusher->v.avelocity, pusher->v.angles);
        pusher->v.ltime += movetime;
        SV_LinkEdict (pusher, false);
 
        pusher->v.ltime += movetime;
        SV_LinkEdict (pusher, false);
 
+       savesolid = pusher->v.solid;
 
 // see if any solid entities are inside the final position
        num_moved = 0;
 
 // see if any solid entities are inside the final position
        num_moved = 0;
@@ -510,213 +585,109 @@ void SV_PushMove (edict_t *pusher, float movetime)
                if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
                {
                        if (check->v.absmin[0] >= maxs[0]
                if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
                {
                        if (check->v.absmin[0] >= maxs[0]
-                        || check->v.absmin[1] >= maxs[1]
-                        || check->v.absmin[2] >= maxs[2]
                         || check->v.absmax[0] <= mins[0]
                         || check->v.absmax[0] <= mins[0]
+                        || check->v.absmin[1] >= maxs[1]
                         || check->v.absmax[1] <= mins[1]
                         || check->v.absmax[1] <= mins[1]
+                        || check->v.absmin[2] >= maxs[2]
                         || check->v.absmax[2] <= mins[2])
                                continue;
 
                         || check->v.absmax[2] <= mins[2])
                                continue;
 
+                       /*
+                       if (forward[0] < 0.999f) // quick way to check if any rotation is used
+                       {
+                               VectorSubtract (check->v.origin, pusher->v.origin, org);
+                               org2[0] = DotProduct (org, forward);
+                               org2[1] = DotProduct (org, left);
+                               org2[2] = DotProduct (org, up);
+                               //VectorSubtract (org2, org, move);
+                               //VectorAdd (move, move1, move);
+                               //VectorSubtract(check->v.origin, move, a);
+                               a[0] = check->v.origin[0] + (org[0] - org2[0]) - move1[0];
+                               a[1] = check->v.origin[1] + (org[1] - org2[1]) - move1[1];
+                               a[2] = check->v.origin[2] + (org[2] - org2[2]) - move1[2];
+                       }
+                       else
+                               VectorSubtract (check->v.origin, move1, a);
+
+                       trace = SV_ClipMoveToEntity (pusher, a, check->v.mins, check->v.maxs, check->v.origin);
+                       if (trace.fraction == 1 && !trace.startsolid)
+                               continue;
+                       */
+                       trace = SV_ClipMoveToEntity (pusher, check->v.origin, check->v.mins, check->v.maxs, check->v.origin);
+                       if (!trace.startsolid)
+                               continue;
+                       /*
                        // see if the ent's bbox is inside the pusher's final position
                        if (!SV_TestEntityPosition (check))
                                continue;
                        // see if the ent's bbox is inside the pusher's final position
                        if (!SV_TestEntityPosition (check))
                                continue;
+                       */
                }
 
                }
 
-               // remove the onground flag for non-players
-               if (check->v.movetype != MOVETYPE_WALK)
-                       check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
-               
-               VectorCopy (check->v.origin, entorig);
-               VectorCopy (check->v.origin, moved_from[num_moved]);
-               moved_edict[num_moved] = check;
-               num_moved++;
-
-               // LordHavoc: pusher fixes (teleport train bug, etc)
-               savesolid = pusher->v.solid;
-               if (savesolid == SOLID_BSP || savesolid == SOLID_BBOX || savesolid == SOLID_SLIDEBOX)
+               if (forward[0] < 0.999f) // quick way to check if any rotation is used
                {
                {
-                       // try moving the contacted entity
-                       pusher->v.solid = SOLID_NOT;
-                       SV_PushEntity (check, move);
-                       pusher->v.solid = savesolid; // was SOLID_BSP
-
-                       // if it is still inside the pusher, block
-                       if (SV_TestEntityPosition (check))
-                       {       // fail the move
-                               if (check->v.mins[0] == check->v.maxs[0])
-                                       continue;
-                               if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
-                               {       // corpse
-                                       check->v.mins[0] = check->v.mins[1] = 0;
-                                       VectorCopy (check->v.mins, check->v.maxs);
-                                       continue;
-                               }
-                               
-                               VectorCopy (entorig, check->v.origin);
-                               SV_LinkEdict (check, true);
-
-                               VectorCopy (pushorig, pusher->v.origin);
-                               SV_LinkEdict (pusher, false);
-                               pusher->v.ltime -= movetime;
-
-                               // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
-                               if (pusher->v.blocked)
-                               {
-                                       pr_global_struct->self = EDICT_TO_PROG(pusher);
-                                       pr_global_struct->other = EDICT_TO_PROG(check);
-                                       PR_ExecuteProgram (pusher->v.blocked, "");
-                               }
-                               
-                               // move back any entities we already moved
-                               num_moved--; // LordHavoc: pop off check, because it was already restored
-                               for (i=0 ; i<num_moved ; i++)
-                               {
-                                       VectorCopy (moved_from[i], moved_edict[i]->v.origin);
-                                       SV_LinkEdict (moved_edict[i], false);
-                               }
-                               return;
-                       }       
+                       VectorSubtract (check->v.origin, pusher->v.origin, org);
+                       org2[0] = DotProduct (org, forward);
+                       org2[1] = DotProduct (org, left);
+                       org2[2] = DotProduct (org, up);
+                       VectorSubtract (org2, org, move);
+                       VectorAdd (move, move1, move);
                }
                }
-       }
-
-       
-}
-
-/*
-============
-SV_PushRotate
-
-============
-*/
-void SV_PushRotate (edict_t *pusher, float movetime)
-{
-       int                     i, e;
-       edict_t         *check;
-       vec3_t          move, a, amove;
-       vec3_t          entorigin, entangles, pushorigin, pushangles;
-       int                     num_moved;
-       edict_t         *moved_edict[MAX_EDICTS];
-       vec3_t          moved_from[MAX_EDICTS];
-       vec3_t          angled_from[MAX_EDICTS];
-       vec3_t          org, org2;
-       vec3_t          forward, right, up;
-       float           savesolid;
-
-       switch ((int) pusher->v.solid)
-       {
-       // LordHavoc: valid pusher types
-       case SOLID_BSP:
-       case SOLID_BBOX:
-       case SOLID_SLIDEBOX:
-       case SOLID_CORPSE: // LordHavoc: this would be weird...
-               break;
-       // LordHavoc: no collisions
-       case SOLID_NOT:
-       case SOLID_TRIGGER:
-               VectorMA (pusher->v.angles, movetime, pusher->v.avelocity, pusher->v.angles);
-               pusher->v.ltime += movetime;
-               SV_LinkEdict (pusher, false);
-               return;
-       default:
-               Host_Error("SV_PushRotate: unrecognized solid type %f\n", pusher->v.solid);
-       }
-       if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
-       {
-               pusher->v.ltime += movetime;
-               return;
-       }
-
-       for (i=0 ; i<3 ; i++)
-               amove[i] = pusher->v.avelocity[i] * movetime;
-
-       VectorNegate (amove, a);
-       AngleVectors (a, forward, right, up);
-
-       VectorCopy (pusher->v.origin, pushorigin);
-       VectorCopy (pusher->v.angles, pushangles);
-       
-// move the pusher to it's final position
-
-       VectorAdd (pusher->v.angles, amove, pusher->v.angles);
-       pusher->v.ltime += movetime;
-       SV_LinkEdict (pusher, false);
-
-
-// see if any solid entities are inside the final position
-       num_moved = 0;
-       check = NEXT_EDICT(sv.edicts);
-       for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
-       {
-               if (check->free)
-                       continue;
-               if (check->v.movetype == MOVETYPE_PUSH
-                || check->v.movetype == MOVETYPE_NONE
-                || check->v.movetype == MOVETYPE_FOLLOW
-                || check->v.movetype == MOVETYPE_NOCLIP)
-                       continue;
+               else
+                       VectorCopy (move1, move);
 
 
-       // if the entity is standing on the pusher, it will definately be moved
-               if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
-               {
-                       if (check->v.absmin[0] >= pusher->v.absmax[0]
-                        || check->v.absmin[1] >= pusher->v.absmax[1]
-                        || check->v.absmin[2] >= pusher->v.absmax[2]
-                        || check->v.absmax[0] <= pusher->v.absmin[0]
-                        || check->v.absmax[1] <= pusher->v.absmin[1]
-                        || check->v.absmax[2] <= pusher->v.absmin[2])
-                               continue;
+               // LordHavoc: debugging
+               //VectorAdd(entorig, move, org2);
+               //CL_RocketTrail2 (entorig, org2, 238, NULL);
 
 
-               // see if the ent's bbox is inside the pusher's final position
-                       if (!SV_TestEntityPosition (check))
-                               continue;
-               }
-
-       // remove the onground flag for non-players
+               // remove the onground flag for non-players
                if (check->v.movetype != MOVETYPE_WALK)
                        check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
                if (check->v.movetype != MOVETYPE_WALK)
                        check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
-               
-               VectorCopy (check->v.origin, entorigin);
+
+               //VectorCopy (check->v.origin, entorig);
+               //VectorCopy (check->v.angles, entang);
                VectorCopy (check->v.origin, moved_from[num_moved]);
                VectorCopy (check->v.origin, moved_from[num_moved]);
-               VectorCopy (check->v.angles, entangles);
-               VectorCopy (check->v.angles, angled_from[num_moved]);
-               moved_edict[num_moved] = check;
-               num_moved++;
-
-               // calculate destination position
-               VectorSubtract (check->v.origin, pusher->v.origin, org);
-               org2[0] = DotProduct (org, forward);
-               org2[1] = -DotProduct (org, right);
-               org2[2] = DotProduct (org, up);
-               VectorSubtract (org2, org, move);
-
-               // try moving the contacted entity 
-               savesolid = pusher->v.solid; // LordHavoc: restore to correct solid type
-               pusher->v.solid = SOLID_NOT;
-               SV_PushEntity (check, move);
-               pusher->v.solid = savesolid; // LordHavoc: restore to correct solid type
+               VectorCopy (check->v.angles, moved_fromangles[num_moved]);
+               moved_edict[num_moved++] = check;
 
 
-               VectorAdd (check->v.angles, amove, check->v.angles);
+               // try moving the contacted entity
+               pusher->v.solid = SOLID_NOT;
+               trace = SV_PushEntity (check, move, moveangle);
+               pusher->v.solid = savesolid; // was SOLID_BSP
 
 
-       // if it is still inside the pusher, block
-               if (SV_TestEntityPosition (check))
-               {       // fail the move
+               // if it is still inside the pusher, block
+               // LordHavoc: cleanup - check trace.fraction and startsolid
+               if (/*trace.fraction != 1 || trace.startsolid || */SV_TestEntityPosition (check))
+               {
+                       // fail the move
                        if (check->v.mins[0] == check->v.maxs[0])
                                continue;
                        if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
                        if (check->v.mins[0] == check->v.maxs[0])
                                continue;
                        if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
-                       {       // corpse
+                       {
+                               // corpse
                                check->v.mins[0] = check->v.mins[1] = 0;
                                VectorCopy (check->v.mins, check->v.maxs);
                                continue;
                        }
                                check->v.mins[0] = check->v.mins[1] = 0;
                                VectorCopy (check->v.mins, check->v.maxs);
                                continue;
                        }
-                       
-                       VectorCopy (entorigin, check->v.origin);
-                       VectorCopy (entangles, check->v.angles);
+
+                       /*
+                       VectorCopy (entorig, check->v.origin);
+                       VectorCopy (entang, check->v.angles);
                        SV_LinkEdict (check, true);
                        SV_LinkEdict (check, true);
+                       */
 
 
-                       VectorCopy (pushorigin, pusher->v.origin);
-                       VectorCopy (pushangles, pusher->v.angles);
+                       VectorCopy (pushorig, pusher->v.origin);
+                       VectorCopy (pushang, pusher->v.angles);
+                       pusher->v.ltime = pushltime;
                        SV_LinkEdict (pusher, false);
                        SV_LinkEdict (pusher, false);
-                       pusher->v.ltime -= movetime;
+
+                       // move back any entities we already moved
+                       //num_moved--; // LordHavoc: pop off check, because it was already restored
+                       for (i=0 ; i<num_moved ; i++)
+                       {
+                               VectorCopy (moved_from[i], moved_edict[i]->v.origin);
+                               VectorCopy (moved_fromangles[i], moved_edict[i]->v.angles);
+                               SV_LinkEdict (moved_edict[i], false);
+                       }
 
                        // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
                        if (pusher->v.blocked)
 
                        // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
                        if (pusher->v.blocked)
@@ -725,15 +696,6 @@ void SV_PushRotate (edict_t *pusher, float movetime)
                                pr_global_struct->other = EDICT_TO_PROG(check);
                                PR_ExecuteProgram (pusher->v.blocked, "");
                        }
                                pr_global_struct->other = EDICT_TO_PROG(check);
                                PR_ExecuteProgram (pusher->v.blocked, "");
                        }
-                       
-               // move back any entities we already moved
-                       num_moved--; // LordHavoc: pop off check, because it was already restored
-                       for (i=0 ; i<num_moved ; i++)
-                       {
-                               VectorCopy (moved_from[i], moved_edict[i]->v.origin);
-                               VectorCopy (angled_from[i], moved_edict[i]->v.angles);
-                               SV_LinkEdict (moved_edict[i], false);
-                       }
                        return;
                }
        }
                        return;
                }
        }
@@ -752,25 +714,20 @@ void SV_Physics_Pusher (edict_t *ent)
        float   movetime;
 
        oldltime = ent->v.ltime;
        float   movetime;
 
        oldltime = ent->v.ltime;
-       
+
        thinktime = ent->v.nextthink;
        thinktime = ent->v.nextthink;
-       if (thinktime < ent->v.ltime + host_frametime)
+       if (thinktime < ent->v.ltime + sv.frametime)
        {
                movetime = thinktime - ent->v.ltime;
                if (movetime < 0)
                        movetime = 0;
        }
        else
        {
                movetime = thinktime - ent->v.ltime;
                if (movetime < 0)
                        movetime = 0;
        }
        else
-               movetime = host_frametime;
+               movetime = sv.frametime;
 
        if (movetime)
 
        if (movetime)
-       {
-               if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2])
-                       SV_PushRotate (ent, movetime);
-               else
-                       SV_PushMove (ent, movetime);    // advances ent->v.ltime if not blocked
-       }
-               
+               SV_PushMove (ent, movetime);    // advances ent->v.ltime if not blocked
+
        if (thinktime > oldltime && thinktime <= ent->v.ltime)
        {
                ent->v.nextthink = 0;
        if (thinktime > oldltime && thinktime <= ent->v.ltime)
        {
                ent->v.nextthink = 0;
@@ -854,7 +811,7 @@ qboolean SV_CheckWater (edict_t *ent)
 
        point[0] = ent->v.origin[0];
        point[1] = ent->v.origin[1];
 
        point[0] = ent->v.origin[0];
        point[1] = ent->v.origin[1];
-       point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;       
+       point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;
        
        ent->v.waterlevel = 0;
        ent->v.watertype = CONTENTS_EMPTY;
        
        ent->v.waterlevel = 0;
        ent->v.watertype = CONTENTS_EMPTY;
@@ -886,17 +843,17 @@ SV_WallFriction
 */
 void SV_WallFriction (edict_t *ent, trace_t *trace)
 {
 */
 void SV_WallFriction (edict_t *ent, trace_t *trace)
 {
-       vec3_t          forward, right, up;
+       vec3_t          forward;
        float           d, i;
        vec3_t          into, side;
        float           d, i;
        vec3_t          into, side;
-       
-       AngleVectors (ent->v.v_angle, forward, right, up);
+
+       AngleVectors (ent->v.v_angle, forward, NULL, NULL);
        d = DotProduct (trace->plane.normal, forward);
        
        d += 0.5;
        if (d >= 0)
                return;
        d = DotProduct (trace->plane.normal, forward);
        
        d += 0.5;
        if (d >= 0)
                return;
-               
+
 // cut the tangential velocity
        i = DotProduct (trace->plane.normal, ent->v.velocity);
        VectorScale (trace->plane.normal, i, into);
 // cut the tangential velocity
        i = DotProduct (trace->plane.normal, ent->v.velocity);
        VectorScale (trace->plane.normal, i, into);
@@ -925,7 +882,7 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
        vec3_t  dir;
        int             clip;
        trace_t steptrace;
        vec3_t  dir;
        int             clip;
        trace_t steptrace;
-       
+
        VectorCopy (ent->v.origin, oldorg);
        VectorClear (dir);
 
        VectorCopy (ent->v.origin, oldorg);
        VectorClear (dir);
 
@@ -943,13 +900,13 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
                        case 6: dir[0] = 2; dir[1] = -2; break;
                        case 7: dir[0] = -2; dir[1] = -2; break;
                }
                        case 6: dir[0] = 2; dir[1] = -2; break;
                        case 7: dir[0] = -2; dir[1] = -2; break;
                }
-               
-               SV_PushEntity (ent, dir);
+
+               SV_PushEntity (ent, dir, vec3_origin);
 
 // retry the original move
                ent->v.velocity[0] = oldvel[0];
 
 // retry the original move
                ent->v.velocity[0] = oldvel[0];
-               ent->v. velocity[1] = oldvel[1];
-               ent->v. velocity[2] = 0;
+               ent->v.velocity[1] = oldvel[1];
+               ent->v.velocity[2] = 0;
                clip = SV_FlyMove (ent, 0.1, &steptrace);
 
                if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
                clip = SV_FlyMove (ent, 0.1, &steptrace);
 
                if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
@@ -958,7 +915,7 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
 //Con_DPrintf ("unstuck!\n");
                        return clip;
                }
 //Con_DPrintf ("unstuck!\n");
                        return clip;
                }
-                       
+
 // go back to the original pos and try again
                VectorCopy (oldorg, ent->v.origin);
        }
 // go back to the original pos and try again
                VectorCopy (oldorg, ent->v.origin);
        }
@@ -983,30 +940,30 @@ void SV_WalkMove (edict_t *ent)
        int                     clip;
        int                     oldonground;
        trace_t         steptrace, downtrace;
        int                     clip;
        int                     oldonground;
        trace_t         steptrace, downtrace;
-       
+
 //
 // do a regular slide move unless it looks like you ran into a step
 //
        oldonground = (int)ent->v.flags & FL_ONGROUND;
        ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
 //
 // do a regular slide move unless it looks like you ran into a step
 //
        oldonground = (int)ent->v.flags & FL_ONGROUND;
        ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
-       
+
        VectorCopy (ent->v.origin, oldorg);
        VectorCopy (ent->v.velocity, oldvel);
        VectorCopy (ent->v.origin, oldorg);
        VectorCopy (ent->v.velocity, oldvel);
-       
-       clip = SV_FlyMove (ent, host_frametime, &steptrace);
+
+       clip = SV_FlyMove (ent, sv.frametime, &steptrace);
 
        if ( !(clip & 2) )
                return;         // move didn't block on a step
 
        if (!oldonground && ent->v.waterlevel == 0)
                return;         // don't stair up while jumping
 
        if ( !(clip & 2) )
                return;         // move didn't block on a step
 
        if (!oldonground && ent->v.waterlevel == 0)
                return;         // don't stair up while jumping
-       
+
        if (ent->v.movetype != MOVETYPE_WALK)
                return;         // gibbed by a trigger
        if (ent->v.movetype != MOVETYPE_WALK)
                return;         // gibbed by a trigger
-       
-       if (sv_nostep.value)
+
+       if (sv_nostep.integer)
                return;
                return;
-       
+
        if ( (int)sv_player->v.flags & FL_WATERJUMP )
                return;
 
        if ( (int)sv_player->v.flags & FL_WATERJUMP )
                return;
 
@@ -1021,16 +978,16 @@ void SV_WalkMove (edict_t *ent)
        VectorClear (upmove);
        VectorClear (downmove);
        upmove[2] = STEPSIZE;
        VectorClear (upmove);
        VectorClear (downmove);
        upmove[2] = STEPSIZE;
-       downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
+       downmove[2] = -STEPSIZE + oldvel[2]*sv.frametime;
 
 // move up
 
 // move up
-       SV_PushEntity (ent, upmove);    // FIXME: don't link?
+       SV_PushEntity (ent, upmove, vec3_origin);       // FIXME: don't link?
 
 // move forward
        ent->v.velocity[0] = oldvel[0];
        ent->v. velocity[1] = oldvel[1];
        ent->v. velocity[2] = 0;
 
 // move forward
        ent->v.velocity[0] = oldvel[0];
        ent->v. velocity[1] = oldvel[1];
        ent->v. velocity[2] = 0;
-       clip = SV_FlyMove (ent, host_frametime, &steptrace);
+       clip = SV_FlyMove (ent, sv.frametime, &steptrace);
 
 // check for stuckness, possibly due to the limited precision of floats
 // in the clipping hulls
 
 // check for stuckness, possibly due to the limited precision of floats
 // in the clipping hulls
@@ -1042,13 +999,13 @@ void SV_WalkMove (edict_t *ent)
                        clip = SV_TryUnstick (ent, oldvel);
                }
        }
                        clip = SV_TryUnstick (ent, oldvel);
                }
        }
-       
+
 // extra friction based on view angle
        if ( clip & 2 )
                SV_WallFriction (ent, &steptrace);
 
 // move down
 // extra friction based on view angle
        if ( clip & 2 )
                SV_WallFriction (ent, &steptrace);
 
 // move down
-       downtrace = SV_PushEntity (ent, downmove);      // FIXME: don't link?
+       downtrace = SV_PushEntity (ent, downmove, vec3_origin); // FIXME: don't link?
 
        if (downtrace.plane.normal[2] > 0.7)
        {
 
        if (downtrace.plane.normal[2] > 0.7)
        {
@@ -1062,7 +1019,7 @@ void SV_WalkMove (edict_t *ent)
        {
 // if the push down didn't end up on good ground, use the move without
 // the step up.  This happens near wall / slope combinations, and can
        {
 // if the push down didn't end up on good ground, use the move without
 // the step up.  This happens near wall / slope combinations, and can
-// cause the player to hop up higher on a slope too steep to climb     
+// cause the player to hop up higher on a slope too steep to climb
                VectorCopy (nosteporg, ent->v.origin);
                VectorCopy (nostepvel, ent->v.velocity);
        }
                VectorCopy (nosteporg, ent->v.origin);
                VectorCopy (nostepvel, ent->v.velocity);
        }
@@ -1083,11 +1040,11 @@ void SV_Physics_Client (edict_t *ent, int num)
 
 //
 // call standard client pre-think
 
 //
 // call standard client pre-think
-//     
+//
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(ent);
        PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(ent);
        PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
-       
+
 //
 // do a move
 //
 //
 // do a move
 //
@@ -1111,7 +1068,7 @@ void SV_Physics_Client (edict_t   *ent, int num)
                SV_CheckStuck (ent);
                SV_WalkMove (ent);
                break;
                SV_CheckStuck (ent);
                SV_WalkMove (ent);
                break;
-               
+
        case MOVETYPE_TOSS:
        case MOVETYPE_BOUNCE:
                SV_Physics_Toss (ent);
        case MOVETYPE_TOSS:
        case MOVETYPE_BOUNCE:
                SV_Physics_Toss (ent);
@@ -1121,23 +1078,23 @@ void SV_Physics_Client (edict_t *ent, int num)
                if (!SV_RunThink (ent))
                        return;
                SV_CheckWater (ent);
                if (!SV_RunThink (ent))
                        return;
                SV_CheckWater (ent);
-               SV_FlyMove (ent, host_frametime, NULL);
+               SV_FlyMove (ent, sv.frametime, NULL);
                break;
                break;
-               
+
        case MOVETYPE_NOCLIP:
                if (!SV_RunThink (ent))
                        return;
                SV_CheckWater (ent);
        case MOVETYPE_NOCLIP:
                if (!SV_RunThink (ent))
                        return;
                SV_CheckWater (ent);
-               VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
+               VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
                break;
                break;
-               
+
        default:
                Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
        }
 
 //
 // call standard player post-think
        default:
                Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
        }
 
 //
 // call standard player post-think
-//             
+//
        SV_LinkEdict (ent, true);
 
        pr_global_struct->time = sv.time;
        SV_LinkEdict (ent, true);
 
        pr_global_struct->time = sv.time;
@@ -1154,11 +1111,14 @@ SV_Physics_None
 Non moving objects can only think
 =============
 */
 Non moving objects can only think
 =============
 */
+// LordHavoc: inlined manually because it was a real time waster
+/*
 void SV_Physics_None (edict_t *ent)
 {
 // regular thinking
        SV_RunThink (ent);
 }
 void SV_Physics_None (edict_t *ent)
 {
 // regular thinking
        SV_RunThink (ent);
 }
+*/
 
 /*
 =============
 
 /*
 =============
@@ -1220,9 +1180,9 @@ void SV_Physics_Noclip (edict_t *ent)
 // regular thinking
        if (!SV_RunThink (ent))
                return;
 // regular thinking
        if (!SV_RunThink (ent))
                return;
-       
-       VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
-       VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
+
+       VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
+       VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
 
        SV_LinkEdict (ent, false);
 }
 
        SV_LinkEdict (ent, false);
 }
@@ -1251,13 +1211,13 @@ void SV_CheckWaterTransition (edict_t *ent)
                ent->v.waterlevel = 1;
                return;
        }
                ent->v.waterlevel = 1;
                return;
        }
-       
+
        if (cont <= CONTENTS_WATER)
        {
                if (ent->v.watertype == CONTENTS_EMPTY)
                {       // just crossed into water
                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
        if (cont <= CONTENTS_WATER)
        {
                if (ent->v.watertype == CONTENTS_EMPTY)
                {       // just crossed into water
                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
-               }               
+               }
                ent->v.watertype = cont;
                ent->v.waterlevel = 1;
        }
                ent->v.watertype = cont;
                ent->v.waterlevel = 1;
        }
@@ -1266,7 +1226,7 @@ void SV_CheckWaterTransition (edict_t *ent)
                if (ent->v.watertype != CONTENTS_EMPTY)
                {       // just crossed into water
                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
                if (ent->v.watertype != CONTENTS_EMPTY)
                {       // just crossed into water
                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
-               }               
+               }
                ent->v.watertype = CONTENTS_EMPTY;
                ent->v.waterlevel = cont;
        }
                ent->v.watertype = CONTENTS_EMPTY;
                ent->v.waterlevel = cont;
        }
@@ -1283,14 +1243,26 @@ void SV_Physics_Toss (edict_t *ent)
 {
        trace_t trace;
        vec3_t  move;
 {
        trace_t trace;
        vec3_t  move;
-       float   backoff;
+       //edict_t *groundentity;
        // regular thinking
        if (!SV_RunThink (ent))
                return;
 
 // if onground, return without moving
        // regular thinking
        if (!SV_RunThink (ent))
                return;
 
 // if onground, return without moving
-       if ( ((int)ent->v.flags & FL_ONGROUND) )
+       if (((int)ent->v.flags & FL_ONGROUND) && ent->v.groundentity == 0)
                return;
                return;
+       /*
+       if ( ((int)ent->v.flags & FL_ONGROUND) )
+       {
+               // LordHavoc: fall if the groundentity was removed
+               if (ent->v.groundentity)
+               {
+                       groundentity = PROG_TO_EDICT(ent->v.groundentity);
+                       if (groundentity && groundentity->v.solid != SOLID_NOT && groundentity->v.solid != SOLID_TRIGGER)
+                               return;
+               }
+       }
+       */
 
        SV_CheckVelocity (ent);
 
 
        SV_CheckVelocity (ent);
 
@@ -1301,37 +1273,50 @@ void SV_Physics_Toss (edict_t *ent)
                SV_AddGravity (ent);
 
 // move angles
                SV_AddGravity (ent);
 
 // move angles
-       VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
+       VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
 
 // move origin
 
 // move origin
-       VectorScale (ent->v.velocity, host_frametime, move);
-       trace = SV_PushEntity (ent, move);
-       if (trace.fraction == 1)
-               return;
+       VectorScale (ent->v.velocity, sv.frametime, move);
+       trace = SV_PushEntity (ent, move, vec3_origin);
        if (ent->free)
                return;
        if (ent->free)
                return;
-       
-       if (ent->v.movetype == MOVETYPE_BOUNCE)
-               backoff = 1.5;
-       else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
-               backoff = 2.0;
-       else
-               backoff = 1;
-
-       ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
+       if (trace.fraction == 1)
+               return;
 
 
-// stop if on ground
-       if (trace.plane.normal[2] > 0.7)
-       {               
-               if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
+       if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
+       {
+               ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, 2.0);
+               ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
+       }
+       else if (ent->v.movetype == MOVETYPE_BOUNCE)
+       {
+               ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, 1.5);
+               // LordHavoc: fixed grenades not bouncing when fired down a slope
+               if (trace.plane.normal[2] > 0.7 && DotProduct(trace.plane.normal, ent->v.velocity) < 60)
+               //if (trace.plane.normal[2] > 0.7 && ent->v.velocity[2] < 60)
                {
                        ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
                        ent->v.groundentity = EDICT_TO_PROG(trace.ent);
                        VectorClear (ent->v.velocity);
                        VectorClear (ent->v.avelocity);
                }
                {
                        ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
                        ent->v.groundentity = EDICT_TO_PROG(trace.ent);
                        VectorClear (ent->v.velocity);
                        VectorClear (ent->v.avelocity);
                }
+               else
+                       ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
        }
        }
-       
+       else
+       {
+               ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, 1.0);
+               if (trace.plane.normal[2] > 0.7)
+               {
+                       ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
+                       ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+                       VectorClear (ent->v.velocity);
+                       VectorClear (ent->v.avelocity);
+               }
+               else
+                       ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
+       }
+
 // check for in water
        SV_CheckWaterTransition (ent);
 }
 // check for in water
        SV_CheckWaterTransition (ent);
 }
@@ -1357,23 +1342,41 @@ will fall if the floor is pulled out from under them.
 */
 void SV_Physics_Step (edict_t *ent)
 {
 */
 void SV_Physics_Step (edict_t *ent)
 {
-       qboolean        hitsound;
+       int flags, fall, hitsound;
+
+       // freefall if not fly/swim
+       fall = true;
+       flags = (int)ent->v.flags;
+       if (flags & (FL_FLY | FL_SWIM))
+       {
+               if (flags & FL_FLY)
+                       fall = false;
+               else if ((flags & FL_SWIM) && SV_PointContents(ent->v.origin) != CONTENTS_EMPTY)
+                       fall = false;
+       }
+       if (fall && (flags & FL_ONGROUND) && ent->v.groundentity == 0)
+               fall = false;
 
 
-// freefall if not onground
-       if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
+       if (fall)
        {
                if (ent->v.velocity[2] < sv_gravity.value*-0.1)
        {
                if (ent->v.velocity[2] < sv_gravity.value*-0.1)
+               {
                        hitsound = true;
                        hitsound = true;
+                       if (flags & FL_ONGROUND)
+                               hitsound = false;
+               }
                else
                        hitsound = false;
 
                SV_AddGravity (ent);
                SV_CheckVelocity (ent);
                else
                        hitsound = false;
 
                SV_AddGravity (ent);
                SV_CheckVelocity (ent);
-               SV_FlyMove (ent, host_frametime, NULL);
-               SV_LinkEdict (ent, true);
+               SV_FlyMove (ent, sv.frametime, NULL);
+               SV_LinkEdict (ent, false);
 
 
-               if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
+               // just hit ground
+               if ((int)ent->v.flags & FL_ONGROUND)
                {
                {
+                       VectorClear(ent->v.velocity);
                        if (hitsound)
                                SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
                }
                        if (hitsound)
                                SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
                }
@@ -1381,7 +1384,7 @@ void SV_Physics_Step (edict_t *ent)
 
 // regular thinking
        SV_RunThink (ent);
 
 // regular thinking
        SV_RunThink (ent);
-       
+
        SV_CheckWaterTransition (ent);
 }
 
        SV_CheckWaterTransition (ent);
 }
 
@@ -1393,7 +1396,6 @@ SV_Physics
 
 ================
 */
 
 ================
 */
-extern dfunction_t *EndFrameQC;
 void SV_Physics (void)
 {
        int             i;
 void SV_Physics (void)
 {
        int             i;
@@ -1431,7 +1433,10 @@ void SV_Physics (void)
                        SV_Physics_Pusher (ent);
                        break;
                case MOVETYPE_NONE:
                        SV_Physics_Pusher (ent);
                        break;
                case MOVETYPE_NONE:
-                       SV_Physics_None (ent);
+//                     SV_Physics_None (ent);
+                       // LordHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects
+                       if (ent->v.nextthink > 0 && ent->v.nextthink <= sv.time + sv.frametime)
+                               SV_RunThink (ent);
                        break;
                case MOVETYPE_FOLLOW:
                        SV_Physics_Follow (ent);
                        break;
                case MOVETYPE_FOLLOW:
                        SV_Physics_Follow (ent);
@@ -1450,6 +1455,7 @@ void SV_Physics (void)
                                        SV_AddGravity (ent);
                                SV_CheckStuck (ent);
                                SV_WalkMove (ent);
                                        SV_AddGravity (ent);
                                SV_CheckStuck (ent);
                                SV_WalkMove (ent);
+                               SV_LinkEdict (ent, true);
                        }
                        break;
                case MOVETYPE_TOSS:
                        }
                        break;
                case MOVETYPE_TOSS:
@@ -1464,9 +1470,9 @@ void SV_Physics (void)
                        break;
                }
        }
                        break;
                }
        }
-       
+
        if (pr_global_struct->force_retouch)
        if (pr_global_struct->force_retouch)
-               pr_global_struct->force_retouch--;      
+               pr_global_struct->force_retouch--;
 
        // LordHavoc: endframe support
        if (EndFrameQC)
 
        // LordHavoc: endframe support
        if (EndFrameQC)
@@ -1477,39 +1483,48 @@ void SV_Physics (void)
                PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), "");
        }
 
                PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), "");
        }
 
-       sv.time += host_frametime;
+       sv.time += sv.frametime;
 }
 
 
 }
 
 
-trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
+trace_t SV_Trace_Toss (edict_t *tossent, edict_t *ignore)
 {
        int i;
        edict_t tempent, *tent;
        trace_t trace;
        vec3_t  move;
        vec3_t  end;
 {
        int i;
        edict_t tempent, *tent;
        trace_t trace;
        vec3_t  move;
        vec3_t  end;
-       double  save_frametime;
-
-       save_frametime = host_frametime;
-       host_frametime = 0.05;
+       float   gravity, savesolid;
+       eval_t  *val;
 
 
-       memcpy(&tempent, ent, sizeof(edict_t));
+       memcpy(&tempent, tossent, sizeof(edict_t));
        tent = &tempent;
        tent = &tempent;
+       savesolid = tossent->v.solid;
+       tossent->v.solid = SOLID_NOT;
+
+       // this has to fetch the field from the original edict, since our copy is truncated
+       val = GETEDICTFIELDVALUE(tossent, eval_gravity);
+       if (val != NULL && val->_float != 0)
+               gravity = val->_float;
+       else
+               gravity = 1.0;
+       gravity *= sv_gravity.value * 0.05;
 
        for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
        {
                SV_CheckVelocity (tent);
 
        for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
        {
                SV_CheckVelocity (tent);
-               SV_AddGravity (tent);
-               VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
-               VectorScale (tent->v.velocity, host_frametime, move);
+               tent->v.velocity[2] -= gravity;
+               VectorMA (tent->v.angles, 0.05, tent->v.avelocity, tent->v.angles);
+               VectorScale (tent->v.velocity, 0.05, move);
                VectorAdd (tent->v.origin, move, end);
                VectorAdd (tent->v.origin, move, end);
-               trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);   
+               trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);
                VectorCopy (trace.endpos, tent->v.origin);
 
                VectorCopy (trace.endpos, tent->v.origin);
 
-               if (trace.ent)
+               if (trace.fraction < 1 && trace.ent)
                        if (trace.ent != ignore)
                                break;
        }
                        if (trace.ent != ignore)
                                break;
        }
-       host_frametime = save_frametime;
+       tossent->v.solid = savesolid;
+       trace.fraction = 0; // not relevant
        return trace;
 }
        return trace;
 }