示例#1
0
文件: sv_phys.c 项目: indev/asquake
/*
============
SV_PushEntity

Does not change the entities velocity at all
============
*/
trace_t SV_PushEntity(edict_t * ent, vec3_t push)
{
    trace_t trace;
    vec3_t end;

    VectorAdd(ent->v.origin, push, end);

    if (ent->v.movetype == MOVETYPE_FLYMISSILE)
	trace =
	    SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end,
		    MOVE_MISSILE, ent);
    else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
	// only clip against bmodels
	trace =
	    SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end,
		    MOVE_NOMONSTERS, ent);
    else
	trace =
	    SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end,
		    MOVE_NORMAL, ent);

    VectorCopy(trace.endpos, ent->v.origin);
    SV_LinkEdict(ent, true);

    if (trace.ent)
	SV_Impact(ent, trace.ent);

    return trace;
}
示例#2
0
文件: sv_move.c 项目: indev/asquake
qboolean SV_CheckBottom(edict_t * ent)
{
    vec3_t mins, maxs, start, stop;
    trace_t trace;
    int x, y;
    float mid, bottom;

    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;
    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];
	    if (SV_PointContents(start) != CONTENTS_SOLID)
		goto realcheck;
	}

    c_yes++;
    return true;		// we got out easy

  realcheck:
    c_no++;
//
// check it for real...
//
    start[2] = mins[2];

// the midpoint must be within 16 of the bottom
    start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5;
    start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5;
    stop[2] = start[2] - 2 * STEPSIZE;
    trace = SV_Move(start, vec3_origin, vec3_origin, stop, true, ent);

    if (trace.fraction == 1.0)
	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];

	    trace =
		SV_Move(start, vec3_origin, vec3_origin, stop, true, ent);

	    if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
		bottom = trace.endpos[2];
	    if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
		return false;
	}

    c_yes++;
    return true;
}
示例#3
0
文件: bot.cpp 项目: DrLabman/QMB
/**
 * This function is used to decide if a bot can see his enemy or not
 * (this is just a recoded PF_traceline)
 */
bool Traceline(vec3_t start, vec3_t end, edict_t *self, edict_t *enemy) {
	trace_t trace = SV_Move(start, vec3_origin, vec3_origin, end, MOVE_NOMONSTERS, self);

	if (trace.fraction >= 0.999f) // If there were no walls
	{
		//AddTrail(start,trace.endpos,3,0.05f,1.5f,zerodir);

		trace = SV_Move(start, vec3_origin, vec3_origin, end, MOVE_NORMAL, self);
		if (trace.ent == enemy) // And there were no other entities in the way
			return true; // Then the bot can see him
	}

	return false; // Otherwise he cant
}
示例#4
0
trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
{
	edict_t	tempent, *tent;
	trace_t	trace;
	vec3_t	move, end;
	double	save_frametime;

	save_frametime = host_frametime;
	host_frametime = 0.05;

	memcpy (&tempent, ent, sizeof(edict_t));
	tent = &tempent;

	while (1)
	{
		SV_CheckVelocity (tent);
		SV_AddGravity (tent);
		VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
		VectorScale (tent->v.velocity, host_frametime, move);
		VectorAdd (tent->v.origin, move, end);
		trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);	
		VectorCopy (trace.endpos, tent->v.origin);

		if (trace.ent)
			if (trace.ent != ignore)
				break;
	}
	host_frametime = save_frametime;

	return trace;
}
示例#5
0
void TraceLineToEntity(vec3_t start, vec3_t end, vec3_t impact, edict_t *ent)
{
	trace_t	trace;
	memset(&trace, 0, sizeof(trace));
	trace = SV_Move(start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
	VectorCopy(trace.endpos, impact);
}
示例#6
0
/*
=========
Traceline

This function is used to decide if a bot can see his enemy or not
(this is just a recoded PF_traceline)
=========
*/
float BotTraceline (vec3_t start, vec3_t end, edict_t *self)
{
	trace_t	trace;

	trace = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, self);

	return trace.fraction;
}
示例#7
0
文件: sv_phys.c 项目: Blzut3/Engoo
//#ifdef QUAKE2	// 2001-09-16 Quake 2 builtin functions by id/Maddes
trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
{
	edict_t	tempent, *tent;
	trace_t	trace;
	vec3_t	move;
	vec3_t	end;
	double	save_frametime;
//	extern particle_t	*active_particles, *free_particles;
//	particle_t	*p;
	int i;	// 2001-09-16 SV_Trace_Toss endless loop fix by LordHavoc

	save_frametime = host_frametime;
	host_frametime = 0.05;

	memcpy(&tempent, ent, sizeof(edict_t));
	tent = &tempent;

// 2001-09-16 SV_Trace_Toss endless loop fix by LordHavoc  start
//	while (1)
	for (i = 0;i < 200;i++)	//sanity check; never trace more than 10 seconds
// 2001-09-16 SV_Trace_Toss endless loop fix by LordHavoc  end
	{
		SV_CheckVelocity (tent);
		SV_AddGravity (tent);
		VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
		VectorScale (tent->v.velocity, host_frametime, move);
		VectorAdd (tent->v.origin, move, end);
		trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);
		VectorCopy (trace.endpos, tent->v.origin);

//		p = free_particles;
//		if (p)
//		{
//			free_particles = p->next;
//			p->next = active_particles;
//			active_particles = p;
//
//			p->die = 256;
//			p->color = 15;
//			p->type = pt_static;
//			VectorCopy (vec3_origin, p->vel);
//			VectorCopy (tent->v.origin, p->org);
//		}

		if (trace.ent)
			if (trace.ent != ignore)
				break;
	}
//	p->color = 224;
	host_frametime = save_frametime;
	
	return trace;
}
示例#8
0
trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
{
	edict_t	tempent, *tent;
	trace_t	trace;
	vec3_t	move;
	vec3_t	end;
	double	save_frametime;
//	extern particle_t	*active_particles, *free_particles;
//	particle_t	*p;


	save_frametime = host_frametime;
	host_frametime = 0.05;

	memcpy(&tempent, ent, sizeof(edict_t));
	tent = &tempent;

	while (1)
	{
		SV_CheckVelocity (tent);
		SV_AddGravity (tent);
		VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
		VectorScale (tent->v.velocity, host_frametime, move);
		VectorAdd (tent->v.origin, move, end);
		trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);	
		VectorCopy (trace.endpos, tent->v.origin);

//		p = free_particles;
//		if (p)
//		{
//			free_particles = p->next;
//			p->next = active_particles;
//			active_particles = p;
//		
//			p->die = 256;
//			p->color = 15;
//			p->type = pt_static;
//			VectorCopy (vec3_origin, p->vel);
//			VectorCopy (tent->v.origin, p->org);
//		}

		if (trace.ent)
			if (trace.ent != ignore)
				break;
	}
//	p->color = 224;
	host_frametime = save_frametime;
	return trace;
}
示例#9
0
static void
CPQW_traceline (progs_t *pr)
{
	float      *v1, *v2;
	edict_t    *ent;
	int         nomonsters;
	trace_t     trace;
	static int  tl_to_move[] = {
		MOVE_NORMAL,
		MOVE_NORMAL,
		MOVE_NORMAL,
		MOVE_TRIGGERS,
		MOVE_EVERYTHING,
	};

	v1 = P_VECTOR (pr, 0);
	v2 = P_VECTOR (pr, 1);
	nomonsters = P_FLOAT (pr, 2);
	ent = P_EDICT (pr, 3);

	if (nomonsters < TL_ANY_SOLID || nomonsters > TL_EVERYTHING)
		nomonsters = TL_ANY_SOLID;
	nomonsters = tl_to_move[nomonsters];

	if (sv_antilag->int_val == 2)
		nomonsters |= MOVE_LAGGED;

	trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);

	*sv_globals.trace_allsolid = trace.allsolid;
	*sv_globals.trace_startsolid = trace.startsolid;
	*sv_globals.trace_fraction = trace.fraction;
	*sv_globals.trace_inwater = trace.inwater;
	*sv_globals.trace_inopen = trace.inopen;
	VectorCopy (trace.endpos, *sv_globals.trace_endpos);
	VectorCopy (trace.plane.normal, *sv_globals.trace_plane_normal);
	*sv_globals.trace_plane_dist = trace.plane.dist;

	if (trace.ent)
		*sv_globals.trace_ent = EDICT_TO_PROG (pr, trace.ent);
	else
		*sv_globals.trace_ent = EDICT_TO_PROG (pr, sv.edicts);
}
示例#10
0
/*
============
SV_PushEntity

Does not change the entities velocity at all
============
*/
trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int *blocked )
{
	trace_t	trace;
	int	type;
	vec3_t	end;

	VectorAdd( ent->v.origin, lpush, end );

	if( ent->v.movetype == MOVETYPE_FLYMISSILE )
		type = MOVE_MISSILE;
	else if( ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT )
		type = MOVE_NOMONSTERS; // only clip against bmodels
	else type = MOVE_NORMAL;

	trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, end, type, ent );

	if( trace.fraction != 0.0f )
	{
		VectorCopy( trace.endpos, ent->v.origin );

		if( sv.state == ss_active && apush[YAW] && ( ent->v.flags & FL_CLIENT ))
		{
			ent->v.avelocity[1] += apush[1];
			ent->v.fixangle = 2;
		}

		// don't rotate pushables!
		if( SV_AllowPushRotate( ent ))
			ent->v.angles[YAW] += trace.fraction * apush[YAW];
	}

	SV_LinkEdict( ent, true );

	if( blocked ) *blocked = !VectorCompare( ent->v.origin, end ); // can't move full distance

	// so we can run impact function afterwards.
	if( SV_IsValidEdict( trace.ent ))
		SV_Impact( ent, trace.ent, &trace );

	return trace;
}
示例#11
0
/*
==================
SV_UserFriction

==================
*/
void SV_UserFriction (void)
{
	float	*vel;
	float	speed, newspeed, control;
	vec3_t	start, stop;
	float	friction;
	trace_t	trace;

	vel = velocity;

	speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
	if (!speed)
		return;

// if the leading edge is over a dropoff, increase friction
	start[0] = stop[0] = origin[0] + vel[0]/speed*16;
	start[1] = stop[1] = origin[1] + vel[1]/speed*16;
	start[2] = origin[2] + sv_player->v.mins[2];
	stop[2] = start[2] - 34;

	trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, sv_player);

	if (trace.fraction == 1.0)
		friction = sv_friction.value*sv_edgefriction.value;
	else
		friction = sv_friction.value;

// apply friction
	control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
	newspeed = speed - host_frametime*control*friction;

	if (newspeed < 0)
		newspeed = 0;
	newspeed /= speed;

	vel[0] = vel[0] * newspeed;
	vel[1] = vel[1] * newspeed;
	vel[2] = vel[2] * newspeed;
}
示例#12
0
void Physics_AddFriction(edict_t *eEntity,vec3_t vVelocity,vec3_t vOrigin)
{
	float	*vel;
	float	speed, newspeed, control;
	vec3_t	start, stop;
	float	friction;
	trace_t	trace;

	vel = vVelocity;

	speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
	if(!speed)
		return;

	// If the leading edge is over a dropoff, increase friction
	start[0] = stop[0] = vOrigin[0] + vel[0]/speed*16.0f;
	start[1] = stop[1] = vOrigin[1] + vel[1]/speed*16.0f;
	start[2] = vOrigin[2] + eEntity->v.mins[2];
	stop[2] = start[2] - 34;

	trace = SV_Move(start,mv3Origin,mv3Origin,stop,true,eEntity);
	if(trace.fraction == 1.0f)
		friction = eEntity->Physics.fFriction*sv_edgefriction.value;
	else
		friction = eEntity->Physics.fFriction;

	// Apply friction
	control = speed < cvPhysicsStopSpeed.value ? cvPhysicsStopSpeed.value : speed;
	newspeed = speed - host_frametime*control*friction;

	if(newspeed < 0)
		newspeed = 0;
	newspeed /= speed;

	Math_VectorScale(vel,newspeed,vel);
}
示例#13
0
/* DESCRIPTION: SV_Trace_Toss
// LOCATION: sv_phys.c
// PATH: PF_TraceToss_Shared
//
// Say I throw a grenade.  Where will it go?  This function finds out by
// simulating ten seconds' worth of frames.
*/
trace_t * SV_Trace_Toss(trace_t * Outgoing_Trace, edict_t *tossent, edict_t *ignore) {

   int i;
   vec3_t var_378_end;
   vec3_t var_36C_move;
   trace_t var_360_trace;
   edict_t var_324_TempEdict;
   edict_t * var_328_TempEdictPtr;
   double var_380_host_frametime;

   var_380_host_frametime = host_frametime;
   host_frametime = .05;

   Q_memcpy(&var_324_TempEdict, tossent, sizeof(edict_t));

   var_328_TempEdictPtr = &var_324_TempEdict;

//   while(1) //a sanity check to avoid tracing more than ten seconds was present in QW, I think it's a good idea.  This may need to be adjusted to account for the alterable frametimes.
   for (i = 0; i < 200; i++)
   {
      SV_CheckVelocity(var_328_TempEdictPtr);
      SV_AddGravity(var_328_TempEdictPtr);
      VectorMA(var_328_TempEdictPtr->v.angles, host_frametime, var_328_TempEdictPtr->v.avelocity, var_328_TempEdictPtr->v.angles);
      VectorScale(var_328_TempEdictPtr->v.velocity, host_frametime, var_36C_move);
      VectorAdd(var_328_TempEdictPtr->v.origin, var_36C_move, var_378_end);

      var_360_trace = SV_Move(var_328_TempEdictPtr->v.origin, var_328_TempEdictPtr->v.mins, var_328_TempEdictPtr->v.maxs, var_378_end, 0, var_328_TempEdictPtr, 0);
      VectorCopy(var_360_trace.endpos, var_328_TempEdictPtr->v.origin);

      if(var_360_trace.pHit != NULL && var_360_trace.pHit != ignore) { break; }
   }

   host_frametime = var_380_host_frametime;
   Q_memcpy(Outgoing_Trace, &var_360_trace, sizeof(trace_t));
   return(Outgoing_Trace);
}
示例#14
0
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_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_WORLDONLY, ent );

	if( trace.allsolid != 0 )
		return 0;

	if( trace.startsolid != 0 )
	{
		neworg[2] -= temp;
		trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_WORLDONLY, 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, MOVE_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;
		}
	}
}
示例#15
0
qboolean SV_MoveStep( edict_t *ent, vec3_t move, qboolean relink )
{
	int	i;
	trace_t	trace;
	vec3_t	oldorg, neworg, end;
	edict_t	*enemy;
	float	dz;

	VectorCopy( ent->v.origin, oldorg );
	VectorAdd( ent->v.origin, move, neworg );

	// well, try it.  Flying and swimming monsters are easiest.
	if( ent->v.flags & ( FL_SWIM|FL_FLY ))
	{
		// try one move with vertical motion, then one without
		for( i = 0; i < 2; i++ )
		{
			VectorAdd( ent->v.origin, move, neworg );

			enemy = ent->v.enemy;
			if( i == 0 && enemy != NULL )
			{
				dz = ent->v.origin[2] - enemy->v.origin[2];

				if( dz > 40 ) neworg[2] -= 8;
				else if( dz < 30 ) neworg[2] += 8;
			}

			trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, neworg, MOVE_NORMAL, ent );

			if( trace.fraction == 1.0f )
			{
				svs.groupmask = ent->v.groupinfo;

				// that move takes us out of the water.
				// apparently though, it's okay to travel into solids, lava, sky, etc :)
				if(( ent->v.flags & FL_SWIM ) && SV_PointContents( trace.endpos ) == CONTENTS_EMPTY )
					return 0;

				VectorCopy( trace.endpos, ent->v.origin );
				if( relink ) SV_LinkEdict( ent, true );

				return 1;
			}
			else
			{
				if( !SV_IsValidEdict( enemy ))
					break;
			}
		}
		return 0;
	}
	else
	{

		dz = svgame.movevars.stepsize;
		neworg[2] += dz;
		VectorCopy( neworg, end );
		end[2] -= dz * 2.0f;

		trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent );
		if( trace.allsolid )
			return 0;

		if( trace.startsolid != 0 )
		{
			neworg[2] -= dz;
			trace = SV_Move( 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, MOVE_NORMAL ) == 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;
			}
		}
	}
}
示例#16
0
void SV_SetIdealPitch (void)
{
	float	angleval, sinval, cosval;
	trace_t	tr;
	vec3_t	top, bottom;
	float	z[MAX_FORWARD];
	int		i, j;
	int		step, dir, steps;

	if (!((int)sv_player->v.flags & FL_ONGROUND))
		return;

	angleval = sv_player->v.angles[YAW] * M_PI*2 / 360;
	sinval = sin(angleval);
	cosval = cos(angleval);

	for (i=0 ; i<MAX_FORWARD ; i++)
	{
		top[0] = sv_player->v.origin[0] + cosval*(i+3)*12;
		top[1] = sv_player->v.origin[1] + sinval*(i+3)*12;
		top[2] = sv_player->v.origin[2] + sv_player->v.view_ofs[2];

		bottom[0] = top[0];
		bottom[1] = top[1];
		bottom[2] = top[2] - 160;

		tr = SV_Move (top, vec3_origin, vec3_origin, bottom, 1, sv_player);
		if (tr.allsolid)
			return;	// looking at a wall, leave ideal the way is was

		if (tr.fraction == 1)
			return;	// near a dropoff

		z[i] = top[2] + tr.fraction*(bottom[2]-top[2]);
	}

	dir = 0;
	steps = 0;
	for (j=1 ; j<i ; j++)
	{
		step = z[j] - z[j-1];
		if (step > -ON_EPSILON && step < ON_EPSILON)
			continue;

		if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) )
			return;		// mixed changes

		steps++;
		dir = step;
	}

	if (!dir)
	{
		sv_player->v.idealpitch = 0;
		return;
	}

	if (steps < 2)
		return;
	sv_player->v.idealpitch = -dir * sv_idealpitchscale.value;
}
示例#17
0
int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
{
	int			bumpcount, numbumps;
	vec3_t		dir;
	float		d;
	int			numplanes;
	vec3_t		planes[MAX_CLIP_PLANES];
	vec3_t		primal_velocity, original_velocity, new_velocity;
	int			i, j;
	trace_t		trace;
	vec3_t		end;
	float		time_left;
	int			blocked;

	numbumps = 4;

	blocked = 0;
	Math_VectorCopy (ent->v.velocity, original_velocity);
	Math_VectorCopy (ent->v.velocity, primal_velocity);
	numplanes = 0;

	time_left = time;

	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
	{
		if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
			break;

		for (i=0 ; i<3 ; i++)
			end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];

		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, FALSE, ent);
		if(trace.bAllSolid)
		{
			// Entity is trapped in another solid
			Math_VectorCopy(mv3Origin, ent->v.velocity);
			return 3;
		}

		if (trace.fraction > 0)
		{
			// Actually covered some distance
			Math_VectorCopy (trace.endpos, ent->v.origin);
			Math_VectorCopy (ent->v.velocity, original_velocity);
			numplanes = 0;
		}

		if (trace.fraction == 1)
			 break;		// moved the entire distance

		if(!trace.ent)
		{
			Sys_Error ("SV_FlyMove: !trace.ent");
			return 0;
		}

		if (trace.plane.normal[2] > 0.7)
		{
			blocked |= 1;		// floor
			if (trace.ent->Physics.iSolid == SOLID_BSP)
			{
				ent->v.flags		|= FL_ONGROUND;
				ent->v.groundentity = trace.ent;
			}
		}

		if (!trace.plane.normal[2])
		{
			blocked |= 2;		// step
			if (steptrace)
				*steptrace = trace;	// save for player extrafriction
		}

		// Run the impact function
		Physics_Impact(ent,trace.ent);
		if (ent->free)
			break;		// removed by the impact function

		time_left -= time_left * trace.fraction;

		// Cliped to another plane
		if(numplanes >= MAX_CLIP_PLANES)
		{
			// This shouldn't really happen
			Math_VectorCopy(mv3Origin, ent->v.velocity);
			return 3;
		}

		Math_VectorCopy (trace.plane.normal, planes[numplanes]);
		numplanes++;

		// Modify original_velocity so it parallels all of the clip planes
		for(i = 0; i < numplanes; i++)
		{
			ClipVelocity (original_velocity, planes[i], new_velocity, 1);
			for (j=0 ; j<numplanes ; j++)
				if (j != i)
				{
					if(Math_DotProduct(new_velocity,planes[j]) < 0)
						break;	// not ok
				}
			if (j == numplanes)
				break;
		}

		if (i != numplanes)
			Math_VectorCopy (new_velocity, ent->v.velocity);
		else
		{
			// Go along the crease
			if (numplanes != 2)
			{
				Math_VectorCopy(mv3Origin, ent->v.velocity);
				return 7;
			}

			Math_CrossProduct(planes[0], planes[1], dir);
			d = Math_DotProduct(dir, ent->v.velocity);
			Math_VectorScale(dir, d, ent->v.velocity);
		}

		// if original velocity is against the original velocity, stop dead
		// to avoid tiny occilations in sloping corners
		if(Math_DotProduct(ent->v.velocity,primal_velocity) <= 0)
		{
			Math_VectorCopy(mv3Origin,ent->v.velocity);
			return blocked;
		}
	}

	return blocked;
}
示例#18
0
qboolean SV_CheckBottom (edict_t *ent)
{//By this point, ent has been moved to it's new position after the
	//move, and adjusted for steps
	vec3_t	mins, maxs, start, stop;
	trace_t	trace;
	int		x, y;
	float	mid, bottom;
	float	save_hull;

	VectorAdd (ent->v.origin, ent->v.mins, mins);
	VectorAdd (ent->v.origin, ent->v.maxs, maxs);

/*//Make it use the clipping hull's size, not their bounding box...
	model = sv.models[ (int)sv.edicts->v.modelindex ];
	VectorSubtract (ent->v.maxs, ent->v.mins, size);
	if(ent->v.hull)
	{
		index = ent->v.hull-1;
		wclip_hull = &model->hulls[index];;
		if (!wclip_hull)  // Invalid hull
		{
			Con_Printf ("ERROR: hull %d is null.\n",wclip_hull);
			wclip_hull = &model->hulls[0];
		}
	}
	else  // Using the old way uses size to determine hull to use
	{
		if (size[0] < 3) // Point
			wclip_hull = &model->hulls[0];
		else if (size[0] <= 8)  // Pentacles
			wclip_hull = &model->hulls[4];
		else if (size[0] <= 32 && size[2] <= 28)  // Half Player
			wclip_hull = &model->hulls[3];
		else if (size[0] <= 32)  // Full Player
			wclip_hull = &model->hulls[1];
		else // Golumn
			wclip_hull = &model->hulls[5];
	}
	VectorAdd (ent->v.origin, wclip_hull->clip_mins, mins);
	VectorAdd (ent->v.origin, wclip_hull->clip_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;
	for	(x=0 ; x<2 ; x++)
		for	(y=0 ; y<2 ; y++)
		{
			if(x)
				start[0] = maxs[0];
			else
				start[0] = mins[0];
			if(y)
				start[1] = maxs[1];
			else
				start[1] = mins[1];
//			start[0] = x ? maxs[0] : mins[0];
//			start[1] = y ? maxs[1] : mins[1];
			if (SV_PointContents (start) != CONTENTS_SOLID)
				goto realcheck;
		}

//	c_yes++;
	return true;		// we got out easy

realcheck:	// check it for real...
//	c_no++;

	start[2] = mins[2];
	
// the midpoint must be within 16 of the bottom
	start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
	start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
	stop[2] = start[2] - 2*STEPSIZE;
//do a trace from the bottom center of the ent down
//to 36 below the bottom center of the ent, using a point hull
//the "true" in this function is telling SV_Move to consider
//this ent's movement as MOVE_NOMONSTERS - means it will
//not clip against entities in this move
//NOTE: these don't check for trace_allsolid of trace_startsolid.
//Technically, these can't possibly be a valid result since
//the start point is in the ent, but what about imprecision?
	
	save_hull = ent->v.hull;//temp hack so it HullForEntity doesn't calculate the wrong offset
	ent->v.hull = 0;
	trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
	ent->v.hull = save_hull;
	
/*	if((int)ent->v.flags&FL_MONSTER)
	{
		if(trace.allsolid)
			Con_DPrintf("Checkbottom midpoint check was all solid!!!\n");
		else if(trace.startsolid)
			Con_DPrintf("Checkbottom midpoint check started solid!!!\n");
	}
*/
	if (trace.fraction == 1.0)
		return false;
//trace did not reach full 36 below, so set mid and bottom
//to whatever distance it did get to below the ent's
//bottom centerpoint (start[2])
	mid = bottom = trace.endpos[2];

	// the corners must be within 16 of the midpoint	
	for	(x=0 ; x<2 ; x++)
		for	(y=0 ; y<2 ; y++)
		{//check 4 corners, in this order:
			//x = 0, y = 0 (NE)
			//x = 0, y = 1 (SE)
			//x = 1, y = 0 (NW)
			//x = 1, y = 1 (SW)
			if(x)
				start[0] = stop[0] = maxs[0];
			else
				start[0] = stop[0] = mins[0];
			if(y)
				start[1] = stop[1] = maxs[1];
			else
				start[1] = stop[1] = mins[1];
//			start[0] = stop[0] = x ? maxs[0] : mins[0];
//			start[1] = stop[1] = y ? maxs[1] : mins[1];
			
			//same check as above, just from the 4 corners down 36
			save_hull = ent->v.hull;//temp hack so it HullForEntity doesn't calculate the wrong offset
			ent->v.hull = 0;
			trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
			ent->v.hull = save_hull;

/*			if((int)ent->v.flags&FL_MONSTER)
			{
				if(trace.allsolid)
					Con_DPrintf("Checkbottom (x=%d,y=%d) check was all solid!!!\n",x,y);
				else if(trace.startsolid)
					Con_DPrintf("Checkbottom (x=%d,y=%d) check started solid!!!\n",x,y);
			}*/
			//Hit a closer surface than did when checked center,
			//so set the "bottom" to the new, closer z height
			//we hit
			if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
				bottom = trace.endpos[2];
			
			//one of the corners does not have a surface within
			//36 below it, or the surface it did hit is more than
			//54 below this corner.  This is a really stupid check,
			//because if it hits a surface more than 54 below the
			//ent,the trace_fraction will be 1
			if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
				return false;
		}

//	c_yes++;
	return true;
}
示例#19
0
/*
============
SV_PushEntity

Does not change the entity's velocity at all
============
*/
trace_t SV_PushEntity (edict_t *ent, vec3_t push)
{
	trace_t	trace;
	vec3_t	end;
	int movetype;
		
	VectorAdd (ent->v.origin, push, end);

	if (ent->v.movetype == MOVETYPE_FLYMISSILE)
		movetype = MOVE_MISSILE;

#ifdef HEXEN2_SUPPORT
	else if (hexen2 && (ent->v.movetype == MOVETYPE_BOUNCEMISSILE))
		movetype = MOVE_MISSILE;
#endif
	else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
		movetype = MOVE_NOMONSTERS;		// only clip against bmodels

#ifdef HEXEN2_SUPPORT
	else if (hexen2 && (ent->v.movetype == MOVETYPE_SWIM))
		movetype = MOVE_WATER;
#endif
	else
		movetype = MOVE_NORMAL;
	
	trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, movetype, ent);	
	
#ifdef HEXEN2_SUPPORT
	if (hexen2)
	{
		if (ent->v.solid != SOLID_PHASE)
		{
			if ((ent->v.movetype == MOVETYPE_BOUNCE) && !(trace.allsolid == 0 && trace.startsolid == 0))
			{
				trace.fraction = 0;
				return trace;
			}
		}
		else	// Entity is PHASED so bounce off walls and other entities, go through monsters and players
		{
			if (trace.ent)
			{	// Go through MONSTERS and PLAYERS, can't use FL_CLIENT cause rotating brushes do
				if (((int) trace.ent->v.flags & FL_MONSTER) || (trace.ent->v.movetype == MOVETYPE_WALK))
				{
					vec3_t  impact;
					edict_t *impact_e;
					
					VectorCopy (trace.endpos, impact);
					impact_e = trace.ent;

					trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_PHASE, ent);

					VectorCopy (impact, ent->v.origin);
					SV_Impact (ent, impact_e);
				}
			}
		}
	}
#endif

	VectorCopy (trace.endpos, ent->v.origin);
	
#ifdef _DEBUG
	if (!VectorCompare(trace.endpos, end))
		movetype *= 1;
#endif
	
	SV_LinkEdict (ent, true);

	if (trace.ent)
		SV_Impact (ent, trace.ent);		

	return trace;
}					
示例#20
0
/*
============
SV_FlyMove

The basic solid body movement clip that slides along multiple planes
*steptrace - if not NULL, the trace results of any vertical wall hit will be stored
Returns the clipflags if the velocity was modified (hit something solid)
1 = floor
2 = wall / step
4 = dead stop
============
*/
int SV_FlyMove( edict_t *ent, float time, trace_t *steptrace )
{
	int	i, j, numplanes, bumpcount, blocked;
	vec3_t	dir, end, planes[MAX_CLIP_PLANES];
	vec3_t	primal_velocity, original_velocity, new_velocity;
	float	d, time_left, allFraction;
	trace_t	trace;

	blocked = 0;
	VectorCopy( ent->v.velocity, original_velocity );
	VectorCopy( ent->v.velocity, primal_velocity );
	numplanes = 0;

	allFraction = 0.0f;
	time_left = time;

	for( bumpcount = 0; bumpcount < MAX_CLIP_PLANES - 1; bumpcount++ )
	{
		if( VectorIsNull( ent->v.velocity ))
			break;

		VectorMA( ent->v.origin, time_left, ent->v.velocity, end );
		trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent );

		allFraction += trace.fraction;

		if( trace.allsolid )
		{	
			// entity is trapped in another solid
			VectorClear( ent->v.velocity );
			return 4;
		}

		if( trace.fraction > 0.0f )
		{	
			// actually covered some distance
			VectorCopy( trace.endpos, ent->v.origin );
			VectorCopy( ent->v.velocity, original_velocity );
			numplanes = 0;
		}

		if( trace.fraction == 1.0f )
			 break; // moved the entire distance

		if( !trace.ent )
			MsgDev( D_ERROR, "SV_FlyMove: trace.ent == NULL\n" );

		if( trace.plane.normal[2] > 0.7f )
		{
			blocked |= 1; // floor

         			if( trace.ent->v.solid == SOLID_BSP || trace.ent->v.solid == SOLID_SLIDEBOX ||
			trace.ent->v.movetype == MOVETYPE_PUSHSTEP || (trace.ent->v.flags & FL_CLIENT))
			{
				ent->v.flags |= FL_ONGROUND;
				ent->v.groundentity = trace.ent;
			}
		}

		if( trace.plane.normal[2] == 0.0f )
		{
			blocked |= 2; // step
			if( steptrace ) *steptrace = trace; // save for player extrafriction
		}

		// run the impact function
		SV_Impact( ent, trace.ent, &trace );

		// break if removed by the impact function
		if( ent->free ) break;

		time_left -= time_left * trace.fraction;

		// clipped to another plane
		if( numplanes >= MAX_CLIP_PLANES )
		{
			// this shouldn't really happen
			VectorClear( ent->v.velocity );
			break;
		}

		VectorCopy( trace.plane.normal, planes[numplanes] );
		numplanes++;

		// modify original_velocity so it parallels all of the clip planes
		for( i = 0; i < numplanes; i++ )
		{
			SV_ClipVelocity( original_velocity, planes[i], new_velocity, 1.0f );

			for( j = 0; j < numplanes; j++ )
			{
				if( j != i )
				{
					if( DotProduct( new_velocity, planes[j] ) < 0.0f )
						break; // not ok
				}
			}

			if( j == numplanes )
				break;
		}

		if( i != numplanes )
		{
			// go along this plane
			VectorCopy( new_velocity, ent->v.velocity );
		}
		else
		{
			// go along the crease
			if( numplanes != 2 )
			{
				VectorClear( ent->v.velocity );
				break;
			}

			CrossProduct( planes[0], planes[1], dir );
			d = DotProduct( dir, ent->v.velocity );
			VectorScale( dir, d, ent->v.velocity );
		}

		// if current velocity is against the original velocity,
		// stop dead to avoid tiny occilations in sloping corners
		if( DotProduct( ent->v.velocity, primal_velocity ) <= 0.0f )
		{
			VectorClear( ent->v.velocity );
			break;
		}
	}

	if( allFraction == 0.0f )
		VectorClear( ent->v.velocity );

	return blocked;
}
示例#21
0
/*
=============
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)
{
	vec3_t	mins, maxs, start, stop;
	trace_t	trace;
	int	x, y;
	float	mid, bottom;
	float	save_hull;

	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;
	for (x = 0; x < 2; x++)
	{
		for (y = 0; y < 2; y++)
		{
			start[0] = x ? maxs[0] : mins[0];
			start[1] = y ? maxs[1] : mins[1];

			if (SV_PointContents (start) != CONTENTS_SOLID)
				goto realcheck;
		}
	}

	return true;	// we got out easy

realcheck:	// check it for real...

	start[2] = mins[2];

	// the midpoint must be within 16 of the bottom
	start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5;
	start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5;
	stop[2] = start[2] - 2*STEPSIZE;

	save_hull = ent->v.hull;//temp hack so it HullForEntity doesn't calculate the wrong offset
	ent->v.hull = 0;
	trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
	ent->v.hull = save_hull;

	if (trace.fraction == 1.0)
		return false;

	mid = bottom = trace.endpos[2];

	// the corners must be within 16 of the midpoint
	for (x = 0; x < 2; x++)
	{
		for (y = 0; y < 2; y++)
		{
			start[0] = stop[0] = x ? maxs[0] : mins[0];
			start[1] = stop[1] = y ? maxs[1] : mins[1];

			save_hull = ent->v.hull;//temp hack so it HullForEntity doesn't calculate the wrong offset
			ent->v.hull = 0;
			trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
			ent->v.hull = save_hull;

			if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
				bottom = trace.endpos[2];
			if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
				return false;
		}
	}

	return true;
}
示例#22
0
/*
=============
SV_movestep

Called by monster program code.
The move will be adjusted for slopes and stairs, but if the move isn't
possible, no move is done, false is returned, and
pr_global_struct->trace_normal is set to the normal of the blocking wall
=============
*/
bool Server::move_step(edict_t *ent, vec3_t move, bool relink)
{
	float		dz;
	vec3_t		oldorg, neworg, end;
	trace_t		trace;
	int			i;
	edict_t		*enemy;

	// try the move	
	VectorCopy(ent->v.origin, oldorg);
	VectorAdd(ent->v.origin, move, neworg);

	// flying monsters don't step up
	if ((int)ent->v.flags & (FL_SWIM | FL_FLY))
	{
		// try one move with vertical motion, then one without
		for (i = 0; i<2; i++)
		{
			VectorAdd(ent->v.origin, move, neworg);
			enemy = m_progs->prog_to_edict(ent->v.enemy);
			if (i == 0 && enemy != m_progs->m_edicts[0])
			{
				dz = ent->v.origin[2] - m_progs->prog_to_edict(ent->v.enemy)->v.origin[2];
				if (dz > 40)
					neworg[2] -= 8;
				if (dz < 30)
					neworg[2] += 8;
			}
			trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);

			if (trace.fraction == 1)
			{
				if (((int)ent->v.flags & FL_SWIM) && point_contents(trace.endpos) == CONTENTS_EMPTY)
					return false;	// swim monster left water

				VectorCopy(trace.endpos, ent->v.origin);
				if (relink)
					link_edict(ent, true);
				return true;
			}

			if (enemy == m_progs->m_edicts[0])
				break;
		}

		return false;
	}

	// push down from a step height above the wished position
	neworg[2] += STEPSIZE;
	VectorCopy(neworg, end);
	end[2] -= STEPSIZE * 2;

	trace = SV_Move(neworg, ent->v.mins, ent->v.maxs, end, false, ent);

	if (trace.allsolid)
		return false;

	if (trace.startsolid)
	{
		neworg[2] -= STEPSIZE;
		trace = SV_Move(neworg, ent->v.mins, ent->v.maxs, end, false, ent);
		if (trace.allsolid || trace.startsolid)
			return false;
	}
	if (trace.fraction == 1)
	{
		// if monster had the ground pulled out, go ahead and fall
		if ((int)ent->v.flags & FL_PARTIALGROUND)
		{
			VectorAdd(ent->v.origin, move, ent->v.origin);
			if (relink)
				link_edict(ent, true);
			ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
			//	Con_Printf ("fall down\n"); 
			return true;
		}

		return false;		// walked off an edge
	}

	// check point traces down for dangling corners
	VectorCopy(trace.endpos, ent->v.origin);

	if (!check_bottom(ent))
	{
		if ((int)ent->v.flags & FL_PARTIALGROUND)
		{	// entity had floor mostly pulled out from underneath it
			// and is trying to correct
			if (relink)
				link_edict(ent, true);
			return true;
		}
		VectorCopy(oldorg, ent->v.origin);
		return false;
	}

	if ((int)ent->v.flags & FL_PARTIALGROUND)
	{
		//		Con_Printf ("back on ground\n"); 
		ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
	}
	ent->v.groundentity = m_progs->edict_to_prog(trace.ent);

	// the move is ok
	if (relink)
		link_edict(ent, true);
	return true;
}
示例#23
0
/* DESCRIPTION: SV_movestep/movetest
// LOCATION: sv_move.c
// PATH: PF_walkmove_I
//
// (from QW): Called by monster program code.
// The move will be adjusted for slopes and stairs, but if the move isn't
// possible, no move is done, false is returned, and
// pr_global_struct->trace_normal is set to the normal of the blocking wall
*/
qboolean SV_movestep(edict_t *ent, vec3_t move, qboolean relink) {

   int i, var_6C_hullnum;
   float dz;
   trace_t trace;
   vec3_t oldorg, neworg, end;
   edict_t * enemy;


   if(ent->v.flags & FL_MONSTERCLIP) { //Don't know what one has to do with the other.
      var_6C_hullnum = 1;
   }
   else {
      var_6C_hullnum = 0;
   }

   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];


   //well, try it.  Flying and swimming monsters are easiest.
   if(ent->v.flags & (FL_SWIM | FL_FLY)) {

      // try one move with vertical motion, then one without
      for(i = 0; i < 2; i++) {

         neworg[0] = ent->v.origin[0] + move[0];
         neworg[1] = ent->v.origin[1] + move[1];
         neworg[2] = ent->v.origin[2] + move[2];

         enemy = ent->v.enemy;
         if(i == 0 && enemy != NULL) {

            dz = ent->v.origin[2] - enemy->v.origin[2];

            if(dz > 40) { neworg[2] -= 8; }
            else if(dz < 30) { neworg[2] += 8; }
         }

         trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, neworg, 0, ent, var_6C_hullnum);

         if(trace.fraction == 1) { //yaay

            global_g_groupmask = ent->v.groupinfo;

            if((ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == Q1CONTENTS_EMPTY) {
               return(0); //That move takes us out of the water.  Apparently though, it's okay to travel into solids, lava, sky, etc :)
            }

            ent->v.origin[0] = trace.endpos[0];
            ent->v.origin[1] = trace.endpos[1];
            ent->v.origin[2] = trace.endpos[2];

            if(relink != 0) {
               SV_LinkEdict(ent, 1);
            }
            return(1);
         }
         else {

            if(enemy == NULL) { break; }
         }
      }

      return(0);
   }
   else {

      dz = cvar_sv_stepsize.value;
      neworg[2] += dz;
      end[0] = neworg[0];
      end[1] = neworg[1];
      end[2] = neworg[2];
      end[2] -= dz*2;

      trace = SV_Move(neworg, ent->v.mins, ent->v.maxs, end, 0, ent, var_6C_hullnum);
      if(trace.allsolid != 0) { return(0); }

      if(trace.startsolid != 0) {

         neworg[2] -= dz;

         trace = SV_Move(neworg, ent->v.mins, ent->v.maxs, end, 0, ent, var_6C_hullnum);

         if(trace.allsolid != 0 || trace.startsolid != 0) { return(0); }
      }

      if(trace.fraction == 1) {
         if(ent->v.flags & FL_PARTIALGROUND) { //Whoa, where'd the ground go?

            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); //Fell off like a green koopa.
      }
      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);
         }
      }
   }
}
示例#24
0
/*
=============
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;
	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 * svgame.movevars.stepsize;

	if( iMode == WALKMOVE_WORLDONLY )
		trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_WORLDONLY, 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_Move( start, vec3_origin, vec3_origin, stop, MOVE_WORLDONLY, 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;
}
示例#25
0
文件: bot.cpp 项目: DrLabman/QMB
/**
 * Called by bots program code.
 * The move will be adjusted for slopes and stairs, but if the move isn't
 * possible, no move is done, false is returned, and
 * pr_global_struct->trace_normal is set to the normal of the blocking wall
 */
bool bot_movestep(edict_t *ent, vec3_t move) {
	//	float		dz;
	vec3_t oldorg, neworg, end;
	trace_t trace;
	//	int			i;
	//	edict_t		*enemy;

	// try the move

	//get the bots org
	VectorCopy(ent->v.origin, oldorg);
	//work out new position
	VectorAdd(ent->v.origin, move, neworg);

	// push down from a step height above the wished position to a step below
	neworg[2] += sv_stepheight.getFloat();
	VectorCopy(neworg, end);
	end[2] -= sv_stepheight.getFloat()*2;

	//trace down to check if there was a floor
	trace = SV_Move(neworg, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);

	if (trace.allsolid) {
		//inside a wall?
		//Con_Printf("Trace all solid...\n");
		return false;
	}

	if (trace.startsolid) {
		//start inside a wall?
		neworg[2] -= sv_stepheight.getFloat();
		trace = SV_Move(neworg, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
		if (trace.allsolid || trace.startsolid) {
			//Con_Printf("Trace start solid...\n");
			return false;
		}
	}
	if (trace.fraction == 1) {
		// if monster had the ground pulled out, go ahead and fall
		if ((int) ent->v.flags & FL_PARTIALGROUND) {
			//			ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
			//	Con_Printf ("fall down\n");
			return true;
		}

		//Con_Printf("Walked off edge...\n");
		return false; // walked off an edge
	}

	// check point traces down for dangling corners
	//	VectorCopy (trace.endpos, ent->v.origin);

	/*	if (!SV_CheckBottom (ent))
		{
			if ( (int)ent->v.flags & FL_PARTIALGROUND )
			{	// entity had floor mostly pulled out from underneath it
				// and is trying to correct
				return true;
			}
			//VectorCopy (oldorg, ent->v.origin);
			Con_Printf("No floor?...\n");
			return false;
		}

		if ( (int)ent->v.flags & FL_PARTIALGROUND )
		{
	//		Con_Printf ("back on ground\n");
			//ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
		}
	//	ent->v.groundentity = EDICT_TO_PROG(trace.ent);
	 */
	// the move is ok
	return true;
}
示例#26
0
/*
=============
SV_movestep

Called by monster program code.
The move will be adjusted for slopes and stairs, but if the move isn't
possible, no move is done, FALSE is returned, and
pr_global_struct->trace_normal is set to the normal of the blocking wall
=============
*/
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
{
	float		dz;
	vec3_t		oldorg, neworg, end;
	trace_t		trace;
	int			i;
	edict_t		*enemy;

// try the move	
	VectorCopy (ent->v.origin, oldorg);
	VectorAdd (ent->v.origin, move, neworg);

// flying monsters don't step up
	if ( (int)ent->v.flags & (FL_SWIM | FL_FLY) )
	{
	// try one move with vertical motion, then one without
		for (i=0 ; i<2 ; i++)
		{
			VectorAdd (ent->v.origin, move, neworg);
			enemy = PROG_TO_EDICT(ent->v.enemy);
			if (i == 0 && enemy != sv.edicts)
			{
				dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2];
				if (dz > 40)
					neworg[2] -= 8;
				if (dz < 30)
					neworg[2] += 8;
			}
			trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, FALSE, ent);
	
			if (trace.fraction == 1)
			{
				if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == CONTENTS_EMPTY )
					return FALSE;	// swim monster left water
	
				VectorCopy (trace.endpos, ent->v.origin);
				if (relink)
					SV_LinkEdict (ent, TRUE);
				return TRUE;
			}
			
			if (enemy == sv.edicts)
				break;
		}
		
		return FALSE;
	}

// push down from a step height above the wished position
	neworg[2] += STEPSIZE;
	VectorCopy (neworg, end);
	end[2] -= STEPSIZE*2;

	trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, FALSE, ent);

	if (trace.allsolid)
		return FALSE;

	if (trace.startsolid)
	{
		neworg[2] -= STEPSIZE;
		trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, FALSE, ent);
		if (trace.allsolid || trace.startsolid)
			return FALSE;
	}
	if (trace.fraction == 1)
	{
	// if monster had the ground pulled out, go ahead and fall
		if ( (int)ent->v.flags & FL_PARTIALGROUND )
		{
			VectorAdd (ent->v.origin, move, ent->v.origin);
			if (relink)
				SV_LinkEdict (ent, TRUE);
			ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
//	Con_Printf ("fall down\n"); 
			return TRUE;
		}
	
		return FALSE;		// walked off an edge
	}

// check point traces down for dangling corners
	VectorCopy (trace.endpos, ent->v.origin);
	
	if (!SV_CheckBottom (ent))
	{
		if ( (int)ent->v.flags & FL_PARTIALGROUND )
		{	// entity had floor mostly pulled out from underneath it
			// and is trying to correct
			if (relink)
				SV_LinkEdict (ent, TRUE);
			return TRUE;
		}
		VectorCopy (oldorg, ent->v.origin);
		return FALSE;
	}

	if ( (int)ent->v.flags & FL_PARTIALGROUND )
	{
//		Con_Printf ("back on ground\n"); 
		ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
	}
	ent->v.groundentity = EDICT_TO_PROG(trace.ent);

// the move is ok
	if (relink)
		SV_LinkEdict (ent, TRUE);
	return TRUE;
}
示例#27
0
/*
=============
SV_movestep

Called by monster program code.
The move will be adjusted for slopes and stairs, but if the move isn't
possible, no move is done, false is returned, and
pr_global_struct->trace_normal is set to the normal of the blocking wall
=============
*/
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy,
					  qboolean set_trace)
{
	float		dz;
	vec3_t		oldorg, neworg, end;
	trace_t		trace;
	int			i;
	edict_t		*enemy;

// try the move	
	VectorCopy (ent->v.origin, oldorg);
	VectorAdd (ent->v.origin, move, neworg);

// flying monsters don't step up, unless no_z turned on
	if ( ((int)ent->v.flags&(FL_SWIM|FL_FLY)) && !((int)ent->v.flags&FL_NOZ) && !((int)ent->v.flags&FL_HUNTFACE))
	{
	// try one move with vertical motion, then one without
		for (i=0 ; i<2 ; i++)
		{
			VectorAdd (ent->v.origin, move, neworg);
			if (!noenemy)
			{
				enemy = PROG_TO_EDICT(ent->v.enemy);
				if (i == 0 && enemy != sv.edicts)
				{
					if((int)ent->v.flags&FL_HUNTFACE)//Go for face
						dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2] + PROG_TO_EDICT(ent->v.enemy)->v.view_ofs[2];
					else
						dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2];

					if (dz > 40)
						neworg[2] -= 8;
					else if (dz < 30)
						neworg[2] += 8;
				}
			}

			if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(neworg) == CONTENTS_EMPTY )
			{//Would end up out of water, don't do z move
				neworg[2]=ent->v.origin[2];
				trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);
				if (set_trace)
					set_move_trace(&trace);
				if(trace.fraction < 1||SV_PointContents(trace.endpos) == CONTENTS_EMPTY )
					return false;	// swim monster left water
			}
			else
			{
				trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);
				if (set_trace)
					set_move_trace(&trace);
			}
	
			if (trace.fraction == 1)
			{
				VectorCopy (trace.endpos, ent->v.origin);
				if (relink)
					SV_LinkEdict (ent, true);

				return true;
			}
			
			if (noenemy || enemy == sv.edicts)
				break;
		}
		
		return false;
	}

// push down from a step height above the wished position
	neworg[2] += STEPSIZE;
	VectorCopy (neworg, end);
	end[2] -= STEPSIZE*2;

	trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);

	if (set_trace)
		set_move_trace(&trace);

	if (trace.allsolid)
	{
		return false;
	}

	if (trace.startsolid)
	{
		neworg[2] -= STEPSIZE;
		trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
		if (set_trace)
			set_move_trace(&trace);
		if (trace.allsolid || trace.startsolid)
		{
			return false;
		}
	}
	if (trace.fraction == 1)
	{
	// if monster had the ground pulled out, go ahead and fall
		if ( (int)ent->v.flags & FL_PARTIALGROUND )
		{
			VectorAdd (ent->v.origin, move, ent->v.origin);
			if (relink)
				SV_LinkEdict (ent, true);
			ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
//	Con_Printf ("fall down\n"); 
			return true;
		}
	
		return false;		// walked off an edge
	}

// check point traces down for dangling corners
	VectorCopy (trace.endpos, ent->v.origin);
	
	if (!SV_CheckBottom (ent))
	{
		if ( (int)ent->v.flags & FL_PARTIALGROUND )
		{	// entity had floor mostly pulled out from underneath it
			// and is trying to correct
			if (relink)
				SV_LinkEdict (ent, true);
			return true;
		}
		VectorCopy (oldorg, ent->v.origin);

		return false;
	}

	if ( (int)ent->v.flags & FL_PARTIALGROUND )
	{
//		Con_Printf ("back on ground\n"); 
		ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
	}
	ent->v.groundentity = EDICT_TO_PROG(trace.ent);

// the move is ok
	if (relink)
		SV_LinkEdict (ent, true);
	return true;
}
示例#28
0
int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
{
	int			bumpcount, numbumps;
	vec3_t		dir;
	float		d;
	int			numplanes;
	vec3_t		planes[MAX_CLIP_PLANES];
	vec3_t		primal_velocity, original_velocity, new_velocity;
	int			i, j;
	trace_t		trace;
	vec3_t		end;
	float		time_left;
	int			blocked;
	
	numbumps = 4;
	
	blocked = 0;
	VectorCopy (ent->v.velocity, original_velocity);
	VectorCopy (ent->v.velocity, primal_velocity);
	numplanes = 0;
	
	time_left = time;

	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
	{
		if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
			break;

		for (i=0 ; i<3 ; i++)
			end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];

		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);

		if (trace.allsolid)
		{	// entity is trapped in another solid
			VectorCopy (vec3_origin, ent->v.velocity);
			return 3;
		}

		if (trace.fraction > 0)
		{	// actually covered some distance
			VectorCopy (trace.endpos, ent->v.origin);
			VectorCopy (ent->v.velocity, original_velocity);
			numplanes = 0;
		}

		if (trace.fraction == 1)
			 break;		// moved the entire distance

		if (!trace.ent)
			Sys_Error ("SV_FlyMove: !trace.ent");

		if (trace.plane.normal[2] > 0.7)
		{
			blocked |= 1;		// floor
			if (trace.ent->v.solid == SOLID_BSP)
			{
				ent->v.flags =	(int)ent->v.flags | FL_ONGROUND;
				ent->v.groundentity = ((int)EDICT_TO_PROG(trace.ent));
			}
		}
		if (!trace.plane.normal[2])
		{
			blocked |= 2;		// step
			if (steptrace)
				*steptrace = trace;	// save for player extrafriction
		}

//
// run the impact function
//
		SV_Impact (ent, trace.ent);
		if (ent->free)
			break;		// removed by the impact function

		
		time_left -= time_left * trace.fraction;
		
	// cliped to another plane
		if (numplanes >= MAX_CLIP_PLANES)
		{	// this shouldn't really happen
			VectorCopy (vec3_origin, ent->v.velocity);
			return 3;
		}

		VectorCopy (trace.plane.normal, planes[numplanes]);
		numplanes++;

//
// modify original_velocity so it parallels all of the clip planes
//
		for (i=0 ; i<numplanes ; i++)
		{
			ClipVelocity (original_velocity, planes[i], new_velocity, 1);
			for (j=0 ; j<numplanes ; j++)
				if (j != i)
				{
					if (DotProduct (new_velocity, planes[j]) < 0)
						break;	// not ok
				}
			if (j == numplanes)
				break;
		}
		
		if (i != numplanes)
		{	// go along this plane
			VectorCopy (new_velocity, ent->v.velocity);
		}
		else
		{	// go along the crease
			if (numplanes != 2)
			{
//				Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
				VectorCopy (vec3_origin, ent->v.velocity);
				return 7;
			}
			CrossProduct (planes[0], planes[1], dir);
			d = DotProduct (dir, ent->v.velocity);
			VectorScale (dir, d, ent->v.velocity);
		}

//
// if original velocity is against the original velocity, stop dead
// to avoid tiny occilations in sloping corners
//
		if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
		{
			VectorCopy (vec3_origin, ent->v.velocity);
			return blocked;
		}
	}

	return blocked;
}
示例#29
0
/*
=============
SV_Physics_Step

Monsters freefall when they don't have a ground entity, otherwise
all movement is done with discrete steps.

This is also used for objects that have become still on the ground, but
will fall if the floor is pulled out from under them.
=============
*/
void SV_Physics_Step( edict_t *ent )
{
	qboolean	inwater;
	qboolean	wasonground;
	qboolean	wasonmover;
	vec3_t	mins, maxs;
	vec3_t	point;
	trace_t	trace;
	int	x, y;

	SV_WaterMove( ent );
	SV_CheckVelocity( ent );

	wasonground = (ent->v.flags & FL_ONGROUND);
	wasonmover = SV_CheckMover( ent );
	inwater = SV_CheckWater( ent );

	if( ent->v.flags & FL_FLOAT && ent->v.waterlevel > 0 )
	{
		float buoyancy = SV_Submerged( ent ) * ent->v.skin * host.frametime;

		SV_AddGravity( ent );
		ent->v.velocity[2] += buoyancy;
	}

	if( !wasonground && !( ent->v.flags & FL_FLY ) && (!( ent->v.flags & FL_SWIM ) || ent->v.waterlevel <= 0 ))
	{
		if( !inwater )
			SV_AddGravity( ent );
	}

	if( !VectorIsNull( ent->v.velocity ) || !VectorIsNull( ent->v.basevelocity ))
	{
		ent->v.flags &= ~FL_ONGROUND;

		if(( wasonground || wasonmover ) && ( ent->v.health > 0 || SV_CheckBottom( ent, MOVE_NORMAL )))
		{
			float	*vel = ent->v.velocity;
			float	control, speed, newspeed;
			float	friction;

			speed = sqrt(( vel[0] * vel[0] ) + ( vel[1] * vel[1] ));	// DotProduct2D

			if( speed )
			{
				friction = sv_friction->value * ent->v.friction;	// factor
				ent->v.friction = 1.0f; // g-cont. ???
				if( wasonmover ) friction *= 0.5f; // add a little friction

				control = (speed < sv_stopspeed->value) ? sv_stopspeed->value : speed;
				newspeed = speed - (host.frametime * control * friction);
				if( newspeed < 0 ) newspeed = 0;
				newspeed /= speed;

				vel[0] = vel[0] * newspeed;
				vel[1] = vel[1] * newspeed;
			}
		}

		VectorAdd( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
		SV_CheckVelocity( ent );

		SV_FlyMove( ent, host.frametime, NULL );
		if( ent->free ) return;

		SV_CheckVelocity( ent );
		VectorSubtract( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );

		SV_CheckVelocity( ent );

		VectorAdd( ent->v.origin, ent->v.mins, mins );
		VectorAdd( ent->v.origin, ent->v.maxs, maxs );

		point[2] = mins[2] - 1.0f;

		for( x = 0; x <= 1; x++ )
		{
			if( ent->v.flags & FL_ONGROUND )
				break;

			for( y = 0; y <= 1; y++ )
			{
				point[0] = x ? maxs[0] : mins[0];
				point[1] = y ? maxs[1] : mins[1];

				trace = SV_Move( point, vec3_origin, vec3_origin, point, MOVE_NORMAL, ent );

				if( trace.startsolid )
				{
					ent->v.flags |= FL_ONGROUND;
					ent->v.groundentity = trace.ent;
					ent->v.friction = 1.0f;
					break;
				}
			}
		}

		SV_LinkEdict( ent, true );
	}
	else
	{
		if( svgame.globals->force_retouch != 0 )
		{
			trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent );

			// hentacle impact code
			if(( trace.fraction < 1.0f || trace.startsolid ) && SV_IsValidEdict( trace.ent ))
			{
				SV_Impact( ent, trace.ent, &trace );
				if( ent->free ) return;
			}
		}
	}

	if( !SV_RunThink( ent )) return;
	SV_CheckWaterTransition( ent );

}