if (ent->fields.server->solid == SOLID_BSP)
{
int modelindex = (int)ent->fields.server->modelindex;
- if (modelindex < 0 || modelindex > MAX_MODELS)
+ if (modelindex < 0 || modelindex >= MAX_MODELS)
{
Con_Printf("edict %i: SOLID_BSP with invalid modelindex!\n", PRVM_NUM_FOR_EDICT(ent));
modelindex = 0;
}
// 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;
}
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");
+ }
}
}
else if (ent->fields.server->movetype == MOVETYPE_BOUNCE)
{
- float d;
- ClipVelocity (ent->fields.server->velocity, trace.plane.normal, ent->fields.server->velocity, 1.5);
+ float d, ent_gravity;
+ prvm_eval_t *val;
+ float bouncefactor = 0.5f;
+ float bouncestop = 60.0f / 800.0f;
+
+ val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.bouncefactor);
+ if (val!=0 && val->_float)
+ bouncefactor = val->_float;
+
+ val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.bouncestop);
+ if (val!=0 && val->_float)
+ bouncestop = val->_float;
+
+ ClipVelocity (ent->fields.server->velocity, trace.plane.normal, ent->fields.server->velocity, 1 + bouncefactor);
// LordHavoc: fixed grenades not bouncing when fired down a slope
+ val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.gravity);
+ if (val!=0 && val->_float)
+ ent_gravity = val->_float;
+ else
+ ent_gravity = 1.0;
if (sv_gameplayfix_grenadebouncedownslopes.integer)
{
d = DotProduct(trace.plane.normal, ent->fields.server->velocity);
- if (trace.plane.normal[2] > 0.7 && fabs(d) < sv_gravity.value * (60.0 / 800.0))
+ if (trace.plane.normal[2] > 0.7 && fabs(d) < sv_gravity.value * bouncestop * ent_gravity)
{
ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
}
else
{
- if (trace.plane.normal[2] > 0.7 && ent->fields.server->velocity[2] < sv_gravity.value * (60.0 / 800.0))
+ if (trace.plane.normal[2] > 0.7 && ent->fields.server->velocity[2] < sv_gravity.value * bouncestop * ent_gravity)
{
ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
else
ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
}
- if (!sv_gameplayfix_slidemoveprojectiles.integer)
+ if (!sv_gameplayfix_slidemoveprojectiles.integer || (ent->fields.server->movetype != MOVETYPE_BOUNCE && ent->fields.server->movetype == MOVETYPE_BOUNCEMISSILE) || ((int)ent->fields.server->flags & FL_ONGROUND))
break;
}
}
// don't run physics here if running asynchronously
- if (host_client->clmovement_skipphysicsframes <= 0)
+ if (host_client->clmovement_inputtimeout <= 0)
{
SV_ClientThink();
//host_client->cmd.time = max(host_client->cmd.time, sv.time);
case MOVETYPE_WALK:
SV_RunThink (ent);
// don't run physics here if running asynchronously
- if (host_client->clmovement_skipphysicsframes <= 0)
+ if (host_client->clmovement_inputtimeout <= 0)
SV_WalkMove (ent);
break;
case MOVETYPE_TOSS:
// decrement the countdown variable used to decide when to go back to
// synchronous physics
- if (host_client->clmovement_skipphysicsframes > 0)
- host_client->clmovement_skipphysicsframes--;
+ if (host_client->clmovement_inputtimeout > sv.frametime)
+ host_client->clmovement_inputtimeout -= sv.frametime;
+ else
+ host_client->clmovement_inputtimeout = 0;
SV_CheckVelocity (ent);
}
// 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;