]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_collision.c
Fix setinfo.
[xonotic/darkplaces.git] / cl_collision.c
index 3283bc61f49f951a82e5056f303781512072be27..eb7a4dd923517688357fb72500d0ff00cd11124f 100644 (file)
@@ -2,47 +2,27 @@
 #include "quakedef.h"
 #include "cl_collision.h"
 
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-float CL_SelectTraceLine(const vec3_t start, const vec3_t pEnd, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent)
-#else
 float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent)
-#endif
 {
-       float maxfrac, maxrealfrac;
+       float maxfrac;
        int n;
        entity_render_t *ent;
-       float tracemins[3], tracemaxs[3];
+       vec_t tracemins[3], tracemaxs[3];
        trace_t trace;
-       float tempnormal[3], starttransformed[3], endtransformed[3];
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-       vec3_t end;
-       vec_t len = 0;
-
-       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
-       {
-               // TRICK: make the trace 1 qu longer!
-               VectorSubtract(pEnd, start, end);
-               len = VectorNormalizeLength(end);
-               VectorMA(pEnd, collision_endposnudge.value, end, end);
-       }
-       else
-               VectorCopy(pEnd, end);
-#endif
+       vec_t tempnormal[3], starttransformed[3], endtransformed[3];
 
        memset (&trace, 0 , sizeof(trace_t));
        trace.fraction = 1;
-       trace.realfraction = 1;
        VectorCopy (end, trace.endpos);
 
        if (hitent)
                *hitent = 0;
        if (cl.worldmodel && cl.worldmodel->TraceLine)
-               cl.worldmodel->TraceLine(cl.worldmodel, NULL, NULL, &trace, start, end, SUPERCONTENTS_SOLID);
+               cl.worldmodel->TraceLine(cl.worldmodel, NULL, NULL, &trace, start, end, SUPERCONTENTS_SOLID, 0, 0);
 
        if (normal)
                VectorCopy(trace.plane.normal, normal);
        maxfrac = trace.fraction;
-       maxrealfrac = trace.realfraction;
 
        tracemins[0] = min(start[0], end[0]);
        tracemaxs[0] = max(start[0], end[0]);
@@ -70,22 +50,17 @@ float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, ve
                        continue;
                Matrix4x4_Transform(&ent->inversematrix, start, starttransformed);
                Matrix4x4_Transform(&ent->inversematrix, end, endtransformed);
-               Collision_ClipTrace_Box(&trace, ent->model->normalmins, ent->model->normalmaxs, starttransformed, vec3_origin, vec3_origin, endtransformed, SUPERCONTENTS_SOLID, SUPERCONTENTS_SOLID, 0, NULL);
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-               if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
-                       Collision_ShortenTrace(&trace, len / (len + collision_endposnudge.value), pEnd);
-#endif
-               if (maxrealfrac < trace.realfraction)
+               Collision_ClipTrace_Box(&trace, ent->model->normalmins, ent->model->normalmaxs, starttransformed, vec3_origin, vec3_origin, endtransformed, SUPERCONTENTS_SOLID, 0, 0, SUPERCONTENTS_SOLID, 0, NULL);
+               if (maxfrac < trace.fraction)
                        continue;
 
-               ent->model->TraceLine(ent->model, ent->frameblend, ent->skeleton, &trace, starttransformed, endtransformed, SUPERCONTENTS_SOLID);
+               ent->model->TraceLine(ent->model, ent->frameblend, ent->skeleton, &trace, starttransformed, endtransformed, SUPERCONTENTS_SOLID, 0, 0);
 
-               if (maxrealfrac > trace.realfraction)
+               if (maxfrac > trace.fraction)
                {
                        if (hitent)
                                *hitent = n;
                        maxfrac = trace.fraction;
-                       maxrealfrac = trace.realfraction;
                        if (normal)
                        {
                                VectorCopy(trace.plane.normal, tempnormal);
@@ -94,7 +69,7 @@ float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, ve
                }
        }
        maxfrac = bound(0, maxfrac, 1);
-       maxrealfrac = bound(0, maxrealfrac, 1);
+       //maxrealfrac = bound(0, maxrealfrac, 1);
        //if (maxfrac < 0 || maxfrac > 1) Con_Printf("fraction out of bounds %f %s:%d\n", maxfrac, __FILE__, __LINE__);
        if (impact)
                VectorLerp(start, maxfrac, end, impact);
@@ -194,7 +169,7 @@ void CL_LinkEdict(prvm_edict_t *ent)
        VectorCopy(mins, PRVM_clientedictvector(ent, absmin));
        VectorCopy(maxs, PRVM_clientedictvector(ent, absmax));
 
-       World_LinkEdict(&cl.world, ent, PRVM_clientedictvector(ent, absmin), PRVM_clientedictvector(ent, absmax));
+       World_LinkEdict(&cl.world, ent, mins, maxs);
 }
 
 int CL_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
@@ -208,19 +183,19 @@ int CL_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
                else if (PRVM_clientedictfloat(passedict, solid) == SOLID_SLIDEBOX)
                {
                        if ((int)PRVM_clientedictfloat(passedict, flags) & FL_MONSTER)
-                               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_MONSTERCLIP | SUPERCONTENTS_SKY;
+                               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_MONSTERCLIP;
                        else
-                               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP | SUPERCONTENTS_SKY;
+                               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP;
                }
                else if (PRVM_clientedictfloat(passedict, solid) == SOLID_CORPSE)
-                       return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY;
+                       return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY;
                else if (PRVM_clientedictfloat(passedict, solid) == SOLID_TRIGGER)
-                       return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY;
+                       return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY;
                else
-                       return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE | SUPERCONTENTS_SKY;
+                       return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE;
        }
        else
-               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE | SUPERCONTENTS_SKY;
+               return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE;
 }
 
 /*
@@ -228,13 +203,15 @@ int CL_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
 CL_Move
 ==================
 */
-trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities)
+trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities)
 {
        prvm_prog_t *prog = CLVM_prog;
        int i, bodysupercontents;
        int passedictprog;
        prvm_edict_t *traceowner, *touch;
        trace_t trace;
+       // temporary storage because prvm_vec_t may need conversion
+       vec3_t touchmins, touchmaxs;
        // bounding box of entire move area
        vec3_t clipboxmins, clipboxmaxs;
        // size when clipping against monsters
@@ -262,8 +239,8 @@ trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
 #endif
 
        // clip to world
-       Collision_ClipPointToWorld(&cliptrace, cl.worldmodel, clipstart, hitsupercontentsmask);
-       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       Collision_ClipPointToWorld(&cliptrace, cl.worldmodel, clipstart, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
+       cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
        if (cliptrace.startsolid || cliptrace.fraction < 1)
                cliptrace.ent = prog ? prog->edicts : NULL;
        if (type == MOVE_WORLDONLY)
@@ -311,8 +288,8 @@ trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
                        entity_render_t *ent = &cl.entities[cl.brushmodel_entities[i]].render;
                        if (!BoxesOverlap(clipboxmins, clipboxmaxs, ent->mins, ent->maxs))
                                continue;
-                       Collision_ClipPointToGenericEntity(&trace, ent->model, ent->frameblend, ent->skeleton, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, hitsupercontentsmask);
-                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       Collision_ClipPointToGenericEntity(&trace, ent->model, ent->frameblend, ent->skeleton, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
+                       if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                                *hitnetworkentity = cl.brushmodel_entities[i];
                        Collision_CombineTraces(&cliptrace, &trace, NULL, true);
                }
@@ -324,7 +301,7 @@ trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
                vec3_t origin, entmins, entmaxs;
                matrix4x4_t entmatrix, entinversematrix;
 
-               if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+               if(IS_OLDNEXUIZ_DERIVED(gamemode))
                {
                        // don't hit network players, if we are a nonsolid player
                        if(cl.scores[cl.playerentity-1].frags == -666 || cl.scores[cl.playerentity-1].frags == -616)
@@ -340,10 +317,12 @@ trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
                                continue;
 
                        // don't hit players that don't exist
+                       if (!cl.entities_active[i])
+                               continue;
                        if (!cl.scores[i-1].name[0])
                                continue;
 
-                       if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+                       if(IS_OLDNEXUIZ_DERIVED(gamemode))
                        {
                                // don't hit spectators or nonsolid players
                                if(cl.scores[i-1].frags == -666 || cl.scores[i-1].frags == -616)
@@ -357,8 +336,8 @@ trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
                                continue;
                        Matrix4x4_CreateTranslate(&entmatrix, origin[0], origin[1], origin[2]);
                        Matrix4x4_CreateTranslate(&entinversematrix, -origin[0], -origin[1], -origin[2]);
-                       Collision_ClipPointToGenericEntity(&trace, NULL, NULL, NULL, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, hitsupercontentsmask);
-                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       Collision_ClipPointToGenericEntity(&trace, NULL, NULL, NULL, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
+                       if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                                *hitnetworkentity = i;
                        Collision_CombineTraces(&cliptrace, &trace, NULL, false);
                }
@@ -418,12 +397,14 @@ skipnetworkplayers:
                else
                        Matrix4x4_CreateTranslate(&matrix, PRVM_clientedictvector(touch, origin)[0], PRVM_clientedictvector(touch, origin)[1], PRVM_clientedictvector(touch, origin)[2]);
                Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               VectorCopy(PRVM_clientedictvector(touch, mins), touchmins);
+               VectorCopy(PRVM_clientedictvector(touch, maxs), touchmaxs);
                if ((int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)
-                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
+                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, 0.0f);
                else
-                       Collision_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
+                       Collision_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
 
-               if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+               if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                        *hitnetworkentity = 0;
                Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_clientedictfloat(touch, solid) == SOLID_BSP);
        }
@@ -437,17 +418,15 @@ finished:
 CL_TraceLine
 ==================
 */
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-trace_t CL_TraceLine(const vec3_t start, const vec3_t pEnd, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities, qboolean hitsurfaces)
-#else
-trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities, qboolean hitsurfaces)
-#endif
+trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities, qboolean hitsurfaces)
 {
        prvm_prog_t *prog = CLVM_prog;
        int i, bodysupercontents;
        int passedictprog;
        prvm_edict_t *traceowner, *touch;
        trace_t trace;
+       // temporary storage because prvm_vec_t may need conversion
+       vec3_t touchmins, touchmaxs;
        // bounding box of entire move area
        vec3_t clipboxmins, clipboxmaxs;
        // size when clipping against monsters
@@ -463,26 +442,8 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
        // list of entities to test for collisions
        int numtouchedicts;
        static prvm_edict_t *touchedicts[MAX_EDICTS];
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-       vec3_t end;
-       vec_t len = 0;
-
-       if (VectorCompare(start, pEnd))
-               return CL_TracePoint(start, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
-
-       if(collision_endposnudge.value > 0)
-       {
-               // TRICK: make the trace 1 qu longer!
-               VectorSubtract(pEnd, start, end);
-               len = VectorNormalizeLength(end);
-               VectorMA(pEnd, collision_endposnudge.value, end, end);
-       }
-       else
-               VectorCopy(pEnd, end);
-#else
        if (VectorCompare(start, end))
-               return CL_TracePoint(start, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
-#endif
+               return CL_TracePoint(start, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
 
        if (hitnetworkentity)
                *hitnetworkentity = 0;
@@ -496,8 +457,8 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
 #endif
 
        // clip to world
-       Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask, hitsurfaces);
-       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend, hitsurfaces);
+       cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
        if (cliptrace.startsolid || cliptrace.fraction < 1)
                cliptrace.ent = prog ? prog->edicts : NULL;
        if (type == MOVE_WORLDONLY)
@@ -545,8 +506,8 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
                        entity_render_t *ent = &cl.entities[cl.brushmodel_entities[i]].render;
                        if (!BoxesOverlap(clipboxmins, clipboxmaxs, ent->mins, ent->maxs))
                                continue;
-                       Collision_ClipLineToGenericEntity(&trace, ent->model, ent->frameblend, ent->skeleton, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, end, hitsupercontentsmask, hitsurfaces);
-                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       Collision_ClipLineToGenericEntity(&trace, ent->model, ent->frameblend, ent->skeleton, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend, hitsurfaces);
+                       if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                                *hitnetworkentity = cl.brushmodel_entities[i];
                        Collision_CombineTraces(&cliptrace, &trace, NULL, true);
                }
@@ -558,7 +519,7 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
                vec3_t origin, entmins, entmaxs;
                matrix4x4_t entmatrix, entinversematrix;
 
-               if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+               if(IS_OLDNEXUIZ_DERIVED(gamemode))
                {
                        // don't hit network players, if we are a nonsolid player
                        if(cl.scores[cl.playerentity-1].frags == -666 || cl.scores[cl.playerentity-1].frags == -616)
@@ -574,10 +535,12 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
                                continue;
 
                        // don't hit players that don't exist
+                       if (!cl.entities_active[i])
+                               continue;
                        if (!cl.scores[i-1].name[0])
                                continue;
 
-                       if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+                       if(IS_OLDNEXUIZ_DERIVED(gamemode))
                        {
                                // don't hit spectators or nonsolid players
                                if(cl.scores[i-1].frags == -666 || cl.scores[i-1].frags == -616)
@@ -591,8 +554,8 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
                                continue;
                        Matrix4x4_CreateTranslate(&entmatrix, origin[0], origin[1], origin[2]);
                        Matrix4x4_CreateTranslate(&entinversematrix, -origin[0], -origin[1], -origin[2]);
-                       Collision_ClipLineToGenericEntity(&trace, NULL, NULL, NULL, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, end, hitsupercontentsmask, hitsurfaces);
-                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       Collision_ClipLineToGenericEntity(&trace, NULL, NULL, NULL, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend, hitsurfaces);
+                       if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                                *hitnetworkentity = i;
                        Collision_CombineTraces(&cliptrace, &trace, NULL, false);
                }
@@ -652,21 +615,19 @@ skipnetworkplayers:
                else
                        Matrix4x4_CreateTranslate(&matrix, PRVM_clientedictvector(touch, origin)[0], PRVM_clientedictvector(touch, origin)[1], PRVM_clientedictvector(touch, origin)[2]);
                Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               VectorCopy(PRVM_clientedictvector(touch, mins), touchmins);
+               VectorCopy(PRVM_clientedictvector(touch, maxs), touchmaxs);
                if (type == MOVE_MISSILE && (int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)
-                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
                else
-                       Collision_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask, hitsurfaces);
+                       Collision_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend, hitsurfaces);
 
-               if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+               if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                        *hitnetworkentity = 0;
                Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_clientedictfloat(touch, solid) == SOLID_BSP);
        }
 
 finished:
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
-               Collision_ShortenTrace(&cliptrace, len / (len + collision_endposnudge.value), pEnd);
-#endif
        return cliptrace;
 }
 
@@ -675,11 +636,7 @@ finished:
 CL_Move
 ==================
 */
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t pEnd, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities)
-#else
-trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities)
-#endif
+trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities)
 {
        prvm_prog_t *prog = CLVM_prog;
        vec3_t hullmins, hullmaxs;
@@ -688,6 +645,8 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
        qboolean pointtrace;
        prvm_edict_t *traceowner, *touch;
        trace_t trace;
+       // temporary storage because prvm_vec_t may need conversion
+       vec3_t touchmins, touchmaxs;
        // bounding box of entire move area
        vec3_t clipboxmins, clipboxmaxs;
        // size of the moving object
@@ -705,46 +664,18 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
        // list of entities to test for collisions
        int numtouchedicts;
        static prvm_edict_t *touchedicts[MAX_EDICTS];
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-       vec3_t end;
-       vec_t len = 0;
-
-       if (VectorCompare(mins, maxs))
-       {
-               vec3_t shiftstart, shiftend;
-               VectorAdd(start, mins, shiftstart);
-               VectorAdd(pEnd, mins, shiftend);
-               if (VectorCompare(start, pEnd))
-                       trace = CL_TracePoint(shiftstart, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
-               else
-                       trace = CL_TraceLine(shiftstart, shiftend, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities, false);
-               VectorSubtract(trace.endpos, mins, trace.endpos);
-               return trace;
-       }
-
-       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
-       {
-               // TRICK: make the trace 1 qu longer!
-               VectorSubtract(pEnd, start, end);
-               len = VectorNormalizeLength(end);
-               VectorMA(pEnd, collision_endposnudge.value, end, end);
-       }
-       else
-               VectorCopy(pEnd, end);
-#else
        if (VectorCompare(mins, maxs))
        {
                vec3_t shiftstart, shiftend;
                VectorAdd(start, mins, shiftstart);
                VectorAdd(end, mins, shiftend);
                if (VectorCompare(start, end))
-                       trace = CL_TracePoint(shiftstart, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
+                       trace = CL_TracePoint(shiftstart, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
                else
-                       trace = CL_TraceLine(shiftstart, shiftend, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities, false);
+                       trace = CL_TraceLine(shiftstart, shiftend, type, passedict, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities, false);
                VectorSubtract(trace.endpos, mins, trace.endpos);
                return trace;
        }
-#endif
 
        if (hitnetworkentity)
                *hitnetworkentity = 0;
@@ -760,8 +691,8 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
 #endif
 
        // clip to world
-       Collision_ClipToWorld(&cliptrace, cl.worldmodel, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
-       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       Collision_ClipToWorld(&cliptrace, cl.worldmodel, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
+       cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
        if (cliptrace.startsolid || cliptrace.fraction < 1)
                cliptrace.ent = prog ? prog->edicts : NULL;
        if (type == MOVE_WORLDONLY)
@@ -820,8 +751,8 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
                        entity_render_t *ent = &cl.entities[cl.brushmodel_entities[i]].render;
                        if (!BoxesOverlap(clipboxmins, clipboxmaxs, ent->mins, ent->maxs))
                                continue;
-                       Collision_ClipToGenericEntity(&trace, ent->model, ent->frameblend, ent->skeleton, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, mins, maxs, end, hitsupercontentsmask);
-                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       Collision_ClipToGenericEntity(&trace, ent->model, ent->frameblend, ent->skeleton, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, mins, maxs, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
+                       if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                                *hitnetworkentity = cl.brushmodel_entities[i];
                        Collision_CombineTraces(&cliptrace, &trace, NULL, true);
                }
@@ -833,7 +764,7 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
                vec3_t origin, entmins, entmaxs;
                matrix4x4_t entmatrix, entinversematrix;
 
-               if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+               if(IS_OLDNEXUIZ_DERIVED(gamemode))
                {
                        // don't hit network players, if we are a nonsolid player
                        if(cl.scores[cl.playerentity-1].frags == -666 || cl.scores[cl.playerentity-1].frags == -616)
@@ -849,10 +780,12 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
                                continue;
 
                        // don't hit players that don't exist
+                       if (!cl.entities_active[i])
+                               continue;
                        if (!cl.scores[i-1].name[0])
                                continue;
 
-                       if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+                       if(IS_OLDNEXUIZ_DERIVED(gamemode))
                        {
                                // don't hit spectators or nonsolid players
                                if(cl.scores[i-1].frags == -666 || cl.scores[i-1].frags == -616)
@@ -866,8 +799,8 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
                                continue;
                        Matrix4x4_CreateTranslate(&entmatrix, origin[0], origin[1], origin[2]);
                        Matrix4x4_CreateTranslate(&entinversematrix, -origin[0], -origin[1], -origin[2]);
-                       Collision_ClipToGenericEntity(&trace, NULL, NULL, NULL, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, mins, maxs, end, hitsupercontentsmask);
-                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       Collision_ClipToGenericEntity(&trace, NULL, NULL, NULL, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, mins, maxs, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
+                       if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                                *hitnetworkentity = i;
                        Collision_CombineTraces(&cliptrace, &trace, NULL, false);
                }
@@ -927,21 +860,19 @@ skipnetworkplayers:
                else
                        Matrix4x4_CreateTranslate(&matrix, PRVM_clientedictvector(touch, origin)[0], PRVM_clientedictvector(touch, origin)[1], PRVM_clientedictvector(touch, origin)[2]);
                Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               VectorCopy(PRVM_clientedictvector(touch, mins), touchmins);
+               VectorCopy(PRVM_clientedictvector(touch, maxs), touchmaxs);
                if ((int)PRVM_clientedictfloat(touch, flags) & FL_MONSTER)
-                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
                else
-                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_clientedictvector(touch, mins), PRVM_clientedictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
+                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touchmins, touchmaxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, extend);
 
-               if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+               if (cliptrace.fraction > trace.fraction && hitnetworkentity)
                        *hitnetworkentity = 0;
                Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_clientedictfloat(touch, solid) == SOLID_BSP);
        }
 
 finished:
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
-               Collision_ShortenTrace(&cliptrace, len / (len + collision_endposnudge.value), pEnd);
-#endif
        return cliptrace;
 }
 
@@ -950,11 +881,7 @@ finished:
 CL_Cache_TraceLine
 ==================
 */
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t pEnd, int type, int hitsupercontentsmask)
-#else
-trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int type, int hitsupercontentsmask)
-#endif
+trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int type, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 {
        prvm_prog_t *prog = CLVM_prog;
        int i;
@@ -973,20 +900,6 @@ trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int typ
        // list of entities to test for collisions
        int numtouchedicts;
        static prvm_edict_t *touchedicts[MAX_EDICTS];
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-       vec3_t end;
-       vec_t len = 0;
-
-       if(collision_endposnudge.value > 0 && !VectorCompare(start, pEnd))
-       {
-               // TRICK: make the trace 1 qu longer!
-               VectorSubtract(pEnd, start, end);
-               len = VectorNormalizeLength(end);
-               VectorMA(pEnd, collision_endposnudge.value, end, end);
-       }
-       else
-               VectorCopy(pEnd, end);
-#endif
 
        VectorCopy(start, clipstart);
        VectorCopy(end, clipend);
@@ -995,8 +908,8 @@ trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int typ
 #endif
 
        // clip to world
-       Collision_Cache_ClipLineToWorldSurfaces(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask);
-       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       Collision_Cache_ClipLineToWorldSurfaces(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
+       cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
        if (cliptrace.startsolid || cliptrace.fraction < 1)
                cliptrace.ent = prog ? prog->edicts : NULL;
        if (type == MOVE_WORLDONLY)
@@ -1019,7 +932,7 @@ trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int typ
                entity_render_t *ent = &cl.entities[cl.brushmodel_entities[i]].render;
                if (!BoxesOverlap(clipboxmins, clipboxmaxs, ent->mins, ent->maxs))
                        continue;
-               Collision_Cache_ClipLineToGenericEntitySurfaces(&trace, ent->model, &ent->matrix, &ent->inversematrix, start, end, hitsupercontentsmask);
+               Collision_Cache_ClipLineToGenericEntitySurfaces(&trace, ent->model, &ent->matrix, &ent->inversematrix, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
                Collision_CombineTraces(&cliptrace, &trace, NULL, true);
        }
 
@@ -1046,22 +959,18 @@ trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int typ
                model = CL_GetModelFromEdict(touch);
                if (!model)
                        continue;
-               // animated models are too slow to collide against and can't be cached
-               if (touch->priv.server->frameblend || touch->priv.server->skeleton.relativetransforms)
+               // animated models are not suitable for caching
+               if ((touch->priv.server->frameblend && (touch->priv.server->frameblend[0].lerp != 1.0 || touch->priv.server->frameblend[0].subframe != 0)) || touch->priv.server->skeleton.relativetransforms)
                        continue;
                if (type == MOVE_NOMONSTERS && PRVM_clientedictfloat(touch, solid) != SOLID_BSP)
                        continue;
                Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_clientedictvector(touch, origin)[0], PRVM_clientedictvector(touch, origin)[1], PRVM_clientedictvector(touch, origin)[2], PRVM_clientedictvector(touch, angles)[0], PRVM_clientedictvector(touch, angles)[1], PRVM_clientedictvector(touch, angles)[2], 1);
                Matrix4x4_Invert_Simple(&imatrix, &matrix);
-               Collision_Cache_ClipLineToGenericEntitySurfaces(&trace, model, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask);
+               Collision_Cache_ClipLineToGenericEntitySurfaces(&trace, model, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
                Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_clientedictfloat(touch, solid) == SOLID_BSP);
        }
 
 finished:
-#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
-               Collision_ShortenTrace(&cliptrace, len / (len + collision_endposnudge.value), pEnd);
-#endif
        return cliptrace;
 }