//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//
//=============================================================================//
#include	"cbase.h"
#include	"ai_default.h"
#include	"ai_task.h"
#include	"ai_schedule.h"
#include	"ai_node.h"
#include	"ai_hull.h"
#include	"ai_hint.h"
#include	"ai_memory.h"
#include	"ai_route.h"
#include	"ai_motor.h"
#include	"soundent.h"
#include	"game.h"
#include	"npcevent.h"
#include	"entitylist.h"
#include	"activitylist.h"
#include	"hl1_basegrenade.h"
#include	"animation.h"
#include	"IEffects.h"
#include	"vstdlib/random.h"
#include	"engine/IEngineSound.h"
#include	"ammodef.h"
#include	"soundenvelope.h"
#include	"hl1_CBaseHelicopter.h"
#include	"ndebugoverlay.h"
#include	"smoke_trail.h"
#include	"beam_shared.h"
#include	"grenade_homer.h"

#define	 HOMER_TRAIL0_LIFE		0.1
#define	 HOMER_TRAIL1_LIFE		0.2
#define	 HOMER_TRAIL2_LIFE		3.0//	1.0

#define  SF_NOTRANSITION 128

extern short g_sModelIndexFireball;

class CNPC_Apache : public CBaseHelicopter
{
	DECLARE_CLASS( CNPC_Apache, CBaseHelicopter );
public:
	DECLARE_DATADESC();

	void Spawn( void );
	void Precache( void );

	int  BloodColor( void ) { return DONT_BLEED; }
	Class_T  Classify( void ) { return CLASS_HUMAN_MILITARY; };
	void InitializeRotorSound( void );
	void LaunchRocket( Vector &viewDir, int damage, int radius, Vector vecLaunchPoint );

	void Flight( void );

	bool FireGun( void );
	void AimRocketGun( void );
	void FireRocket( void );
	void DyingThink( void );

	int  ObjectCaps( void );
	
	void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );

/*	bool OnInternalDrawModel( ClientModelRenderInfo_t *pInfo )
	{
		BaseClass::OnInteralDrawModel( pInfo );
		Vector origin = GetAbsOrigin();
		origin.z += 32;
		SetAbsOrigin( origin );
	}*/

/*(	void SetAbsOrigin( const Vector& absOrigin )
	{
		((Vector&)absOrigin).z += 32;
		BaseClass::SetAbsOrigin( absOrigin );
	}*/

	

   /* int		Save( CSave &save );
	int		Restore( CRestore &restore );
	static	TYPEDESCRIPTION m_SaveData[];

	void Spawn( void );
	void Precache( void );

	
	void Killed( entvars_t *pevAttacker, int iGib );
	void GibMonster( void );

	void EXPORT HuntThink( void );
	void EXPORT FlyTouch( CBaseEntity *pOther );
	void EXPORT CrashTouch( CBaseEntity *pOther );
	void EXPORT DyingThink( void );
	void EXPORT StartupUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
	void EXPORT NullThink( void );

	void ShowDamage( void );
	void Flight( void );
	void FireRocket( void );
	BOOL FireGun( void );
	
	int  TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
	void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);*/

	int m_iRockets;
	float m_flForce;
	float m_flNextRocket;

	int m_iAmmoType;

	Vector m_vecTarget;
	Vector m_posTarget;

	Vector m_vecDesired;
	Vector m_posDesired;

	Vector m_vecGoal;

	QAngle m_angGun;
	
	int m_iSoundState; // don't save this

	int m_iExplode;
	int m_iBodyGibs;
	int	m_nDebrisModel;

	float m_flGoalSpeed;

	CHandle<SmokeTrail>	m_hSmoke;
	CBeam *m_pBeam;
};

BEGIN_DATADESC( CNPC_Apache )
	DEFINE_FIELD( m_iRockets, FIELD_INTEGER ),
	DEFINE_FIELD( m_flForce, FIELD_FLOAT ),
	DEFINE_FIELD( m_flNextRocket, FIELD_TIME ),
	DEFINE_FIELD( m_vecTarget, FIELD_VECTOR ),
	DEFINE_FIELD( m_posTarget, FIELD_POSITION_VECTOR ),
	DEFINE_FIELD( m_vecDesired, FIELD_VECTOR ),
	DEFINE_FIELD( m_posDesired, FIELD_POSITION_VECTOR ),
	DEFINE_FIELD( m_vecGoal, FIELD_VECTOR ),
	DEFINE_FIELD( m_angGun, FIELD_VECTOR ),
	DEFINE_FIELD( m_flLastSeen, FIELD_TIME ),
	DEFINE_FIELD( m_flPrevSeen, FIELD_TIME ),
//	DEFINE_FIELD( m_iSoundState, FIELD_INTEGER ),
//	DEFINE_FIELD( m_iSpriteTexture, FIELD_INTEGER ),
//	DEFINE_FIELD( m_iExplode, FIELD_INTEGER ),
//	DEFINE_FIELD( m_iBodyGibs, FIELD_INTEGER ),
	DEFINE_FIELD( m_pBeam, FIELD_CLASSPTR ),
	DEFINE_FIELD( m_flGoalSpeed, FIELD_FLOAT ),
	DEFINE_FIELD( m_hSmoke, FIELD_EHANDLE ),
END_DATADESC()

ConVar	sk_apache_health( "sk_apache_health","100");

static Vector s_vecSurroundingMins( -300, -300, -172);
static Vector s_vecSurroundingMaxs(300, 300, 8);


void CNPC_Apache::Spawn( void )
{
	Precache( );
	SetModel( "models/apache.mdl" );

	BaseClass::Spawn();

	AddFlag( FL_NPC );
	SetSolid( SOLID_BBOX );
	SetMoveType( MOVETYPE_STEP );
	AddFlag( FL_FLY );


	m_iHealth			=  sk_apache_health.GetFloat();

	m_flFieldOfView = -0.707; // 270 degrees

	m_fHelicopterFlags	= BITS_HELICOPTER_MISSILE_ON | BITS_HELICOPTER_GUN_ON;

	InitBoneControllers();

	SetRenderColor( 255, 255, 255, 255 );

	m_iRockets = 10;

	Vector mins, maxs;
	ExtractBbox(0, mins, maxs);
	UTIL_SetSize(this, mins, maxs);

	//CollisionProp()->SetSurroundingBoundsType( USE_SPECIFIED_BOUNDS, &s_vecSurroundingMins, &s_vecSurroundingMaxs );
	//AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST );

	m_hSmoke = NULL;
}

LINK_ENTITY_TO_CLASS ( monster_apache, CNPC_Apache );

int CNPC_Apache::ObjectCaps( void ) 
{ 
	if ( GetSpawnFlags() & SF_NOTRANSITION )
	     return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; 
	else 
		 return BaseClass::ObjectCaps();
}

void CNPC_Apache::Precache( void )
{
	// Get to tha chopper!
	PrecacheModel( "models/apache.mdl" );
	PrecacheScriptSound( "Apache.Rotor" );
	m_nDebrisModel = PrecacheModel(   "models/metalplategibs_green.mdl" );

	// Gun
	PrecacheScriptSound( "Apache.FireGun" );
	m_iAmmoType = GetAmmoDef()->Index("9mmRound"); 

	// Rockets
	UTIL_PrecacheOther( "grenade_homer" );
	PrecacheScriptSound( "Apache.RPG" );
	PrecacheModel( "models/weapons/w_missile.mdl" );

	BaseClass::Precache();
}

void CNPC_Apache::InitializeRotorSound( void )
{
	CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();

	CPASAttenuationFilter filter( this );
	m_pRotorSound	= controller.SoundCreate( filter, entindex(), "Apache.Rotor" );

	BaseClass::InitializeRotorSound();
}

void CNPC_Apache::Flight( void )
{
	StudioFrameAdvance( );

	float flDistToDesiredPosition = (GetAbsOrigin() - m_vecDesiredPosition).Length();
	// NDebugOverlay::Line(GetAbsOrigin(), m_vecDesiredPosition, 0,0,255, true, 0.1);

	if (m_flGoalSpeed < 800 )
		m_flGoalSpeed += GetAcceleration();


//	Vector vecGoalOrientation;
	if (flDistToDesiredPosition > 250) // 500
	{
		Vector v1 = (m_vecTargetPosition - GetAbsOrigin());
		Vector v2 = (m_vecDesiredPosition - GetAbsOrigin());

		VectorNormalize( v1 );
		VectorNormalize( v2 );

		if (m_flLastSeen + 90 > gpGlobals->curtime && DotProduct( v1, v2 ) > 0.25)
		{
			m_vecGoalOrientation = ( m_vecTargetPosition - GetAbsOrigin());
		}
		else
		{
			m_vecGoalOrientation = (m_vecDesiredPosition - GetAbsOrigin());
		}
		VectorNormalize( m_vecGoalOrientation );
	}
	else
	{
		AngleVectors( GetGoalEnt()->GetAbsAngles(), &m_vecGoalOrientation );
	}
//	SetGoalOrientation( vecGoalOrientation );
	

	if (GetGoalEnt())
	{
		// ALERT( at_console, "%.0f\n", flLength );
		if ( HasReachedTarget() )
		{
			// If we get this close to the desired position, it's assumed that we've reached
			// the desired position, so move on.

			// Fire target that I've reached my goal
			m_AtTarget.FireOutput( GetGoalEnt(), this );

			OnReachedTarget( GetGoalEnt() );

			SetGoalEnt( gEntList.FindEntityByName( NULL, GetGoalEnt()->m_target ) );

			if (GetGoalEnt())
			{
				m_vecDesiredPosition = GetGoalEnt()->GetAbsOrigin();
				
//				Vector vecGoalOrientation;
				AngleVectors( GetGoalEnt()->GetAbsAngles(), &m_vecGoalOrientation );

//				SetGoalOrientation( vecGoalOrientation );

				flDistToDesiredPosition = (GetAbsOrigin() - m_vecDesiredPosition).Length();
			}
		}
	}
	else
	{
		// If we can't find a new target, just stay where we are.
		m_vecDesiredPosition = GetAbsOrigin();
	}

	// tilt model 5 degrees
	QAngle angAdj = QAngle( 5.0, 0, 0 );

	// estimate where I'll be facing in one seconds
	Vector forward, right, up;
	AngleVectors( GetAbsAngles() + GetLocalAngularVelocity() * 2 + angAdj, &forward, &right, &up );
	// Vector vecEst1 = GetAbsOrigin() + pev->velocity + gpGlobals->v_up * m_flForce - Vector( 0, 0, 384 );
	// float flSide = DotProduct( m_posDesired - vecEst1, gpGlobals->v_right );
	

	QAngle angVel = GetLocalAngularVelocity();
	float flSide = DotProduct( m_vecGoalOrientation, right );

	if (flSide < 0)
	{
		if ( angVel.y < 60)
		{
			 angVel.y += 8; // 9 * (3.0/2.0);
		}
	}
	else
	{
		if ( angVel.y > -60)
		{
			 angVel.y -= 8; // 9 * (3.0/2.0);
		}
	}
	angVel.y *= 0.98;
	SetLocalAngularVelocity( angVel );

	Vector vecVel = GetAbsVelocity();

	// estimate where I'll be in two seconds
	AngleVectors( GetAbsAngles() + GetLocalAngularVelocity() * 1 + angAdj, &forward, &right, &up );
	Vector vecEst = GetAbsOrigin() + vecVel * 2.0 + up * m_flForce * 20 - Vector( 0, 0, 384 * 2 );

	// add immediate force
	AngleVectors( GetAbsAngles() + angAdj, &forward, &right, &up );

	vecVel.x += up.x * m_flForce;
	vecVel.y += up.y * m_flForce;
	vecVel.z += up.z * m_flForce;
	// add gravity
	vecVel.z -= 38.4; // 32ft/sec

	float flSpeed = vecVel.Length();
	float flDir = DotProduct( Vector( forward.x, forward.y, 0 ), Vector( vecVel.x, vecVel.y, 0 ) );
	if (flDir < 0)
		flSpeed = -flSpeed;

	float flDist = DotProduct( m_vecDesiredPosition - vecEst, forward );

	// float flSlip = DotProduct( pev->velocity, gpGlobals->v_right );
	float flSlip = -DotProduct( m_vecDesiredPosition - vecEst, right );

	angVel = GetLocalAngularVelocity();
	// fly sideways
	if (flSlip > 0)
	{
		if (GetAbsAngles().z > -30 && angVel.z > -15)
			angVel.z -= 4;
		else
			angVel.z += 2;
	}
	else
	{

		if (GetAbsAngles().z < 30 && angVel.z < 15)
			angVel.z += 4;
		else
			angVel.z -= 2;
	}
	SetLocalAngularVelocity( angVel );

	// sideways drag
	vecVel.x = vecVel.x * (1.0 - fabs( right.x ) * 0.05);
    vecVel.y = vecVel.y * (1.0 - fabs( right.y ) * 0.05);
	vecVel.z = vecVel.z * (1.0 - fabs( right.z ) * 0.05);

	// general drag
	vecVel = vecVel * 0.995;

	// Set final computed velocity
	SetAbsVelocity( vecVel );
	
	// apply power to stay correct height
	if (m_flForce < 80 && vecEst.z < m_vecDesiredPosition.z) 
	{
		m_flForce += 12;
	}
	else if (m_flForce > 30)
	{
		if (vecEst.z > m_vecDesiredPosition.z) 
			m_flForce -= 8;
	}


	angVel = GetLocalAngularVelocity();
	// pitch forward or back to get to target
	if (flDist > 0 && flSpeed < m_flGoalSpeed && GetAbsAngles().x + angVel.x < 40)
	{
		// ALERT( at_console, "F " );
		// lean forward
		angVel.x += 12.0;
	}
	else if (flDist < 0 && flSpeed > -50 && GetAbsAngles().x + angVel.x  > -20)
	{
		// ALERT( at_console, "B " );
		// lean backward
		angVel.x -= 12.0;
	}
	else if (GetAbsAngles().x + angVel.x < 0)
	{
		// ALERT( at_console, "f " );
		angVel.x += 4.0;
	}
	else if (GetAbsAngles().x + angVel.x > 0)
	{
		// ALERT( at_console, "b " );
		angVel.x -= 4.0;
	}

	// Set final computed angular velocity
	SetLocalAngularVelocity( angVel );

	// ALERT( at_console, "%.0f %.0f : %.0f %.0f : %.0f %.0f : %.0f\n", GetAbsOrigin().x, pev->velocity.x, flDist, flSpeed, GetAbsAngles().x, pev->avelocity.x, m_flForce ); 
	// ALERT( at_console, "%.0f %.0f : %.0f %0.f : %.0f\n", GetAbsOrigin().z, pev->velocity.z, vecEst.z, m_posDesired.z, m_flForce ); 
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------

#define CHOPPER_AP_GUN_TIP			0
#define CHOPPER_AP_GUN_BASE			1

#define CHOPPER_BC_GUN_YAW			0
#define CHOPPER_BC_GUN_PITCH		1
#define CHOPPER_BC_POD_PITCH		2

bool CNPC_Apache::FireGun( )
{
	if ( !GetEnemy() )
		return false;

	Vector vForward, vRight, vUp;

	AngleVectors( GetAbsAngles(), &vForward, &vUp, &vRight );
		
	Vector posGun;
	QAngle angGun;
	GetAttachment( 1, posGun, angGun );

	Vector vecTarget = (m_vecTargetPosition - posGun);

	VectorNormalize( vecTarget );

	Vector vecOut;

	vecOut.x = DotProduct( vForward, vecTarget );
	vecOut.y = -DotProduct( vUp, vecTarget );
	vecOut.z = DotProduct( vRight, vecTarget );

	QAngle angles;

	VectorAngles( vecOut, angles );
	
	angles.y = AngleNormalize(angles.y);
	angles.x = AngleNormalize(angles.x);	

	if (angles.x > m_angGun.x)
		m_angGun.x = MIN( angles.x, m_angGun.x + 12 );
	if (angles.x < m_angGun.x)
		m_angGun.x = MAX( angles.x, m_angGun.x - 12 );
	if (angles.y > m_angGun.y)
		m_angGun.y = MIN( angles.y, m_angGun.y + 12 );
	if (angles.y < m_angGun.y)
		m_angGun.y = MAX( angles.y, m_angGun.y - 12 );

	// hacks - shouldn't be hardcoded, oh well.
	// limit it so it doesn't pop if you try to set it to the max value
	m_angGun.y = clamp( m_angGun.y, -89.9, 89.9 );
	m_angGun.x = clamp( m_angGun.x, -9.9, 44.9 );

	m_angGun.y = SetBoneController( 0, m_angGun.y );
	m_angGun.x = SetBoneController( 1, m_angGun.x );

	Vector posBarrel;
	QAngle angBarrel;
	GetAttachment( 0, posBarrel, angBarrel );

	Vector forward;
	AngleVectors( angBarrel + m_angGun, &forward );

	Vector2D vec2LOS = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ).AsVector2D();
	vec2LOS.NormalizeInPlace();

	float flDot = vec2LOS.Dot( forward.AsVector2D() );

	//forward
//	NDebugOverlay::Line(  GetAbsOrigin(), GetAbsOrigin() + ( forward * 200 ), 255,0,0, false, 0.1);
	//LOS
//	NDebugOverlay::Line( posGun, m_vecTargetPosition , 0,0,255, false, 0.1);
//	NDebugOverlay::Box( GetAbsOrigin(), s_vecSurroundingMins, s_vecSurroundingMaxs, 0, 255,0, false, 0.1);

	if ( flDot > 0.98 )
	{
		CPASAttenuationFilter filter( this, 0.2f );

		EmitSound( filter, entindex(), "Apache.FireGun" );//<<TEMP>>temp sound

		// gun is a bit dodgy, just fire at the target if we are close
		FireBullets( 1, posGun, vecTarget, VECTOR_CONE_4DEGREES, 8192, m_iAmmoType, 2 );

		return true;
	}

	return false;
}

void CNPC_Apache::FireRocket( void )
{
	static float side = 1.0;
	static int count;
	Vector vForward, vRight, vUp;


	AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
	Vector vecSrc = GetAbsOrigin() + 1.5 * ( vForward * 21 + vRight * 70 * side + vUp * -79 );

	// pick firing pod to launch from
	switch( m_iRockets % 5)
	{
	case 0:	vecSrc = vecSrc + vRight * 10; break;
	case 1: vecSrc = vecSrc - vRight * 10; break;
	case 2: vecSrc = vecSrc + vUp * 10; break;
	case 3: vecSrc = vecSrc - vUp * 10; break;
	case 4: break;
	}

	Vector vTargetDir = m_vecTargetPosition - GetAbsOrigin();
	VectorNormalize ( vTargetDir );
	LaunchRocket( vTargetDir, 100, 150, vecSrc);

	m_iRockets--;

	side = - side;
}
void CNPC_Apache::AimRocketGun( void )
{
	Vector vForward, vRight, vUp;
	
	if (m_iRockets <= 0)
		return;
	
	Vector vTargetDir = m_vecTargetPosition - GetAbsOrigin();
	VectorNormalize ( vTargetDir );

	AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
	Vector vecEst = ( vForward * 800 + GetAbsVelocity());
	VectorNormalize ( vecEst );

	trace_t tr1;
	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecEst * 4096, MASK_ALL, this, COLLISION_GROUP_NONE, &tr1);

//	NDebugOverlay::Line(GetAbsOrigin(), tr1.endpos, 255,255,0, false, 0.1);

	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vTargetDir * 4096, MASK_ALL, this, COLLISION_GROUP_NONE, &tr1);

//	NDebugOverlay::Line(GetAbsOrigin(), tr1.endpos, 0,255,0, false, 0.1);

	// ALERT( at_console, "%d %d %d %4.2f\n", GetAbsAngles().x < 0, DotProduct( pev->velocity, gpGlobals->v_forward ) > -100, m_flNextRocket < gpGlobals->curtime, DotProduct( m_vecTarget, vecEst ) );

	if ((m_iRockets % 2) == 1)
	{
		FireRocket( );
		m_flNextRocket = gpGlobals->curtime + 0.5;
		if (m_iRockets <= 0)
		{
			m_flNextRocket = gpGlobals->curtime + 10;
			m_iRockets = 10;
		}
	}
	else if (DotProduct( GetAbsVelocity(), vForward ) > -100 && m_flNextRocket < gpGlobals->curtime)
	{
		if (m_flLastSeen + 60 > gpGlobals->curtime)
		{
			if (GetEnemy() != NULL)
			{
				// make sure it's a good shot
				//if (DotProduct( vTargetDir, vecEst) > 0.5)
				{
					trace_t tr;
					
					UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecEst * 4096, MASK_ALL, this, COLLISION_GROUP_NONE, &tr);

			//		NDebugOverlay::Line(GetAbsOrigin(), tr.endpos, 255,0,255, false, 5);

//					if ((tr.endpos - m_vecTargetPosition).Length() < 512)
					if ((tr.endpos - m_vecTargetPosition).Length() < 1024)
						FireRocket( );
				}
			}
			else
			{
				trace_t tr;
				
				UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecEst * 4096, MASK_ALL, this, COLLISION_GROUP_NONE, &tr);
				// just fire when close
				if ((tr.endpos - m_vecTargetPosition).Length() < 512)
					FireRocket( );
			}
		}
	}
}

#define MISSILE_HOMING_STRENGTH		0.3
#define MISSILE_HOMING_DELAY		5.0
#define MISSILE_HOMING_RAMP_UP		0.5
#define MISSILE_HOMING_DURATION		1.0
#define MISSILE_HOMING_RAMP_DOWN	0.5

void CNPC_Apache::LaunchRocket( Vector &viewDir, int damage, int radius, Vector vecLaunchPoint )
{

	CGrenadeHomer *pGrenade = CGrenadeHomer::CreateGrenadeHomer( 
		MAKE_STRING("models/weapons/w_missile.mdl"), 
		MAKE_STRING( "Apache.RPG" ), 
		vecLaunchPoint, vec3_angle, edict() );
	pGrenade->Spawn( );
	pGrenade->SetHoming(MISSILE_HOMING_STRENGTH, MISSILE_HOMING_DELAY,
						MISSILE_HOMING_RAMP_UP,	MISSILE_HOMING_DURATION,
						MISSILE_HOMING_RAMP_DOWN);
	pGrenade->SetDamage( damage );
	pGrenade->m_DmgRadius = radius;

	pGrenade->Launch( this, GetEnemy(), viewDir * 1500, 500, 0, HOMER_SMOKE_TRAIL_ON );

}


//-----------------------------------------------------------------------------
// Purpose:	Lame, temporary death
//-----------------------------------------------------------------------------
void CNPC_Apache::DyingThink( void )
{
	StudioFrameAdvance( );
	SetNextThink( gpGlobals->curtime + 0.1f );

	if( gpGlobals->curtime > m_flNextCrashExplosion )
	{
		CPASFilter pasFilter( GetAbsOrigin() );
		Vector pos;

		pos = GetAbsOrigin();
		pos.x += random->RandomFloat( -150, 150 );
		pos.y += random->RandomFloat( -150, 150 );
		pos.z += random->RandomFloat( -150, -50 );

		te->Explosion( pasFilter, 0.0,	&pos, g_sModelIndexFireball, 10, 15, TE_EXPLFLAG_NONE, 100, 0 );
		
		Vector vecSize = Vector( 500, 500, 60 );
		CPVSFilter pvsFilter( GetAbsOrigin() );

		te->BreakModel( pvsFilter, 0.0, GetAbsOrigin(), vec3_angle, vecSize, vec3_origin, 
			m_nDebrisModel, 100, 0, 2.5, BREAK_METAL );

		m_flNextCrashExplosion = gpGlobals->curtime + random->RandomFloat( 0.3, 0.5 );
	}

	QAngle angVel = GetLocalAngularVelocity();
	if( angVel.y < 400 )
	{
		angVel.y *= 1.1;
		SetLocalAngularVelocity( angVel );
	}

	Vector vecImpulse( 0, 0, -38.4 );	// gravity - 32ft/sec
	ApplyAbsVelocityImpulse( vecImpulse );

	if( m_hSmoke )
	{
		m_hSmoke->SetLifetime(0.1f);
		m_hSmoke = NULL;
	}

}



void CNPC_Apache::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
{

	CTakeDamageInfo dmgInfo = info;

	// HITGROUPS don't work currently.
	// ignore blades
	//if (ptr->hitgroup == 6 && (info.GetDamageType() & (DMG_ENERGYBEAM|DMG_BULLET|DMG_CLUB)))
	//		return;

	// hit hard, hits cockpit
	if (info.GetDamage() > 50 || ptr->hitgroup == 1 || ptr->hitgroup == 2 || ptr->hitgroup == 3 )
	{
		// ALERT( at_console, "%map .0f\n", flDamage );
		AddMultiDamage( dmgInfo, this );

		if ( info.GetDamage() > 50 )
		{
			if ( m_hSmoke == NULL && (m_hSmoke = SmokeTrail::CreateSmokeTrail()) != NULL )
			{
				m_hSmoke->m_Opacity = 1.0f;
				m_hSmoke->m_SpawnRate = 60;
				m_hSmoke->m_ParticleLifetime = 1.3f;
				m_hSmoke->m_StartColor.Init( 0.65f, 0.65f , 0.65f );
				m_hSmoke->m_EndColor.Init( 0.65f, 0.65f, 0.65f );
				m_hSmoke->m_StartSize = 12;
				m_hSmoke->m_EndSize = 64;
				m_hSmoke->m_SpawnRadius = 8;
				m_hSmoke->m_MinSpeed = 2;
				m_hSmoke->m_MaxSpeed = 24;				

				m_hSmoke->SetLifetime( 1e6 );
				m_hSmoke->FollowEntity( this );

			}
		}
	}
	else
	{
		// do half damage in the body
		dmgInfo.ScaleDamage(0.5);
		AddMultiDamage( dmgInfo, this );
		g_pEffects->Ricochet( ptr->endpos, ptr->plane.normal );
	}

	if ( m_iHealth < 10 )
	{
		if ( m_hSmoke == NULL && (m_hSmoke = SmokeTrail::CreateSmokeTrail()) != NULL )
		{
			m_hSmoke->m_Opacity = 1.0f;
			m_hSmoke->m_SpawnRate = 60;
			m_hSmoke->m_ParticleLifetime = 1.3f;
			m_hSmoke->m_StartColor.Init( 0.65f, 0.65f , 0.65f );
			m_hSmoke->m_EndColor.Init( 0.65f, 0.65f, 0.65f );
			m_hSmoke->m_StartSize = 12;
			m_hSmoke->m_EndSize = 64;
			m_hSmoke->m_SpawnRadius = 8;
			m_hSmoke->m_MinSpeed = 2;
			m_hSmoke->m_MaxSpeed = 24;				

			m_hSmoke->SetLifetime( 1e6 );
			m_hSmoke->FollowEntity( this );

		}
	}
}