]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_phys.c
cl_input: movevars for "warsowbunny" mode, also implemented in Nexuiz cl_physics...
[xonotic/darkplaces.git] / sv_phys.c
index 6a6dda8c68383f6e84c4159f86ab708f39ec65de..434d08346b05f8a3b7312652782c3ee1a1dea0d5 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -519,7 +519,20 @@ static int SV_TestEntityPosition (prvm_edict_t *ent, vec3_t offset)
        }
        // if the trace found a better position for the entity, move it there
        if (VectorDistance2(trace.endpos, ent->fields.server->origin) >= 0.0001)
+       {
+#if 0
+               // please switch back to this code when trace.endpos sometimes being in solid bug is fixed
                VectorCopy(trace.endpos, ent->fields.server->origin);
+#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, SUPERCONTENTS_SOLID);
+               if(trace.startsolid)
+                       Con_Printf("SV_TestEntityPosition: trace.endpos detected to be in solid. NOT using it.\n");
+               else
+                       VectorCopy(org, ent->fields.server->origin);
+#endif
+       }
        return false;
 }
 
@@ -1390,111 +1403,123 @@ CLIENT MOVEMENT
 
 static float unstickoffsets[] =
 {
+       // poutting -/+z changes first as they are least weird
+        0,  0,  -1,
+        0,  0,  1,
+        // x or y changes
        -1,  0,  0,
         1,  0,  0,
         0, -1,  0,
         0,  1,  0,
+        // x and y changes
        -1, -1,  0,
         1, -1,  0,
        -1,  1,  0,
         1,  1,  0,
-        0,  0,  -1,
-        0,  0,  1,
-        0,  0,  -2,
-        0,  0,  2,
-        0,  0,  -3,
-        0,  0,  3,
-        0,  0,  -4,
-        0,  0,  4,
-        0,  0,  -5,
-        0,  0,  5,
-        0,  0,  -6,
-        0,  0,  6,
-        0,  0,  -7,
-        0,  0,  7,
-        0,  0,  -8,
-        0,  0,  8,
-        0,  0,  -9,
-        0,  0,  9,
-        0,  0,  -10,
-        0,  0,  10,
-        0,  0,  -11,
-        0,  0,  11,
-        0,  0,  -12,
-        0,  0,  12,
-        0,  0,  -13,
-        0,  0,  13,
-        0,  0,  -14,
-        0,  0,  14,
-        0,  0,  -15,
-        0,  0,  15,
-        0,  0,  -16,
-        0,  0,  16,
-        0,  0,  -17,
-        0,  0,  17,
 };
 
-/*
-=============
-SV_CheckStuck
+typedef enum unstickresult_e
+{
+       UNSTICK_STUCK = 0,
+       UNSTICK_GOOD = 1,
+       UNSTICK_UNSTUCK = 2
+}
+unstickresult_t;
 
-This is a big hack to try and fix the rare case of getting stuck in the world
-clipping hull.
-=============
-*/
-void SV_CheckStuck (prvm_edict_t *ent)
+unstickresult_t SV_UnstickEntityReturnOffset (prvm_edict_t *ent, vec3_t offset)
 {
-       int i;
-       vec3_t offset;
+       int i, maxunstick;
 
+       // if not stuck in a bmodel, just return
        if (!SV_TestEntityPosition(ent, vec3_origin))
-       {
-               VectorCopy (ent->fields.server->origin, ent->fields.server->oldorigin);
-               return;
-       }
+               return UNSTICK_GOOD;
 
        for (i = 0;i < (int)(sizeof(unstickoffsets) / sizeof(unstickoffsets[0]));i += 3)
        {
                if (!SV_TestEntityPosition(ent, unstickoffsets + i))
                {
-                       Con_DPrintf("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname), unstickoffsets[i+0], unstickoffsets[i+1], unstickoffsets[i+2]);
+                       VectorCopy(unstickoffsets + i, offset);
                        SV_LinkEdict (ent, true);
-                       return;
+                       return UNSTICK_UNSTUCK;
                }
        }
 
-       VectorSubtract(ent->fields.server->oldorigin, ent->fields.server->origin, offset);
-       if (!SV_TestEntityPosition(ent, offset))
+       maxunstick = (int) ((ent->fields.server->maxs[2] - ent->fields.server->mins[2]) * 0.36);
+       // magic number 0.36 allows unsticking by up to 17 units with the largest supported bbox
+
+       for(i = 2; i <= maxunstick; ++i)
        {
-               Con_DPrintf("Unstuck player entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname));
-               SV_LinkEdict (ent, true);
-               return;
+               VectorClear(offset);
+               offset[2] = -i;
+               if (!SV_TestEntityPosition(ent, offset))
+               {
+                       SV_LinkEdict (ent, true);
+                       return UNSTICK_UNSTUCK;
+               }
+               offset[2] = i;
+               if (!SV_TestEntityPosition(ent, offset))
+               {
+                       SV_LinkEdict (ent, true);
+                       return UNSTICK_UNSTUCK;
+               }
        }
 
-       Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname));
+       return UNSTICK_STUCK;
 }
 
 qboolean SV_UnstickEntity (prvm_edict_t *ent)
 {
-       int i;
-
-       // if not stuck in a bmodel, just return
-       if (!SV_TestEntityPosition(ent, vec3_origin))
-               return true;
-
-       for (i = 0;i < (int)(sizeof(unstickoffsets) / sizeof(unstickoffsets[0]));i += 3)
+       vec3_t offset;
+       switch(SV_UnstickEntityReturnOffset(ent, offset))
        {
-               if (!SV_TestEntityPosition(ent, unstickoffsets + i))
-               {
-                       Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname), unstickoffsets[i+0], unstickoffsets[i+1], unstickoffsets[i+2]);
-                       SV_LinkEdict (ent, true);
+               case UNSTICK_GOOD:
                        return true;
-               }
+               case UNSTICK_UNSTUCK:
+                       Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname), offset[0], offset[1], offset[2]);
+                       return true;
+               case UNSTICK_STUCK:
+                       if (developer.integer >= 100)
+                               Con_Printf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname));
+                       return false;
+               default:
+                       Con_Printf("SV_UnstickEntityReturnOffset returned a value outside its enum.\n");
+                       return false;
        }
+}
 
-       if (developer.integer >= 100)
-               Con_Printf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname));
-       return false;
+/*
+=============
+SV_CheckStuck
+
+This is a big hack to try and fix the rare case of getting stuck in the world
+clipping hull.
+=============
+*/
+void SV_CheckStuck (prvm_edict_t *ent)
+{
+       vec3_t offset;
+
+       switch(SV_UnstickEntityReturnOffset(ent, offset))
+       {
+               case UNSTICK_GOOD:
+                       VectorCopy (ent->fields.server->origin, ent->fields.server->oldorigin);
+                       break;
+               case UNSTICK_UNSTUCK:
+                       Con_DPrintf("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname), offset[0], offset[1], offset[2]);
+                       break;
+               case UNSTICK_STUCK:
+                       VectorSubtract(ent->fields.server->oldorigin, ent->fields.server->origin, offset);
+                       if (!SV_TestEntityPosition(ent, offset))
+                       {
+                               Con_DPrintf("Unstuck player entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname));
+                               SV_LinkEdict (ent, true);
+                       }
+                       else
+                               Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname));
+                       break;
+               default:
+                       Con_Printf("SV_UnstickEntityReturnOffset returned a value outside its enum.\n");
+       }
 }
 
 
@@ -2374,7 +2399,7 @@ void SV_Physics (void)
        }
 
        // decrement prog->num_edicts if the highest number entities died
-       for (;PRVM_EDICT_NUM(prog->num_edicts - 1)->priv.server->free;prog->num_edicts--);
+       for (;PRVM_ED_CanAlloc(PRVM_EDICT_NUM(prog->num_edicts - 1));prog->num_edicts--);
 
        if (!sv_freezenonclients.integer)
                sv.time += sv.frametime;