Beispiel #1
0
void G_RollMissile( gentity_t *ent )
{
	int			bumpcount, numbumps;
	vec3_t		dir;
	float		d;
	int			numplanes;
	vec3_t		planes[MAX_CLIP_PLANES];
	vec3_t		primal_velocity;
	vec3_t		clipVelocity;
	int			i, j, k;
	trace_t	trace;
	vec3_t		end;
	float		time_left;
	float		into;
	vec3_t		endVelocity;
	vec3_t		endClipVelocity;
	pml_t		objPML;
	float		bounceAmt = BUMPCLIP;
	gentity_t	*hitEnt = NULL;

	memset( &objPML, 0, sizeof( objPML ) );
	
	G_GroundTrace( ent, &objPML );

	objPML.frametime = (level.time - level.previousTime)*0.001;
	
	numbumps = 4;

	VectorCopy ( ent->s.pos.trDelta, primal_velocity );

	VectorCopy( ent->s.pos.trDelta, endVelocity );
	endVelocity[2] -= g_gravity->value * objPML.frametime;
	ent->s.pos.trDelta[2] = ( ent->s.pos.trDelta[2] + endVelocity[2] ) * 0.5;
	primal_velocity[2] = endVelocity[2];
	if ( objPML.groundPlane ) 
	{//FIXME: never happens!
		// slide along the ground plane
		G_ClipVelocity( ent->s.pos.trDelta, objPML.groundTrace.plane.normal, ent->s.pos.trDelta, BUMPCLIP ); 
		VectorScale( ent->s.pos.trDelta, 0.9f, ent->s.pos.trDelta );
	}

	time_left = objPML.frametime;

	// never turn against the ground plane
	if ( objPML.groundPlane ) 
	{
		numplanes = 1;
		VectorCopy( objPML.groundTrace.plane.normal, planes[0] );
	} 
	else 
	{
		numplanes = 0;
	}

	// never turn against original velocity
	/*
	VectorNormalize2( ent->s.pos.trDelta, planes[numplanes] );
	numplanes++;
	*/

	for ( bumpcount = 0; bumpcount < numbumps; bumpcount++ ) 
	{
		// calculate position we are trying to move to
		VectorMA( ent->currentOrigin, time_left, ent->s.pos.trDelta, end );

		// see if we can make it there
		gi.trace ( &trace, ent->currentOrigin, ent->mins, ent->maxs, end, ent->s.number, ent->clipmask, G2_RETURNONHIT, 10 );

		//TEMP HACK:
		//had to move this up above the trace.allsolid check now that for some reason ghoul2 impacts tell me I'm allsolid?!
		//this needs to be fixed, really
		if ( trace.entityNum < ENTITYNUM_WORLD )
		{//hit another ent
			hitEnt = &g_entities[trace.entityNum];
			if ( hitEnt && (hitEnt->takedamage || (hitEnt->contents&CONTENTS_LIGHTSABER) ) )
			{
				G_MissileImpact( ent, &trace );
				if ( ent->s.eType == ET_GENERAL )
				{//exploded
					return;
				}
			}
		}

		if ( trace.allsolid )
		{
			// entity is completely trapped in another solid
			//FIXME: this happens a lot now when we hit a G2 ent... WTF?
			ent->s.pos.trDelta[2] = 0;	// don't build up falling damage, but allow sideways acceleration
			return;// qtrue;
		}

		if ( trace.fraction > 0 ) 
		{
			// actually covered some distance
			VectorCopy( trace.endpos, ent->currentOrigin );
		}

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

		//pm->ps->pm_flags |= PMF_BUMPED;

		// save entity for contact
		//PM_AddTouchEnt( trace.entityNum );

		//Hit it
		/*
		if ( PM_ClientImpact( trace.entityNum, qtrue ) )
		{
			continue;
		}
		*/

		time_left -= time_left * trace.fraction;

		if ( numplanes >= MAX_CLIP_PLANES ) 
		{
			// this shouldn't really happen
			VectorClear( ent->s.pos.trDelta );
			return;// qtrue;
		}

		//
		// if this is the same plane we hit before, nudge velocity
		// out along it, which fixes some epsilon issues with
		// non-axial planes
		//
		for ( i = 0 ; i < numplanes ; i++ ) 
		{
			if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 ) 
			{
				VectorAdd( trace.plane.normal, ent->s.pos.trDelta, ent->s.pos.trDelta );
				break;
			}
		}
		if ( i < numplanes ) 
		{
			continue;
		}
		VectorCopy( trace.plane.normal, planes[numplanes] );
		numplanes++;

		//
		// modify velocity so it parallels all of the clip planes
		//
		if ( &g_entities[trace.entityNum] != NULL && g_entities[trace.entityNum].client ) 
		{//hit a person, bounce off much less
			bounceAmt = OVERCLIP;
		}
		else
		{
			bounceAmt = BUMPCLIP;
		}

		// find a plane that it enters
		for ( i = 0 ; i < numplanes ; i++ ) 
		{
			into = DotProduct( ent->s.pos.trDelta, planes[i] );
			if ( into >= 0.1 ) 
			{
				continue;		// move doesn't interact with the plane
			}

			// see how hard we are hitting things
			if ( -into > pml.impactSpeed ) 
			{
				pml.impactSpeed = -into;
			}

			// slide along the plane
			G_ClipVelocity( ent->s.pos.trDelta, planes[i], clipVelocity, bounceAmt );

			// slide along the plane
			G_ClipVelocity( endVelocity, planes[i], endClipVelocity, bounceAmt );

			// see if there is a second plane that the new move enters
			for ( j = 0 ; j < numplanes ; j++ ) 
			{
				if ( j == i ) 
				{
					continue;
				}
				if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) 
				{
					continue;		// move doesn't interact with the plane
				}

				// try clipping the move to the plane
				G_ClipVelocity( clipVelocity, planes[j], clipVelocity, bounceAmt );
				G_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, bounceAmt );

				// see if it goes back into the first clip plane
				if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) 
				{
					continue;
				}

				// slide the original velocity along the crease
				CrossProduct (planes[i], planes[j], dir);
				VectorNormalize( dir );
				d = DotProduct( dir, ent->s.pos.trDelta );
				VectorScale( dir, d, clipVelocity );

				CrossProduct (planes[i], planes[j], dir);
				VectorNormalize( dir );
				d = DotProduct( dir, endVelocity );
				VectorScale( dir, d, endClipVelocity );

				// see if there is a third plane the the new move enters
				for ( k = 0 ; k < numplanes ; k++ ) 
				{
					if ( k == i || k == j ) 
					{
						continue;
					}
					if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 ) 
					{
						continue;		// move doesn't interact with the plane
					}

					// stop dead at a triple plane interaction
					VectorClear( ent->s.pos.trDelta );
					return;// qtrue;
				}
			}

			// if we have fixed all interactions, try another move
			VectorCopy( clipVelocity, ent->s.pos.trDelta );
			VectorCopy( endClipVelocity, endVelocity );
			break;
		}
		VectorScale( endVelocity, 0.975f, endVelocity );
	}

	VectorCopy( endVelocity, ent->s.pos.trDelta );

	// don't change velocity if in a timer (FIXME: is this correct?)
	/*
	if ( pm->ps->pm_time ) 
	{
		VectorCopy( primal_velocity, ent->s.pos.trDelta );
	}
	*/

	return;// ( bumpcount != 0 );
}
Beispiel #2
0
/*
 * @brief Toss, bounce, and fly movement. When on ground, do nothing.
 */
static void G_Physics_Toss(g_edict_t *ent) {
	vec3_t org, move;

	// regular thinking
	G_RunThink(ent);

	// if not a team captain, movement will be handled elsewhere
	if (ent->locals.flags & FL_TEAM_SLAVE)
		return;

	// check for the ground entity going away
	if (ent->locals.ground_entity) {
		if (!ent->locals.ground_entity->in_use)
			ent->locals.ground_entity = NULL;
		else if (ent->locals.velocity[2] > ent->locals.ground_entity->locals.velocity[2] + 0.1)
			ent->locals.ground_entity = NULL;
		else
			return;
	}

	// if on ground, or intentionally floating, return without moving
	if (ent->locals.ground_entity || (ent->locals.item && (ent->locals.spawn_flags & 4)))
		return;

	// enforce max velocity values
	G_ClampVelocity(ent);

	// move angles
	VectorMA(ent->s.angles, gi.frame_seconds, ent->locals.avelocity, ent->s.angles);

	// move origin
	VectorCopy(ent->s.origin, org);
	VectorScale(ent->locals.velocity, gi.frame_seconds, move);

	// push through the world, interacting with triggers and other ents
	c_trace_t trace = G_PushEntity(ent, move);

	if (!ent->in_use)
		return;

	if (trace.fraction < 1.0) { // move was blocked

		// if it was a floor, we might bounce or come to rest
		vec_t *vel = ent->locals.velocity;
		if (G_ClipVelocity(vel, trace.plane.normal, vel, 1.3) & 1) {

			VectorSubtract(ent->s.origin, org, move);

			// if we're approaching a stop, clear our velocity and set ground
			if (VectorLength(move) < STOP_EPSILON) {

				VectorClear(ent->locals.velocity);

				ent->locals.ground_entity = trace.ent;
				ent->locals.ground_entity_link_count = trace.ent->link_count;
			} else {
				// bounce and slide along the floor
				vec_t bounce, speed = VectorLength(ent->locals.velocity);
				bounce = sqrt(speed);

				if (ent->locals.velocity[2] < bounce)
					ent->locals.velocity[2] = bounce;
			}
		}

		// all impacts reduce velocity and angular velocity
		VectorScale(ent->locals.velocity, 0.9, ent->locals.velocity);
		VectorScale(ent->locals.avelocity, 0.9, ent->locals.avelocity);
	}

	// check for water transition
	const _Bool was_in_water = (ent->locals.water_type & MASK_WATER);
	ent->locals.water_type = gi.PointContents(ent->s.origin);
	const _Bool is_in_water = ent->locals.water_type & MASK_WATER;

	if (is_in_water)
		ent->locals.water_level = 1;
	else
		ent->locals.water_level = 0;

	// add gravity
	if (ent->locals.move_type == MOVE_TYPE_FLY)
		G_AddFlying(ent);
	else
		G_AddGravity(ent);

	if (!was_in_water && is_in_water) {
		gi.PositionedSound(ent->s.origin, g_game.edicts, gi.SoundIndex("world/water_in"), ATTEN_NORM);
		VectorScale(ent->locals.velocity, 0.66, ent->locals.velocity);
	} else if (was_in_water && !is_in_water)
		gi.PositionedSound(ent->s.origin, g_game.edicts, gi.SoundIndex("world/water_out"),
				ATTEN_NORM);

	// move team slaves
	g_edict_t *slave = ent->locals.team_chain;
	while (slave) {
		VectorCopy(ent->s.origin, slave->s.origin);
		gi.LinkEdict(slave);

		slave = slave->locals.team_chain;
	}
}