From: divverent Date: Wed, 22 Apr 2009 17:26:58 +0000 (+0000) Subject: rewrote entity unsticking to be safe from world fallthrough for small entities too... X-Git-Tag: xonotic-v0.1.0preview~1675 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=509d0579232b21bce445380ea844e93b84839847;p=xonotic%2Fdarkplaces.git rewrote entity unsticking to be safe from world fallthrough for small entities too (by making the z offsets tried depend on the height of the entity) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8937 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/sv_phys.c b/sv_phys.c index 2bcea7ff..434d0834 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -1403,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"); + } }