]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_phys.c
fixed numerous bugs in SV_Trace_Toss
[xonotic/darkplaces.git] / sv_phys.c
index 56f1d1906148f378608b8d60619406681a1cbcd9..26775e843931350fa12becc0041b98b832ea40d4 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
 
@@ -137,7 +137,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)
@@ -148,7 +148,7 @@ qboolean SV_RunThink (edict_t *ent)
        pr_global_struct->time = thinktime;
        pr_global_struct->self = EDICT_TO_PROG(ent);
        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
        pr_global_struct->time = thinktime;
        pr_global_struct->self = EDICT_TO_PROG(ent);
        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
-       PR_ExecuteProgram (ent->v.think);
+       PR_ExecuteProgram (ent->v.think, "NULL think function");
        return !ent->free;
 }
 
        return !ent->free;
 }
 
@@ -171,14 +171,14 @@ void SV_Impact (edict_t *e1, edict_t *e2)
        {
                pr_global_struct->self = EDICT_TO_PROG(e1);
                pr_global_struct->other = EDICT_TO_PROG(e2);
        {
                pr_global_struct->self = EDICT_TO_PROG(e1);
                pr_global_struct->other = EDICT_TO_PROG(e2);
-               PR_ExecuteProgram (e1->v.touch);
+               PR_ExecuteProgram (e1->v.touch, "");
        }
        
        if (e2->v.touch && e2->v.solid != SOLID_NOT)
        {
                pr_global_struct->self = EDICT_TO_PROG(e2);
                pr_global_struct->other = EDICT_TO_PROG(e1);
        }
        
        if (e2->v.touch && e2->v.solid != SOLID_NOT)
        {
                pr_global_struct->self = EDICT_TO_PROG(e2);
                pr_global_struct->other = EDICT_TO_PROG(e1);
-               PR_ExecuteProgram (e2->v.touch);
+               PR_ExecuteProgram (e2->v.touch, "");
        }
 
        pr_global_struct->self = old_self;
        }
 
        pr_global_struct->self = old_self;
@@ -217,7 +217,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,7 +234,11 @@ 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
 ============
 */
-#define        MAX_CLIP_PLANES 5
+// LordHavoc: increased from 5 to 20, to partially fix angled corner sticking
+// (example - start.bsp hall to e4, leading to the pool there are two
+//  angled corners, which you could get stuck on, now they are just a one
+//  frame hiccup)
+#define        MAX_CLIP_PLANES 20
 int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
 {
        int                     bumpcount, numbumps;
 int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
 {
        int                     bumpcount, numbumps;
@@ -255,7 +259,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
        VectorCopy (ent->v.velocity, original_velocity);
        VectorCopy (ent->v.velocity, primal_velocity);
        numplanes = 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++)
@@ -266,11 +270,11 @@ 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
 
                if (trace.allsolid)
                {       // entity is trapped in another solid
-                       VectorCopy (vec3_origin, ent->v.velocity);
+                       VectorClear(ent->v.velocity);
                        return 3;
                }
 
                        return 3;
                }
 
@@ -316,7 +320,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
        // 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
-                       VectorCopy (vec3_origin, ent->v.velocity);
+                       VectorClear(ent->v.velocity);
                        return 3;
                }
 
                        return 3;
                }
 
@@ -348,10 +352,12 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
                        if (numplanes != 2)
                        {
 //                             Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
                        if (numplanes != 2)
                        {
 //                             Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
-                               VectorCopy (vec3_origin, ent->v.velocity);
+                               VectorClear(ent->v.velocity);
                                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);
                }
@@ -362,7 +368,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
 //
                if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
                {
 //
                if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
                {
-                       VectorCopy (vec3_origin, ent->v.velocity);
+                       VectorClear(ent->v.velocity);
                        return blocked;
                }
        }
                        return blocked;
                }
        }
@@ -388,7 +394,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;
 }
 
 
 }
 
 
@@ -449,6 +455,24 @@ void SV_PushMove (edict_t *pusher, float movetime)
        vec3_t          moved_from[MAX_EDICTS];
        float           savesolid;
 
        vec3_t          moved_from[MAX_EDICTS];
        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.origin, movetime, pusher->v.velocity, pusher->v.origin);
+               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])
        {
                pusher->v.ltime += movetime;
        if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
        {
                pusher->v.ltime += movetime;
@@ -537,16 +561,16 @@ void SV_PushMove (edict_t *pusher, float movetime)
                                SV_LinkEdict (pusher, false);
                                pusher->v.ltime -= movetime;
 
                                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 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);
                                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);
+                                       PR_ExecuteProgram (pusher->v.blocked, "");
                                }
                                
                                // move back any entities we already moved
                                }
                                
                                // 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);
                                for (i=0 ; i<num_moved ; i++)
                                {
                                        VectorCopy (moved_from[i], moved_edict[i]->v.origin);
@@ -571,14 +595,33 @@ void SV_PushRotate (edict_t *pusher, float movetime)
        int                     i, e;
        edict_t         *check;
        vec3_t          move, a, amove;
        int                     i, e;
        edict_t         *check;
        vec3_t          move, a, amove;
-       vec3_t          entorig, pushorig;
+       vec3_t          entorigin, entangles, pushorigin, pushangles;
        int                     num_moved;
        edict_t         *moved_edict[MAX_EDICTS];
        vec3_t          moved_from[MAX_EDICTS];
        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;
 
        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;
        if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
        {
                pusher->v.ltime += movetime;
@@ -588,10 +631,11 @@ void SV_PushRotate (edict_t *pusher, float movetime)
        for (i=0 ; i<3 ; i++)
                amove[i] = pusher->v.avelocity[i] * movetime;
 
        for (i=0 ; i<3 ; i++)
                amove[i] = pusher->v.avelocity[i] * movetime;
 
-       VectorSubtract (vec3_origin, amove, a);
+       VectorNegate (amove, a);
        AngleVectors (a, forward, right, up);
 
        AngleVectors (a, forward, right, up);
 
-       VectorCopy (pusher->v.angles, pushorig);
+       VectorCopy (pusher->v.origin, pushorigin);
+       VectorCopy (pusher->v.angles, pushangles);
        
 // move the pusher to it's final position
 
        
 // move the pusher to it's final position
 
@@ -608,21 +652,20 @@ void SV_PushRotate (edict_t *pusher, float movetime)
                if (check->free)
                        continue;
                if (check->v.movetype == MOVETYPE_PUSH
                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)
+                || check->v.movetype == MOVETYPE_NONE
+                || check->v.movetype == MOVETYPE_FOLLOW
+                || check->v.movetype == MOVETYPE_NOCLIP)
                        continue;
 
        // if the entity is standing on the pusher, it will definately be moved
                        continue;
 
        // 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 (!(((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] )
+                       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;
 
                // see if the ent's bbox is inside the pusher's final position
                                continue;
 
                // see if the ent's bbox is inside the pusher's final position
@@ -634,8 +677,10 @@ void SV_PushRotate (edict_t *pusher, float movetime)
                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, entorig);
+               VectorCopy (check->v.origin, entorigin);
                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++;
 
                moved_edict[num_moved] = check;
                num_moved++;
 
@@ -652,6 +697,8 @@ void SV_PushRotate (edict_t *pusher, float movetime)
                SV_PushEntity (check, move);
                pusher->v.solid = savesolid; // LordHavoc: restore to correct solid type
 
                SV_PushEntity (check, move);
                pusher->v.solid = savesolid; // LordHavoc: restore to correct solid type
 
+               VectorAdd (check->v.angles, amove, check->v.angles);
+
        // if it is still inside the pusher, block
                if (SV_TestEntityPosition (check))
                {       // fail the move
        // if it is still inside the pusher, block
                if (SV_TestEntityPosition (check))
                {       // fail the move
@@ -664,40 +711,35 @@ void SV_PushRotate (edict_t *pusher, float movetime)
                                continue;
                        }
                        
                                continue;
                        }
                        
-                       VectorCopy (entorig, check->v.origin);
+                       VectorCopy (entorigin, check->v.origin);
+                       VectorCopy (entangles, check->v.angles);
                        SV_LinkEdict (check, true);
 
                        SV_LinkEdict (check, true);
 
-                       VectorCopy (pushorig, pusher->v.angles);
+                       VectorCopy (pushorigin, pusher->v.origin);
+                       VectorCopy (pushangles, pusher->v.angles);
                        SV_LinkEdict (pusher, false);
                        pusher->v.ltime -= movetime;
 
                        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 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);
                        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);
+                               PR_ExecuteProgram (pusher->v.blocked, "");
                        }
                        
                // move back any entities we already moved
                        }
                        
                // 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);
                        for (i=0 ; i<num_moved ; i++)
                        {
                                VectorCopy (moved_from[i], moved_edict[i]->v.origin);
-                               VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
+                               VectorCopy (angled_from[i], moved_edict[i]->v.angles);
                                SV_LinkEdict (moved_edict[i], false);
                        }
                        return;
                }
                                SV_LinkEdict (moved_edict[i], false);
                        }
                        return;
                }
-               else
-               {
-                       VectorAdd (check->v.angles, amove, check->v.angles);
-               }
        }
        }
-
-       
 }
 }
-//#endif
 
 /*
 ================
 
 /*
 ================
@@ -712,16 +754,16 @@ 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)
        {
@@ -737,7 +779,7 @@ void SV_Physics_Pusher (edict_t *ent)
                pr_global_struct->time = sv.time;
                pr_global_struct->self = EDICT_TO_PROG(ent);
                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                pr_global_struct->time = sv.time;
                pr_global_struct->self = EDICT_TO_PROG(ent);
                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
-               PR_ExecuteProgram (ent->v.think);
+               PR_ExecuteProgram (ent->v.think, "NULL think function");
                if (ent->free)
                        return;
        }
                if (ent->free)
                        return;
        }
@@ -846,17 +888,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);
@@ -887,7 +929,7 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
        trace_t steptrace;
        
        VectorCopy (ent->v.origin, oldorg);
        trace_t steptrace;
        
        VectorCopy (ent->v.origin, oldorg);
-       VectorCopy (vec3_origin, dir);
+       VectorClear (dir);
 
        for (i=0 ; i<8 ; i++)
        {
 
        for (i=0 ; i<8 ; i++)
        {
@@ -908,8 +950,8 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
 
 // 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
@@ -923,7 +965,7 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
                VectorCopy (oldorg, ent->v.origin);
        }
        
                VectorCopy (oldorg, ent->v.origin);
        }
        
-       VectorCopy (vec3_origin, ent->v.velocity);
+       VectorClear (ent->v.velocity);
        return 7;               // still not moving
 }
 
        return 7;               // still not moving
 }
 
@@ -952,8 +994,8 @@ void SV_WalkMove (edict_t *ent)
        
        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 ( !(clip & 2) )
                return;         // move didn't block on a step
@@ -964,7 +1006,7 @@ void SV_WalkMove (edict_t *ent)
        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;
        
        if ( (int)sv_player->v.flags & FL_WATERJUMP )
                return;
        
        if ( (int)sv_player->v.flags & FL_WATERJUMP )
@@ -978,10 +1020,10 @@ void SV_WalkMove (edict_t *ent)
 //
        VectorCopy (oldorg, ent->v.origin);     // back to start pos
 
 //
        VectorCopy (oldorg, ent->v.origin);     // back to start pos
 
-       VectorCopy (vec3_origin, upmove);
-       VectorCopy (vec3_origin, downmove);
+       VectorClear (upmove);
+       VectorClear (downmove);
        upmove[2] = STEPSIZE;
        upmove[2] = STEPSIZE;
-       downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
+       downmove[2] = -STEPSIZE + oldvel[2]*sv.frametime;
 
 // move up
        SV_PushEntity (ent, upmove);    // FIXME: don't link?
 
 // move up
        SV_PushEntity (ent, upmove);    // FIXME: don't link?
@@ -990,7 +1032,7 @@ void SV_WalkMove (edict_t *ent)
        ent->v.velocity[0] = oldvel[0];
        ent->v. velocity[1] = oldvel[1];
        ent->v. velocity[2] = 0;
        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
@@ -1022,7 +1064,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);
        }
@@ -1046,7 +1088,7 @@ void SV_Physics_Client (edict_t   *ent, int num)
 //     
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(ent);
 //     
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(ent);
-       PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
+       PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
        
 //
 // do a move
        
 //
 // do a move
@@ -1080,13 +1122,15 @@ void SV_Physics_Client (edict_t *ent, int num)
        case MOVETYPE_FLY:
                if (!SV_RunThink (ent))
                        return;
        case MOVETYPE_FLY:
                if (!SV_RunThink (ent))
                        return;
-               SV_FlyMove (ent, host_frametime, NULL);
+               SV_CheckWater (ent);
+               SV_FlyMove (ent, sv.frametime, NULL);
                break;
                
        case MOVETYPE_NOCLIP:
                if (!SV_RunThink (ent))
                        return;
                break;
                
        case MOVETYPE_NOCLIP:
                if (!SV_RunThink (ent))
                        return;
-               VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
+               SV_CheckWater (ent);
+               VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
                break;
                
        default:
                break;
                
        default:
@@ -1100,7 +1144,7 @@ void SV_Physics_Client (edict_t   *ent, int num)
 
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(ent);
 
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(ent);
-       PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
+       PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
 }
 
 //============================================================================
 }
 
 //============================================================================
@@ -1112,11 +1156,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);
 }
+*/
 
 /*
 =============
 
 /*
 =============
@@ -1127,19 +1174,40 @@ Entities that are "stuck" to another entity
 */
 void SV_Physics_Follow (edict_t *ent)
 {
 */
 void SV_Physics_Follow (edict_t *ent)
 {
-       vec3_t vf, vu, vr, angles;
+       vec3_t vf, vr, vu, angles, v;
        edict_t *e;
 // regular thinking
        edict_t *e;
 // regular thinking
-       SV_RunThink (ent);
+       if (!SV_RunThink (ent))
+               return;
        // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
        e = PROG_TO_EDICT(ent->v.aiment);
        // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
        e = PROG_TO_EDICT(ent->v.aiment);
-       angles[0] = -e->v.angles[0];
-       angles[1] = e->v.angles[1];
-       angles[2] = e->v.angles[2];
-       AngleVectors (angles, vf, vr, vu);
-       VectorMA (e->v.origin, ent->v.view_ofs[0], vf, ent->v.origin);
-       VectorMA (ent->v.origin, ent->v.view_ofs[1], vr, ent->v.origin);
-       VectorMA (ent->v.origin, ent->v.view_ofs[2], vu, ent->v.origin);
+       if (e->v.angles[0] == ent->v.punchangle[0] && e->v.angles[1] == ent->v.punchangle[1] && e->v.angles[2] == ent->v.punchangle[2])
+       {
+               // quick case for no rotation
+               VectorAdd(e->v.origin, ent->v.view_ofs, ent->v.origin);
+       }
+       else
+       {
+               angles[0] = -ent->v.punchangle[0];
+               angles[1] =  ent->v.punchangle[1];
+               angles[2] =  ent->v.punchangle[2];
+               AngleVectors (angles, vf, vr, vu);
+               v[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[2] * vu[0];
+               v[1] = ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[2] * vu[1];
+               v[2] = ent->v.view_ofs[0] * vf[2] + ent->v.view_ofs[1] * vr[2] + ent->v.view_ofs[2] * vu[2];
+               angles[0] = -e->v.angles[0];
+               angles[1] =  e->v.angles[1];
+               angles[2] =  e->v.angles[2];
+               AngleVectors (angles, vf, vr, vu);
+               ent->v.origin[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + e->v.origin[0];
+               ent->v.origin[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + e->v.origin[1];
+               ent->v.origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->v.origin[2];
+               /*
+               ent->v.origin[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[0] * vf[2] + e->v.origin[0];
+               ent->v.origin[1] = ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[1] * vr[2] + e->v.origin[1];
+               ent->v.origin[2] = ent->v.view_ofs[2] * vu[0] + ent->v.view_ofs[2] * vu[1] + ent->v.view_ofs[2] * vu[2] + e->v.origin[2];
+               */
+       }
        VectorAdd (e->v.angles, ent->v.v_angle, ent->v.angles);
 //     VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
        SV_LinkEdict (ent, true);
        VectorAdd (e->v.angles, ent->v.v_angle, ent->v.angles);
 //     VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
        SV_LinkEdict (ent, true);
@@ -1158,8 +1226,8 @@ void SV_Physics_Noclip (edict_t *ent)
        if (!SV_RunThink (ent))
                return;
        
        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);
 }
@@ -1221,13 +1289,23 @@ void SV_Physics_Toss (edict_t *ent)
        trace_t trace;
        vec3_t  move;
        float   backoff;
        trace_t trace;
        vec3_t  move;
        float   backoff;
+       edict_t *groundentity;
        // regular thinking
        if (!SV_RunThink (ent))
                return;
 
 // if onground, return without moving
        if ( ((int)ent->v.flags & FL_ONGROUND) )
        // regular thinking
        if (!SV_RunThink (ent))
                return;
 
 // if onground, return without moving
        if ( ((int)ent->v.flags & FL_ONGROUND) )
-               return;
+       {
+               // 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;
+               }
+       }
+       ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
 
        SV_CheckVelocity (ent);
 
 
        SV_CheckVelocity (ent);
 
@@ -1238,16 +1316,16 @@ 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);
+       VectorScale (ent->v.velocity, sv.frametime, move);
        trace = SV_PushEntity (ent, move);
        if (trace.fraction == 1)
                return;
        if (ent->free)
                return;
        trace = SV_PushEntity (ent, move);
        if (trace.fraction == 1)
                return;
        if (ent->free)
                return;
-       
+
        if (ent->v.movetype == MOVETYPE_BOUNCE)
                backoff = 1.5;
        else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
        if (ent->v.movetype == MOVETYPE_BOUNCE)
                backoff = 1.5;
        else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
@@ -1259,16 +1337,22 @@ void SV_Physics_Toss (edict_t *ent)
 
 // stop if on ground
        if (trace.plane.normal[2] > 0.7)
 
 // 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))
+       {
+               // LordHavoc: fixed grenades not bouncing when fired down a slope
+               if (fabs(ent->v.velocity[2]) < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
+               //if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
                {
                        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);
-                       VectorCopy (vec3_origin, ent->v.velocity);
-                       VectorCopy (vec3_origin, ent->v.avelocity);
+                       VectorClear (ent->v.velocity);
+                       VectorClear (ent->v.avelocity);
                }
                }
+               else
+                       ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
        }
        }
-       
+       else
+               ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
+
 // check for in water
        SV_CheckWaterTransition (ent);
 }
 // check for in water
        SV_CheckWaterTransition (ent);
 }
@@ -1306,7 +1390,7 @@ void SV_Physics_Step (edict_t *ent)
 
                SV_AddGravity (ent);
                SV_CheckVelocity (ent);
 
                SV_AddGravity (ent);
                SV_CheckVelocity (ent);
-               SV_FlyMove (ent, host_frametime, NULL);
+               SV_FlyMove (ent, sv.frametime, NULL);
                SV_LinkEdict (ent, true);
 
                if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
                SV_LinkEdict (ent, true);
 
                if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
@@ -1318,7 +1402,7 @@ void SV_Physics_Step (edict_t *ent)
 
 // regular thinking
        SV_RunThink (ent);
 
 // regular thinking
        SV_RunThink (ent);
-       
+
        SV_CheckWaterTransition (ent);
 }
 
        SV_CheckWaterTransition (ent);
 }
 
@@ -1330,7 +1414,6 @@ SV_Physics
 
 ================
 */
 
 ================
 */
-extern dfunction_t *EndFrameQC;
 void SV_Physics (void)
 {
        int             i;
 void SV_Physics (void)
 {
        int             i;
@@ -1340,7 +1423,7 @@ void SV_Physics (void)
        pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
        pr_global_struct->time = sv.time;
-       PR_ExecuteProgram (pr_global_struct->StartFrame);
+       PR_ExecuteProgram (pr_global_struct->StartFrame, "QC function StartFrame is missing");
 
 //SV_CheckAllEnts ();
 
 
 //SV_CheckAllEnts ();
 
@@ -1354,41 +1437,56 @@ void SV_Physics (void)
                        continue;
 
                if (pr_global_struct->force_retouch)
                        continue;
 
                if (pr_global_struct->force_retouch)
-               {
                        SV_LinkEdict (ent, true);       // force retouch even for stationary
                        SV_LinkEdict (ent, true);       // force retouch even for stationary
-               }
 
                if (i > 0 && i <= svs.maxclients)
 
                if (i > 0 && i <= svs.maxclients)
+               {
                        SV_Physics_Client (ent, i);
                        SV_Physics_Client (ent, i);
-               else if (ent->v.movetype == MOVETYPE_PUSH)
+                       continue;
+               }
+
+               switch ((int) ent->v.movetype)
+               {
+               case MOVETYPE_PUSH:
                        SV_Physics_Pusher (ent);
                        SV_Physics_Pusher (ent);
-               else if (ent->v.movetype == MOVETYPE_NONE)
-                       SV_Physics_None (ent);
-               else if (ent->v.movetype == MOVETYPE_FOLLOW)
+                       break;
+               case MOVETYPE_NONE:
+//                     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);
                        SV_Physics_Follow (ent);
-               else if (ent->v.movetype == MOVETYPE_NOCLIP)
+                       break;
+               case MOVETYPE_NOCLIP:
                        SV_Physics_Noclip (ent);
                        SV_Physics_Noclip (ent);
-               else if (ent->v.movetype == MOVETYPE_STEP)
+                       break;
+               case MOVETYPE_STEP:
                        SV_Physics_Step (ent);
                        SV_Physics_Step (ent);
+                       break;
                // LordHavoc: added support for MOVETYPE_WALK on normal entities! :)
                // LordHavoc: added support for MOVETYPE_WALK on normal entities! :)
-               else if (ent->v.movetype == MOVETYPE_WALK)
-               {
+               case MOVETYPE_WALK:
                        if (SV_RunThink (ent))
                        {
                                if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
                                        SV_AddGravity (ent);
                                SV_CheckStuck (ent);
                                SV_WalkMove (ent);
                        if (SV_RunThink (ent))
                        {
                                if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
                                        SV_AddGravity (ent);
                                SV_CheckStuck (ent);
                                SV_WalkMove (ent);
+                               SV_LinkEdict (ent, true);
                        }
                        }
-               }
-               else if (ent->v.movetype == MOVETYPE_TOSS 
-               || ent->v.movetype == MOVETYPE_BOUNCE
-               || ent->v.movetype == MOVETYPE_BOUNCEMISSILE
-               || ent->v.movetype == MOVETYPE_FLY
-               || ent->v.movetype == MOVETYPE_FLYMISSILE)
+                       break;
+               case MOVETYPE_TOSS:
+               case MOVETYPE_BOUNCE:
+               case MOVETYPE_BOUNCEMISSILE:
+               case MOVETYPE_FLY:
+               case MOVETYPE_FLYMISSILE:
                        SV_Physics_Toss (ent);
                        SV_Physics_Toss (ent);
-               else
-                       Host_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);                       
+                       break;
+               default:
+                       Host_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);
+                       break;
+               }
        }
        
        if (pr_global_struct->force_retouch)
        }
        
        if (pr_global_struct->force_retouch)
@@ -1400,42 +1498,51 @@ void SV_Physics (void)
                pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                pr_global_struct->time = sv.time;
                pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                pr_global_struct->time = sv.time;
-               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;
 }