]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_phys.c
added vid.support struct containing extension detection flags, to
[xonotic/darkplaces.git] / sv_phys.c
index bd8b50ce30262ed9a36b8092fd8f49a009552867..7235fac729278bed36c7ad98dceefd8b6101edc3 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -46,9 +46,8 @@ void SV_Physics_Toss (prvm_edict_t *ent);
 int SV_GetPitchSign(prvm_edict_t *ent)
 {
        dp_model_t *model;
-       int modelindex;
        if (
-                       ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
+                       (model = SV_GetModelFromEdict(ent))
                        ?
                        model->type == mod_alias
                        :
@@ -214,10 +213,7 @@ trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
                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];
+                       model = SV_GetModelFromEdict(touch);
                        pitchsign = SV_GetPitchSign(touch);
                }
                if (model)
@@ -225,10 +221,13 @@ trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int
                else
                        Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
                Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+               VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+               VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
                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, clipstart, hitsupercontentsmask);
+                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, 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_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, 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);
        }
@@ -272,12 +271,12 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
        vec3_t end;
        vec_t len = 0;
 
-       if(!VectorCompare(start, pEnd))
+       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
        {
                // TRICK: make the trace 1 qu longer!
                VectorSubtract(pEnd, start, end);
                len = VectorNormalizeLength(end);
-               VectorAdd(pEnd, end, end);
+               VectorMA(pEnd, collision_endposnudge.value, end, end);
        }
        else
                VectorCopy(pEnd, end);
@@ -377,10 +376,7 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
                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];
+                       model = SV_GetModelFromEdict(touch);
                        pitchsign = SV_GetPitchSign(touch);
                }
                if (model)
@@ -388,18 +384,21 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_
                else
                        Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
                Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+               VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+               VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
                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);
+                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, 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_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, 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);
+       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
+               Collision_ShortenTrace(&cliptrace, len / (len + collision_endposnudge.value), pEnd);
 #endif
        return cliptrace;
 }
@@ -451,12 +450,12 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
        vec3_t end;
        vec_t len = 0;
 
-       if(!VectorCompare(start, pEnd))
+       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
        {
                // TRICK: make the trace 1 qu longer!
                VectorSubtract(pEnd, start, end);
                len = VectorNormalizeLength(end);
-               VectorAdd(pEnd, end, end);
+               VectorMA(pEnd, collision_endposnudge.value, end, end);
        }
        else
                VectorCopy(pEnd, end);
@@ -577,11 +576,7 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
                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;
+                       model = SV_GetModelFromEdict(touch);
                        pitchsign = SV_GetPitchSign(touch);
                }
                if (model)
@@ -589,18 +584,21 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co
                else
                        Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
                Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+               VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+               VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
                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);
+                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
                else
-                       Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
+                       Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, 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);
+       if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
+               Collision_ShortenTrace(&cliptrace, len / (len + collision_endposnudge.value), pEnd);
 #endif
        return cliptrace;
 }
@@ -635,7 +633,6 @@ int SV_PointSuperContents(const vec3_t point)
        matrix4x4_t matrix, imatrix;
        // model of other entity
        dp_model_t *model;
-       unsigned int modelindex;
        int frame;
        // list of entities to test for collisions
        int numtouchedicts;
@@ -666,10 +663,7 @@ int SV_PointSuperContents(const vec3_t point)
                        continue;
 
                // might interact, so do an exact clip
-               modelindex = (unsigned int)touch->fields.server->modelindex;
-               if (modelindex >= MAX_MODELS)
-                       continue;
-               model = sv.models[(int)touch->fields.server->modelindex];
+               model = SV_GetModelFromEdict(touch);
                if (!model || !model->PointSuperContents)
                        continue;
                Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
@@ -795,6 +789,7 @@ void SV_LinkEdict (prvm_edict_t *ent)
 {
        dp_model_t *model;
        vec3_t mins, maxs;
+       int modelindex;
 
        if (ent == prog->edicts)
                return;         // don't add the world
@@ -802,6 +797,18 @@ void SV_LinkEdict (prvm_edict_t *ent)
        if (ent->priv.server->free)
                return;
 
+       modelindex = (int)ent->fields.server->modelindex;
+       if (modelindex < 0 || modelindex >= MAX_MODELS)
+       {
+               Con_Printf("edict %i: SOLID_BSP with invalid modelindex!\n", PRVM_NUM_FOR_EDICT(ent));
+               modelindex = 0;
+       }
+       model = SV_GetModelByIndex(modelindex);
+
+       VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
+       VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
+       VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
+
 // set the abs box
 
        if (ent->fields.server->movetype == MOVETYPE_PHYSICS)
@@ -814,13 +821,6 @@ void SV_LinkEdict (prvm_edict_t *ent)
        }
        else if (ent->fields.server->solid == SOLID_BSP)
        {
-               int modelindex = (int)ent->fields.server->modelindex;
-               if (modelindex < 0 || modelindex >= MAX_MODELS)
-               {
-                       Con_Printf("edict %i: SOLID_BSP with invalid modelindex!\n", PRVM_NUM_FOR_EDICT(ent));
-                       modelindex = 0;
-               }
-               model = sv.models[modelindex];
                if (model != NULL)
                {
                        if (!model->TraceBox && developer.integer >= 1)
@@ -1592,7 +1592,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                Con_Printf("SV_PushMove: entity #%i has an invalid modelindex %f\n", PRVM_NUM_FOR_EDICT(pusher), pusher->fields.server->modelindex);
                return;
        }
-       pushermodel = sv.models[index];
+       pushermodel = SV_GetModelByIndex(index);
        pusherowner = pusher->fields.server->owner;
        pusherprog = PRVM_EDICT_TO_PROG(pusher);
 
@@ -1664,9 +1664,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
        pusher->fields.server->ltime += movetime;
        SV_LinkEdict(pusher);
 
-       pushermodel = NULL;
-       if (pusher->fields.server->modelindex >= 1 && pusher->fields.server->modelindex < MAX_MODELS)
-               pushermodel = sv.models[(int)pusher->fields.server->modelindex];
+       pushermodel = SV_GetModelFromEdict(pusher);
        Matrix4x4_CreateFromQuakeEntity(&pusherfinalmatrix, pusher->fields.server->origin[0], pusher->fields.server->origin[1], pusher->fields.server->origin[2], pusher->fields.server->angles[0], pusher->fields.server->angles[1], pusher->fields.server->angles[2], 1);
        Matrix4x4_Invert_Simple(&pusherfinalimatrix, &pusherfinalmatrix);
 
@@ -1710,7 +1708,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                // final position, move it
                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);
+                       Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, 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_TraceBox(check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, MOVE_NOMONSTERS, check, checkcontents);
                        if (!trace.startsolid)
                        {
@@ -1768,7 +1766,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                        check->fields.server->flags = (int)check->fields.server->flags & ~FL_ONGROUND;
 
                // if it is still inside the pusher, block
-               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);
+               Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, 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);
                if (trace.startsolid)
                {
                        // try moving the contacted entity a tiny bit further to account for precision errors
@@ -1783,7 +1781,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                                continue;
                        }
                        pusher->fields.server->solid = savesolid;
-                       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);
+                       Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, 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);
                        if (trace.startsolid)
                        {
                                // try moving the contacted entity a tiny bit less to account for precision errors
@@ -1797,7 +1795,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                                        continue;
                                }
                                pusher->fields.server->solid = savesolid;
-                               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);
+                               Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, 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);
                                if (trace.startsolid)
                                {
                                        // still inside pusher, so it's really blocked
@@ -2159,7 +2157,7 @@ Only used by players
 */
 void SV_WalkMove (prvm_edict_t *ent)
 {
-       int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity, hitsupercontentsmask;
+       int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity, hitsupercontentsmask, type;
        vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity;
        trace_t downtrace, trace;
        qboolean applygravity;
@@ -2185,8 +2183,27 @@ void SV_WalkMove (prvm_edict_t *ent)
 
        clip = SV_FlyMove (ent, sv.frametime, applygravity, NULL, hitsupercontentsmask);
 
+       if(sv_gameplayfix_downtracesupportsongroundflag.integer)
+       if(!(clip & 1))
+       {
+               // only try this if there was no floor in the way in the trace (no,
+               // this check seems to be not REALLY necessary, because if clip & 1,
+               // our trace will hit that thing too)
+               VectorSet(upmove, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + 1);
+               VectorSet(downmove, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] - 1);
+               if (ent->fields.server->movetype == MOVETYPE_FLYMISSILE)
+                       type = MOVE_MISSILE;
+               else if (ent->fields.server->solid == SOLID_TRIGGER || ent->fields.server->solid == SOLID_NOT)
+                       type = MOVE_NOMONSTERS; // only clip against bmodels
+               else
+                       type = MOVE_NORMAL;
+               trace = SV_TraceBox(upmove, ent->fields.server->mins, ent->fields.server->maxs, downmove, type, ent, SV_GenericHitSuperContentsMask(ent));
+               if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
+                       clip |= 1; // but we HAVE found a floor
+       }
+
        // if the move did not hit the ground at any point, we're not on ground
-       if (!(clip & 1))
+       if(!(clip & 1))
                ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
 
        SV_CheckVelocity(ent);