Example #1
0
// drops us down from the specified position, to the floor
bool CASW_Simple_Alien::ApplyGravity(Vector &vecSrc, float deltatime)
{
	// decide if we're on the ground or not	
	Ray_t ray;
	trace_t trace;
	CTraceFilterSimple traceFilter(this, GetCollisionGroup() );
	ray.Init( vecSrc, vecSrc - Vector(0,0,2), GetHullMins(), GetHullMaxs() );
	enginetrace->TraceRay( ray, MASK_NPCSOLID, &traceFilter, &trace );	
	
	m_bOnGround = (trace.fraction < 1.0f);

	// if we're on the ground, just drop us down as much as we can
	if (m_bOnGround)
	{
		Vector vecGravityTarget = vecSrc;
		vecGravityTarget.z -= sv_gravity.GetFloat() * deltatime;
		// do a trace to the floor
		Ray_t ray;
		trace_t trace;
		CTraceFilterSimple traceFilter(this, GetCollisionGroup() );
		ray.Init( vecSrc, vecGravityTarget, GetHullMins(), GetHullMaxs() );
		enginetrace->TraceRay( ray, MASK_NPCSOLID, &traceFilter, &trace );

		if (trace.fraction > 0 && fabs(trace.endpos.z - vecSrc.z) > 1) // if we moved up/down
		{
			vecSrc = trace.endpos;
			
			return true;
		}
		m_fFallSpeed = 0;  // clear fall speed if we can't fall any further

		return false;
	}

	// we're falling, so apply the fall speed and increase the fall speed over time
	m_fFallSpeed -= sv_gravity.GetFloat() * 1.5f * deltatime;

	Vector vecGravityTarget = vecSrc;
	vecGravityTarget.z += m_fFallSpeed * deltatime;

	// do a trace to the floor
	Ray_t ray2;
	trace_t trace2;
	CTraceFilterSimple traceFilter2(this, GetCollisionGroup() );
	ray2.Init( vecSrc, vecGravityTarget, GetHullMins(), GetHullMaxs() );
	enginetrace->TraceRay( ray2, MASK_NPCSOLID, &traceFilter2, &trace2 );

	if (trace2.fraction > 0 && fabs(trace2.endpos.z - vecSrc.z) > 1) // if we moved up/down
	{
		vecSrc = trace2.endpos;
		return true;
	}
	m_fFallSpeed = 0;  // clear fall speed if we can't fall any further
	return false;
}
Example #2
0
// make this alien jump off the head of the ent he's standing on
bool CASW_Alien_Jumper::DoJumpOffHead()
{
	//Too soon to try to jump
	if ( m_flJumpTime > gpGlobals->curtime )
		return false;

	if (!(GetGroundEntity()) || GetNavType() == NAV_JUMP )
		return false;

	// force this drone to have jumping capabilities
	m_bDisableJump = false;
	CapabilitiesAdd( bits_CAP_MOVE_JUMP );

	//Vector vecDest = RandomVector(-1, 1);
	//vecDest.z = 0;
	//vecDest *= random->RandomFloat(30, 100);
	Vector vecDest;
	AngleVectors(GetAbsAngles(), &vecDest);
	vecDest *= 200.0f;
	vecDest += GetAbsOrigin();

	// Try the jump
	AIMoveTrace_t moveTrace;
	GetMoveProbe()->MoveLimit( NAV_JUMP, GetAbsOrigin(), vecDest, MASK_NPCSOLID, NULL, &moveTrace );

	//See if it succeeded
	if ( IsMoveBlocked( moveTrace.fStatus ) )
	{
		if ( asw_debug_aliens.GetInt() == 2 )
		{
			NDebugOverlay::Box( vecDest, GetHullMins(), GetHullMaxs(), 255, 0, 0, 0, 5 );
			NDebugOverlay::Line( GetAbsOrigin(), vecDest, 255, 0, 0, 0, 5 );
		}

		m_flJumpTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f );
		return false;
	}

	if ( asw_debug_aliens.GetInt() == 2 )
	{
		NDebugOverlay::Box( vecDest, GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 5 );
		NDebugOverlay::Line( GetAbsOrigin(), vecDest, 0, 255, 0, 0, 5 );
	}

	//Save this jump in case the next time fails	
	m_vecSavedJump = moveTrace.vJumpVelocity;
	m_vecLastJumpAttempt = vecDest;
	SetSchedule(SCHED_ASW_ALIEN_JUMP);
	m_bForcedStuckJump = true;

	return true;
}
void CNPC_SO_BaseZombie::ForceMove( const Vector &targetPos, const Vector &traceDir, bool bRun ) 
{
	// Make sure our zombie gets the message (sometimes it is stubborn)
	// This bit should force our zombie to listen to us
	SetEnemy( NULL );
	SetSchedule( SCHED_ZOMBIE_AMBUSH_MODE );

	Vector chasePosition = targetPos;

	Vector vUpBit = chasePosition;
	vUpBit.z += 1;

	trace_t tr;
	AI_TraceHull( chasePosition, vUpBit, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );

	m_vecLastPosition = chasePosition;

	if ( m_hCine != NULL )
		ExitScriptedSequence();

	SetCondition( COND_RECEIVED_ORDERS );

	if ( bRun )
		SetSchedule( SCHED_FORCED_GO_RUN );
	else
		SetSchedule( SCHED_FORCED_GO );

	m_flMoveWaitFinished = gpGlobals->curtime;
}
Example #4
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : flDot - 
//			flDist - 
// Output : int CNPC_Assassin::RangeAttack1Conditions
//-----------------------------------------------------------------------------
int CNPC_Assassin::RangeAttack2Conditions ( float flDot, float flDist )
{
	if ( m_flNextLungeTime > gpGlobals->curtime )
		return 0;

	float lungeRange = GetSequenceMoveDist( SelectWeightedSequence( (Activity) ACT_ASSASSIN_FLIP_FORWARD ) );

	if ( flDist < lungeRange * 0.25f )
		return COND_TOO_CLOSE_TO_ATTACK;

	if ( flDist > lungeRange * 1.5f )
		return COND_TOO_FAR_TO_ATTACK;

	if ( flDot < 0.75f )
		return COND_NOT_FACING_ATTACK;

	if ( GetEnemy() == NULL )
		return 0;

	// Check for a clear path
	trace_t	tr;
	UTIL_TraceHull( GetAbsOrigin(), GetEnemy()->GetAbsOrigin(), GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );
	
	if ( tr.fraction == 1.0f || tr.m_pEnt == GetEnemy() )
		return COND_CAN_RANGE_ATTACK2;

	return 0;
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pTargetEnt - 
//			vecDir - 
//			flDistance - 
//			flInterval - 
//-----------------------------------------------------------------------------
void CNPC_Ichthyosaur::MoveFlyExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flDistance, float flInterval )
{
	IchthyosaurMoveType_t eMoveType = ( GetNavigator()->CurWaypointIsGoal() ) ? ICH_MOVETYPE_ARRIVE : ICH_MOVETYPE_SEEK;

	m_flGroundSpeed = GetGroundSpeed();

	Vector	moveGoal = GetNavigator()->GetCurWaypointPos();

	//See if we can move directly to our goal
	if ( ( GetEnemy() != NULL ) && ( GetNavigator()->GetGoalTarget() == (CBaseEntity *) GetEnemy() ) )
	{
		trace_t	tr;
		Vector	goalPos = GetEnemy()->GetAbsOrigin() + ( GetEnemy()->GetSmoothedVelocity() * 0.5f );

		AI_TraceHull( GetAbsOrigin(), goalPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, GetEnemy(), COLLISION_GROUP_NONE, &tr );

		if ( tr.fraction == 1.0f )
		{
			moveGoal = tr.endpos;
		}
	}

	//Move
	DoMovement( flInterval, moveGoal, eMoveType );

	//Save the info from that run
	m_vecLastMoveTarget	= moveGoal;
	m_bHasMoveTarget	= true;
}
Example #6
0
bool CASW_Alien_Jumper::DoJumpTo(Vector &vecDest)
{	
	//Too soon to try to jump
	if ( m_flJumpTime > gpGlobals->curtime )
		return false;

	// only jump if you're on the ground
  	if (!(GetFlags() & FL_ONGROUND) || GetNavType() == NAV_JUMP )
		return false;

	// Don't jump if I'm not allowed
	if ( ( CapabilitiesGet() & bits_CAP_MOVE_JUMP ) == false )
		return false;

	// Try the jump
	AIMoveTrace_t moveTrace;
	GetMoveProbe()->MoveLimit( NAV_JUMP, GetAbsOrigin(), vecDest, MASK_NPCSOLID, NULL, &moveTrace );

	//See if it succeeded
	if ( IsMoveBlocked( moveTrace.fStatus ) )
	{
		if ( asw_debug_aliens.GetInt() == 2 )
		{
			NDebugOverlay::Box( vecDest, GetHullMins(), GetHullMaxs(), 255, 0, 0, 0, 5 );
			NDebugOverlay::Line( GetAbsOrigin(), vecDest, 255, 0, 0, 0, 5 );
		}

		m_flJumpTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f );
		return false;
	}

	if ( asw_debug_aliens.GetInt() == 2 )
	{
		NDebugOverlay::Box( vecDest, GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 5 );
		NDebugOverlay::Line( GetAbsOrigin(), vecDest, 0, 255, 0, 0, 5 );
	}

	//Save this jump in case the next time fails	
	m_vecSavedJump = moveTrace.vJumpVelocity;
	m_vecLastJumpAttempt = vecDest;
	SetSchedule(SCHED_ASW_ALIEN_JUMP);
	m_bForcedStuckJump = true;

	//Msg("Drone saving jump vec %f %f %f\n", m_vecSavedJump.x, m_vecSavedJump.y, m_vecSavedJump.z);

	return true;
}
Example #7
0
int CASW_Parasite::RangeAttack1Conditions( float flDot, float flDist )
{
	if ( gpGlobals->curtime < m_flNextAttack )
		return 0;

	if ( ( GetFlags() & FL_ONGROUND ) == false )
		return 0;

	// This code stops lots of headcrabs swarming you and blocking you
	// whilst jumping up and down in your face over and over. It forces
	// them to back up a bit. If this causes problems, consider using it
	// for the fast headcrabs only, rather than just removing it.(sjb)
	if ( flDist < ASW_PARASITE_MIN_JUMP_DIST )
		return COND_TOO_CLOSE_TO_ATTACK;

	if ( flDist > ASW_PARASITE_MAX_JUMP_DIST )
		return COND_TOO_FAR_TO_ATTACK;

	// Make sure the way is clear!
	CBaseEntity *pEnemy = GetEnemy();
	if( pEnemy )
	{
		bool bEnemyIsBullseye = ( dynamic_cast<CNPC_Bullseye *>(pEnemy) != NULL );

		trace_t tr;
		AI_TraceLine( EyePosition(), pEnemy->EyePosition(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );

		if ( tr.m_pEnt != GetEnemy() )
		{
			if ( !bEnemyIsBullseye || tr.m_pEnt != NULL )
				return COND_NONE;
		}

		if( GetEnemy()->EyePosition().z - 36.0f > GetAbsOrigin().z )
		{
			// Only run this test if trying to jump at a player who is higher up than me, else this 
			// code will always prevent a headcrab from jumping down at an enemy, and sometimes prevent it
			// jumping just slightly up at an enemy.
			Vector vStartHullTrace = GetAbsOrigin();
			vStartHullTrace.z += 1.0;

			Vector vEndHullTrace = GetEnemy()->EyePosition() - GetAbsOrigin();
			vEndHullTrace.NormalizeInPlace();
			vEndHullTrace *= 8.0;
			vEndHullTrace += GetAbsOrigin();

			AI_TraceHull( vStartHullTrace, vEndHullTrace,GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, GetCollisionGroup(), &tr );

			if ( tr.m_pEnt != NULL && tr.m_pEnt != GetEnemy() )
			{
				return COND_TOO_CLOSE_TO_ATTACK;
			}
		}
	}

	return COND_CAN_RANGE_ATTACK1;
}
//-----------------------------------------------------------------------------
// Purpose: 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CNPC_Ichthyosaur::Beached( void )
{
	trace_t	tr;
	Vector	testPos;

	testPos = GetAbsOrigin() - Vector( 0, 0, ICH_DEPTH_PREFERENCE );
	
	AI_TraceHull( GetAbsOrigin(), testPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );

	return ( tr.fraction < 1.0f );
}
Example #9
0
bool CASW_Simple_Alien::TryMove(const Vector &vecSrc, Vector &vecTarget, float deltatime, bool bStepMove)
{
	// do a trace to the dest
	Ray_t ray;
	trace_t trace;
	CTraceFilterSimple traceFilter(this, GetCollisionGroup() );
	ray.Init( vecSrc, vecTarget, GetHullMins(), GetHullMaxs() );
	enginetrace->TraceRay( ray, MASK_NPCSOLID, &traceFilter, &trace );
	if (trace.startsolid)
	{
		// doh, we're stuck in something!
		//  todo: move us to a safe spot? wait for push out phys props?
		if (asw_debug_simple_alien.GetBool())
			Msg("CASW_Simple_Alien stuck!\n");
		m_MoveFailure.trace = trace;
		m_MoveFailure.vecStartPos = vecSrc;
		m_MoveFailure.vecTargetPos = vecTarget;
		return false;
	}
	if (trace.fraction < 0.1f)	 // barely/didn't move
	{
		// try and do a 'stepped up' move to the target
		if (!bStepMove)
		{
			Vector vecStepSrc = vecSrc;
			vecStepSrc.z += 24;
			Vector vecStepTarget = vecTarget;
			vecTarget.z += 24;
			if (TryMove(vecStepSrc, vecStepTarget, deltatime, true))
			{
				vecTarget = vecStepTarget;
				return true;
			}
		}

		m_MoveFailure.trace = trace;
		m_MoveFailure.vecStartPos = vecSrc;
		m_MoveFailure.vecTargetPos = vecTarget;

		return false;
	}
	else if (trace.fraction < 1)  // we hit something early, but we did move
	{
		// we hit something early
		m_MoveFailure.trace = trace;
		m_MoveFailure.vecStartPos = vecSrc;
		m_MoveFailure.vecTargetPos = vecTarget;

		vecTarget = trace.endpos;		
	}

	return true;
}
Example #10
0
//-----------------------------------------------------------------------------
// Purpose: Plays the engine sound.
//-----------------------------------------------------------------------------
void CNPC_Houndeye::NPCThink(void)
{
	if (m_pEnergyWave)
	{
		if (gpGlobals->curtime > m_flEndEnergyWaveTime)
		{
			UTIL_Remove(m_pEnergyWave);
			m_pEnergyWave = NULL;
		}
	}

	// -----------------------------------------------------
	//  Update collision group
	//		While I'm running I'm allowed to penetrate
	//		other houndeyes
	// -----------------------------------------------------
	Vector vVelocity;
	GetVelocity( &vVelocity, NULL );
	if (vVelocity.Length() > 10)
	{
		SetCollisionGroup( HL2COLLISION_GROUP_HOUNDEYE );
	}
	else 
	{
		// Don't go solid if resting in another houndeye 
		trace_t tr;
		AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,1), 
						GetHullMins(), GetHullMaxs(),
						MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );
		if (!tr.startsolid)
		{
			SetCollisionGroup( COLLISION_GROUP_NONE );
		}
		else
		{
			SetCollisionGroup( HL2COLLISION_GROUP_HOUNDEYE );
		}
	}
/*
	if (GetCollisionGroup() == HL2COLLISION_GROUP_HOUNDEYE)
	{
		NDebugOverlay::Box(GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 0);
	}
	else
	{
		NDebugOverlay::Box(GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 255, 0, 0, 0, 0);
	}
*/
	BaseClass::NPCThink();
}
Example #11
0
// Purpose: Returns true if a reasonable jumping distance
bool CASW_Alien_Jumper::IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const
{
	const float MAX_JUMP_RISE		= 512;
	//const float MIN_JUMP_RISE		= 16;
	const float MAX_JUMP_DROP		= 512;
	const float MAX_JUMP_DISTANCE	= 1024;
	const float MIN_JUMP_DISTANCE   = 128;	

	// make sure we don't do really flat jumps
	//float fHeight = (apex.z - startPos.z);
	//Msg("checking legality of jump with height %f\n", fHeight);
	//if ((apex.z - startPos.z) < 10 || fHeight != 0) 
		//return false;
	
	//Adrian: Don't try to jump if my destination is right next to me.
	if ( ( endPos - GetAbsOrigin()).Length() < MIN_JUMP_DISTANCE ) 
		 return false;

	if ( HasSpawnFlags( SF_ANTLION_USE_GROUNDCHECKS ) && asw_test_new_alien_jump.GetBool() == true )
	{
		trace_t	tr;
		AI_TraceHull( endPos, endPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );
		
		if ( tr.m_pEnt )
		{
			CAI_BaseNPC *pBlocker = tr.m_pEnt->MyNPCPointer();

			if ( pBlocker && pBlocker->Classify() == CLASS_ASW_DRONE )
			{
				// HACKHACK	- push other jumpers out of the way
				CASW_Alien_Jumper *pJumper = dynamic_cast< CASW_Alien_Jumper * > ( pBlocker );

				if ( pJumper )
				{
					if ( pJumper->AllowedToBePushed() == true )
					{
					//	NDebugOverlay::Line( GetAbsOrigin(), endPos, 255, 0, 0, 0, 2 );
					//	NDebugOverlay::Box( pAntlion->GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0, 0, 255, 0, 2 );
						pJumper->GetMotor()->SetIdealYawToTarget( endPos );
						pJumper->SetSchedule( SCHED_MOVE_AWAY );
						pJumper->m_flNextJumpPushTime = gpGlobals->curtime + 2.0f;
					}
				}
			}
		}
	}

	return BaseClass::IsJumpLegal( startPos, apex, endPos, MAX_JUMP_RISE, MAX_JUMP_DROP, MAX_JUMP_DISTANCE );
}
//------------------------------------------------------------------------------
// Purpose :  Is cover node valid
// Input   :
// Output  :
//------------------------------------------------------------------------------
bool CAI_BaseNPC::IsValidCover( const Vector &vecCoverLocation, CAI_Hint const *pHint )
{
	// firstly, limit choices to hint groups
	string_t iszHint = GetHintGroup();
	char *pszHint = (char *)STRING(iszHint);
	if ((iszHint != NULL_STRING) && (pszHint[0] != '\0'))
	{
		if (!pHint || pHint->GetGroup() != GetHintGroup())
		{
			return false;
		}
	}

	/*
	// If I'm in a squad don't pick cover node it other squad member
	// is already nearby
	if (m_pSquad)
	{
		return m_pSquad->IsValidCover( vecCoverLocation, pHint );
	}
	*/
	
	// UNDONE: Do we really need this test?
	// ----------------------------------------------------------------
	// Make sure my hull can fit at this node before accepting it. 
	// Could be another NPC there or it could be blocked
	// ----------------------------------------------------------------
	// FIXME: shouldn't this see that if I crouch behind it it'll be safe?
	Vector startPos = vecCoverLocation;
	startPos.z -= GetHullMins().z;  // Move hull bottom up to node
	Vector endPos	= startPos;
	endPos.z += 0.01;
	trace_t tr;
	AI_TraceEntity( this, vecCoverLocation, endPos, MASK_NPCSOLID, &tr );
	if (tr.startsolid)
	{
		return false;
	}

	return true;
}
Example #13
0
//-----------------------------------------------------------------------------
// Purpose: Looks ahead to see if we are going to hit something. If we are, a
//			recommended avoidance path is returned.
// Input  : vecMoveDir - 
//			flSpeed - 
//			vecDeflect - 
// Output : Returns true if we hit something and need to deflect our course,
//			false if all is well.
//-----------------------------------------------------------------------------
bool CNPC_Crow::Probe( const Vector &vecMoveDir, float flSpeed, Vector &vecDeflect )
{
	//
	// Look 1/2 second ahead.
	//
	trace_t tr;
	AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + vecMoveDir * flSpeed, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, HL2COLLISION_GROUP_CROW, &tr );
	if ( tr.fraction < 1.0f )
	{
		//
		// If we hit something, deflect flight path parallel to surface hit.
		//
		Vector vecUp;
		CrossProduct( vecMoveDir, tr.plane.normal, vecUp );
		CrossProduct( tr.plane.normal, vecUp, vecDeflect );
		VectorNormalize( vecDeflect );
		return true;
	}

	vecDeflect = vec3_origin;
	return false;
}
Example #14
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  :
// Output :
//-----------------------------------------------------------------------------
int CNPC_Houndeye::RangeAttack1Conditions ( float flDot, float flDist )
{
	// I'm not allowed to attack if standing in another hound eye 
	// (note houndeyes allowed to interpenetrate)
	trace_t tr;
	AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,0.1), 
					GetHullMins(), GetHullMaxs(),
					MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );
	if (tr.startsolid)
	{
		CBaseEntity *pEntity = tr.m_pEnt;
		if (pEntity->Classify() == CLASS_HOUNDEYE)
		{
			return( COND_NONE );
		}
	}

	// If I'm really close to my enemy allow me to attack if 
	// I'm facing regardless of next attack time
	if (flDist < 100 && flDot >= 0.3)
	{
		return COND_CAN_RANGE_ATTACK1;
	}
	if ( gpGlobals->curtime < m_flNextAttack )
	{
		return( COND_NONE );
	}
	if (flDist > ( HOUNDEYE_MAX_ATTACK_RADIUS * 0.5 ))
	{
		return COND_TOO_FAR_TO_ATTACK;
	}
	if (flDot < 0.3)
	{
		return COND_NOT_FACING_ATTACK;
	}
	return COND_CAN_RANGE_ATTACK1;
}
Example #15
0
//-----------------------------------------------------------------------------
// Purpose: 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CASW_Alien_Jumper::ShouldJump( void )
{
	if ( GetEnemy() == NULL )
		return false;

	// don't jump if we're stunned
	if (m_bElectroStunned)
		return false;

	//Too soon to try to jump
	if ( m_flJumpTime > gpGlobals->curtime )
		return false;

	// only jump if you're on the ground
  	if (!(GetFlags() & FL_ONGROUND) || GetNavType() == NAV_JUMP )
		return false;

	// Don't jump if I'm not allowed
	if ( ( CapabilitiesGet() & bits_CAP_MOVE_JUMP ) == false )
		return false;

	Vector vEnemyForward, vForward;

	GetEnemy()->GetVectors( &vEnemyForward, NULL, NULL );
	GetVectors( &vForward, NULL, NULL );

	float flDot = DotProduct( vForward, vEnemyForward );

	if ( flDot < 0.5f )
		 flDot = 0.5f;

	Vector vecPredictedPos;

	//Get our likely position in two seconds
	UTIL_PredictedPosition( GetEnemy(), flDot * 2.5f, &vecPredictedPos );

	// Don't jump if we're already near the target
	if ( ( GetAbsOrigin() - vecPredictedPos ).LengthSqr() < (512*512) )
		return false;

	//Don't retest if the target hasn't moved enough
	//FIXME: Check your own distance from last attempt as well
	if ( ( ( m_vecLastJumpAttempt - vecPredictedPos ).LengthSqr() ) < (128*128) )
	{
		m_flJumpTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f );		
		return false;
	}

	Vector	targetDir = ( vecPredictedPos - GetAbsOrigin() );

	float flDist = VectorNormalize( targetDir );

	// don't jump at target it it's very close
	if (flDist < ANTLION_JUMP_MIN)
		return false;

	Vector	targetPos = vecPredictedPos + ( targetDir * (GetHullWidth()*4.0f) );

	// Try the jump
	AIMoveTrace_t moveTrace;
	GetMoveProbe()->MoveLimit( NAV_JUMP, GetAbsOrigin(), targetPos, MASK_NPCSOLID, GetNavTargetEntity(), &moveTrace );

	//See if it succeeded
	if ( IsMoveBlocked( moveTrace.fStatus ) )
	{
		if ( asw_debug_aliens.GetInt() == 2 )
		{
			NDebugOverlay::Box( targetPos, GetHullMins(), GetHullMaxs(), 255, 0, 0, 0, 5 );
			NDebugOverlay::Line( GetAbsOrigin(), targetPos, 255, 0, 0, 0, 5 );
		}

		m_flJumpTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f );
		return false;
	}

	if ( asw_debug_aliens.GetInt() == 2 )
	{
		NDebugOverlay::Box( targetPos, GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 5 );
		NDebugOverlay::Line( GetAbsOrigin(), targetPos, 0, 255, 0, 0, 5 );
	}

	//Save this jump in case the next time fails
	m_vecSavedJump = moveTrace.vJumpVelocity;
	m_vecLastJumpAttempt = targetPos;

	return true;
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &Steer - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CNPC_Ichthyosaur::SteerAvoidObstacles(Vector &Steer, const Vector &Velocity, const Vector &Forward, const Vector &Right, const Vector &Up)
{
	trace_t	tr;

	bool	collided = false;
	Vector	dir = Velocity;
	float	speed = VectorNormalize( dir );

	//Look ahead one second and avoid whatever is in our way.
	AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + (dir*speed), GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );

	Vector	forward;

	GetVectors( &forward, NULL, NULL );

	//If we're hitting our enemy, just continue on
	if ( ( GetEnemy() != NULL ) && ( tr.m_pEnt == GetEnemy() ) )
		return false;

	if ( tr.fraction < 1.0f )
	{
		CBaseEntity *pBlocker = tr.m_pEnt;
		
		if ( ( pBlocker != NULL ) && ( pBlocker->MyNPCPointer() != NULL ) )
		{
			DevMsg( 2, "Avoiding an NPC\n" );

			Vector HitOffset = tr.endpos - GetAbsOrigin();

			Vector SteerUp = CrossProduct( HitOffset, Velocity );
			Steer = CrossProduct(  SteerUp, Velocity  );
			VectorNormalize( Steer );

			/*Vector probeDir = tr.endpos - GetAbsOrigin();
			Vector normalToProbeAndWallNormal = probeDir.Cross( tr.plane.normal );
			
			Steer = normalToProbeAndWallNormal.Cross( probeDir );
			VectorNormalize( Steer );*/

			if ( tr.fraction > 0 )
			{
				Steer = (Steer * Velocity.Length()) / tr.fraction;
				//NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f );
			}
			else
			{
				Steer = (Steer * 1000 * Velocity.Length());
				//NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f );
			}
		}
		else
		{
			if ( ( pBlocker != NULL ) && ( pBlocker == GetEnemy() ) )
			{
				DevMsg( "Avoided collision\n" );
				return false;
			}

			DevMsg( 2, "Avoiding the world\n" );
			
			Vector	steeringVector = tr.plane.normal;

			if ( tr.fraction == 0.0f )
				return false;

			Steer = steeringVector * ( Velocity.Length() / tr.fraction );
			
			//NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f );
		}

		//return true;
		collided = true;
	}

	//Try to remain 8 feet above the ground.
	AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -ICH_HEIGHT_PREFERENCE), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );

	if ( tr.fraction < 1.0f )
	{
		Steer += Vector( 0, 0, m_vecAccelerationMax.z / tr.fraction );
		collided = true;
	}
	
	//Stay under the surface
	if ( m_bIgnoreSurface == false )
	{
		float waterLevel = ( UTIL_WaterLevel( GetAbsOrigin(), GetAbsOrigin().z, GetAbsOrigin().z+ICH_DEPTH_PREFERENCE ) - GetAbsOrigin().z ) / ICH_DEPTH_PREFERENCE;

		if ( waterLevel < 1.0f )
		{
			Steer += -Vector( 0, 0, m_vecAccelerationMax.z / waterLevel );
			collided = true;
		}
	}

	return collided;
}
Vector CNPC_Ichthyosaur::DoProbe( const Vector &probe )
{
	trace_t	tr;
	float	fraction = 1.0f;
	bool	collided = false;
	Vector	normal	 = Vector( 0, 0, -1 );

	float	waterLevel = UTIL_WaterLevel( GetAbsOrigin(), GetAbsOrigin().z, GetAbsOrigin().z+150 );

	waterLevel -= GetAbsOrigin().z;
	waterLevel /= 150;

	if ( waterLevel < 1.0f )
	{
		collided = true;
		fraction = waterLevel;
	}

	AI_TraceHull( GetAbsOrigin(), probe, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );
	
	if ( ( collided == false ) || ( tr.fraction < fraction ) )
	{
		fraction	= tr.fraction;
		normal		= tr.plane.normal;
	}

	if ( ( fraction < 1.0f ) && ( GetEnemy() == NULL || tr.u.ent != GetEnemy()->pev ) )
	{
#if FEELER_COLLISION_VISUALIZE
		NDebugOverlay::Line( GetLocalOrigin(), probe, 255, 0, 0, false, 0.1f );
#endif
		
		Vector	probeDir = probe - GetLocalOrigin();

		Vector	normalToProbeAndWallNormal = probeDir.Cross( normal );
		Vector	steeringVector = normalToProbeAndWallNormal.Cross( probeDir );

		Vector	velDir = GetAbsVelocity();
		VectorNormalize( velDir );

		float	steeringForce = m_flGroundSpeed * ( 1.0f - fraction ) * normal.Dot( velDir );

		if ( steeringForce < 0.0f )
		{
			steeringForce = -steeringForce;
		}

		velDir = steeringVector;
		VectorNormalize( velDir );

		steeringVector = steeringForce * velDir;
		
		return steeringVector;
	}

#if FEELER_COLLISION_VISUALIZE
	NDebugOverlay::Line( GetLocalOrigin(), probe, 0, 255, 0, false, 0.1f );
#endif

	return Vector( 0.0f, 0.0f, 0.0f );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_Ichthyosaur::PrescheduleThink( void )
{
	BaseClass::PrescheduleThink();
	
	//Ambient sounds
	/*
	if ( random->RandomInt( 0, 20 ) == 10 )
	{
		if ( random->RandomInt( 0, 1 ) )
		{
			ENVELOPE_CONTROLLER.SoundChangeVolume( m_pSwimSound, random->RandomFloat( 0.0f, 0.5f ), 1.0f );
		}
		else
		{
			ENVELOPE_CONTROLLER.SoundChangeVolume( m_pVoiceSound, random->RandomFloat( 0.0f, 0.5f ), 1.0f );
		}
	}
	*/

	//Pings
	if ( m_flNextPingTime < gpGlobals->curtime )
	{
		m_flNextPingTime = gpGlobals->curtime + random->RandomFloat( 3.0f, 8.0f );
	}
	
	//Growls
	if ( ( m_NPCState == NPC_STATE_COMBAT || m_NPCState == NPC_STATE_ALERT ) && ( m_flNextGrowlTime < gpGlobals->curtime ) )
	{
		m_flNextGrowlTime = gpGlobals->curtime + random->RandomFloat( 2.0f, 6.0f );
	}

	//Randomly emit bubbles
	if ( random->RandomInt( 0, 10 ) == 0 )
	{
		UTIL_Bubbles( GetAbsOrigin()+(GetHullMins()*0.5f), GetAbsOrigin()+(GetHullMaxs()*0.5f), 1 );
	}

	//Check our water level
	if ( GetWaterLevel() != 3 )
	{
		if ( GetWaterLevel() < 2 )
		{
			DevMsg( 2, "Came out of water\n" );
			
			if ( Beached() )
			{
				SetSchedule( SCHED_ICH_THRASH );

				Vector vecNewVelocity = GetAbsVelocity();
				vecNewVelocity[2] = 8.0f;
				SetAbsVelocity( vecNewVelocity );
			}
		}
		else
		{
			//TODO: Wake effects
		}
	}

	//If we have a victim, update them
	if ( m_pVictim != NULL )
	{
		//See if it's time to release the victim
		if ( m_flHoldTime < gpGlobals->curtime )
		{
			ReleaseVictim();
			return;
		}

		Bite();
	}
}
Example #19
0
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//
// Returns number of events handled, 0 if none.
//=========================================================
void CNPC_Vortigaunt::HandleAnimEvent( animevent_t *pEvent )
{
    // ALERT( at_console, "event %d : %f\n", pEvent->event, pev->frame );
    switch( pEvent->event )
    {
    case ISLAVE_AE_CLAW:
    {
        // SOUND HERE!
        CBaseEntity *pHurt = CheckTraceHullAttack( 40, Vector(-10,-10,-10), Vector(10,10,10), sk_islave_dmg_claw.GetFloat(), DMG_SLASH );
        CPASAttenuationFilter filter( this );
        if ( pHurt )
        {
            if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) )
                pHurt->ViewPunch( QAngle( 5, 0, -18 ) );

            // Play a random attack hit sound
            enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, pAttackHitSounds[ random->RandomInt(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, m_iVoicePitch );
        }
        else
            // Play a random attack miss sound
            enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, pAttackMissSounds[ random->RandomInt(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, m_iVoicePitch );
    }
    break;

    case ISLAVE_AE_CLAWRAKE:
    {
        CBaseEntity *pHurt = CheckTraceHullAttack( 40, Vector(-10,-10,-10), Vector(10,10,10), sk_islave_dmg_clawrake.GetFloat(), DMG_SLASH );
        CPASAttenuationFilter filter2( this );
        if ( pHurt )
        {
            if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) )
                pHurt->ViewPunch( QAngle( 5, 0, 18 ) );

            enginesound->EmitSound( filter2, entindex(), CHAN_WEAPON, pAttackHitSounds[ random->RandomInt(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, m_iVoicePitch );
        }
        else
            enginesound->EmitSound( filter2, entindex(), CHAN_WEAPON, pAttackMissSounds[ random->RandomInt(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, m_iVoicePitch );
    }
    break;

    case ISLAVE_AE_ZAP_POWERUP:
    {
        // speed up attack when on hard
        if ( g_iSkillLevel == SKILL_HARD )
            m_flPlaybackRate = 1.5;

        Vector v_forward;
        GetVectors( &v_forward, NULL, NULL );

        CBroadcastRecipientFilter filter;
        te->DynamicLight( filter, 0.0, &GetAbsOrigin(), 125, 200, 100, 2, 120, 0.2 / m_flPlaybackRate, 0 );

        if ( m_hDead != NULL )
        {
            WackBeam( -1, m_hDead );
            WackBeam( 1, m_hDead );
        }
        else
        {
            ArmBeam( -1 );
            ArmBeam( 1 );
            BeamGlow( );
        }

        CPASAttenuationFilter filter3( this );
        enginesound->EmitSound( filter3, entindex(), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0, 100 + m_iBeams * 10 );

// Huh?  Model doesn't have multiple texturegroups, commented this out.  -LH
//			m_nSkin = m_iBeams / 2;
    }
    break;

    case ISLAVE_AE_ZAP_SHOOT:
    {
        ClearBeams( );

        if ( m_hDead != NULL )
        {
            Vector vecDest = m_hDead->GetAbsOrigin() + Vector( 0, 0, 38 );
            trace_t trace;
            UTIL_TraceHull( vecDest, vecDest, GetHullMins(), GetHullMaxs(),MASK_SOLID, m_hDead, COLLISION_GROUP_NONE, &trace );

            if ( !trace.startsolid )
            {
                CBaseEntity *pNew = Create( "monster_alien_slave", m_hDead->GetAbsOrigin(), m_hDead->GetAbsAngles() );

                pNew->AddSpawnFlags( 1 );
                WackBeam( -1, pNew );
                WackBeam( 1, pNew );
                UTIL_Remove( m_hDead );
                break;
            }
        }

        ClearMultiDamage();

        ZapBeam( -1 );
        ZapBeam( 1 );

        CPASAttenuationFilter filter4( this );
        enginesound->EmitSound( filter4, entindex(), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, random->RandomInt( 130, 160 ) );
        ApplyMultiDamage();

        m_flNextAttack = gpGlobals->curtime + random->RandomFloat( 0.5, 4.0 );
    }
    break;

    case ISLAVE_AE_ZAP_DONE:
    {
        ClearBeams();
    }
    break;

    default:
        BaseClass::HandleAnimEvent( pEvent );
        break;
    }
}
Example #20
0
//=========================================================
// SelectSchedule
//=========================================================
int CNPC_Houndeye::SelectSchedule( void )
{
	switch	( m_NPCState )
	{
	case NPC_STATE_IDLE:
	case NPC_STATE_ALERT:
		{
			if ( HasCondition(COND_LIGHT_DAMAGE) ||
				 HasCondition(COND_HEAVY_DAMAGE) )
			{
				return SCHED_TAKE_COVER_FROM_ORIGIN;
			}
			break;
		}
	case NPC_STATE_COMBAT:
		{
			// dead enemy

			if ( HasCondition( COND_ENEMY_DEAD ) )
			{
				// call base class, all code to handle dead enemies is centralized there.
				return BaseClass::SelectSchedule();
			}

			// If a group attack was requested attack even if attack conditions not met
			if ( HasCondition( COND_HOUND_GROUP_ATTACK ))
			{
				// Check that I'm not standing in another hound eye 
				// before attacking
				trace_t tr;
				AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,1), 
								GetHullMins(), GetHullMaxs(),
								MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );
				if (!tr.startsolid)
				{
					return SCHED_HOUND_GROUP_ATTACK;
				}

				// Otherwise attack as soon as I can
				else
				{
					m_flNextAttack = gpGlobals->curtime;
					SCHED_HOUND_ATTACK_STRAFE;
				}
			}

			// If a group retread was requested 
			if ( HasCondition( COND_HOUND_GROUP_RETREAT ))
			{
				return SCHED_HOUND_GROUP_RETREAT;
			}

			if ( HasCondition( COND_LIGHT_DAMAGE ) | 
				 HasCondition( COND_HEAVY_DAMAGE ) )
			{
				if ( random->RandomFloat( 0 , 1 ) <= 0.4 )
				{
					trace_t tr;
					Vector forward;
					AngleVectors( GetAbsAngles(), &forward );
					AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + forward * -128, 
						GetHullMins(), GetHullMaxs(),
						MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );

					if ( tr.fraction == 1.0 )
					{
						// it's clear behind, so the hound will jump
						return SCHED_HOUND_HOP_RETREAT;
					}
				}

				return SCHED_TAKE_COVER_FROM_ENEMY;
			}

			// If a group rally was requested 
			if ( HasCondition( COND_HOUND_GROUP_RALLEY ))
			{
				return SCHED_HOUND_GROUP_RALLEY;
			}

			if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) )
			{
				if (m_pSquad && random->RandomInt(0,4) == 0)
				{
					if (!IsAnyoneInSquadAttacking())
					{
						EmitSound( "NPC_Houndeye.GroupAttack" );
						
						m_flSoundWaitTime = gpGlobals->curtime + 1.0;

						m_pSquad->BroadcastInteraction( g_interactionHoundeyeGroupAttack, NULL, this );
						return SCHED_HOUND_GROUP_ATTACK;
					}
				}
				//<<TEMP>>comment
				SetCollisionGroup( COLLISION_GROUP_NONE );
				return SCHED_RANGE_ATTACK1;
			}
			else
			{
				if (m_pSquad && random->RandomInt(0,5) == 0)
				{
					if (!IsAnyoneInSquadAttacking())
					{
						EmitSound( "NPC_Houndeye.GroupFollow" );

						m_flSoundWaitTime = gpGlobals->curtime + 1.0;

						m_pSquad->BroadcastInteraction( g_interactionHoundeyeGroupRalley, NULL, this );
						return SCHED_HOUND_ATTACK_STRAFE;
					}
				}
				return SCHED_HOUND_ATTACK_STRAFE;
			}
			break;
		}
	}

	return BaseClass::SelectSchedule();
}
Example #21
0
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//
// Returns number of events handled, 0 if none.
//=========================================================
void CNPC_AlienGrunt::HandleAnimEvent( animevent_t *pEvent )
{
	switch( pEvent->event )
	{
	case AGRUNT_AE_HORNET1:
	case AGRUNT_AE_HORNET2:
	case AGRUNT_AE_HORNET3:
	case AGRUNT_AE_HORNET4:
	case AGRUNT_AE_HORNET5:
		{
			// m_vecEnemyLKP should be center of enemy body
			Vector vecArmPos;
			QAngle angArmDir;
			Vector vecDirToEnemy;
			QAngle angDir;

			if (HasCondition( COND_SEE_ENEMY) && GetEnemy())
			{
				Vector vecEnemyLKP = GetEnemy()->GetAbsOrigin();

				vecDirToEnemy = ( ( vecEnemyLKP ) - GetAbsOrigin() );
				VectorAngles( vecDirToEnemy, angDir );
				VectorNormalize( vecDirToEnemy );
			}
			else
			{
				angDir = GetAbsAngles();
				angDir.x = -angDir.x;

				Vector vForward;
				AngleVectors( angDir, &vForward );
				vecDirToEnemy = vForward;
			}

			DoMuzzleFlash();

			// make angles +-180
			if (angDir.x > 180)
			{
				angDir.x = angDir.x - 360;
			}

		//	SetBlending( 0, angDir.x );
			GetAttachment( "0", vecArmPos, angArmDir );

			vecArmPos = vecArmPos + vecDirToEnemy * 32;
		
			CPVSFilter filter( GetAbsOrigin() );
			te->Sprite( filter, 0.0,
				&vecArmPos, iAgruntMuzzleFlash, random->RandomFloat( 0.4, 0.8 ), 128 );

			CBaseEntity *pHornet = CBaseEntity::Create( "hornet", vecArmPos, QAngle( 0, 0, 0 ), this );

			Vector vForward;
			AngleVectors( angDir, &vForward );
	
			pHornet->SetAbsVelocity( vForward * 300 );
			pHornet->SetOwnerEntity( this );
			
			EmitSound( "Weapon_Hornetgun.Single" );

			CHL1BaseNPC *pHornetMonster = (CHL1BaseNPC *)pHornet->MyNPCPointer();

			if ( pHornetMonster )
			{
				pHornetMonster->SetEnemy( GetEnemy() );
			}
		}
		break;

	case AGRUNT_AE_LEFT_FOOT:
		// left foot
		{
			CPASAttenuationFilter filter2( this );
			EmitSound( filter2, entindex(), "AlienGrunt.LeftFoot" );
		}
		break;
	case AGRUNT_AE_RIGHT_FOOT:
		// right foot
		{
			CPASAttenuationFilter filter3( this );
			EmitSound( filter3, entindex(), "AlienGrunt.RightFoot" );
		}
		break;

	case AGRUNT_AE_LEFT_PUNCH:
		{
			Vector vecMins = GetHullMins();
			Vector vecMaxs = GetHullMaxs();
			vecMins.z = vecMins.x;
			vecMaxs.z = vecMaxs.x;

			CBaseEntity *pHurt = CheckTraceHullAttack( AGRUNT_MELEE_DIST, vecMins, vecMaxs, sk_agrunt_dmg_punch.GetFloat(), DMG_CLUB );
			CPASAttenuationFilter filter4( this );
			
			if ( pHurt )
			{
				if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) )
					 pHurt->ViewPunch( QAngle( -25, 8, 0) );

				Vector vRight;
				AngleVectors( GetAbsAngles(), NULL, &vRight, NULL );

				// OK to use gpGlobals without calling MakeVectors, cause CheckTraceHullAttack called it above.
				if ( pHurt->IsPlayer() )
				{
					// this is a player. Knock him around.
					pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + vRight * 250 );
				}

				EmitSound(filter4, entindex(), "AlienGrunt.AttackHit" );

				Vector vecArmPos;
				QAngle angArmAng;
				GetAttachment( 0, vecArmPos, angArmAng );
				SpawnBlood(vecArmPos, g_vecAttackDir, pHurt->BloodColor(), 25);// a little surface blood.
			}
			else
			{
				// Play a random attack miss sound
				EmitSound(filter4, entindex(), "AlienGrunt.AttackMiss" );
			}
		}
		break;

	case AGRUNT_AE_RIGHT_PUNCH:
		{
			Vector vecMins = GetHullMins();
			Vector vecMaxs = GetHullMaxs();
			vecMins.z = vecMins.x;
			vecMaxs.z = vecMaxs.x;

			CBaseEntity *pHurt = CheckTraceHullAttack( AGRUNT_MELEE_DIST, vecMins, vecMaxs, sk_agrunt_dmg_punch.GetFloat(), DMG_CLUB );
			CPASAttenuationFilter filter5( this );
				
			if ( pHurt )
			{
				if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) )
					 pHurt->ViewPunch( QAngle( 25, 8, 0) );

				// OK to use gpGlobals without calling MakeVectors, cause CheckTraceHullAttack called it above.
				if ( pHurt->IsPlayer() )
				{
					// this is a player. Knock him around.
					Vector vRight;
					AngleVectors( GetAbsAngles(), NULL, &vRight, NULL );
					pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + vRight * -250 );
				}

				EmitSound( filter5, entindex(), "AlienGrunt.AttackHit" );

				Vector vecArmPos;
				QAngle angArmAng;
				GetAttachment( 0, vecArmPos, angArmAng );
				SpawnBlood(vecArmPos, g_vecAttackDir, pHurt->BloodColor(), 25);// a little surface blood.
			}
			else
			{
				// Play a random attack miss sound
				EmitSound( filter5, entindex(), "AlienGrunt.AttackMiss" );
			}
		}
		break;

	default:
		BaseClass::HandleAnimEvent( pEvent );
		break;
	}
}