Exemplo n.º 1
0
//extern void G_Knockdown( gentity_t *victim );
//[/KnockdownSys]
static void Howler_TryDamage( int damage, qboolean tongue, qboolean knockdown )
{
	vec3_t	start, end, dir;
	trace_t	tr;
	float dist;

	if ( tongue )
	{
		G_GetBoltPosition( NPC, NPC->NPC->genericBolt1, start, 0 );
		G_GetBoltPosition( NPC, NPC->NPC->genericBolt2, end, 0 );
		VectorSubtract( end, start, dir );
		dist = VectorNormalize( dir );
		VectorMA( start, dist+16, dir, end );
	}
	else
	{
		VectorCopy( NPC->r.currentOrigin, start );
		AngleVectors( NPC->r.currentAngles, dir, NULL, NULL );
		VectorMA( start, MIN_DISTANCE*2, dir, end );
	}
/* RACC - don't need this for now.
#ifndef FINAL_BUILD
	if ( d_saberCombat.integer > 1 )
	{
		G_DebugLine(start, end, 1000, 0x000000ff, qtrue);
	}
#endif
*/
	// Should probably trace from the mouth, but, ah well.
	trap_Trace( &tr, start, vec3_origin, vec3_origin, end, NPC->s.number, MASK_SHOT );

	if ( tr.entityNum < ENTITYNUM_WORLD )
	{//hit *something*
		gentity_t *victim = &g_entities[tr.entityNum];
		if ( !victim->client
			|| victim->client->NPC_class != CLASS_HOWLER )
		{//not another howler

			if ( knockdown && victim->client )
			{//only do damage if victim isn't knocked down.  If he isn't, knock him down
				if ( PM_InKnockDown( &victim->client->ps ) )
				{
					return;
				}
			}
			//FIXME: some sort of damage effect (claws and tongue are cutting you... blood?)
			G_Damage( victim, NPC, NPC, dir, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_MELEE );
			if ( knockdown && victim->health > 0 )
			{//victim still alive
				//[KnockdownSys]
				G_Knockdown( victim, NPC, NPC->client->ps.velocity, 500, qfalse );
				//G_Knockdown(victim);
				//[/KnockdownSys]
			}
		}
	}
}
Exemplo n.º 2
0
float NPC_EntRangeFromBolt( gentity_t *targEnt, int boltIndex )
{
	vec3_t	org;

	if ( !targEnt )
	{
		return Q3_INFINITE;
	}

	G_GetBoltPosition( NPC, boltIndex, org, 0 );

	return (Distance( targEnt->r.currentOrigin, org ));
}
Exemplo n.º 3
0
int NPC_GetEntsNearBolt( int *radiusEnts, float radius, int boltIndex, vec3_t boltOrg )
{
	vec3_t		mins, maxs;
	int			i;

	//get my handRBolt's position
	vec3_t	org;

	G_GetBoltPosition( NPC, boltIndex, org, 0 );

	VectorCopy( org, boltOrg );

	//Setup the bbox to search in
	for ( i = 0; i < 3; i++ )
	{
		mins[i] = boltOrg[i] - radius;
		maxs[i] = boltOrg[i] + radius;
	}

	//Get the number of entities in a given space
	return (trap_EntitiesInBox( mins, maxs, radiusEnts, 128 ));
}
Exemplo n.º 4
0
void Rancor_Attack( float distance, qboolean doCharge )
{

	if ( !TIMER_Exists( NPCS.NPC, "attacking" ) )
	{
		if ( NPCS.NPC->count == 2 && NPCS.NPC->activator )
		{
		}
		else if ( NPCS.NPC->count == 1 && NPCS.NPC->activator )
		{//holding enemy
			if ( NPCS.NPC->activator->health > 0 && Q_irand( 0, 1 ) )
			{//quick bite
				NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_ATTACK1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
				TIMER_Set( NPCS.NPC, "attack_dmg", 450 );
			}
			else
			{//full eat
				NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_ATTACK3, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
				TIMER_Set( NPCS.NPC, "attack_dmg", 900 );
				//Make victim scream in fright
				if ( NPCS.NPC->activator->health > 0 && NPCS.NPC->activator->client )
				{
					G_AddEvent( NPCS.NPC->activator, Q_irand(EV_DEATH1, EV_DEATH3), 0 );
					NPC_SetAnim( NPCS.NPC->activator, SETANIM_TORSO, BOTH_FALLDEATH1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
					if ( NPCS.NPC->activator->NPC )
					{//no more thinking for you
						TossClientItems( NPCS.NPC );
						NPCS.NPC->activator->NPC->nextBStateThink = Q3_INFINITE;
					}
				}
			}
		}
		else if ( NPCS.NPC->enemy->health > 0 && doCharge )
		{//charge
			vec3_t	fwd, yawAng;
			VectorSet( yawAng, 0, NPCS.NPC->client->ps.viewangles[YAW], 0 );
			AngleVectors( yawAng, fwd, NULL, NULL );
			VectorScale( fwd, distance*1.5f, NPCS.NPC->client->ps.velocity );
			NPCS.NPC->client->ps.velocity[2] = 150;
			NPCS.NPC->client->ps.groundEntityNum = ENTITYNUM_NONE;

			NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_MELEE2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
			TIMER_Set( NPCS.NPC, "attack_dmg", 1250 );
		}
		else if ( !Q_irand(0, 1) )
		{//smash
			NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_MELEE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
			TIMER_Set( NPCS.NPC, "attack_dmg", 1000 );
		}
		else
		{//try to grab
			NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_ATTACK2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
			TIMER_Set( NPCS.NPC, "attack_dmg", 1000 );
		}

		TIMER_Set( NPCS.NPC, "attacking", NPCS.NPC->client->ps.legsTimer + random() * 200 );
	}

	// Need to do delayed damage since the attack animations encapsulate multiple mini-attacks

	if ( TIMER_Done2( NPCS.NPC, "attack_dmg", qtrue ) )
	{
		vec3_t shakePos;
		switch ( NPCS.NPC->client->ps.legsAnim )
		{
		case BOTH_MELEE1:
			Rancor_Smash();
			G_GetBoltPosition( NPCS.NPC, NPCS.NPC->client->renderInfo.handLBolt, shakePos, 0 );
			G_ScreenShake( shakePos, NULL, 4.0f, 1000, qfalse );
			//CGCam_Shake( 1.0f*playerDist/128.0f, 1000 );
			break;
		case BOTH_MELEE2:
			Rancor_Bite();
			TIMER_Set( NPCS.NPC, "attack_dmg2", 450 );
			break;
		case BOTH_ATTACK1:
			if ( NPCS.NPC->count == 1 && NPCS.NPC->activator )
			{
				G_Damage( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC, vec3_origin, NPCS.NPC->activator->r.currentOrigin, Q_irand( 25, 40 ), DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK, MOD_MELEE );
				if ( NPCS.NPC->activator->health <= 0 )
				{//killed him
					//make it look like we bit his head off
					//NPC->activator->client->dismembered = qfalse;
					G_Dismember( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC->activator->r.currentOrigin, G2_MODELPART_HEAD, 90, 0, NPCS.NPC->activator->client->ps.torsoAnim, qtrue);
					//G_DoDismemberment( NPC->activator, NPC->activator->r.currentOrigin, MOD_SABER, 1000, HL_HEAD, qtrue );
					NPCS.NPC->activator->client->ps.forceHandExtend = HANDEXTEND_NONE;
					NPCS.NPC->activator->client->ps.forceHandExtendTime = 0;
					NPC_SetAnim( NPCS.NPC->activator, SETANIM_BOTH, BOTH_SWIM_IDLE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
				}
				G_Sound( NPCS.NPC->activator, CHAN_AUTO, G_SoundIndex( "sound/chars/rancor/chomp.wav" ) );
			}
			break;
		case BOTH_ATTACK2:
			//try to grab
			Rancor_Swing( qtrue );
			break;
		case BOTH_ATTACK3:
			if ( NPCS.NPC->count == 1 && NPCS.NPC->activator )
			{
				//cut in half
				if ( NPCS.NPC->activator->client )
				{
					//NPC->activator->client->dismembered = qfalse;
					G_Dismember( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC->activator->r.currentOrigin, G2_MODELPART_WAIST, 90, 0, NPCS.NPC->activator->client->ps.torsoAnim, qtrue);
					//G_DoDismemberment( NPC->activator, NPC->enemy->r.currentOrigin, MOD_SABER, 1000, HL_WAIST, qtrue );
				}
				//KILL
				G_Damage( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC, vec3_origin, NPCS.NPC->activator->r.currentOrigin, NPCS.NPC->enemy->health+10, DAMAGE_NO_PROTECTION|DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK|DAMAGE_NO_HIT_LOC, MOD_MELEE );//, HL_NONE );//
				if ( NPCS.NPC->activator->client )
				{
					NPCS.NPC->activator->client->ps.forceHandExtend = HANDEXTEND_NONE;
					NPCS.NPC->activator->client->ps.forceHandExtendTime = 0;
					NPC_SetAnim( NPCS.NPC->activator, SETANIM_BOTH, BOTH_SWIM_IDLE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
				}
				TIMER_Set( NPCS.NPC, "attack_dmg2", 1350 );
				G_Sound( NPCS.NPC->activator, CHAN_AUTO, G_SoundIndex( "sound/chars/rancor/swipehit.wav" ) );
				G_AddEvent( NPCS.NPC->activator, EV_JUMP, NPCS.NPC->activator->health );
			}
			break;
		}
	}
	else if ( TIMER_Done2( NPCS.NPC, "attack_dmg2", qtrue ) )
	{
		switch ( NPCS.NPC->client->ps.legsAnim )
		{
		case BOTH_MELEE1:
			break;
		case BOTH_MELEE2:
			Rancor_Bite();
			break;
		case BOTH_ATTACK1:
			break;
		case BOTH_ATTACK2:
			break;
		case BOTH_ATTACK3:
			if ( NPCS.NPC->count == 1 && NPCS.NPC->activator )
			{//swallow victim
				G_Sound( NPCS.NPC->activator, CHAN_AUTO, G_SoundIndex( "sound/chars/rancor/chomp.wav" ) );
				//FIXME: sometimes end up with a live one in our mouths?
				//just make sure they're dead
				if ( NPCS.NPC->activator->health > 0 )
				{
					//cut in half
					//NPC->activator->client->dismembered = qfalse;
					G_Dismember( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC->activator->r.currentOrigin, G2_MODELPART_WAIST, 90, 0, NPCS.NPC->activator->client->ps.torsoAnim, qtrue);
					//G_DoDismemberment( NPC->activator, NPC->enemy->r.currentOrigin, MOD_SABER, 1000, HL_WAIST, qtrue );
					//KILL
					G_Damage( NPCS.NPC->activator, NPCS.NPC, NPCS.NPC, vec3_origin, NPCS.NPC->activator->r.currentOrigin, NPCS.NPC->enemy->health+10, DAMAGE_NO_PROTECTION|DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK|DAMAGE_NO_HIT_LOC, MOD_MELEE );//, HL_NONE );
					NPCS.NPC->activator->client->ps.forceHandExtend = HANDEXTEND_NONE;
					NPCS.NPC->activator->client->ps.forceHandExtendTime = 0;
					NPC_SetAnim( NPCS.NPC->activator, SETANIM_BOTH, BOTH_SWIM_IDLE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
					G_AddEvent( NPCS.NPC->activator, EV_JUMP, NPCS.NPC->activator->health );
				}
				if ( NPCS.NPC->activator->client )
				{//*sigh*, can't get tags right, just remove them?
					NPCS.NPC->activator->client->ps.eFlags |= EF_NODRAW;
				}
				NPCS.NPC->count = 2;
				TIMER_Set( NPCS.NPC, "clearGrabbed", 2600 );
			}
			break;
		}
	}
	else if ( NPCS.NPC->client->ps.legsAnim == BOTH_ATTACK2 )
	{
		if ( NPCS.NPC->client->ps.legsTimer >= 1200 && NPCS.NPC->client->ps.legsTimer <= 1350 )
		{
			if ( Q_irand( 0, 2 ) )
			{
				Rancor_Swing( qfalse );
			}
			else
			{
				Rancor_Swing( qtrue );
			}
		}
		else if ( NPCS.NPC->client->ps.legsTimer >= 1100 && NPCS.NPC->client->ps.legsTimer <= 1550 )
		{
			Rancor_Swing( qtrue );
		}
	}

	// Just using this to remove the attacking flag at the right time
	TIMER_Done2( NPCS.NPC, "attacking", qtrue );
}
Exemplo n.º 5
0
static void Howler_Attack( float enemyDist, qboolean howl )
{
	int dmg = (NPCInfo->localState==LSTATE_BERZERK)?5:2;

	vec3_t boltOrg;
	vec3_t fwd;

	if ( !TIMER_Exists( NPC, "attacking" ))
	{
		int attackAnim = BOTH_GESTURE1;
		// Going to do an attack
		if ( NPC->enemy && NPC->enemy->client && PM_InKnockDown( &NPC->enemy->client->ps )
			&& enemyDist <= MIN_DISTANCE )
		{
			attackAnim = BOTH_ATTACK2;
		}
		else if ( !Q_irand( 0, 4 ) || howl )
		{//howl attack
			//G_SoundOnEnt( NPC, CHAN_VOICE, "sound/chars/howler/howl.mp3" );
		}
		else if ( enemyDist > MIN_DISTANCE && Q_irand( 0, 1 ) )
		{//lunge attack
			//jump foward
			vec3_t	fwd, yawAng;
			
			VectorSet( yawAng, 0, NPC->client->ps.viewangles[YAW], 0 );
			AngleVectors( yawAng, fwd, NULL, NULL );
			VectorScale( fwd, (enemyDist*3.0f), NPC->client->ps.velocity );
			NPC->client->ps.velocity[2] = 200;
			NPC->client->ps.groundEntityNum = ENTITYNUM_NONE;
			
			attackAnim = BOTH_ATTACK1;
		}
		else
		{//tongue attack
			attackAnim = BOTH_ATTACK2;
		}

		NPC_SetAnim( NPC, SETANIM_BOTH, attackAnim, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD | SETANIM_FLAG_RESTART );
		if ( NPCInfo->localState == LSTATE_BERZERK )
		{//attack again right away
			TIMER_Set( NPC, "attacking", NPC->client->ps.legsTimer );
		}
		else
		{
			TIMER_Set( NPC, "attacking", NPC->client->ps.legsTimer + Q_irand( 0, 1500 ) );//FIXME: base on skill
			TIMER_Set( NPC, "standing", -level.time );
			TIMER_Set( NPC, "walking", -level.time );
			TIMER_Set( NPC, "running", NPC->client->ps.legsTimer + 5000 );
		}

		TIMER_Set( NPC, "attack_dmg", 200 ); // level two damage
	}

	// Need to do delayed damage since the attack animations encapsulate multiple mini-attacks
	switch ( NPC->client->ps.legsAnim )
	{
	case BOTH_ATTACK1:
	case BOTH_MELEE1:
		if ( NPC->client->ps.legsTimer > 650//more than 13 frames left
			&& BG_AnimLength( NPC->localAnimIndex, (animNumber_t)NPC->client->ps.legsAnim ) - NPC->client->ps.legsTimer >= 800 )//at least 16 frames into anim
		{
			Howler_TryDamage( dmg, qfalse, qfalse );
		}
		break;
	case BOTH_ATTACK2:
	case BOTH_MELEE2:
		if ( NPC->client->ps.legsTimer > 350//more than 7 frames left
			&& BG_AnimLength( NPC->localAnimIndex, (animNumber_t)NPC->client->ps.legsAnim ) - NPC->client->ps.legsTimer >= 550 )//at least 11 frames into anim
		{
			Howler_TryDamage( dmg, qtrue, qfalse );
		}
		break;
	case BOTH_GESTURE1:
		{
			if ( NPC->client->ps.legsTimer > 1800//more than 36 frames left
				&& BG_AnimLength( NPC->localAnimIndex, (animNumber_t)NPC->client->ps.legsAnim ) - NPC->client->ps.legsTimer >= 950 )//at least 19 frames into anim
			{
				Howler_Howl();
				if ( !NPC->count )
				{
					//RAFIXME - this probably won't work correctly.
					G_GetBoltPosition(NPC, NPC->NPC->genericBolt1, boltOrg, 0);
					AngleVectors( NPC->client->ps.viewangles, fwd, NULL, NULL );
					G_PlayEffectID( G_EffectIndex( "howler/sonic" ), boltOrg, fwd);
					//G_PlayEffect( G_EffectIndex( "howler/sonic" ), NPC->ghoul2, NPC->NPC->genericBolt1, NPC->s.number, NPC->currentOrigin, 4750, qtrue );
					G_SoundOnEnt( NPC, CHAN_VOICE, "sound/chars/howler/howl.mp3" );
					NPC->count = 1;
				}
			}
		}
		break;
	default:
		//anims seem to get reset after a load, so just stop attacking and it will restart as needed.
		TIMER_Remove( NPC, "attacking" );
		break;
	}

	// Just using this to remove the attacking flag at the right time
	TIMER_Done2( NPC, "attacking", qtrue );
}
Exemplo n.º 6
0
void G_KickSomeMofos(gentity_t *ent)
{
	vec3_t	kickDir, kickEnd, fwdAngs;
	float animLength = BG_AnimLength( ent->localAnimIndex, (animNumber_t)ent->client->ps.legsAnim );
	float elapsedTime = (float)(animLength-ent->client->ps.legsTimer);
	float remainingTime = (animLength-elapsedTime);
	float kickDist = (ent->r.maxs[0]*1.5f)+STAFF_KICK_RANGE+8.0f;//fudge factor of 8
	int	  kickDamage = Q_irand(10, 15);//Q_irand( 3, 8 ); //since it can only hit a guy once now
	int	  kickPush = flrand( 50.0f, 100.0f );
	qboolean doKick = qfalse;
	renderInfo_t *ri = &ent->client->renderInfo;

	VectorSet(kickDir, 0.0f, 0.0f, 0.0f);
	VectorSet(kickEnd, 0.0f, 0.0f, 0.0f);
	VectorSet(fwdAngs, 0.0f, ent->client->ps.viewangles[YAW], 0.0f);

	//HMM... or maybe trace from origin to footRBolt/footLBolt?  Which one?  G2 trace?  Will do hitLoc, if so...
	if ( ent->client->ps.torsoAnim == BOTH_A7_HILT )
	{
		if ( elapsedTime >= 250 && remainingTime >= 250 )
		{//front
			doKick = qtrue;
			if ( ri->handRBolt != -1 )
			{//actually trace to a bolt
				G_GetBoltPosition( ent, ri->handRBolt, kickEnd, 0 );
				VectorSubtract( kickEnd, ent->client->ps.origin, kickDir );
				kickDir[2] = 0;//ah, flatten it, I guess...
				VectorNormalize( kickDir );
			}
			else
			{//guess
				AngleVectors( fwdAngs, kickDir, NULL, NULL );
			}
		}
	}
	else
	{
		switch ( ent->client->ps.legsAnim )
		{
		case BOTH_GETUP_BROLL_B:
		case BOTH_GETUP_BROLL_F:
		case BOTH_GETUP_FROLL_B:
		case BOTH_GETUP_FROLL_F:
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//front
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->client->ps.origin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
			}
			break;
		case BOTH_A7_KICK_F_AIR:
		case BOTH_A7_KICK_B_AIR:
		case BOTH_A7_KICK_R_AIR:
		case BOTH_A7_KICK_L_AIR:
			if ( elapsedTime >= 100 && remainingTime >= 250 )
			{//air
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
			}
			break;
		case BOTH_A7_KICK_F:
			//FIXME: push forward?
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//front
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
			}
			break;
		case BOTH_A7_KICK_B:
			//FIXME: push back?
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//back
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		case BOTH_A7_KICK_R:
			//FIXME: push right?
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//right
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
				}
			}
			break;
		case BOTH_A7_KICK_L:
			//FIXME: push left?
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//left
				doKick = qtrue;
				if ( ri->footLBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footLBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		case BOTH_A7_KICK_S:
			kickPush = flrand( 75.0f, 125.0f );
			if ( ri->footRBolt != -1 )
			{//actually trace to a bolt
				if ( elapsedTime >= 550 
					&& elapsedTime <= 1050 )
				{
					doKick = qtrue;
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
					//NOTE: have to fudge this a little because it's not getting enough range with the anim as-is
					VectorMA( kickEnd, 8.0f, kickDir, kickEnd );
				}
			}
			else
			{//guess
				if ( elapsedTime >= 400 && elapsedTime < 500 )
				{//front
					doKick = qtrue;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
				else if ( elapsedTime >= 500 && elapsedTime < 600 )
				{//front-right?
					doKick = qtrue;
					fwdAngs[YAW] += 45;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
				else if ( elapsedTime >= 600 && elapsedTime < 700 )
				{//right
					doKick = qtrue;
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
				}
				else if ( elapsedTime >= 700 && elapsedTime < 800 )
				{//back-right?
					doKick = qtrue;
					fwdAngs[YAW] += 45;
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
				}
				else if ( elapsedTime >= 800 && elapsedTime < 900 )
				{//back
					doKick = qtrue;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
				else if ( elapsedTime >= 900 && elapsedTime < 1000 )
				{//back-left?
					doKick = qtrue;
					fwdAngs[YAW] += 45;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
				else if ( elapsedTime >= 1000 && elapsedTime < 1100 )
				{//left
					doKick = qtrue;
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
				else if ( elapsedTime >= 1100 && elapsedTime < 1200 )
				{//front-left?
					doKick = qtrue;
					fwdAngs[YAW] += 45;
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		case BOTH_A7_KICK_BF:
			kickPush = flrand( 75.0f, 125.0f );
			kickDist += 20.0f;
			if ( elapsedTime < 1500 )
			{//auto-aim!
	//			overridAngles = PM_AdjustAnglesForBFKick( ent, ucmd, fwdAngs, qboolean(elapsedTime<850) )?qtrue:overridAngles;
				//FIXME: if we haven't done the back kick yet and there's no-one there to
				//			kick anymore, go into some anim that returns us to our base stance
			}
			if ( ri->footRBolt != -1 )
			{//actually trace to a bolt
				if ( ( elapsedTime >= 750 && elapsedTime < 850 )
					|| ( elapsedTime >= 1400 && elapsedTime < 1500 ) )
				{//right, though either would do
					doKick = qtrue;
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
					//NOTE: have to fudge this a little because it's not getting enough range with the anim as-is
					VectorMA( kickEnd, 8, kickDir, kickEnd );
				}
			}
			else
			{//guess
				if ( elapsedTime >= 250 && elapsedTime < 350 )
				{//front
					doKick = qtrue;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
				else if ( elapsedTime >= 350 && elapsedTime < 450 )
				{//back
					doKick = qtrue;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		case BOTH_A7_KICK_RL:
			kickPush = flrand( 75.0f, 125.0f );
			kickDist += 10.0f;

			//ok, I'm tracing constantly on these things, they NEVER hit otherwise (in MP at least)

			//FIXME: auto aim at enemies on the side of us?
			//overridAngles = PM_AdjustAnglesForRLKick( ent, ucmd, fwdAngs, qboolean(elapsedTime<850) )?qtrue:overridAngles;
			//if ( elapsedTime >= 250 && elapsedTime < 350 )
			if (level.framenum&1)
			{//right
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
					//NOTE: have to fudge this a little because it's not getting enough range with the anim as-is
					VectorMA( kickEnd, 8, kickDir, kickEnd );
				}
				else
				{//guess
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
				}
			}
			//else if ( elapsedTime >= 350 && elapsedTime < 450 )
			else
			{//left
				doKick = qtrue;
				if ( ri->footLBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footLBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
					//NOTE: have to fudge this a little because it's not getting enough range with the anim as-is
					VectorMA( kickEnd, 8, kickDir, kickEnd );
				}
				else
				{//guess
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		}
	}

	if ( doKick )
	{
//		G_KickTrace( ent, kickDir, kickDist, kickEnd, kickDamage, kickPush );
		G_KickTrace( ent, kickDir, kickDist, NULL, kickDamage, kickPush );
	}
}