]> 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 06ed1185f8e47c97aeb2549b545c35929b843f92..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
 
@@ -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;
 }
 
@@ -235,7 +235,7 @@ 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
 ============
 */
 // 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
+// (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
 //  angled corners, which you could get stuck on, now they are just a one
 //  frame hiccup)
 #define        MAX_CLIP_PLANES 20
@@ -259,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++)
@@ -270,7 +270,7 @@ 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
@@ -356,6 +356,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);
                }
@@ -752,7 +754,7 @@ void SV_Physics_Pusher (edict_t *ent)
        float   movetime;
 
        oldltime = ent->v.ltime;
        float   movetime;
 
        oldltime = ent->v.ltime;
-       
+
        thinktime = ent->v.nextthink;
        if (thinktime < ent->v.ltime + sv.frametime)
        {
        thinktime = ent->v.nextthink;
        if (thinktime < ent->v.ltime + sv.frametime)
        {
@@ -896,7 +898,7 @@ void SV_WallFriction (edict_t *ent, trace_t *trace)
        d += 0.5;
        if (d >= 0)
                return;
        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);
@@ -948,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
@@ -992,7 +994,7 @@ 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, sv.frametime, &steptrace);
 
        if ( !(clip & 2) )
        clip = SV_FlyMove (ent, sv.frametime, &steptrace);
 
        if ( !(clip & 2) )
@@ -1004,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 )
@@ -1062,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);
        }
@@ -1154,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);
 }
+*/
 
 /*
 =============
 
 /*
 =============
@@ -1284,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);
 
@@ -1310,7 +1325,7 @@ void SV_Physics_Toss (edict_t *ent)
                return;
        if (ent->free)
                return;
                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)
@@ -1322,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);
                        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
+               ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
+
 // check for in water
        SV_CheckWaterTransition (ent);
 }
 // check for in water
        SV_CheckWaterTransition (ent);
 }
@@ -1381,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);
 }
 
@@ -1393,7 +1414,6 @@ SV_Physics
 
 ================
 */
 
 ================
 */
-extern dfunction_t *EndFrameQC;
 void SV_Physics (void)
 {
        int             i;
 void SV_Physics (void)
 {
        int             i;
@@ -1431,7 +1451,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);
@@ -1482,31 +1505,44 @@ void SV_Physics (void)
 }
 
 
 }
 
 
-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;
+       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);
+               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);
                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);
-               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;
        }
+       tossent->v.solid = savesolid;
        trace.fraction = 0; // not relevant
        return trace;
 }
        trace.fraction = 0; // not relevant
        return trace;
 }