Exemple #1
0
/*
============
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;
}
Exemple #2
0
/*
* G_ProjectileDistancePrestep
*/
static void G_ProjectileDistancePrestep( edict_t *projectile, float distance )
{
	float speed;
	vec3_t dir, dest;
	int mask, i;
	trace_t	trace;
#ifdef PLASMAHACK
	vec3_t plasma_hack_start;
#endif

	if( projectile->movetype != MOVETYPE_TOSS 
		&& projectile->movetype != MOVETYPE_LINEARPROJECTILE
		&& projectile->movetype != MOVETYPE_BOUNCE 
		&& projectile->movetype != MOVETYPE_BOUNCEGRENADE )
		return;

	if( !distance )
		return;

	if( ( speed = VectorNormalize2( projectile->velocity, dir ) ) == 0.0f )
		return;

	mask = ( projectile->r.clipmask ) ? projectile->r.clipmask : MASK_SHOT; // race trick should come set up inside clipmask

	if( projectile->movetype == MOVETYPE_LINEARPROJECTILE )
		VectorCopy( projectile->s.origin2, projectile->s.origin );

#ifdef PLASMAHACK
	VectorCopy( projectile->s.origin, plasma_hack_start );
#endif

	VectorMA( projectile->s.origin, distance, dir, dest );
	G_Trace4D( &trace, projectile->s.origin, projectile->r.mins, projectile->r.maxs, dest, projectile->r.owner, mask, projectile->timeDelta );

	for( i = 0; i < 3; i++ )
		projectile->s.origin[i] = projectile->s.origin2[i] = projectile->olds.origin[i] = projectile->olds.origin2[i] = trace.endpos[i];

	GClip_LinkEntity( projectile );
	SV_Impact( projectile, &trace );

	// set initial water state
	if( !projectile->r.inuse )
		return;

	projectile->waterlevel = ( G_PointContents4D( projectile->s.origin, projectile->timeDelta ) & MASK_WATER ) ? qtrue : qfalse;

	// ffs : hack for the plasmagun
#ifdef PLASMAHACK
	if( projectile->s.type == ET_PLASMA )
		if (trap_Cvar_Get( "rs_plasma_hack", "1", CVAR_ARCHIVE )->integer==1)//racesow
			W_Plasma_Backtrace( projectile, plasma_hack_start );
#endif
}
Exemple #3
0
/*
 * Does not change the entities velocity at all
 */
trace_t
SV_PushEntity(edict_t *ent, vec3_t push)
{
	trace_t trace;
	vec3_t start;
	vec3_t end;
	int mask;

	VectorCopy(ent->s.origin, start);
	VectorAdd(start, push, end);

retry:

	if (ent->clipmask)
	{
		mask = ent->clipmask;
	}
	else
	{
		mask = MASK_SOLID;
	}

	trace = gi.trace(start, ent->mins, ent->maxs, end, ent, mask);

	VectorCopy(trace.endpos, ent->s.origin);
	gi.linkentity(ent);

	if (trace.fraction != 1.0)
	{
		SV_Impact(ent, &trace);

		/* if the pushed entity went away and the pusher is still there */
		if (!trace.ent->inuse && ent->inuse)
		{
			/* move the pusher back and try again */
			VectorCopy(start, ent->s.origin);
			gi.linkentity(ent);
			goto retry;
		}
	}

	if (ent->inuse)
	{
		G_TouchTriggers(ent);
	}

	return trace;
}
/*
============
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	start;
	vec3_t	end;
	int		mask;

	VectorCopy (ent->s.origin, start);
	VectorAdd (start, push, end);

retry:
	if (ent->clipmask)
		mask = ent->clipmask;
	else
		mask = MASK_SOLID;

	trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask);
	
	VectorCopy (trace.endpos, ent->s.origin);
	gi.linkentity (ent);

	if (trace.fraction != 1.0)
	{
		SV_Impact (ent, &trace);

		// if the pushed entity went away and the pusher is still there
		if (!trace.ent->inuse && ent->inuse)
		{
			// move the pusher back and try again
			VectorCopy (start, ent->s.origin);
			gi.linkentity (ent);
			goto retry;
		}
	}

// ================
// PGM
	// FIXME - is this needed?
	ent->gravity = 1.0;
// PGM
// ================

	if (ent->inuse)
		G_TouchTriggers (ent);

	return trace;
}					
Exemple #5
0
/*
* SV_PushEntity
*
* Does not change the entities velocity at all
*/
static trace_t SV_PushEntity( edict_t *ent, vec3_t push ) {
	trace_t trace;
	vec3_t start;
	vec3_t end;
	int mask;

	VectorCopy( ent->s.origin, start );
	VectorAdd( start, push, end );

retry:
	if( ent->r.clipmask ) {
		mask = ent->r.clipmask;
	} else {
		mask = MASK_SOLID;
	}

	G_Trace4D( &trace, start, ent->r.mins, ent->r.maxs, end, ent, mask, ent->timeDelta );
	if( ent->movetype == MOVETYPE_PUSH || !trace.startsolid ) {
		VectorCopy( trace.endpos, ent->s.origin );
	}

	GClip_LinkEntity( ent );

	if( trace.fraction < 1.0 ) {
		SV_Impact( ent, &trace );

		// if the pushed entity went away and the pusher is still there
		if( !game.edicts[trace.ent].r.inuse && ent->movetype == MOVETYPE_PUSH && ent->r.inuse ) {
			// move the pusher back and try again
			VectorCopy( start, ent->s.origin );
			GClip_LinkEntity( ent );
			goto retry;
		}
	}

	if( ent->r.inuse ) {
		GClip_TouchTriggers( ent );
	}

	return trace;
}
Exemple #6
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;
}
Exemple #7
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;
}
int SV_FlyMove (edict_t *ent, float time, int mask)
{
	edict_t		*hit;
	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->velocity, original_velocity);
	VectorCopy (ent->velocity, primal_velocity);
	numplanes = 0;
	
	time_left = time;

	ent->groundentity = NULL;
	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
	{
		for (i=0 ; i<3 ; i++)
			end[i] = ent->s.origin[i] + time_left * ent->velocity[i];

		trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask);

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

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

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

		hit = trace.ent;

		if (trace.plane.normal[2] > 0.7)
		{
			blocked |= 1;		// floor
			if ( hit->solid == SOLID_BSP)
			{
				ent->groundentity = hit;
				ent->groundentity_linkcount = hit->linkcount;
			}
		}
		if (!trace.plane.normal[2])
		{
			blocked |= 2;		// step
		}

//
// run the impact function
//
		SV_Impact (ent, &trace);
		if (!ent->inuse)
			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->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) && !VectorCompare (planes[i], planes[j]))
				{
					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->velocity);
		}
		else
		{	// go along the crease
			if (numplanes != 2)
			{
//				gi.dprintf ("clip velocity, numplanes == %i\n",numplanes);
				VectorCopy (vec3_origin, ent->velocity);
				return 7;
			}
			CrossProduct (planes[0], planes[1], dir);
			d = DotProduct (dir, ent->velocity);
			VectorScale (dir, d, ent->velocity);
		}

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

	return blocked;
}
Exemple #9
0
int SV_FlyMove (edict_t *ent, float time, int mask)
{
	edict_t		*hit;
	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->velocity, original_velocity);
	VectorCopy (ent->velocity, primal_velocity);
	numplanes = 0;
	
	time_left = time;

	ent->groundentity = NULL;
	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
	{
		for (i=0 ; i<3 ; i++)
			end[i] = ent->s.origin[i] + time_left * ent->velocity[i];

		trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask);

		if (trace.allsolid)
		{	// entity is trapped in another solid
//			if (bumpcount == 0)
//				gi.dprintf( "WARNING: %s is stuck inside %s at (%s)\n", ent->classname, trace.ent->classname, vtos(ent->s.origin) );
			VectorCopy (vec3_origin, ent->velocity);
			return 3;
		}

		if ((trace.fraction > 0) && !(trace.ent->svflags & SVF_MONSTER) && !trace.ent->client)
		{	// covered some distance
			VectorCopy (trace.endpos, ent->s.origin);
			VectorCopy (ent->velocity, original_velocity);
			numplanes = 0;
		}
		else if ((trace.ent->svflags & SVF_MONSTER) || trace.ent->client)	// stay well clear of other characters
		{
			// Ridah, don't climb beneath another character
			if (ent->flags & FL_FLY)
			{	// abort climbing
				AngleVectors( ent->s.angles, ent->velocity, NULL, NULL );
				VectorScale( ent->velocity, -32, ent->velocity );

				ent->velocity[2] = 0;

				ent->flags &= ~FL_FLY;

				if (ent->cast_info.move_end_climb)
					ent->cast_info.currentmove = ent->cast_info.move_end_climb;
			}
			else if (ent->s.origin[2] > (trace.ent->s.origin[2] + trace.ent->maxs[2]))
			{	// they're below us, jump randomly to get off
				VectorSet (ent->velocity, random()*128, random()*128, 220);

				return 20;
			}
			else
			{
				VectorCopy (vec3_origin, ent->velocity);
			}

			return 3;
		}

		if (trace.fraction == 1)
		{
			blocked = -1;
			break;		// moved the entire distance
		}

		hit = trace.ent;

		if (trace.plane.normal[2] > 0.7)
		{
			blocked |= 1;		// floor
			if ( hit->solid == SOLID_BSP)
			{
				ent->groundentity = hit;
				ent->groundentity_linkcount = hit->linkcount;
			}
		}
		if (!trace.plane.normal[2])
		{
			blocked |= 2;		// step
		}

//
// run the impact function
//
		SV_Impact (ent, &trace);
		if (!ent->inuse)
			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->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) && !VectorCompare (planes[i], planes[j]))
				{
					if (DotProduct (new_velocity, planes[j]) < 0)
						break;	// not ok
				}
			if (j == numplanes)
				break;
		}
		
		if (i != numplanes)
		{	// go along this plane
//gi.dprintf( "Adjusting velocity for %s\n", ent->classname );
			VectorCopy (new_velocity, ent->velocity);

// Xatrix/Ridah, help Cast members's jump up to ledges
			if ( ent->velocity[2] > 60 && !(ent->flags & FL_FLY) )
				ent->velocity[2] += (sv_gravity->value*FRAMETIME*0.5);
// Xatrix/Ridah, help grunt's jump up to ledges
		}
		else
		{	// go along the crease
			if (numplanes != 2)
			{
//				gi.dprintf ("clip velocity, numplanes == %i\n",numplanes);
				VectorCopy (vec3_origin, ent->velocity);
				return 7;
			}
			CrossProduct (planes[0], planes[1], dir);
			d = DotProduct (dir, ent->velocity);
			VectorScale (dir, d, ent->velocity);
		}

//
// if original velocity is against the original velocity, stop dead
// to avoid tiny occilations in sloping corners
//
		if (DotProduct (ent->velocity, primal_velocity) <= 0)
		{
//gi.dprintf( "Clearing velocity for occilations for %s\n", ent->classname );
			VectorCopy (vec3_origin, ent->velocity);
			return blocked;
		}
	}

// Ridah, trying to fix jumping onto ledges problem in SR1 (for example)
//	ent->velocity[0] = primal_velocity[0];
//	ent->velocity[1] = primal_velocity[1];

	return blocked;
}
Exemple #10
0
/*
* SV_Physics_Toss
*
* Toss, bounce, and fly movement.  When onground, do nothing.
*
* FIXME: This function needs a serious rewrite
*/
static void SV_Physics_Toss( edict_t *ent ) {
	trace_t trace;
	vec3_t move;
	float backoff;
	edict_t *slave;
	bool wasinwater;
	bool isinwater;
	vec3_t old_origin;
	float oldSpeed;

	// if not a team captain, so movement will be handled elsewhere
	if( ent->flags & FL_TEAMSLAVE ) {
		return;
	}

	// refresh the ground entity
	if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
		if( ent->velocity[2] > 0.1f ) {
			ent->groundentity = NULL;
		}
	}

	if( ent->groundentity && ent->groundentity != world && !ent->groundentity->r.inuse ) {
		ent->groundentity = NULL;
	}

	oldSpeed = VectorLength( ent->velocity );

	if( ent->groundentity ) {
		if( !oldSpeed ) {
			return;
		}

		if( ent->movetype == MOVETYPE_TOSS ) {
			if( ent->velocity[2] >= 8 ) {
				ent->groundentity = NULL;
			} else {
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
				return;
			}
		}
	}

	VectorCopy( ent->s.origin, old_origin );

	if( ent->accel != 0 ) {
		if( ent->accel < 0 && VectorLength( ent->velocity ) < 50 ) {
			VectorClear( ent->velocity );
		} else {
			vec3_t acceldir;
			VectorNormalize2( ent->velocity, acceldir );
			VectorScale( acceldir, ent->accel * FRAMETIME, acceldir );
			VectorAdd( ent->velocity, acceldir, ent->velocity );
		}
	}

	SV_CheckVelocity( ent );

	// add gravity
	if( ent->movetype != MOVETYPE_FLY && !ent->groundentity ) {
		SV_AddGravity( ent );
	}

	// move angles
	VectorMA( ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles );

	// move origin
	VectorScale( ent->velocity, FRAMETIME, move );

	trace = SV_PushEntity( ent, move );
	if( !ent->r.inuse ) {
		return;
	}

	if( trace.fraction < 1.0f ) {
		if( ent->movetype == MOVETYPE_BOUNCE ) {
			backoff = 1.5;
		} else if( ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
			backoff = 1.5;
		} else {
			backoff = 1;
		}

		GS_ClipVelocity( ent->velocity, trace.plane.normal, ent->velocity, backoff );

		// stop if on ground

		if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
			// stop dead on allsolid

			// LA: hopefully will fix grenades bouncing down slopes
			// method taken from Darkplaces sourcecode
			if( trace.allsolid ||
				( ISWALKABLEPLANE( &trace.plane ) &&
				  fabs( DotProduct( trace.plane.normal, ent->velocity ) ) < 40
				)
				) {
				ent->groundentity = &game.edicts[trace.ent];
				ent->groundentity_linkcount = ent->groundentity->linkcount;
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
			}
		} else {
			// in movetype_toss things stop dead when touching ground
#if 0
			G_CheckGround( ent );

			if( ent->groundentity ) {
#else

			// walkable or trapped inside solid brush
			if( trace.allsolid || ISWALKABLEPLANE( &trace.plane ) ) {
				ent->groundentity = trace.ent < 0 ? world : &game.edicts[trace.ent];
				ent->groundentity_linkcount = ent->groundentity->linkcount;
#endif
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
			}
		}
	}

	// check for water transition
	wasinwater = ( ent->watertype & MASK_WATER ) ? true : false;
	ent->watertype = G_PointContents( ent->s.origin );
	isinwater = ent->watertype & MASK_WATER ? true : false;

	// never allow items in CONTENTS_NODROP
	if( ent->item && ( ent->watertype & CONTENTS_NODROP ) ) {
		G_FreeEdict( ent );
		return;
	}

	if( isinwater ) {
		ent->waterlevel = 1;
	} else {
		ent->waterlevel = 0;
	}

	if( !wasinwater && isinwater ) {
		G_PositionedSound( old_origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	} else if( wasinwater && !isinwater ) {
		G_PositionedSound( ent->s.origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	}

	// move teamslaves
	for( slave = ent->teamchain; slave; slave = slave->teamchain ) {
		VectorCopy( ent->s.origin, slave->s.origin );
		GClip_LinkEntity( slave );
	}
}

//============================================================================

void SV_Physics_LinearProjectile( edict_t *ent ) {
	vec3_t start, end;
	int mask;
	float startFlyTime, endFlyTime;
	trace_t trace;
	int old_waterLevel;

	// if not a team captain movement will be handled elsewhere
	if( ent->flags & FL_TEAMSLAVE ) {
		return;
	}

	old_waterLevel = ent->waterlevel;

	mask = ( ent->r.clipmask ) ? ent->r.clipmask : MASK_SOLID;

	// find it's current position given the starting timeStamp
	startFlyTime = (float)( max( game.prevServerTime - ent->s.linearMovementTimeStamp, 0 ) ) * 0.001f;
	endFlyTime = (float)( game.serverTime - ent->s.linearMovementTimeStamp ) * 0.001f;

	VectorMA( ent->s.linearMovementBegin, startFlyTime, ent->s.linearMovementVelocity, start );
	VectorMA( ent->s.linearMovementBegin, endFlyTime, ent->s.linearMovementVelocity, end );

	G_Trace4D( &trace, start, ent->r.mins, ent->r.maxs, end, ent, mask, ent->timeDelta );
	VectorCopy( trace.endpos, ent->s.origin );
	GClip_LinkEntity( ent );
	SV_Impact( ent, &trace );

	if( !ent->r.inuse ) { // the projectile may be freed if touched something
		return;
	}

	// update some data required for the transmission
	//VectorCopy( ent->velocity, ent->s.linearMovementVelocity );

	GClip_TouchTriggers( ent );
	ent->groundentity = NULL; // projectiles never have ground entity
	ent->waterlevel = ( G_PointContents4D( ent->s.origin, ent->timeDelta ) & MASK_WATER ) ? true : false;

	if( !old_waterLevel && ent->waterlevel ) {
		G_PositionedSound( start, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	} else if( old_waterLevel && !ent->waterlevel ) {
		G_PositionedSound( ent->s.origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	}
}
Exemple #11
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;
}
Exemple #12
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 );

}
Exemple #13
0
/*
===========
SV_RunCmd
===========
*/
void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
{
    usercmd_t lastcmd;
    edict_t	*clent, *touch;
    double	frametime;
    int	i, oldmsec;
    pmtrace_t	*pmtrace;
    trace_t	trace;
    vec3_t	oldvel;

    clent = cl->edict;

    if( cl->next_movetime > host.realtime )
    {
        cl->last_movetime += ( ucmd->msec * 0.001f );
        return;
    }

    cl->next_movetime = 0.0;

    // chop up very long commands
    if( ucmd->msec > 50 )
    {
        lastcmd = *ucmd;
        oldmsec = ucmd->msec;
        lastcmd.msec = oldmsec / 2;

        SV_RunCmd( cl, &lastcmd, random_seed );

        lastcmd.msec = oldmsec / 2 + (oldmsec & 1);	// give them back thier msec.
        lastcmd.impulse = 0;
        SV_RunCmd( cl, &lastcmd, random_seed );
        return;
    }

    if( !cl->fakeclient )
    {
        SV_SetupMoveInterpolant( cl );
    }

    lastcmd = *ucmd;
    svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, random_seed );

    frametime = ucmd->msec * 0.001;
    cl->timebase += frametime;
    cl->last_movetime += frametime;

    PM_CheckMovingGround( clent, frametime );

    VectorCopy( clent->v.v_angle, svgame.pmove->oldangles ); // save oldangles
    if( !clent->v.fixangle ) VectorCopy( ucmd->viewangles, clent->v.v_angle );

    VectorClear( clent->v.clbasevelocity );

    // copy player buttons
    clent->v.button = ucmd->buttons;
    if( ucmd->impulse ) clent->v.impulse = ucmd->impulse;

    if( ucmd->impulse == 204 )
    {
        // force client.dll update
        SV_RefreshUserinfo();
    }

    svgame.globals->time = cl->timebase;
    svgame.dllFuncs.pfnPlayerPreThink( clent );
    SV_PlayerRunThink( clent, frametime, cl->timebase );

    // If conveyor, or think, set basevelocity, then send to client asap too.
    if( !VectorIsNull( clent->v.basevelocity ))
        VectorCopy( clent->v.basevelocity, clent->v.clbasevelocity );

    // setup playermove state
    SV_SetupPMove( svgame.pmove, cl, ucmd, cl->physinfo );

    // motor!
    svgame.dllFuncs.pfnPM_Move( svgame.pmove, true );

    // copy results back to client
    SV_FinishPMove( svgame.pmove, cl );

    // link into place and touch triggers
    SV_LinkEdict( clent, true );
    VectorCopy( clent->v.velocity, oldvel ); // save velocity

    // touch other objects
    for( i = 0; i < svgame.pmove->numtouch; i++ )
    {
        // never touch the objects when "playersonly" is active
        if( i == MAX_PHYSENTS || ( sv.hostflags & SVF_PLAYERSONLY ))
            break;

        pmtrace = &svgame.pmove->touchindex[i];
        touch = EDICT_NUM( svgame.pmove->physents[pmtrace->ent].info );
        if( touch == clent ) continue;

        VectorCopy( pmtrace->deltavelocity, clent->v.velocity );
        SV_ConvertPMTrace( &trace, pmtrace, touch );
        SV_Impact( touch, clent, &trace );
    }

    // restore velocity
    VectorCopy( oldvel, clent->v.velocity );

    svgame.pmove->numtouch = 0;
    svgame.globals->time = cl->timebase;
    svgame.globals->frametime = frametime;

    // run post-think
    svgame.dllFuncs.pfnPlayerPostThink( clent );
    svgame.dllFuncs.pfnCmdEnd( clent );

    if( !cl->fakeclient )
    {
        SV_RestoreMoveInterpolant( cl );
    }
}
Exemple #14
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;
}