qboolean SV_MoveTest( edict_t *ent, vec3_t move, qboolean relink ) { float temp; vec3_t oldorg, neworg, end; trace_t trace; VectorCopy( ent->v.origin, oldorg ); VectorAdd( ent->v.origin, move, neworg ); temp = svgame.movevars.stepsize; neworg[2] += temp; VectorCopy( neworg, end ); end[2] -= temp * 2.0f; trace = SV_MoveNoEnts( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent ); if( trace.allsolid != 0 ) return 0; if( trace.startsolid != 0 ) { neworg[2] -= temp; trace = SV_MoveNoEnts( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent ); if( trace.allsolid != 0 || trace.startsolid != 0 ) return 0; } if( trace.fraction == 1.0f ) { if( ent->v.flags & FL_PARTIALGROUND ) { VectorAdd( ent->v.origin, move, ent->v.origin ); if( relink ) SV_LinkEdict( ent, true ); ent->v.flags &= ~FL_ONGROUND; return 1; } return 0; } else { VectorCopy( trace.endpos, ent->v.origin ); if( SV_CheckBottom( ent, WALKMOVE_WORLDONLY ) == 0 ) { if( ent->v.flags & FL_PARTIALGROUND ) { if( relink ) SV_LinkEdict( ent, true ); return 1; } VectorCopy( oldorg, ent->v.origin ); return 0; } else { ent->v.flags &= ~FL_PARTIALGROUND; ent->v.groundentity = trace.ent; if( relink ) SV_LinkEdict( ent, true ); return 1; } } }
qboolean SV_movetest(edict_t *ent, vec3_t move, qboolean relink) { float temp; vec3_t oldorg, neworg, end; trace_t trace; oldorg[0] = ent->v.origin[0]; oldorg[1] = ent->v.origin[1]; oldorg[2] = ent->v.origin[2]; neworg[0] = ent->v.origin[0] + move[0]; neworg[1] = ent->v.origin[1] + move[1]; neworg[2] = ent->v.origin[2] + move[2]; temp = cvar_sv_stepsize.value; neworg[2] += temp; end[0] = neworg[0]; end[1] = neworg[1]; end[2] = neworg[2]; end[2] -= temp*2; trace = SV_MoveNoEnts(neworg, ent->v.mins, ent->v.maxs, end, 0, ent); if(trace.allsolid != 0) { return(0); } if(trace.startsolid != 0) { neworg[2] -= temp; trace = SV_MoveNoEnts(neworg, ent->v.mins, ent->v.maxs, end, 0, ent); if(trace.allsolid != 0 || trace.startsolid != 0) { return(0); } } if(trace.fraction == 1) { if(ent->v.flags & FL_PARTIALGROUND) { ent->v.origin[0] += move[0]; ent->v.origin[1] += move[1]; ent->v.origin[2] += move[2]; if(relink != 0) { SV_LinkEdict(ent, 1); } ent->v.flags &= ~FL_ONGROUND; return(1); } return(0); } else { ent->v.origin[0] = trace.endpos[0]; ent->v.origin[1] = trace.endpos[1]; ent->v.origin[2] = trace.endpos[2]; if(SV_CheckBottom(ent) == 0) { if(ent->v.flags & FL_PARTIALGROUND) { if(relink != 0) { SV_LinkEdict(ent, 1); } return(1); } ent->v.origin[0] = oldorg[0]; ent->v.origin[1] = oldorg[1]; ent->v.origin[2] = oldorg[2]; return(0); } else { if(ent->v.flags & FL_PARTIALGROUND) { ent->v.flags &= ~FL_PARTIALGROUND; } ent->v.groundentity = trace.pHit; if(relink != 0) { SV_LinkEdict(ent, 1); } return(1); } } }
/* ============= SV_CheckBottom Returns false if any part of the bottom of the entity is off an edge that is not a staircase. ============= */ qboolean SV_CheckBottom( edict_t *ent, int iMode ) { vec3_t mins, maxs, start, stop; float mid, bottom; trace_t trace; int x, y; VectorAdd( ent->v.origin, ent->v.mins, mins ); VectorAdd( ent->v.origin, ent->v.maxs, maxs ); // if all of the points under the corners are solid world, don't bother // with the tougher checks // the corners must be within 16 of the midpoint start[2] = mins[2] - 1.0f; for( x = 0; x <= 1; x++ ) { for( y = 0; y <= 1; y++ ) { start[0] = x ? maxs[0] : mins[0]; start[1] = y ? maxs[1] : mins[1]; svs.groupmask = ent->v.groupinfo; if( SV_PointContents( start ) != CONTENTS_SOLID ) goto realcheck; } } return true; // we got out easy realcheck: // check it for real... start[2] = mins[2] + svgame.movevars.stepsize; // the midpoint must be within 16 of the bottom start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5f; start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5f; stop[2] = start[2] - 2.0f * svgame.movevars.stepsize; if( iMode == WALKMOVE_WORLDONLY ) trace = SV_MoveNoEnts( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent ); else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent ); if( trace.fraction == 1.0f ) return false; mid = bottom = trace.endpos[2]; // the corners must be within 16 of the midpoint for( x = 0; x <= 1; x++ ) { for( y = 0; y <= 1; y++ ) { start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; if( iMode == WALKMOVE_WORLDONLY ) trace = SV_MoveNoEnts( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent ); else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent ); if( trace.fraction != 1.0f && trace.endpos[2] > bottom ) bottom = trace.endpos[2]; if( trace.fraction == 1.0f || mid - trace.endpos[2] > svgame.movevars.stepsize ) return false; } } return true; }