Exemple #1
0
/*
================
G_BounceItem

================
*/
void G_BounceItem( gentity_t *ent, trace_t *trace ) {
	vec3_t	velocity;
	float	dot;
	int		hitTime;

	// reflect the velocity on the trace plane
	hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
	EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
	dot = DotProduct( velocity, trace->plane.normal );
	VectorMA( velocity, -2*dot, trace->plane.normal, ent->s.pos.trDelta );

	// cut the velocity to keep from bouncing forever
	VectorScale( ent->s.pos.trDelta, ent->physicsBounce, ent->s.pos.trDelta );

	// check for stop
	if ( trace->plane.normal[2] > 0 && ent->s.pos.trDelta[2] < 40 ) {
		G_SetOrigin( ent, trace->endpos );
		ent->s.groundEntityNum = trace->entityNum;
		return;
	}

	VectorAdd( ent->currentOrigin, trace->plane.normal, ent->currentOrigin);
	VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
	ent->s.pos.trTime = level.time;
}
/*
================
CG_ReflectVelocity
================
*/
void CG_ReflectVelocity( localEntity_t *le, trace_t *trace ) 
{
	vec3_t	velocity;
	float	dot;
	int		hitTime;

	// reflect the velocity on the trace plane
	hitTime = cg.time - cg.frametime + cg.frametime * trace->fraction;
	EvaluateTrajectoryDelta( &le->pos, hitTime, velocity );
	dot = DotProduct( velocity, trace->plane.normal );
	VectorMA( velocity, -2*dot, trace->plane.normal, le->pos.trDelta );

	VectorScale( le->pos.trDelta, le->bounceFactor, le->pos.trDelta );

	VectorCopy( trace->endpos, le->pos.trBase );
	le->pos.trTime = cg.time;

	// check for stop, making sure that even on low FPS systems it doesn't bobble
	if ( trace->allsolid || 
		( trace->plane.normal[2] > 0 && 
		( le->pos.trDelta[2] < 40 || le->pos.trDelta[2] < -cg.frametime * le->pos.trDelta[2] ) ) ) 
	{
		le->pos.trType = TR_STATIONARY;
	}
}
Exemple #3
0
/*
================
G_BounceRollMissile

================
*/
void G_BounceRollMissile( gentity_t *ent, trace_t *trace ) 
{
	vec3_t	velocity, normal;
	float	dot, speedXY, velocityZ, normalZ;
	int		hitTime;

	// reflect the velocity on the trace plane
	hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
	EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
	//Do horizontal
	//FIXME: Need to roll up, down slopes
	velocityZ = velocity[2];
	velocity[2] = 0;
	speedXY = VectorLength( velocity );//friction
	VectorCopy( trace->plane.normal, normal );
	normalZ = normal[2];
	normal[2] = 0;
	dot = DotProduct( velocity, normal );
	VectorMA( velocity, -2*dot, normal, ent->s.pos.trDelta );
	//now do the z reflection
	//FIXME: Bobbles when it stops
	VectorSet( velocity, 0, 0, velocityZ );
	VectorSet( normal, 0, 0, normalZ );
	dot = DotProduct( velocity, normal )*-1;
	if ( dot > 10 )
	{
		ent->s.pos.trDelta[2] = dot*0.3f;//not very bouncy
	}
	else
	{
		ent->s.pos.trDelta[2] = 0;
	}

	// check for stop
	if ( speedXY <= 0 ) 
	{
		G_SetOrigin( ent, trace->endpos );
		VectorCopy( ent->currentAngles, ent->s.apos.trBase );
		VectorClear( ent->s.apos.trDelta );
		ent->s.apos.trType = TR_STATIONARY;
		return;
	}

	//FIXME: rolling needs to match direction
	VectorCopy( ent->currentAngles, ent->s.apos.trBase );
	VectorCopy( ent->s.pos.trDelta, ent->s.apos.trDelta );

	//remember this spot
	VectorCopy( trace->endpos, ent->currentOrigin );
	ent->s.pos.trTime = hitTime - 10;
	VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
	//VectorCopy( trace->plane.normal, ent->pos1 );
}
Exemple #4
0
void FX_FlechetteProjectileThink( centity_t *cent, const struct weaponInfo_s *weapon )
{
	vec3_t forward;

	EvaluateTrajectoryDelta( &cent->gent->s.pos, cg.time, forward );

	if ( VectorNormalize( forward ) == 0.0f )
	{
		forward[2] = 1.0f;
	}

	theFxScheduler.PlayEffect( cgs.effects.flechetteShotEffect, cent->lerpOrigin, forward );
}
Exemple #5
0
/*
================
G_BounceMissile

================
*/
void G_BounceObject( gentity_t *ent, trace_t *trace ) 
{
	vec3_t	velocity;
	float	dot;
	int		hitTime;

	// reflect the velocity on the trace plane
	hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
	EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
	dot = DotProduct( velocity, trace->plane.normal );
	float bounceFactor = 60/ent->mass;
	if ( bounceFactor > 1.0f )
	{
		bounceFactor = 1.0f;
	}
	VectorMA( velocity, -2*dot*bounceFactor, trace->plane.normal, ent->s.pos.trDelta );

	//FIXME: customized or material-based impact/bounce sounds
	if ( ent->s.eFlags & EF_BOUNCE_HALF ) 
	{
		VectorScale( ent->s.pos.trDelta, 0.5, ent->s.pos.trDelta );

		// check for stop
		if ( ((trace->plane.normal[2] > 0.7&&g_gravity->value>0) || (trace->plane.normal[2]<-0.7&&g_gravity->value<0)) && ((ent->s.pos.trDelta[2]<40&&g_gravity->value>0)||(ent->s.pos.trDelta[2]>-40&&g_gravity->value<0)) ) //this can happen even on very slightly sloped walls, so changed it from > 0 to > 0.7
		{
			//G_SetOrigin( ent, trace->endpos );
			//ent->nextthink = level.time + 500;
			ent->s.apos.trType = TR_STATIONARY;
			VectorCopy( ent->currentAngles, ent->s.apos.trBase );
			VectorCopy( trace->endpos, ent->currentOrigin );
			VectorCopy( trace->endpos, ent->s.pos.trBase );
			ent->s.pos.trTime = level.time;
			return;
		}
	}

	// NEW--It would seem that we want to set our trBase to the trace endpos
	//	and set the trTime to the actual time of impact....
	//	FIXME: Should we still consider adding the normal though??
	VectorCopy( trace->endpos, ent->currentOrigin );
	ent->s.pos.trTime = hitTime;

	VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
	VectorCopy( trace->plane.normal, ent->pos1 );//???
}
Exemple #6
0
//-------------------------------------------------------------------------
static void G_MissileStick( gentity_t *missile, gentity_t *other, trace_t *tr )
{ 
	if ( other->NPC || !Q_stricmp( other->classname, "misc_model_breakable" ))
	{
		// we bounce off of NPC's and misc model breakables because sticking to them requires too much effort
		vec3_t velocity;

		int hitTime = level.previousTime + ( level.time - level.previousTime ) * tr->fraction;

		EvaluateTrajectoryDelta( &missile->s.pos, hitTime, velocity );

		float dot = DotProduct( velocity, tr->plane.normal );
		G_SetOrigin( missile, tr->endpos );
		VectorMA( velocity, -1.6f * dot, tr->plane.normal, missile->s.pos.trDelta );
		VectorMA( missile->s.pos.trDelta, 10, tr->plane.normal, missile->s.pos.trDelta );
		missile->s.pos.trTime = level.time - 10; // move a bit on the first frame

		// check for stop
		if ( tr->entityNum >= 0 && tr->entityNum < ENTITYNUM_WORLD && 
				tr->plane.normal[2] > 0.7 && missile->s.pos.trDelta[2] < 40 ) //this can happen even on very slightly sloped walls, so changed it from > 0 to > 0.7
		{
			missile->nextthink = level.time + 100;
		}
		else
		{
			// fall till we hit the ground
			missile->s.pos.trType = TR_GRAVITY;
		}

		return; // don't stick yet
	}

	if ( missile->e_TouchFunc != touchF_NULL )
	{
		GEntity_TouchFunc( missile, other, tr );
	}

	G_AddEvent( missile, EV_MISSILE_STICK, 0 );

	if ( other->s.eType == ET_MOVER || other->e_DieFunc == dieF_funcBBrushDie || other->e_DieFunc == dieF_funcGlassDie)
	{
		// movers and breakable brushes need extra info...so sticky missiles can ride lifts and blow up when the thing they are attached to goes away.
		missile->s.groundEntityNum = tr->entityNum;
	}
}
Exemple #7
0
/*
================
G_BounceItem

================
*/
void G_BounceItem( gentity_t *ent, trace_t *trace ) {
	vec3_t	velocity;
	float	dot;
	int		hitTime;
	qboolean droppedSaber = qtrue;

	if ( ent->item
		&& ent->item->giType == IT_WEAPON
		&& ent->item->giTag == WP_SABER 
		&& (ent->flags&FL_DROPPED_ITEM) )
	{
		droppedSaber = qtrue;
	}

	// reflect the velocity on the trace plane
	hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
	EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
	dot = DotProduct( velocity, trace->plane.normal );
	VectorMA( velocity, -2*dot, trace->plane.normal, ent->s.pos.trDelta );

	// cut the velocity to keep from bouncing forever
	VectorScale( ent->s.pos.trDelta, ent->physicsBounce, ent->s.pos.trDelta );

	if ( droppedSaber )
	{//a dropped saber item
		//FIXME: use NPC_type (as saberType) to get proper bounce sound?
		WP_SaberFallSound( NULL, ent );
	}

	// check for stop
	if ( trace->plane.normal[2] > 0 && ent->s.pos.trDelta[2] < 40 ) 
	{//stop
		G_SetOrigin( ent, trace->endpos );
		ent->s.groundEntityNum = trace->entityNum;
		if ( droppedSaber )
		{//a dropped saber item
			//stop rotation
			VectorClear( ent->s.apos.trDelta );
			ent->currentAngles[PITCH] = SABER_PITCH_HACK;
			ent->currentAngles[ROLL] = 0;
			if ( ent->NPC_type 
				&& ent->NPC_type[0] )
			{//we have a valid saber for this
				saberInfo_t saber;
				if ( WP_SaberParseParms( ent->NPC_type, &saber ) )
				{
					if ( (saber.saberFlags&SFL_BOLT_TO_WRIST) )
					{
						ent->currentAngles[PITCH] = 0;
					}
				}
			}
			pitch_roll_for_slope( ent, trace->plane.normal, ent->currentAngles, qtrue );
			G_SetAngles( ent, ent->currentAngles );
		}
		return;
	}
	//bounce
	if ( droppedSaber )
	{//a dropped saber item
		//change rotation
		VectorCopy( ent->currentAngles, ent->s.apos.trBase );
		ent->s.apos.trType = TR_LINEAR;
		ent->s.apos.trTime = level.time;
		VectorSet( ent->s.apos.trDelta, Q_irand( -300, 300 ), Q_irand( -300, 300 ), Q_irand( -300, 300 ) );
	}

	VectorAdd( ent->currentOrigin, trace->plane.normal, ent->currentOrigin);
	VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
	ent->s.pos.trTime = level.time;
}
Exemple #8
0
void G_MissileImpacted( gentity_t *ent, gentity_t *other, vec3_t impactPos, vec3_t normal, int hitLoc=HL_NONE )
{
	// impact damage
	if ( other->takedamage ) 
	{
		// FIXME: wrong damage direction?
		if ( ent->damage ) 
		{
			vec3_t	velocity;

			EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
			if ( VectorLength( velocity ) == 0 ) 
			{
				velocity[2] = 1;	// stepped on a grenade
			}

			int damage = ent->damage;

			if( other->client )
			{
				class_t	npc_class = other->client->NPC_class;

				// If we are a robot and we aren't currently doing the full body electricity...
				if ( npc_class == CLASS_SEEKER || npc_class == CLASS_PROBE || npc_class == CLASS_MOUSE ||
					   npc_class == CLASS_GONK || npc_class == CLASS_R2D2 || npc_class == CLASS_R5D2 || npc_class == CLASS_REMOTE ||
					   npc_class == CLASS_MARK1 || npc_class == CLASS_MARK2 || //npc_class == CLASS_PROTOCOL ||//no protocol, looks odd
					   npc_class == CLASS_INTERROGATOR || npc_class == CLASS_ATST || npc_class == CLASS_SENTRY )
				{
					// special droid only behaviors
					if ( other->client->ps.powerups[PW_SHOCKED] < level.time + 100 )
					{
						// ... do the effect for a split second for some more feedback
						other->s.powerups |= ( 1 << PW_SHOCKED );
						other->client->ps.powerups[PW_SHOCKED] = level.time + 450;
					}
					//FIXME: throw some sparks off droids,too
				}
			}

			G_Damage( other, ent, ent->owner, velocity,
					impactPos, damage, 
					ent->dflags, ent->methodOfDeath, hitLoc);

			if ( ent->s.weapon == WP_DEMP2 )
			{//a hit with demp2 decloaks saboteurs
				if ( other && other->client && other->client->NPC_class == CLASS_SABOTEUR )
				{//FIXME: make this disabled cloak hold for some amount of time?
					Saboteur_Decloak( other, Q_irand( 3000, 10000 ) );
					if ( ent->methodOfDeath == MOD_DEMP2_ALT )
					{//direct hit with alt disabled cloak forever
						if ( other->NPC )
						{//permanently disable the saboteur's cloak
							other->NPC->aiFlags &= ~NPCAI_SHIELDS;
						}
					}
				}
			}
		}
	}

	// is it cheaper in bandwidth to just remove this ent and create a new
	// one, rather than changing the missile into the explosion?
	//G_FreeEntity(ent);
	
	if ( (other->takedamage && other->client ) || (ent->s.weapon == WP_FLECHETTE && other->contents&CONTENTS_LIGHTSABER) ) 
	{
		G_AddEvent( ent, EV_MISSILE_HIT, DirToByte( normal ) );
		ent->s.otherEntityNum = other->s.number;
	} 
	else 
	{
		G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( normal ) );
		ent->s.otherEntityNum = other->s.number;
	}

	VectorCopy( normal, ent->pos1 );

	if ( ent->owner )//&& ent->owner->s.number == 0 )
	{
		//Add the event
		AddSoundEvent( ent->owner, ent->currentOrigin, 256, AEL_SUSPICIOUS, qfalse, qtrue );
		AddSightEvent( ent->owner, ent->currentOrigin, 512, AEL_DISCOVERED, 75 );
	}

	ent->freeAfterEvent = qtrue;

	// change over to a normal entity right at the point of impact
	ent->s.eType = ET_GENERAL;

	//SnapVectorTowards( trace->endpos, ent->s.pos.trBase );	// save net bandwidth
	VectorCopy( impactPos, ent->s.pos.trBase );

	G_SetOrigin( ent, impactPos );

	// splash damage (doesn't apply to person directly hit)
	if ( ent->splashDamage ) 
	{
		G_RadiusDamage( impactPos, ent->owner, ent->splashDamage, ent->splashRadius, 
			other, ent->splashMethodOfDeath );
	}

	if ( ent->s.weapon == WP_NOGHRI_STICK )
	{
		G_SpawnNoghriGasCloud( ent );
	}

	gi.linkentity( ent );
}
Exemple #9
0
/*
================
G_BounceMissile

================
*/
void G_BounceMissile( gentity_t *ent, trace_t *trace ) {
	vec3_t	velocity;
	float	dot;
	int		hitTime;

	// reflect the velocity on the trace plane
	hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
	EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
	dot = DotProduct( velocity, trace->plane.normal );
	VectorMA( velocity, -2*dot, trace->plane.normal, ent->s.pos.trDelta );

	if ( ent->s.eFlags & EF_BOUNCE_SHRAPNEL ) 
	{
		VectorScale( ent->s.pos.trDelta, 0.25f, ent->s.pos.trDelta );
		ent->s.pos.trType = TR_GRAVITY;

		// check for stop
		if ( trace->plane.normal[2] > 0.7 && ent->s.pos.trDelta[2] < 40 ) //this can happen even on very slightly sloped walls, so changed it from > 0 to > 0.7
		{
			G_SetOrigin( ent, trace->endpos );
			ent->nextthink = level.time + 100;
			return;
		}
	}
	else if ( ent->s.eFlags & EF_BOUNCE_HALF ) 
	{
		VectorScale( ent->s.pos.trDelta, 0.5, ent->s.pos.trDelta );

		// check for stop
		if ( trace->plane.normal[2] > 0.7 && ent->s.pos.trDelta[2] < 40 ) //this can happen even on very slightly sloped walls, so changed it from > 0 to > 0.7
		{
			if ( ent->s.weapon == WP_THERMAL )
			{//roll when you "stop"
				ent->s.pos.trType = TR_INTERPOLATE;
			}
			else
			{
				G_SetOrigin( ent, trace->endpos );
				ent->nextthink = level.time + 500;
				return;
			}
		}

		if ( ent->s.weapon == WP_THERMAL )
		{
			ent->has_bounced = qtrue;
		}
	}

#if 0
	// OLD--this looks so wrong.  It looked wrong in EF.  It just must be wrong.
	VectorAdd( ent->currentOrigin, trace->plane.normal, ent->currentOrigin);

	ent->s.pos.trTime = level.time - 10;
#else
	// NEW--It would seem that we want to set our trBase to the trace endpos
	//	and set the trTime to the actual time of impact....
	VectorAdd( trace->endpos, trace->plane.normal, ent->currentOrigin );
	if ( hitTime >= level.time )
	{//trace fraction must have been 1
		ent->s.pos.trTime = level.time - 10;
	}
	else
	{
		ent->s.pos.trTime = hitTime - 10; // this is kinda dumb hacking, but it pushes the missile away from the impact plane a bit
	}
#endif

	VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
	VectorCopy( trace->plane.normal, ent->pos1 );

	if ( ent->s.weapon != WP_SABER 
		&& ent->s.weapon != WP_THERMAL 
		&& ent->e_clThinkFunc != clThinkF_CG_Limb
		&& ent->e_ThinkFunc != thinkF_LimbThink )
	{//not a saber, bouncing thermal or limb
		//now you can damage the guy you came from
		ent->owner = NULL;
	}
}