split CL_Move into CL_TracePoint, CL_TraceLine, CL_TraceBox and similar
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 3 Oct 2009 22:53:55 +0000 (22:53 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 3 Oct 2009 22:53:55 +0000 (22:53 +0000)
for SV_Move
split code paths for tracing lines and points out from box code
this is for better profiling reports because single statistics for Box,
Line and Point traces are unfair to the performance of line and point
traces

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9292 d7cf8633-e32d-0410-b094-e92efae38249

19 files changed:
cl_collision.c
cl_collision.h
cl_input.c
cl_main.c
cl_particles.c
clvm_cmds.c
collision.c
collision.h
model_alias.c
model_brush.c
model_shared.h
r_explosion.c
r_shadow.c
server.h
sv_move.c
sv_phys.c
sv_user.c
svvm_cmds.c
view.c

index 140e0e6..7f6d9c6 100644 (file)
@@ -36,8 +36,8 @@ float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, ve
 
        if (hitent)
                *hitent = 0;
-       if (cl.worldmodel && cl.worldmodel->TraceBox)
-               cl.worldmodel->TraceBox(cl.worldmodel, 0, &trace, start, vec3_origin, vec3_origin, end, SUPERCONTENTS_SOLID);
+       if (cl.worldmodel && cl.worldmodel->TraceLine)
+               cl.worldmodel->TraceLine(cl.worldmodel, 0, &trace, start, end, SUPERCONTENTS_SOLID);
 
        if (normal)
                VectorCopy(trace.plane.normal, normal);
@@ -59,7 +59,7 @@ float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, ve
                ent = &cl.entities[n].render;
                if (!BoxesOverlap(ent->mins, ent->maxs, tracemins, tracemaxs))
                        continue;
-               if (!ent->model || !ent->model->TraceBox)
+               if (!ent->model || !ent->model->TraceLine)
                        continue;
                if ((ent->flags & RENDER_EXTERIORMODEL) && !chase_active.integer)
                        continue;
@@ -78,7 +78,7 @@ float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, ve
                if (maxrealfrac < trace.realfraction)
                        continue;
 
-               ent->model->TraceBox(ent->model, ent->frameblend[0].subframe, &trace, starttransformed, vec3_origin, vec3_origin, endtransformed, SUPERCONTENTS_SOLID);
+               ent->model->TraceLine(ent->model, ent->frameblend[0].subframe, &trace, starttransformed, endtransformed, SUPERCONTENTS_SOLID);
 
                if (maxrealfrac > trace.realfraction)
                {
@@ -226,10 +226,462 @@ 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)
+{
+       int i, bodysupercontents;
+       int passedictprog;
+       prvm_edict_t *traceowner, *touch;
+       trace_t trace;
+       // bounding box of entire move area
+       vec3_t clipboxmins, clipboxmaxs;
+       // size when clipping against monsters
+       vec3_t clipmins2, clipmaxs2;
+       // start and end origin of move
+       vec3_t clipstart;
+       // trace results
+       trace_t cliptrace;
+       // matrices to transform into/out of other entity's space
+       matrix4x4_t matrix, imatrix;
+       // model of other entity
+       dp_model_t *model;
+       // list of entities to test for collisions
+       int numtouchedicts;
+       prvm_edict_t *touchedicts[MAX_EDICTS];
+
+       if (hitnetworkentity)
+               *hitnetworkentity = 0;
+
+       VectorCopy(start, clipstart);
+       VectorClear(clipmins2);
+       VectorClear(clipmaxs2);
+#if COLLISIONPARANOID >= 3
+       Con_Printf("move(%f %f %f)", clipstart[0], clipstart[1], clipstart[2]);
+#endif
+
+       // clip to world
+       Collision_ClipPointToWorld(&cliptrace, cl.worldmodel, clipstart, hitsupercontentsmask);
+       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       if (cliptrace.startsolid || cliptrace.fraction < 1)
+               cliptrace.ent = prog ? prog->edicts : NULL;
+       if (type == MOVE_WORLDONLY)
+               goto finished;
+
+       if (type == MOVE_MISSILE)
+       {
+               // LordHavoc: modified this, was = -15, now -= 15
+               for (i = 0;i < 3;i++)
+               {
+                       clipmins2[i] -= 15;
+                       clipmaxs2[i] += 15;
+               }
+       }
+
+       // create the bounding box of the entire move
+       for (i = 0;i < 3;i++)
+       {
+               clipboxmins[i] = clipstart[i] - 1;
+               clipboxmaxs[i] = clipstart[i] + 1;
+       }
+
+       // debug override to test against everything
+       if (sv_debugmove.integer)
+       {
+               clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = -999999999;
+               clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] =  999999999;
+       }
+
+       // if the passedict is world, make it NULL (to avoid two checks each time)
+       // this checks prog because this function is often called without a CSQC
+       // VM context
+       if (prog == NULL || passedict == prog->edicts)
+               passedict = NULL;
+       // precalculate prog value for passedict for comparisons
+       passedictprog = prog != NULL ? PRVM_EDICT_TO_PROG(passedict) : 0;
+       // precalculate passedict's owner edict pointer for comparisons
+       traceowner = passedict ? PRVM_PROG_TO_EDICT(passedict->fields.client->owner) : NULL;
+
+       // collide against network entities
+       if (hitnetworkbrushmodels)
+       {
+               for (i = 0;i < cl.num_brushmodel_entities;i++)
+               {
+                       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[0].subframe, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, hitsupercontentsmask);
+                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                               *hitnetworkentity = cl.brushmodel_entities[i];
+                       Collision_CombineTraces(&cliptrace, &trace, NULL, true);
+               }
+       }
+
+       // collide against player entities
+       if (hitnetworkplayers)
+       {
+               vec3_t origin, entmins, entmaxs;
+               matrix4x4_t entmatrix, entinversematrix;
+
+               if(gamemode == GAME_NEXUIZ)
+               {
+                       // 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)
+                               goto skipnetworkplayers;
+               }
+
+               for (i = 1;i <= cl.maxclients;i++)
+               {
+                       entity_render_t *ent = &cl.entities[i].render;
+
+                       // don't hit ourselves
+                       if (i == cl.playerentity)
+                               continue;
+
+                       // don't hit players that don't exist
+                       if (!cl.scores[i-1].name[0])
+                               continue;
+
+                       if(gamemode == GAME_NEXUIZ)
+                       {
+                               // don't hit spectators or nonsolid players
+                               if(cl.scores[i-1].frags == -666 || cl.scores[i-1].frags == -616)
+                                       continue;
+                       }
+
+                       Matrix4x4_OriginFromMatrix(&ent->matrix, origin);
+                       VectorAdd(origin, cl.playerstandmins, entmins);
+                       VectorAdd(origin, cl.playerstandmaxs, entmaxs);
+                       if (!BoxesOverlap(clipboxmins, clipboxmaxs, entmins, entmaxs))
+                               continue;
+                       Matrix4x4_CreateTranslate(&entmatrix, origin[0], origin[1], origin[2]);
+                       Matrix4x4_CreateTranslate(&entinversematrix, -origin[0], -origin[1], -origin[2]);
+                       Collision_ClipPointToGenericEntity(&trace, NULL, 0, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, hitsupercontentsmask);
+                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                               *hitnetworkentity = i;
+                       Collision_CombineTraces(&cliptrace, &trace, NULL, false);
+               }
+
+skipnetworkplayers:
+               ;
+       }
+
+       // clip to entities
+       // because this uses World_EntitiestoBox, we know all entity boxes overlap
+       // the clip region, so we can skip culling checks in the loop below
+       // note: if prog is NULL then there won't be any linked entities
+       numtouchedicts = 0;
+       if (hitcsqcentities && prog != NULL)
+       {
+               numtouchedicts = World_EntitiesInBox(&cl.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+               if (numtouchedicts > MAX_EDICTS)
+               {
+                       // this never happens
+                       Con_Printf("CL_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
+                       numtouchedicts = MAX_EDICTS;
+               }
+       }
+       for (i = 0;i < numtouchedicts;i++)
+       {
+               touch = touchedicts[i];
+
+               if (touch->fields.client->solid < SOLID_BBOX)
+                       continue;
+               if (type == MOVE_NOMONSTERS && touch->fields.client->solid != SOLID_BSP)
+                       continue;
+
+               if (passedict)
+               {
+                       // don't clip against self
+                       if (passedict == touch)
+                               continue;
+                       // don't clip owned entities against owner
+                       if (traceowner == touch)
+                               continue;
+                       // don't clip owner against owned entities
+                       if (passedictprog == touch->fields.client->owner)
+                               continue;
+                       // don't clip points against points (they can't collide)
+                       if (VectorCompare(touch->fields.client->mins, touch->fields.client->maxs) && (type != MOVE_MISSILE || !((int)touch->fields.client->flags & FL_MONSTER)))
+                               continue;
+               }
+
+               bodysupercontents = touch->fields.client->solid == SOLID_CORPSE ? SUPERCONTENTS_CORPSE : SUPERCONTENTS_BODY;
+
+               // might interact, so do an exact clip
+               model = NULL;
+               if ((int) touch->fields.client->solid == SOLID_BSP || type == MOVE_HITMODEL)
+               {
+                       unsigned int modelindex = (unsigned int)touch->fields.client->modelindex;
+                       // if the modelindex is 0, it shouldn't be SOLID_BSP!
+                       if (modelindex > 0 && modelindex < MAX_MODELS)
+                               model = cl.model_precache[(int)touch->fields.client->modelindex];
+               }
+               if (model)
+                       Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.client->origin[0], touch->fields.client->origin[1], touch->fields.client->origin[2], touch->fields.client->angles[0], touch->fields.client->angles[1], touch->fields.client->angles[2], 1);
+               else
+                       Matrix4x4_CreateTranslate(&matrix, touch->fields.client->origin[0], touch->fields.client->origin[1], touch->fields.client->origin[2]);
+               Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               if ((int)touch->fields.client->flags & FL_MONSTER)
+                       Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.client->frame, touch->fields.client->mins, touch->fields.client->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
+               else
+                       Collision_ClipPointToGenericEntity(&trace, model, (int) touch->fields.client->frame, touch->fields.client->mins, touch->fields.client->maxs, bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
+
+               if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       *hitnetworkentity = 0;
+               Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.client->solid == SOLID_BSP);
+       }
+
+finished:
+       return cliptrace;
+}
+
+/*
+==================
+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)
+#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)
+#endif
+{
+       int i, bodysupercontents;
+       int passedictprog;
+       prvm_edict_t *traceowner, *touch;
+       trace_t trace;
+       // bounding box of entire move area
+       vec3_t clipboxmins, clipboxmaxs;
+       // size when clipping against monsters
+       vec3_t clipmins2, clipmaxs2;
+       // start and end origin of move
+       vec3_t clipstart, clipend;
+       // trace results
+       trace_t cliptrace;
+       // matrices to transform into/out of other entity's space
+       matrix4x4_t matrix, imatrix;
+       // model of other entity
+       dp_model_t *model;
+       // list of entities to test for collisions
+       int numtouchedicts;
+       prvm_edict_t *touchedicts[MAX_EDICTS];
 #ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
-trace_t CL_Move(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)
+       vec3_t end;
+       vec_t len = 0;
+
+       if(!VectorCompare(start, pEnd))
+       {
+               // TRICK: make the trace 1 qu longer!
+               VectorSubtract(pEnd, start, end);
+               len = VectorNormalizeLength(end);
+               VectorAdd(pEnd, end, end);
+       }
+       else
+               VectorCopy(pEnd, end);
+#endif
+
+       if (VectorCompare(start, end))
+               return CL_TracePoint(start, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
+
+       if (hitnetworkentity)
+               *hitnetworkentity = 0;
+
+       VectorCopy(start, clipstart);
+       VectorCopy(end, clipend);
+       VectorClear(clipmins2);
+       VectorClear(clipmaxs2);
+#if COLLISIONPARANOID >= 3
+       Con_Printf("move(%f %f %f,%f %f %f)", clipstart[0], clipstart[1], clipstart[2], clipend[0], clipend[1], clipend[2]);
+#endif
+
+       // clip to world
+       Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask);
+       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       if (cliptrace.startsolid || cliptrace.fraction < 1)
+               cliptrace.ent = prog ? prog->edicts : NULL;
+       if (type == MOVE_WORLDONLY)
+               goto finished;
+
+       if (type == MOVE_MISSILE)
+       {
+               // LordHavoc: modified this, was = -15, now -= 15
+               for (i = 0;i < 3;i++)
+               {
+                       clipmins2[i] -= 15;
+                       clipmaxs2[i] += 15;
+               }
+       }
+
+       // create the bounding box of the entire move
+       for (i = 0;i < 3;i++)
+       {
+               clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + clipmins2[i] - 1;
+               clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + clipmaxs2[i] + 1;
+       }
+
+       // debug override to test against everything
+       if (sv_debugmove.integer)
+       {
+               clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = -999999999;
+               clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] =  999999999;
+       }
+
+       // if the passedict is world, make it NULL (to avoid two checks each time)
+       // this checks prog because this function is often called without a CSQC
+       // VM context
+       if (prog == NULL || passedict == prog->edicts)
+               passedict = NULL;
+       // precalculate prog value for passedict for comparisons
+       passedictprog = prog != NULL ? PRVM_EDICT_TO_PROG(passedict) : 0;
+       // precalculate passedict's owner edict pointer for comparisons
+       traceowner = passedict ? PRVM_PROG_TO_EDICT(passedict->fields.client->owner) : NULL;
+
+       // collide against network entities
+       if (hitnetworkbrushmodels)
+       {
+               for (i = 0;i < cl.num_brushmodel_entities;i++)
+               {
+                       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[0].subframe, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, end, hitsupercontentsmask);
+                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                               *hitnetworkentity = cl.brushmodel_entities[i];
+                       Collision_CombineTraces(&cliptrace, &trace, NULL, true);
+               }
+       }
+
+       // collide against player entities
+       if (hitnetworkplayers)
+       {
+               vec3_t origin, entmins, entmaxs;
+               matrix4x4_t entmatrix, entinversematrix;
+
+               if(gamemode == GAME_NEXUIZ)
+               {
+                       // 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)
+                               goto skipnetworkplayers;
+               }
+
+               for (i = 1;i <= cl.maxclients;i++)
+               {
+                       entity_render_t *ent = &cl.entities[i].render;
+
+                       // don't hit ourselves
+                       if (i == cl.playerentity)
+                               continue;
+
+                       // don't hit players that don't exist
+                       if (!cl.scores[i-1].name[0])
+                               continue;
+
+                       if(gamemode == GAME_NEXUIZ)
+                       {
+                               // don't hit spectators or nonsolid players
+                               if(cl.scores[i-1].frags == -666 || cl.scores[i-1].frags == -616)
+                                       continue;
+                       }
+
+                       Matrix4x4_OriginFromMatrix(&ent->matrix, origin);
+                       VectorAdd(origin, cl.playerstandmins, entmins);
+                       VectorAdd(origin, cl.playerstandmaxs, entmaxs);
+                       if (!BoxesOverlap(clipboxmins, clipboxmaxs, entmins, entmaxs))
+                               continue;
+                       Matrix4x4_CreateTranslate(&entmatrix, origin[0], origin[1], origin[2]);
+                       Matrix4x4_CreateTranslate(&entinversematrix, -origin[0], -origin[1], -origin[2]);
+                       Collision_ClipLineToGenericEntity(&trace, NULL, 0, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, end, hitsupercontentsmask);
+                       if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                               *hitnetworkentity = i;
+                       Collision_CombineTraces(&cliptrace, &trace, NULL, false);
+               }
+
+skipnetworkplayers:
+               ;
+       }
+
+       // clip to entities
+       // because this uses World_EntitiestoBox, we know all entity boxes overlap
+       // the clip region, so we can skip culling checks in the loop below
+       // note: if prog is NULL then there won't be any linked entities
+       numtouchedicts = 0;
+       if (hitcsqcentities && prog != NULL)
+       {
+               numtouchedicts = World_EntitiesInBox(&cl.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+               if (numtouchedicts > MAX_EDICTS)
+               {
+                       // this never happens
+                       Con_Printf("CL_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
+                       numtouchedicts = MAX_EDICTS;
+               }
+       }
+       for (i = 0;i < numtouchedicts;i++)
+       {
+               touch = touchedicts[i];
+
+               if (touch->fields.client->solid < SOLID_BBOX)
+                       continue;
+               if (type == MOVE_NOMONSTERS && touch->fields.client->solid != SOLID_BSP)
+                       continue;
+
+               if (passedict)
+               {
+                       // don't clip against self
+                       if (passedict == touch)
+                               continue;
+                       // don't clip owned entities against owner
+                       if (traceowner == touch)
+                               continue;
+                       // don't clip owner against owned entities
+                       if (passedictprog == touch->fields.client->owner)
+                               continue;
+                       // don't clip points against points (they can't collide)
+                       if (VectorCompare(touch->fields.client->mins, touch->fields.client->maxs) && (type != MOVE_MISSILE || !((int)touch->fields.client->flags & FL_MONSTER)))
+                               continue;
+               }
+
+               bodysupercontents = touch->fields.client->solid == SOLID_CORPSE ? SUPERCONTENTS_CORPSE : SUPERCONTENTS_BODY;
+
+               // might interact, so do an exact clip
+               model = NULL;
+               if ((int) touch->fields.client->solid == SOLID_BSP || type == MOVE_HITMODEL)
+               {
+                       unsigned int modelindex = (unsigned int)touch->fields.client->modelindex;
+                       // if the modelindex is 0, it shouldn't be SOLID_BSP!
+                       if (modelindex > 0 && modelindex < MAX_MODELS)
+                               model = cl.model_precache[(int)touch->fields.client->modelindex];
+               }
+               if (model)
+                       Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.client->origin[0], touch->fields.client->origin[1], touch->fields.client->origin[2], touch->fields.client->angles[0], touch->fields.client->angles[1], touch->fields.client->angles[2], 1);
+               else
+                       Matrix4x4_CreateTranslate(&matrix, touch->fields.client->origin[0], touch->fields.client->origin[1], touch->fields.client->origin[2]);
+               Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               if (type == MOVE_MISSILE && (int)touch->fields.client->flags & FL_MONSTER)
+                       Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.client->frame, touch->fields.client->mins, touch->fields.client->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+               else
+                       Collision_ClipLineToGenericEntity(&trace, model, (int) touch->fields.client->frame, touch->fields.client->mins, touch->fields.client->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask);
+
+               if (cliptrace.realfraction > trace.realfraction && hitnetworkentity)
+                       *hitnetworkentity = 0;
+               Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.client->solid == SOLID_BSP);
+       }
+
+finished:
+#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
+       if(!VectorCompare(start, pEnd))
+               Collision_ShortenTrace(&cliptrace, len / (len + 1), pEnd);
+#endif
+       return cliptrace;
+}
+
+/*
+==================
+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_Move(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)
+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
 {
        vec3_t hullmins, hullmaxs;
@@ -270,6 +722,21 @@ trace_t CL_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const
                VectorCopy(pEnd, end);
 #endif
 
+       if (VectorCompare(mins, maxs))
+       {
+               vec3_t shiftstart, shiftend;
+               VectorAdd(start, mins, shiftstart);
+               VectorAdd(end, mins, shiftend);
+               if (VectorCompare(start, end))
+                       return CL_TracePoint(shiftstart, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
+               else
+               {
+                       trace = CL_TraceLine(shiftstart, shiftend, type, passedict, hitsupercontentsmask, hitnetworkbrushmodels, hitnetworkplayers, hitnetworkentity, hitcsqcentities);
+                       VectorSubtract(trace.endpos, mins, trace.endpos);
+                       return trace;
+               }
+       }
+
        if (hitnetworkentity)
                *hitnetworkentity = 0;
 
index cf523f8..dbf3dd7 100644 (file)
@@ -10,7 +10,9 @@ dp_model_t *CL_GetModelFromEdict(prvm_edict_t *ed);
 
 void CL_LinkEdict(prvm_edict_t *ent);
 int CL_GenericHitSuperContentsMask(const prvm_edict_t *edict);
-trace_t CL_Move(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);
-#define CL_PointSuperContents(point) (CL_Move((point), vec3_origin, vec3_origin, (point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL, 0, true, false, NULL, false).startsupercontents)
+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);
+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);
+trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities);
+#define CL_PointSuperContents(point) (CL_TracePoint((point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL, 0, true, false, NULL, false).startsupercontents)
 
 #endif
index aae1f63..6e41506 100644 (file)
@@ -846,7 +846,7 @@ qboolean CL_ClientMovement_Unstick(cl_clientmovement_state_t *s)
        for (i = 0;i < NUMOFFSETS;i++)
        {
                VectorAdd(offsets[i], s->origin, neworigin);
-               if (!CL_Move(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false).startsolid)
+               if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false).startsolid)
                {
                        VectorCopy(neworigin, s->origin);
                        return true;
@@ -877,7 +877,7 @@ void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
                // low ceiling first
                if (s->crouched)
                {
-                       trace = CL_Move(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                       trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                        if (!trace.startsolid)
                                s->crouched = false;
                }
@@ -896,22 +896,22 @@ void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
        // set onground
        VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + 1);
        VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 1); // -2 causes clientside doublejump bug at above 150fps, raising that to 300fps :)
-       trace = CL_Move(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+       trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
        s->onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7;
 
        // set watertype/waterlevel
        VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + s->mins[2] + 1);
        s->waterlevel = WATERLEVEL_NONE;
-       s->watertype = CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
+       s->watertype = CL_TracePoint(origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
        if (s->watertype)
        {
                s->waterlevel = WATERLEVEL_WETFEET;
                origin1[2] = s->origin[2] + (s->mins[2] + s->maxs[2]) * 0.5f;
-               if (CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+               if (CL_TracePoint(origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
                {
                        s->waterlevel = WATERLEVEL_SWIMMING;
                        origin1[2] = s->origin[2] + 22;
-                       if (CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+                       if (CL_TracePoint(origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
                                s->waterlevel = WATERLEVEL_SUBMERGED;
                }
        }
@@ -938,20 +938,20 @@ void CL_ClientMovement_Move(cl_clientmovement_state_t *s)
        for (bump = 0, t = s->cmd.frametime;bump < 8 && VectorLength2(s->velocity) > 0;bump++)
        {
                VectorMA(s->origin, t, s->velocity, neworigin);
-               trace = CL_Move(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+               trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                if (trace.fraction < 1 && trace.plane.normal[2] == 0)
                {
                        // may be a step or wall, try stepping up
                        // first move forward at a higher level
                        VectorSet(currentorigin2, s->origin[0], s->origin[1], s->origin[2] + cl.movevars_stepheight);
                        VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + cl.movevars_stepheight);
-                       trace2 = CL_Move(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                       trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                        if (!trace2.startsolid)
                        {
                                // then move down from there
                                VectorCopy(trace2.endpos, currentorigin2);
                                VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], s->origin[2]);
-                               trace3 = CL_Move(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                               trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                                //Con_Printf("%f %f %f %f : %f %f %f %f : %f %f %f %f\n", trace.fraction, trace.endpos[0], trace.endpos[1], trace.endpos[2], trace2.fraction, trace2.endpos[0], trace2.endpos[1], trace2.endpos[2], trace3.fraction, trace3.endpos[0], trace3.endpos[1], trace3.endpos[2]);
                                // accept the new trace if it made some progress
                                if (fabs(trace3.endpos[0] - trace.endpos[0]) >= 0.03125 || fabs(trace3.endpos[1] - trace.endpos[1]) >= 0.03125)
@@ -1001,10 +1001,10 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
                AngleVectors(yawangles, forward, NULL, NULL);
                VectorMA(s->origin, 24, forward, spot);
                spot[2] += 8;
-               if (CL_Move(spot, vec3_origin, vec3_origin, spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
+               if (CL_TracePoint(spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
                {
                        spot[2] += 24;
-                       if (!CL_Move(spot, vec3_origin, vec3_origin, spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
+                       if (!CL_TracePoint(spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
                        {
                                VectorScale(forward, 50, s->velocity);
                                s->velocity[2] = 310;
@@ -1254,9 +1254,9 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                                VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/f), s->origin[1] + s->velocity[1]*(16/f), s->origin[2] + s->mins[2]);
                                VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34);
                                if (cls.protocol == PROTOCOL_QUAKEWORLD)
-                                       trace = CL_Move(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                                       trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                                else
-                                       trace = CL_Move(neworigin2, vec3_origin, vec3_origin, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                                       trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                                if (trace.fraction == 1 && !trace.startsolid)
                                        friction *= cl.movevars_edgefriction;
                        }
@@ -1478,13 +1478,13 @@ void CL_ClientMovement_Replay(void)
                        cl.movecmd[i].canjump = s.cmd.canjump;
                }
                //Con_Printf("\n");
+               CL_ClientMovement_UpdateStatus(&s);
        }
        else
        {
                // get the first movement queue entry to know whether to crouch and such
                s.cmd = cl.movecmd[0];
        }
-       CL_ClientMovement_UpdateStatus(&s);
 
        if (cls.demoplayback) // for bob, speedometer
                VectorCopy(cl.mvelocity[0], cl.movement_velocity);
index cd2d7cc..0fe873b 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -1354,7 +1354,7 @@ void CL_LinkNetworkEntity(entity_t *e)
                trace_t trace;
                matrix4x4_t tempmatrix;
                Matrix4x4_Transform(&e->render.matrix, muzzleflashorigin, v2);
-               trace = CL_Move(origin, vec3_origin, vec3_origin, v2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, NULL, false);
+               trace = CL_TraceLine(origin, v2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, NULL, false);
                Matrix4x4_Normalize(&tempmatrix, &e->render.matrix);
                Matrix4x4_SetOrigin(&tempmatrix, trace.endpos[0], trace.endpos[1], trace.endpos[2]);
                Matrix4x4_Scale(&tempmatrix, 150, 1);
index e935cab..ae5aa38 100644 (file)
@@ -613,7 +613,7 @@ static particle_t *CL_NewParticle(unsigned short ptypeindex, int pcolor1, int pc
                part->typeindex = pt_spark;
                part->bounce = 0;
                VectorMA(part->org, lifetime, part->vel, endvec);
-               trace = CL_Move(part->org, vec3_origin, vec3_origin, endvec, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_LIQUIDSMASK, true, false, NULL, false);
+               trace = CL_TraceLine(part->org, endvec, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_LIQUIDSMASK, true, false, NULL, false);
                part->die = cl.time + lifetime * trace.fraction;
                part2 = CL_NewParticle(pt_raindecal, pcolor1, pcolor2, tex_rainsplash, part->size, part->size * 20, part->alpha, part->alpha / 0.4, 0, 0, trace.endpos[0] + trace.plane.normal[0], trace.endpos[1] + trace.plane.normal[1], trace.endpos[2] + trace.plane.normal[2], trace.plane.normal[0], trace.plane.normal[1], trace.plane.normal[2], 0, 0, 0, 0, pqualityreduction, 0, 1, PBLEND_ADD, PARTICLE_ORIENTED_DOUBLESIDED, -1, -1, -1);
                if (part2)
@@ -637,7 +637,7 @@ static particle_t *CL_NewParticle(unsigned short ptypeindex, int pcolor1, int pc
                vec3_t endvec;
                trace_t trace;
                VectorMA(part->org, lifetime, part->vel, endvec);
-               trace = CL_Move(part->org, vec3_origin, vec3_origin, endvec, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, true, false, NULL, false);
+               trace = CL_TraceLine(part->org, endvec, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, true, false, NULL, false);
                part->delayedcollisions = cl.time + lifetime * trace.fraction - 0.1;
        }
        return part;
@@ -700,7 +700,7 @@ void CL_SpawnDecalParticleForPoint(const vec3_t org, float maxdist, float size,
        {
                VectorRandom(org2);
                VectorMA(org, maxdist, org2, org2);
-               trace = CL_Move(org, vec3_origin, vec3_origin, org2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, &hitent, false);
+               trace = CL_TraceLine(org, org2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, &hitent, false);
                // take the closest trace result that doesn't end up hitting a NOMARKS
                // surface (sky for example)
                if (bestfrac > trace.fraction && !(trace.hitq3surfaceflags & Q3SURFACEFLAG_NOMARKS))
@@ -1548,7 +1548,7 @@ void CL_ParticleExplosion (const vec3_t org)
                                        {
                                                VectorRandom(v2);
                                                VectorMA(org, 128, v2, v);
-                                               trace = CL_Move(org, vec3_origin, vec3_origin, v, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
+                                               trace = CL_TraceLine(org, v, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
                                                if (trace.fraction >= 0.1)
                                                        break;
                                        }
@@ -2552,7 +2552,7 @@ void R_DrawParticles (void)
                                VectorMA(p->org, frametime, p->vel, p->org);
                                if (p->bounce && cl.time >= p->delayedcollisions)
                                {
-                                       trace = CL_Move(oldorg, vec3_origin, vec3_origin, p->org, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | ((p->typeindex == pt_rain || p->typeindex == pt_snow) ? SUPERCONTENTS_LIQUIDSMASK : 0), true, false, &hitent, false);
+                                       trace = CL_TraceLine(oldorg, p->org, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | ((p->typeindex == pt_rain || p->typeindex == pt_snow) ? SUPERCONTENTS_LIQUIDSMASK : 0), true, false, &hitent, false);
                                        // if the trace started in or hit something of SUPERCONTENTS_NODROP
                                        // or if the trace hit something flagged as NOIMPACT
                                        // then remove the particle
index 8ed5cdf..3ce123a 100644 (file)
@@ -261,7 +261,7 @@ static void VM_CL_traceline (void)
        if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
                PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
+       trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
 
        CL_VM_SetTraceGlobals(&trace, svent);
 }
@@ -299,7 +299,7 @@ static void VM_CL_tracebox (void)
        if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
                PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
+       trace = CL_TraceBox(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
 
        CL_VM_SetTraceGlobals(&trace, svent);
 }
@@ -334,7 +334,7 @@ trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
                VectorMA (tossent->fields.client->angles, 0.05, tossent->fields.client->avelocity, tossent->fields.client->angles);
                VectorScale (tossent->fields.client->velocity, 0.05, move);
                VectorAdd (tossent->fields.client->origin, move, end);
-               trace = CL_Move (tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
+               trace = CL_TraceBox(tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
                VectorCopy (trace.endpos, tossent->fields.client->origin);
 
                if (trace.fraction < 1)
@@ -522,7 +522,7 @@ static void VM_CL_droptofloor (void)
        VectorCopy (ent->fields.client->origin, end);
        end[2] -= 256;
 
-       trace = CL_Move(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+       trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
 
        if (trace.fraction != 1)
        {
@@ -601,7 +601,7 @@ realcheck:
        start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
        start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
        stop[2] = start[2] - 2*sv_stepheight.value;
-       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+       trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
 
        if (trace.fraction == 1.0)
                return;
@@ -615,7 +615,7 @@ realcheck:
                        start[0] = stop[0] = x ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
 
-                       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+                       trace = CL_TraceLine(start, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -2882,7 +2882,7 @@ realcheck:
        start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
        start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
        stop[2] = start[2] - 2*sv_stepheight.value;
-       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true);
+       trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true);
 
        if (trace.fraction == 1.0)
                return false;
@@ -2895,7 +2895,7 @@ realcheck:
                        start[0] = stop[0] = x ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
 
-                       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true);
+                       trace = CL_TraceLine(start, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true);
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -2944,7 +2944,7 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
                                if (dz < 30)
                                        neworg[2] += 8;
                        }
-                       trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+                       trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
                        if (settrace)
                                CL_VM_SetTraceGlobals(&trace, svent);
 
@@ -2972,14 +2972,14 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
        VectorCopy (neworg, end);
        end[2] -= sv_stepheight.value*2;
 
-       trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+       trace = CL_TraceBox(neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
        if (settrace)
                CL_VM_SetTraceGlobals(&trace, svent);
 
        if (trace.startsolid)
        {
                neworg[2] -= sv_stepheight.value;
-               trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+               trace = CL_TraceBox(neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
                if (settrace)
                        CL_VM_SetTraceGlobals(&trace, svent);
                if (trace.startsolid)
index 3149889..192e772 100644 (file)
@@ -1569,6 +1569,76 @@ void Collision_ClipToWorld(trace_t *trace, dp_model_t *model, const vec3_t start
        VectorLerp(start, trace->fraction, end, trace->endpos);
 }
 
+void Collision_ClipLineToGenericEntity(trace_t *trace, dp_model_t *model, int frame, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+{
+       float starttransformed[3], endtransformed[3];
+
+       memset(trace, 0, sizeof(*trace));
+       trace->fraction = trace->realfraction = 1;
+       VectorCopy(end, trace->endpos);
+
+       Matrix4x4_Transform(inversematrix, start, starttransformed);
+       Matrix4x4_Transform(inversematrix, end, endtransformed);
+#if COLLISIONPARANOID >= 3
+       Con_Printf("trans(%f %f %f -> %f %f %f, %f %f %f -> %f %f %f)", start[0], start[1], start[2], starttransformed[0], starttransformed[1], starttransformed[2], end[0], end[1], end[2], endtransformed[0], endtransformed[1], endtransformed[2]);
+#endif
+
+       if (model && model->TraceLine)
+               model->TraceLine(model, bound(0, frame, (model->numframes - 1)), trace, starttransformed, endtransformed, hitsupercontentsmask);
+       else
+               Collision_ClipTrace_Box(trace, bodymins, bodymaxs, starttransformed, vec3_origin, vec3_origin, endtransformed, hitsupercontentsmask, bodysupercontents, 0, NULL);
+       trace->fraction = bound(0, trace->fraction, 1);
+       trace->realfraction = bound(0, trace->realfraction, 1);
+
+       VectorLerp(start, trace->fraction, end, trace->endpos);
+       // transform plane
+       // NOTE: this relies on plane.dist being directly after plane.normal
+       Matrix4x4_TransformPositivePlane(matrix, trace->plane.normal[0], trace->plane.normal[1], trace->plane.normal[2], trace->plane.dist, trace->plane.normal);
+}
+
+void Collision_ClipLineToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t end, int hitsupercontents)
+{
+       memset(trace, 0, sizeof(*trace));
+       trace->fraction = trace->realfraction = 1;
+       if (model && model->TraceLine)
+               model->TraceLine(model, 0, trace, start, end, hitsupercontents);
+       trace->fraction = bound(0, trace->fraction, 1);
+       trace->realfraction = bound(0, trace->realfraction, 1);
+       VectorLerp(start, trace->fraction, end, trace->endpos);
+}
+
+void Collision_ClipPointToGenericEntity(trace_t *trace, dp_model_t *model, int frame, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, int hitsupercontentsmask)
+{
+       float starttransformed[3];
+
+       memset(trace, 0, sizeof(*trace));
+       trace->fraction = trace->realfraction = 1;
+       VectorCopy(start, trace->endpos);
+
+       Matrix4x4_Transform(inversematrix, start, starttransformed);
+#if COLLISIONPARANOID >= 3
+       Con_Printf("trans(%f %f %f -> %f %f %f)", start[0], start[1], start[2], starttransformed[0], starttransformed[1], starttransformed[2]);
+#endif
+
+       if (model && model->TracePoint)
+               model->TracePoint(model, bound(0, frame, (model->numframes - 1)), trace, starttransformed, hitsupercontentsmask);
+       else
+               Collision_ClipTrace_Point(trace, bodymins, bodymaxs, starttransformed, hitsupercontentsmask, bodysupercontents, 0, NULL);
+
+       // transform plane
+       // NOTE: this relies on plane.dist being directly after plane.normal
+       Matrix4x4_TransformPositivePlane(matrix, trace->plane.normal[0], trace->plane.normal[1], trace->plane.normal[2], trace->plane.dist, trace->plane.normal);
+}
+
+void Collision_ClipPointToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, int hitsupercontents)
+{
+       memset(trace, 0, sizeof(*trace));
+       trace->fraction = trace->realfraction = 1;
+       VectorCopy(start, trace->endpos);
+       if (model && model->TracePoint)
+               model->TracePoint(model, 0, trace, start, hitsupercontents);
+}
+
 void Collision_CombineTraces(trace_t *cliptrace, const trace_t *trace, void *touch, qboolean isbmodel)
 {
        // take the 'best' answers from the new trace and combine with existing data
index 67b5eaa..1a933be 100644 (file)
@@ -57,6 +57,7 @@ trace_t;
 
 void Collision_Init(void);
 void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int boxsupercontents, int boxq3surfaceflags, texture_t *boxtexture);
+void Collision_ClipTrace_Point(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, int hitsupercontentsmask, int boxsupercontents, int boxq3surfaceflags, texture_t *boxtexture);
 
 typedef struct colpointf_s
 {
@@ -131,8 +132,12 @@ void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, co
 //
 // passedict is excluded from clipping checks
 void Collision_ClipToGenericEntity(trace_t *trace, dp_model_t *model, int frame, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask);
+void Collision_ClipLineToGenericEntity(trace_t *trace, dp_model_t *model, int frame, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t end, int hitsupercontentsmask);
+void Collision_ClipPointToGenericEntity(trace_t *trace, dp_model_t *model, int frame, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, int hitsupercontentsmask);
 // like above but does not do a transform and does nothing if model is NULL
 void Collision_ClipToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontents);
+void Collision_ClipLineToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t end, int hitsupercontents);
+void Collision_ClipPointToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, int hitsupercontents);
 // combines data from two traces:
 // merges contents flags, startsolid, allsolid, inwater
 // updates fraction, endpos, plane and surface info if new fraction is shorter
index ac857ca..2cd55b3 100644 (file)
@@ -633,10 +633,9 @@ static void Mod_Alias_MorphMesh_CompileFrames(void)
        }
 }
 
-static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
 {
        int i;
-       vec3_t shiftstart, shiftend;
        float segmentmins[3], segmentmaxs[3];
        frameblend_t frameblend[MAX_FRAMEBLENDS];
        msurface_t *surface;
@@ -656,52 +655,78 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace,
                maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
                vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
        }
+       segmentmins[0] = min(start[0], end[0]) - 1;
+       segmentmins[1] = min(start[1], end[1]) - 1;
+       segmentmins[2] = min(start[2], end[2]) - 1;
+       segmentmaxs[0] = max(start[0], end[0]) + 1;
+       segmentmaxs[1] = max(start[1], end[1]) + 1;
+       segmentmaxs[2] = max(start[2], end[2]) + 1;
+       for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
+       {
+               model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
+               Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
+       }
+}
+
+static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+{
+       int i;
+       vec3_t shiftstart, shiftend;
+       float segmentmins[3], segmentmaxs[3];
+       frameblend_t frameblend[MAX_FRAMEBLENDS];
+       msurface_t *surface;
+       static int maxvertices = 0;
+       static float *vertex3f = NULL;
+       colbrushf_t *thisbrush_start, *thisbrush_end;
+       vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
+
        if (VectorCompare(boxmins, boxmaxs))
        {
-               // line trace
                VectorAdd(start, boxmins, shiftstart);
                VectorAdd(end, boxmins, shiftend);
-               segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
-               segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
-               segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
-               segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
-               segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
-               segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
-               for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
-               {
-                       model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
-                       Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
-               }
+               Mod_MDLMD2MD3_TraceLine(model, frame, trace, start, end, hitsupercontentsmask);
+               VectorSubtract(trace->endpos, boxmins, trace->endpos);
+               return;
        }
-       else
+
+       // box trace, performed as brush trace
+       memset(trace, 0, sizeof(*trace));
+       trace->fraction = 1;
+       trace->realfraction = 1;
+       trace->hitsupercontentsmask = hitsupercontentsmask;
+       memset(frameblend, 0, sizeof(frameblend));
+       frameblend[0].subframe = frame;
+       frameblend[0].lerp = 1;
+       if (maxvertices < model->surfmesh.num_vertices)
        {
-               // box trace, performed as brush trace
-               colbrushf_t *thisbrush_start, *thisbrush_end;
-               vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
-               segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
-               segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
-               segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
-               segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
-               segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
-               segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
-               VectorAdd(start, boxmins, boxstartmins);
-               VectorAdd(start, boxmaxs, boxstartmaxs);
-               VectorAdd(end, boxmins, boxendmins);
-               VectorAdd(end, boxmaxs, boxendmaxs);
-               thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
-               thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
-               for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
+               if (vertex3f)
+                       Z_Free(vertex3f);
+               maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
+               vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
+       }
+       segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
+       segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
+       segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
+       segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
+       segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
+       segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
+       VectorAdd(start, boxmins, boxstartmins);
+       VectorAdd(start, boxmaxs, boxstartmaxs);
+       VectorAdd(end, boxmins, boxendmins);
+       VectorAdd(end, boxmaxs, boxendmaxs);
+       thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
+       thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
+       for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
+       {
+               if (maxvertices < model->surfmesh.num_vertices)
                {
-                       if (maxvertices < model->surfmesh.num_vertices)
-                       {
-                               if (vertex3f)
-                                       Z_Free(vertex3f);
-                               maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
-                               vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
-                       }
-                       model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
-                       Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
+                       if (vertex3f)
+                               Z_Free(vertex3f);
+                       maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
+                       vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
                }
+               model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
+               Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
        }
 }
 
@@ -892,6 +917,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
        loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+       loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
        loadmodel->PointSuperContents = NULL;
 
        loadmodel->num_surfaces = 1;
@@ -1224,6 +1250,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
        loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+       loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
        loadmodel->PointSuperContents = NULL;
 
        if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
@@ -1466,6 +1493,7 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
        loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+       loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
        loadmodel->PointSuperContents = NULL;
        loadmodel->synctype = ST_RAND;
        // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
@@ -1681,6 +1709,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+       loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
        loadmodel->PointSuperContents = NULL;
 
        loadmodel->numframes = pheader->numscenes;
@@ -1985,6 +2014,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+       loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
        loadmodel->PointSuperContents = NULL;
 
        // model bbox
@@ -2266,6 +2296,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+       loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
        loadmodel->PointSuperContents = NULL;
        loadmodel->synctype = ST_RAND;
 
@@ -2834,6 +2865,7 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
        loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+       loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
        loadmodel->PointSuperContents = NULL;
 
        // parse the OBJ text now
index 93407e2..213a0be 100644 (file)
@@ -851,12 +851,89 @@ static int Mod_Q1BSP_RecursiveHullCheckPoint(RecursiveHullCheckTraceInfo_t *t, i
 }
 //#endif
 
+static void Mod_Q1BSP_TracePoint(struct model_s *model, int frame, trace_t *trace, const vec3_t start, int hitsupercontentsmask)
+{
+       RecursiveHullCheckTraceInfo_t rhc;
+
+       memset(&rhc, 0, sizeof(rhc));
+       memset(trace, 0, sizeof(trace_t));
+       rhc.trace = trace;
+       rhc.trace->fraction = 1;
+       rhc.trace->realfraction = 1;
+       rhc.trace->allsolid = true;
+       rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
+       VectorCopy(start, rhc.start);
+       VectorCopy(start, rhc.end);
+       Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode);
+}
+
+static void Mod_Q1BSP_TraceLine(struct model_s *model, int frame, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+{
+       RecursiveHullCheckTraceInfo_t rhc;
+
+       if (VectorCompare(start, end))
+       {
+               Mod_Q1BSP_TracePoint(model, frame, trace, start, hitsupercontentsmask);
+               return;
+       }
+
+       memset(&rhc, 0, sizeof(rhc));
+       memset(trace, 0, sizeof(trace_t));
+       rhc.trace = trace;
+       rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+       rhc.trace->fraction = 1;
+       rhc.trace->realfraction = 1;
+       rhc.trace->allsolid = true;
+       rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
+       VectorCopy(start, rhc.start);
+       VectorCopy(end, rhc.end);
+       VectorSubtract(rhc.end, rhc.start, rhc.dist);
+#if COLLISIONPARANOID >= 2
+       Con_Printf("t(%f %f %f,%f %f %f)", rhc.start[0], rhc.start[1], rhc.start[2], rhc.end[0], rhc.end[1], rhc.end[2]);
+       Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+       {
+
+               double test[3];
+               trace_t testtrace;
+               VectorLerp(rhc.start, rhc.trace->fraction, rhc.end, test);
+               memset(&testtrace, 0, sizeof(trace_t));
+               rhc.trace = &testtrace;
+               rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
+               rhc.trace->fraction = 1;
+               rhc.trace->realfraction = 1;
+               rhc.trace->allsolid = true;
+               VectorCopy(test, rhc.start);
+               VectorCopy(test, rhc.end);
+               VectorClear(rhc.dist);
+               Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode);
+               //Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, test, test);
+               if (!trace->startsolid && testtrace.startsolid)
+                       Con_Printf(" - ended in solid!\n");
+       }
+       Con_Print("\n");
+#else
+       if (VectorLength2(rhc.dist))
+               Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+       else
+               Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode);
+#endif
+}
+
 static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
 {
        // this function currently only supports same size start and end
        double boxsize[3];
        RecursiveHullCheckTraceInfo_t rhc;
 
+       if (VectorCompare(boxmins, boxmaxs))
+       {
+               if (VectorCompare(start, end))
+                       Mod_Q1BSP_TracePoint(model, frame, trace, start, hitsupercontentsmask);
+               else
+                       Mod_Q1BSP_TraceLine(model, frame, trace, start, end, hitsupercontentsmask);
+               return;
+       }
+
        memset(&rhc, 0, sizeof(rhc));
        memset(trace, 0, sizeof(trace_t));
        rhc.trace = trace;
@@ -1042,6 +1119,22 @@ void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cm
 #endif
 }
 
+void Collision_ClipTrace_Point(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, int hitsupercontentsmask, int boxsupercontents, int boxq3surfaceflags, texture_t *boxtexture)
+{
+       memset(trace, 0, sizeof(trace_t));
+       trace->fraction = 1;
+       trace->realfraction = 1;
+       if (BoxesOverlap(start, start, cmins, cmaxs))
+       {
+               trace->startsupercontents |= boxsupercontents;
+               if (hitsupercontentsmask & boxsupercontents)
+               {
+                       trace->startsolid = true;
+                       trace->allsolid = true;
+               }
+       }
+}
+
 static int Mod_Q1BSP_TraceLineOfSight_RecursiveNodeCheck(mnode_t *node, double p1[3], double p2[3])
 {
        double t1, t2;
@@ -3472,6 +3565,8 @@ void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend)
 
        mod->soundfromcenter = true;
        mod->TraceBox = Mod_Q1BSP_TraceBox;
+       mod->TraceLine = Mod_Q1BSP_TraceLine;
+       mod->TracePoint = Mod_Q1BSP_TracePoint;
        mod->PointSuperContents = Mod_Q1BSP_PointSuperContents;
        mod->brush.TraceLineOfSight = Mod_Q1BSP_TraceLineOfSight;
        mod->brush.SuperContentsFromNativeContents = Mod_Q1BSP_SuperContentsFromNativeContents;
@@ -5718,87 +5813,117 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, dp_model_t *mo
        }
 }
 
-static void Mod_Q3BSP_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+static void Mod_Q3BSP_TracePoint(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, int hitsupercontentsmask)
+{
+       int i;
+       static int markframe = 0x80000000;
+       q3mbrush_t *brush;
+       memset(trace, 0, sizeof(*trace));
+       trace->fraction = 1;
+       trace->realfraction = 1;
+       trace->hitsupercontentsmask = hitsupercontentsmask;
+       if (model->brush.submodel)
+       {
+               for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
+                       if (brush->colbrushf)
+                               Collision_TracePointBrushFloat(trace, start, brush->colbrushf);
+       }
+       else
+               Mod_Q3BSP_TracePoint_RecursiveBSPNode(trace, model, model->brush.data_nodes, start, ++markframe);
+}
+
+static void Mod_Q3BSP_TraceLine(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
 {
        int i;
-       vec3_t shiftstart, shiftend;
        float segmentmins[3], segmentmaxs[3];
-       static int markframe = 0;
+       static int markframe = 0x40000000;
        msurface_t *surface;
        q3mbrush_t *brush;
+
+       if (VectorCompare(start, end))
+       {
+               Mod_Q3BSP_TracePoint(model, frame, trace, start, hitsupercontentsmask);
+               return;
+       }
+
        memset(trace, 0, sizeof(*trace));
        trace->fraction = 1;
        trace->realfraction = 1;
        trace->hitsupercontentsmask = hitsupercontentsmask;
+       segmentmins[0] = min(start[0], end[0]) - 1;
+       segmentmins[1] = min(start[1], end[1]) - 1;
+       segmentmins[2] = min(start[2], end[2]) - 1;
+       segmentmaxs[0] = max(start[0], end[0]) + 1;
+       segmentmaxs[1] = max(start[1], end[1]) + 1;
+       segmentmaxs[2] = max(start[2], end[2]) + 1;
+       if (model->brush.submodel)
+       {
+               for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
+                       if (brush->colbrushf)
+                               Collision_TraceLineBrushFloat(trace, start, end, brush->colbrushf, brush->colbrushf);
+               if (mod_q3bsp_curves_collisions.integer)
+                       for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+                               if (surface->num_collisiontriangles)
+                                       Collision_TraceLineTriangleMeshFloat(trace, start, end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionbboxstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
+       }
+       else
+               Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, model, model->brush.data_nodes, start, end, 0, 1, start, end, ++markframe, segmentmins, segmentmaxs);
+}
+
+static void Mod_Q3BSP_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+{
+       int i;
+       float segmentmins[3], segmentmaxs[3];
+       static int markframe = 0;
+       msurface_t *surface;
+       q3mbrush_t *brush;
+       colbrushf_t *thisbrush_start, *thisbrush_end;
+       vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
+
        if (mod_q3bsp_optimizedtraceline.integer && VectorCompare(boxmins, boxmaxs))
        {
+               vec3_t shiftstart, shiftend;
                VectorAdd(start, boxmins, shiftstart);
                VectorAdd(end, boxmins, shiftend);
-               if (VectorCompare(shiftstart, shiftend))
-               {
-                       // point trace
-                       if (model->brush.submodel)
-                       {
-                               for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
-                                       if (brush->colbrushf)
-                                               Collision_TracePointBrushFloat(trace, shiftstart, brush->colbrushf);
-                       }
-                       else
-                               Mod_Q3BSP_TracePoint_RecursiveBSPNode(trace, model, model->brush.data_nodes, shiftstart, ++markframe);
-               }
+               if (VectorCompare(start, end))
+                       Mod_Q3BSP_TracePoint(model, frame, trace, shiftstart, hitsupercontentsmask);
                else
                {
-                       // line trace
-                       segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
-                       segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
-                       segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
-                       segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
-                       segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
-                       segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
-                       if (model->brush.submodel)
-                       {
-                               for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
-                                       if (brush->colbrushf)
-                                               Collision_TraceLineBrushFloat(trace, shiftstart, shiftend, brush->colbrushf, brush->colbrushf);
-                               if (mod_q3bsp_curves_collisions.integer)
-                                       for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
-                                               if (surface->num_collisiontriangles)
-                                                       Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionbboxstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
-                       }
-                       else
-                               Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, model, model->brush.data_nodes, shiftstart, shiftend, 0, 1, shiftstart, shiftend, ++markframe, segmentmins, segmentmaxs);
+                       Mod_Q3BSP_TraceLine(model, frame, trace, shiftstart, shiftend, hitsupercontentsmask);
+                       VectorSubtract(trace->endpos, boxmins, trace->endpos);
                }
+               return;
        }
-       else
+
+       // box trace, performed as brush trace
+       memset(trace, 0, sizeof(*trace));
+       trace->fraction = 1;
+       trace->realfraction = 1;
+       trace->hitsupercontentsmask = hitsupercontentsmask;
+       segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
+       segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
+       segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
+       segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
+       segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
+       segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
+       VectorAdd(start, boxmins, boxstartmins);
+       VectorAdd(start, boxmaxs, boxstartmaxs);
+       VectorAdd(end, boxmins, boxendmins);
+       VectorAdd(end, boxmaxs, boxendmaxs);
+       thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
+       thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
+       if (model->brush.submodel)
        {
-               // box trace, performed as brush trace
-               colbrushf_t *thisbrush_start, *thisbrush_end;
-               vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
-               segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
-               segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
-               segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
-               segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
-               segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
-               segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
-               VectorAdd(start, boxmins, boxstartmins);
-               VectorAdd(start, boxmaxs, boxstartmaxs);
-               VectorAdd(end, boxmins, boxendmins);
-               VectorAdd(end, boxmaxs, boxendmaxs);
-               thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
-               thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
-               if (model->brush.submodel)
-               {
-                       for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
-                               if (brush->colbrushf)
-                                       Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, brush->colbrushf, brush->colbrushf);
-                       if (mod_q3bsp_curves_collisions.integer)
-                               for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
-                                       if (surface->num_collisiontriangles)
-                                               Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionbboxstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
-               }
-               else
-                       Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model, model->brush.data_nodes, thisbrush_start, thisbrush_end, ++markframe, segmentmins, segmentmaxs);
+               for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
+                       if (brush->colbrushf)
+                               Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, brush->colbrushf, brush->colbrushf);
+               if (mod_q3bsp_curves_collisions.integer)
+                       for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+                               if (surface->num_collisiontriangles)
+                                       Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionbboxstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
        }
+       else
+               Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model, model->brush.data_nodes, thisbrush_start, thisbrush_end, ++markframe, segmentmins, segmentmaxs);
 }
 
 static int Mod_Q3BSP_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
@@ -5929,6 +6054,8 @@ void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend)
 
        mod->soundfromcenter = true;
        mod->TraceBox = Mod_Q3BSP_TraceBox;
+       mod->TraceLine = Mod_Q3BSP_TraceLine;
+       mod->TracePoint = Mod_Q3BSP_TracePoint;
        mod->PointSuperContents = Mod_Q3BSP_PointSuperContents;
        mod->brush.TraceLineOfSight = Mod_Q1BSP_TraceLineOfSight;
        mod->brush.SuperContentsFromNativeContents = Mod_Q3BSP_SuperContentsFromNativeContents;
index e9cc94c..9f02b21 100644 (file)
@@ -896,6 +896,10 @@ typedef struct model_s
        void(*DrawLight)(struct entity_render_s *ent, int numsurfaces, const int *surfacelist, const unsigned char *trispvs);
        // trace a box against this model
        void (*TraceBox)(struct model_s *model, int frame, struct trace_s *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask);
+       // trace a box against this model
+       void (*TraceLine)(struct model_s *model, int frame, struct trace_s *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask);
+       // trace a point against this model (like PointSuperContents)
+       void (*TracePoint)(struct model_s *model, int frame, struct trace_s *trace, const vec3_t start, int hitsupercontentsmask);
        // find the supercontents value at a point in this model
        int (*PointSuperContents)(struct model_s *model, int frame, const vec3_t point);
        // fields belonging to some types of model
index a2282c9..2c1f72f 100644 (file)
@@ -175,7 +175,7 @@ void R_NewExplosion(const vec3_t org)
                                // clip start origin
                                if (e->clipping)
                                {
-                                       trace = CL_Move(e->origin, vec3_origin, vec3_origin, e->vert[j], MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
+                                       trace = CL_TraceLine(e->origin, e->vert[j], MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
                                        VectorCopy(trace.endpos, e->vert[i]);
                                }
                        }
@@ -236,7 +236,7 @@ static void R_MoveExplosion(explosion_t *e)
                        VectorMA(e->vert[i], frametime, e->vertvel[i], end);
                        if (e->clipping)
                        {
-                               trace = CL_Move(e->vert[i], vec3_origin, vec3_origin, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
+                               trace = CL_TraceLine(e->vert[i], end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
                                if (trace.fraction < 1)
                                {
                                        // clip velocity against the wall
index 99eb35f..c7dc780 100644 (file)
@@ -4338,7 +4338,7 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
        else
        {
                // FIXME: these traces should scan all render entities instead of cl.world
-               if (CL_Move(r_refdef.view.origin, vec3_origin, vec3_origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
+               if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
                        return;
        }
        VectorScale(rtlight->color, cscale, color);
@@ -4719,7 +4719,7 @@ void R_Shadow_SelectLightInView(void)
                if (rating >= 0.95)
                {
                        rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
-                       if (bestrating < rating && CL_Move(light->origin, vec3_origin, vec3_origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1.0f)
+                       if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1.0f)
                        {
                                bestrating = rating;
                                best = light;
@@ -5165,7 +5165,7 @@ void R_Shadow_SetCursorLocationForView(void)
        vec3_t dest, endpos;
        trace_t trace;
        VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest);
-       trace = CL_Move(r_refdef.view.origin, vec3_origin, vec3_origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
+       trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false);
        if (trace.fraction < 1)
        {
                dist = trace.fraction * r_editlights_cursordistance.value;
@@ -5839,7 +5839,7 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu
                        light = r_refdef.scene.lights[i];
                        Matrix4x4_Transform(&light->matrix_worldtolight, p, v);
                        f = 1 - VectorLength2(v);
-                       if (f > 0 && CL_Move(p, vec3_origin, vec3_origin, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
+                       if (f > 0 && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1)
                                VectorMA(ambientcolor, f, light->currentcolor, ambientcolor);
                }
        }
index 7e7124e..ed44332 100644 (file)
--- a/server.h
+++ b/server.h
@@ -519,7 +519,9 @@ qboolean SV_UnstickEntity (prvm_edict_t *ent);
 /// calculates hitsupercontentsmask for a generic qc entity
 int SV_GenericHitSuperContentsMask(const prvm_edict_t *edict);
 /// traces a box move against worldmodel and all entities in the specified area
-trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask);
+trace_t SV_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);
+trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask);
+trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask);
 
 int SV_PointSuperContents(const vec3_t point);
 
index 6778992..fa55187 100644 (file)
--- a/sv_move.c
+++ b/sv_move.c
@@ -70,7 +70,7 @@ realcheck:
        start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
        start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
        stop[2] = start[2] - 2*sv_stepheight.value;
-       trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceLine(start, stop, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
 
        if (trace.fraction == 1.0)
                return false;
@@ -83,7 +83,7 @@ realcheck:
                        start[0] = stop[0] = x ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
 
-                       trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
+                       trace = SV_TraceLine(start, stop, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -138,7 +138,7 @@ qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
                                                neworg[2] += 8;
                                }
                        }
-                       trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, neworg, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+                       trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, neworg, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
 
                        if (trace.fraction == 1)
                        {
@@ -164,12 +164,12 @@ qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
        VectorCopy (neworg, end);
        end[2] -= sv_stepheight.value*2;
 
-       trace = SV_Move (neworg, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceBox(neworg, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
 
        if (trace.startsolid)
        {
                neworg[2] -= sv_stepheight.value;
-               trace = SV_Move (neworg, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+               trace = SV_TraceBox(neworg, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
                if (trace.startsolid)
                        return false;
        }
index 507168c..d7b38c5 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -77,6 +77,334 @@ int SV_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
                return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE;
 }
 
+/*
+==================
+SV_TracePoint
+==================
+*/
+trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
+{
+       int i, bodysupercontents;
+       int passedictprog;
+       float pitchsign = 1;
+       prvm_edict_t *traceowner, *touch;
+       trace_t trace;
+       // bounding box of entire move area
+       vec3_t clipboxmins, clipboxmaxs;
+       // size when clipping against monsters
+       vec3_t clipmins2, clipmaxs2;
+       // start and end origin of move
+       vec3_t clipstart;
+       // trace results
+       trace_t cliptrace;
+       // matrices to transform into/out of other entity's space
+       matrix4x4_t matrix, imatrix;
+       // model of other entity
+       dp_model_t *model;
+       // list of entities to test for collisions
+       int numtouchedicts;
+       prvm_edict_t *touchedicts[MAX_EDICTS];
+
+       VectorCopy(start, clipstart);
+       VectorClear(clipmins2);
+       VectorClear(clipmaxs2);
+#if COLLISIONPARANOID >= 3
+       Con_Printf("move(%f %f %f)", clipstart[0], clipstart[1], clipstart[2]);
+#endif
+
+       // clip to world
+       Collision_ClipPointToWorld(&cliptrace, sv.worldmodel, clipstart, hitsupercontentsmask);
+       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       if (cliptrace.startsolid || cliptrace.fraction < 1)
+               cliptrace.ent = prog->edicts;
+       if (type == MOVE_WORLDONLY)
+               goto finished;
+
+       if (type == MOVE_MISSILE)
+       {
+               // LordHavoc: modified this, was = -15, now -= 15
+               for (i = 0;i < 3;i++)
+               {
+                       clipmins2[i] -= 15;
+                       clipmaxs2[i] += 15;
+               }
+       }
+
+       // create the bounding box of the entire move
+       for (i = 0;i < 3;i++)
+       {
+               clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + clipmins2[i] - 1;
+               clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + clipmaxs2[i] + 1;
+       }
+
+       // debug override to test against everything
+       if (sv_debugmove.integer)
+       {
+               clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = -999999999;
+               clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] =  999999999;
+       }
+
+       // if the passedict is world, make it NULL (to avoid two checks each time)
+       if (passedict == prog->edicts)
+               passedict = NULL;
+       // precalculate prog value for passedict for comparisons
+       passedictprog = PRVM_EDICT_TO_PROG(passedict);
+       // precalculate passedict's owner edict pointer for comparisons
+       traceowner = passedict ? PRVM_PROG_TO_EDICT(passedict->fields.server->owner) : 0;
+
+       // clip to entities
+       // because this uses World_EntitiestoBox, we know all entity boxes overlap
+       // the clip region, so we can skip culling checks in the loop below
+       numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+       if (numtouchedicts > MAX_EDICTS)
+       {
+               // this never happens
+               Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
+               numtouchedicts = MAX_EDICTS;
+       }
+       for (i = 0;i < numtouchedicts;i++)
+       {
+               touch = touchedicts[i];
+
+               if (touch->fields.server->solid < SOLID_BBOX)
+                       continue;
+               if (type == MOVE_NOMONSTERS && touch->fields.server->solid != SOLID_BSP)
+                       continue;
+
+               if (passedict)
+               {
+                       // don't clip against self
+                       if (passedict == touch)
+                               continue;
+                       // don't clip owned entities against owner
+                       if (traceowner == touch)
+                               continue;
+                       // don't clip owner against owned entities
+                       if (passedictprog == touch->fields.server->owner)
+                               continue;
+                       // don't clip points against points (they can't collide)
+                       if (VectorCompare(touch->fields.server->mins, touch->fields.server->maxs) && (type != MOVE_MISSILE || !((int)touch->fields.server->flags & FL_MONSTER)))
+                               continue;
+               }
+
+               bodysupercontents = touch->fields.server->solid == SOLID_CORPSE ? SUPERCONTENTS_CORPSE : SUPERCONTENTS_BODY;
+
+               // might interact, so do an exact clip
+               model = NULL;
+               if ((int) touch->fields.server->solid == SOLID_BSP || type == MOVE_HITMODEL)
+               {
+                       unsigned int modelindex = (unsigned int)touch->fields.server->modelindex;
+                       // if the modelindex is 0, it shouldn't be SOLID_BSP!
+                       if (modelindex > 0 && modelindex < MAX_MODELS)
+                               model = sv.models[(int)touch->fields.server->modelindex];
+                       //pitchsign = 1;
+                       if (
+                               ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex]))
+                               ?
+                                       model->type == mod_alias
+                               :
+                                       (
+                                               (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
+                                               ||
+                                               ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32)))
+                                       )
+                       )
+                               pitchsign = -1;
+               }
+               if (model)
+                       Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
+               else
+                       Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
+               Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               if ((int)touch->fields.server->flags & FL_MONSTER)
+                       Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
+               else
+                       Collision_ClipPointToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
+
+               Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.server->solid == SOLID_BSP);
+       }
+
+finished:
+       return cliptrace;
+}
+
+/*
+==================
+SV_TraceLine
+==================
+*/
+#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
+trace_t SV_TraceLine(const vec3_t start, const vec3_t pEnd, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
+#else
+trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
+#endif
+{
+       int i, bodysupercontents;
+       int passedictprog;
+       float pitchsign = 1;
+       prvm_edict_t *traceowner, *touch;
+       trace_t trace;
+       // bounding box of entire move area
+       vec3_t clipboxmins, clipboxmaxs;
+       // size when clipping against monsters
+       vec3_t clipmins2, clipmaxs2;
+       // start and end origin of move
+       vec3_t clipstart, clipend;
+       // trace results
+       trace_t cliptrace;
+       // matrices to transform into/out of other entity's space
+       matrix4x4_t matrix, imatrix;
+       // model of other entity
+       dp_model_t *model;
+       // list of entities to test for collisions
+       int numtouchedicts;
+       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))
+       {
+               // TRICK: make the trace 1 qu longer!
+               VectorSubtract(pEnd, start, end);
+               len = VectorNormalizeLength(end);
+               VectorAdd(pEnd, end, end);
+       }
+       else
+               VectorCopy(pEnd, end);
+#endif
+
+       if (VectorCompare(start, end))
+               return SV_TracePoint(start, type, passedict, hitsupercontentsmask);
+
+       VectorCopy(start, clipstart);
+       VectorCopy(end, clipend);
+       VectorClear(clipmins2);
+       VectorClear(clipmaxs2);
+#if COLLISIONPARANOID >= 3
+       Con_Printf("move(%f %f %f,%f %f %f)", clipstart[0], clipstart[1], clipstart[2], clipend[0], clipend[1], clipend[2]);
+#endif
+
+       // clip to world
+       Collision_ClipLineToWorld(&cliptrace, sv.worldmodel, clipstart, clipend, hitsupercontentsmask);
+       cliptrace.bmodelstartsolid = cliptrace.startsolid;
+       if (cliptrace.startsolid || cliptrace.fraction < 1)
+               cliptrace.ent = prog->edicts;
+       if (type == MOVE_WORLDONLY)
+               goto finished;
+
+       if (type == MOVE_MISSILE)
+       {
+               // LordHavoc: modified this, was = -15, now -= 15
+               for (i = 0;i < 3;i++)
+               {
+                       clipmins2[i] -= 15;
+                       clipmaxs2[i] += 15;
+               }
+       }
+
+       // create the bounding box of the entire move
+       for (i = 0;i < 3;i++)
+       {
+               clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + clipmins2[i] - 1;
+               clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + clipmaxs2[i] + 1;
+       }
+
+       // debug override to test against everything
+       if (sv_debugmove.integer)
+       {
+               clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = -999999999;
+               clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] =  999999999;
+       }
+
+       // if the passedict is world, make it NULL (to avoid two checks each time)
+       if (passedict == prog->edicts)
+               passedict = NULL;
+       // precalculate prog value for passedict for comparisons
+       passedictprog = PRVM_EDICT_TO_PROG(passedict);
+       // precalculate passedict's owner edict pointer for comparisons
+       traceowner = passedict ? PRVM_PROG_TO_EDICT(passedict->fields.server->owner) : 0;
+
+       // clip to entities
+       // because this uses World_EntitiestoBox, we know all entity boxes overlap
+       // the clip region, so we can skip culling checks in the loop below
+       numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+       if (numtouchedicts > MAX_EDICTS)
+       {
+               // this never happens
+               Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
+               numtouchedicts = MAX_EDICTS;
+       }
+       for (i = 0;i < numtouchedicts;i++)
+       {
+               touch = touchedicts[i];
+
+               if (touch->fields.server->solid < SOLID_BBOX)
+                       continue;
+               if (type == MOVE_NOMONSTERS && touch->fields.server->solid != SOLID_BSP)
+                       continue;
+
+               if (passedict)
+               {
+                       // don't clip against self
+                       if (passedict == touch)
+                               continue;
+                       // don't clip owned entities against owner
+                       if (traceowner == touch)
+                               continue;
+                       // don't clip owner against owned entities
+                       if (passedictprog == touch->fields.server->owner)
+                               continue;
+                       // don't clip points against points (they can't collide)
+                       if (VectorCompare(touch->fields.server->mins, touch->fields.server->maxs) && (type != MOVE_MISSILE || !((int)touch->fields.server->flags & FL_MONSTER)))
+                               continue;
+               }
+
+               bodysupercontents = touch->fields.server->solid == SOLID_CORPSE ? SUPERCONTENTS_CORPSE : SUPERCONTENTS_BODY;
+
+               // might interact, so do an exact clip
+               model = NULL;
+               if ((int) touch->fields.server->solid == SOLID_BSP || type == MOVE_HITMODEL)
+               {
+                       unsigned int modelindex = (unsigned int)touch->fields.server->modelindex;
+                       // if the modelindex is 0, it shouldn't be SOLID_BSP!
+                       if (modelindex > 0 && modelindex < MAX_MODELS)
+                               model = sv.models[(int)touch->fields.server->modelindex];
+                       //pitchsign = 1;
+                       if (
+                               ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex]))
+                               ?
+                                       model->type == mod_alias
+                               :
+                                       (
+                                               (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
+                                               ||
+                                               ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32)))
+                                       )
+                       )
+                               pitchsign = -1;
+               }
+               if (model)
+                       Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
+               else
+                       Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
+               Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               if (type == MOVE_MISSILE && (int)touch->fields.server->flags & FL_MONSTER)
+                       Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+               else
+                       Collision_ClipLineToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask);
+
+               Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.server->solid == SOLID_BSP);
+       }
+
+finished:
+#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
+       if(!VectorCompare(start, pEnd))
+               Collision_ShortenTrace(&cliptrace, len / (len + 1), pEnd);
+#endif
+       return cliptrace;
+}
+
 /*
 ==================
 SV_Move
@@ -84,15 +412,15 @@ SV_Move
 */
 #ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
 #if COLLISIONPARANOID >= 1
-trace_t SV_Move_(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t pEnd, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
+trace_t SV_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)
 #else
-trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t pEnd, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
+trace_t SV_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)
 #endif
 #else
 #if COLLISIONPARANOID >= 1
-trace_t SV_Move_(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
+trace_t SV_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)
 #else
-trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
+trace_t SV_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)
 #endif
 #endif
 {
@@ -135,6 +463,21 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const
                VectorCopy(pEnd, end);
 #endif
 
+       if (VectorCompare(mins, maxs))
+       {
+               vec3_t shiftstart, shiftend;
+               VectorAdd(start, mins, shiftstart);
+               VectorAdd(end, mins, shiftend);
+               if (VectorCompare(start, end))
+                       return SV_TracePoint(shiftstart, type, passedict, hitsupercontentsmask);
+               else
+               {
+                       trace = SV_TraceLine(shiftstart, shiftend, type, passedict, hitsupercontentsmask);
+                       VectorSubtract(trace.endpos, mins, trace.endpos);
+                       return trace;
+               }
+       }
+
        VectorCopy(start, clipstart);
        VectorCopy(end, clipend);
        VectorCopy(mins, clipmins);
@@ -277,16 +620,16 @@ finished:
 }
 
 #if COLLISIONPARANOID >= 1
-trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
+trace_t SV_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 endstuck;
        trace_t trace;
        vec3_t temp;
-       trace = SV_Move_(start, mins, maxs, end, type, passedict, hitsupercontentsmask);
+       trace = SV_TraceBox_(start, mins, maxs, end, type, passedict, hitsupercontentsmask);
        if (passedict)
        {
                VectorCopy(trace.endpos, temp);
-               endstuck = SV_Move_(temp, mins, maxs, temp, type, passedict, hitsupercontentsmask).startsolid;
+               endstuck = SV_TraceBox_(temp, mins, maxs, temp, type, passedict, hitsupercontentsmask).startsolid;
 #if COLLISIONPARANOID < 3
                if (trace.startsolid || endstuck)
 #endif
@@ -530,7 +873,7 @@ static int SV_TestEntityPosition (prvm_edict_t *ent, vec3_t offset)
        trace_t trace;
        contents = SV_GenericHitSuperContentsMask(ent);
        VectorAdd(ent->fields.server->origin, offset, org);
-       trace = SV_Move (org, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, MOVE_NOMONSTERS, ent, contents);
+       trace = SV_TraceBox(org, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, MOVE_NOMONSTERS, ent, contents);
        if (trace.startsupercontents & contents)
                return true;
        else
@@ -569,7 +912,7 @@ static int SV_TestEntityPosition (prvm_edict_t *ent, vec3_t offset)
 #else
                // verify if the endpos is REALLY outside solid
                VectorCopy(trace.endpos, org);
-               trace = SV_Move (org, ent->fields.server->mins, ent->fields.server->maxs, org, MOVE_NOMONSTERS, ent, contents);
+               trace = SV_TraceBox(org, ent->fields.server->mins, ent->fields.server->maxs, org, MOVE_NOMONSTERS, ent, contents);
                if(trace.startsolid)
                        Con_Printf("SV_TestEntityPosition: trace.endpos detected to be in solid. NOT using it.\n");
                else
@@ -880,7 +1223,7 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, flo
                        start[2] += 3;//0.03125;
                        VectorMA(ent->fields.server->origin, time_left, ent->fields.server->velocity, end);
                        end[2] += 3;//0.03125;
-                       testtrace = SV_Move(start, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask);
+                       testtrace = SV_TraceBox(start, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask);
                        if (trace.fraction < testtrace.fraction && !testtrace.startsolid && (testtrace.fraction == 1 || DotProduct(trace.plane.normal, ent->fields.server->velocity) < DotProduct(testtrace.plane.normal, ent->fields.server->velocity)))
                        {
                                Con_Printf("got further (new %f > old %f)\n", testtrace.fraction, trace.fraction);
@@ -895,7 +1238,7 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, flo
                                VectorMA(ent->fields.server->origin, time_left, ent->fields.server->velocity, end);
                                VectorMA(start, 3, planes[i], start);
                                VectorMA(end, 3, planes[i], end);
-                               testtrace = SV_Move(start, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask);
+                               testtrace = SV_TraceBox(start, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask);
                                if (trace.fraction < testtrace.fraction)
                                {
                                        trace = testtrace;
@@ -1046,7 +1389,7 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, flo
        {
                // LordHavoc: fix the 'fall to your death in a wedge corner' glitch
                // flag ONGROUND if there's ground under it
-               trace = SV_Move(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask);
+               trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask);
        }
        */
 
@@ -1110,7 +1453,7 @@ static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, q
        else
                type = MOVE_NORMAL;
 
-       *trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent));
+       *trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent));
        if (trace->bmodelstartsolid && failonbmodelstartsolid)
                return true;
 
@@ -1118,7 +1461,7 @@ static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, q
 
 #if 0
        if(!trace->startsolid)
-       if(SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, type, ent, SV_GenericHitSuperContentsMask(ent)).startsolid)
+       if(SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, type, ent, SV_GenericHitSuperContentsMask(ent)).startsolid)
        {
                Con_Printf("something eeeeevil happened\n");
        }
@@ -1308,7 +1651,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                if (!((int)check->fields.server->flags & FL_ONGROUND) || PRVM_PROG_TO_EDICT(check->fields.server->groundentity) != pusher)
                {
                        Collision_ClipToGenericEntity(&trace, pushermodel, (int) pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, checkcontents);
-                       //trace = SV_Move(check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, MOVE_NOMONSTERS, check, checkcontents);
+                       //trace = SV_TraceBox(check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, MOVE_NOMONSTERS, check, checkcontents);
                        if (!trace.startsolid)
                        {
                                //Con_Printf("- not in solid\n");
index 0870147..6d9a39d 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -58,7 +58,7 @@ void SV_SetIdealPitch (void)
                bottom[1] = top[1];
                bottom[2] = top[2] - 160;
 
-               tr = SV_Move (top, vec3_origin, vec3_origin, bottom, MOVE_NOMONSTERS, host_client->edict, SUPERCONTENTS_SOLID);
+               tr = SV_TraceLine(top, bottom, MOVE_NOMONSTERS, host_client->edict, SUPERCONTENTS_SOLID);
                // if looking at a wall, leave ideal the way is was
                if (tr.startsolid)
                        return;
@@ -124,7 +124,7 @@ void SV_UserFriction (void)
        start[2] = host_client->edict->fields.server->origin[2] + host_client->edict->fields.server->mins[2];
        stop[2] = start[2] - 34;
 
-       trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, host_client->edict, SV_GenericHitSuperContentsMask(host_client->edict));
+       trace = SV_TraceLine(start, stop, MOVE_NOMONSTERS, host_client->edict, SV_GenericHitSuperContentsMask(host_client->edict));
 
        if (trace.fraction == 1.0)
                friction = sv_friction.value*sv_edgefriction.value;
index 6fde46d..1efe5a5 100644 (file)
@@ -582,7 +582,7 @@ static void VM_SV_traceline (void)
        if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
                PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
 
        VM_SetTraceGlobals(&trace);
 }
@@ -621,7 +621,7 @@ static void VM_SV_tracebox (void)
        if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
                PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
 
        VM_SetTraceGlobals(&trace);
 }
@@ -657,7 +657,7 @@ static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
                VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
                VectorScale (tossent->fields.server->velocity, 0.05, move);
                VectorAdd (tossent->fields.server->origin, move, end);
-               trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
+               trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
                VectorCopy (trace.endpos, tossent->fields.server->origin);
                tossent->fields.server->velocity[2] -= gravity;
 
@@ -1077,13 +1077,13 @@ static void VM_SV_droptofloor (void)
        if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
                SV_UnstickEntity(ent);
 
-       trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
        if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
        {
                vec3_t offset, org;
                VectorSet(offset, 0.5f * (ent->fields.server->mins[0] + ent->fields.server->maxs[0]), 0.5f * (ent->fields.server->mins[1] + ent->fields.server->maxs[1]), ent->fields.server->mins[2]);
                VectorAdd(ent->fields.server->origin, offset, org);
-               trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+               trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
                VectorSubtract(trace.endpos, offset, trace.endpos);
                if (trace.startsolid)
                {
@@ -1230,7 +1230,7 @@ static void VM_SV_aim (void)
 // try sending a trace straight
        VectorCopy (prog->globals.server->v_forward, dir);
        VectorMA (start, 2048, dir, end);
-       tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
+       tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
        if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
        && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
        {
@@ -1262,7 +1262,7 @@ static void VM_SV_aim (void)
                dist = DotProduct (dir, prog->globals.server->v_forward);
                if (dist < bestdist)
                        continue;       // to far to turn
-               tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
+               tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
                if (tr.ent == check)
                {       // can shoot at this one
                        bestdist = dist;
diff --git a/view.c b/view.c
index 7c8c08e..d94c2bd 100644 (file)
--- a/view.c
+++ b/view.c
@@ -439,13 +439,13 @@ void V_CalcRefdef (void)
                                        chase_dest[1] = vieworg[1] - forward[1] * camback + up[1] * camup;
                                        chase_dest[2] = vieworg[2] - forward[2] * camback + up[2] * camup;
 #if 0
-                                       //trace = CL_Move(vieworg, eyeboxmins, eyeboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
-                                       trace = CL_Move(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+                                       //trace = CL_TraceBox(vieworg, eyeboxmins, eyeboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+                                       trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
                                        VectorCopy(trace.endpos, vieworg);
                                        vieworg[2] -= 8;
 #else
                                        // trace from first person view location to our chosen third person view location
-                                       trace = CL_Move(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+                                       trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
                                        VectorCopy(trace.endpos, bestvieworg);
                                        offset[2] = 0;
                                        for (offset[0] = -16;offset[0] <= 16;offset[0] += 8)
@@ -456,7 +456,7 @@ void V_CalcRefdef (void)
                                                        chase_dest[0] = vieworg[0] - forward[0] * camback + up[0] * camup + offset[0];
                                                        chase_dest[1] = vieworg[1] - forward[1] * camback + up[1] * camup + offset[1];
                                                        chase_dest[2] = vieworg[2] - forward[2] * camback + up[2] * camup + offset[2];
-                                                       trace = CL_Move(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+                                                       trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
                                                        if (bestvieworg[2] > trace.endpos[2])
                                                                bestvieworg[2] = trace.endpos[2];
                                                }
@@ -481,7 +481,7 @@ void V_CalcRefdef (void)
                                        chase_dest[0] = vieworg[0] + forward[0] * dist;
                                        chase_dest[1] = vieworg[1] + forward[1] * dist;
                                        chase_dest[2] = vieworg[2] + forward[2] * dist + camup;
-                                       trace = CL_Move(vieworg, vec3_origin, vec3_origin, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+                                       trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
                                        VectorMAMAM(1, trace.endpos, 8, forward, 4, trace.plane.normal, vieworg);
                                }
                        }