//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Grenade used by the city scanner
//
// $NoKeywords: $
//=============================================================================//

#include "cbase.h"
#include "grenade_homer.h"
#include "weapon_ar2.h"
#include "soundent.h"
#include "decals.h"
#include "shake.h"
#include "smoke_trail.h"
#include "ar2_explosion.h"
#include "mathlib/mathlib.h" 
#include "game.h"			
#include "ndebugoverlay.h"
#include "hl2_shareddefs.h"
#include "vstdlib/random.h"
#include "engine/IEngineSound.h"
#include "movevars_shared.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

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

extern short	g_sModelIndexFireball;			// (in combatweapon.cpp) holds the index for the smoke cloud

ConVar    sk_dmg_homer_grenade( "sk_dmg_homer_grenade","0" );
ConVar	  sk_homer_grenade_radius( "sk_homer_grenade_radius","0" );

BEGIN_DATADESC( CGrenadeHomer )

	DEFINE_ARRAY( m_hRocketTrail,					FIELD_EHANDLE, 3 ),
	DEFINE_FIELD( m_sFlySound,					FIELD_STRING),
	DEFINE_FIELD( m_flNextFlySoundTime,			FIELD_TIME),

	DEFINE_FIELD( m_flHomingStrength,				FIELD_FLOAT),
	DEFINE_FIELD( m_flHomingDelay,				FIELD_FLOAT),
	DEFINE_FIELD( m_flHomingRampUp,				FIELD_FLOAT),
	DEFINE_FIELD( m_flHomingDuration,				FIELD_FLOAT),
	DEFINE_FIELD( m_flHomingRampDown,				FIELD_FLOAT),
	DEFINE_FIELD( m_flHomingSpeed,				FIELD_FLOAT),
	DEFINE_FIELD( m_flSpinMagnitude,				FIELD_FLOAT),
	DEFINE_FIELD( m_flSpinSpeed,					FIELD_FLOAT),
	DEFINE_FIELD( m_nRocketTrailType,				FIELD_INTEGER),

//	DEFINE_FIELD( m_spriteTexture,				FIELD_INTEGER),

	DEFINE_FIELD( m_flHomingLaunchTime,			FIELD_TIME),
	DEFINE_FIELD( m_flHomingStartTime,			FIELD_TIME ),
	DEFINE_FIELD( m_flHomingEndTime,				FIELD_TIME ),
	DEFINE_FIELD( m_flSpinOffset,					FIELD_FLOAT),
	
	DEFINE_FIELD( m_hTarget,						FIELD_EHANDLE),

	// Function pointers
	DEFINE_THINKFUNC( AimThink ),
	DEFINE_ENTITYFUNC( GrenadeHomerTouch ),

END_DATADESC()

LINK_ENTITY_TO_CLASS( grenade_homer, CGrenadeHomer );


///------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
CGrenadeHomer* CGrenadeHomer::CreateGrenadeHomer( string_t sModelName, string_t sFlySound, const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner )
{
	CGrenadeHomer *pGrenade = (CGrenadeHomer*)CreateEntityByName( "grenade_homer" );
	if ( !pGrenade )
	{
		Warning( "NULL Ent in Create!\n" );
		return NULL;
	}

	if ( pGrenade->edict() )
	{
		pGrenade->m_sFlySound	= sFlySound;
		pGrenade->SetOwnerEntity( Instance( pentOwner ) );
		pGrenade->SetLocalOrigin( vecOrigin );
		pGrenade->SetLocalAngles( vecAngles );
		pGrenade->SetModel( STRING(sModelName) );
	}
	return pGrenade;
}


void CGrenadeHomer::Precache( void )
{
	m_spriteTexture = PrecacheModel( "sprites/lgtning.vmt" );

	PrecacheScriptSound( "GrenadeHomer.StopSounds" );
	if ( NULL_STRING != m_sFlySound )
	{
		PrecacheScriptSound( STRING(m_sFlySound) );
	}

}


//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenadeHomer::Spawn( void )
{
	Precache( );

	SetSolid( SOLID_BBOX );
	SetMoveType( MOVETYPE_FLY );

	UTIL_SetSize(this, Vector(0, 0, 0), Vector(0, 0, 0));

	m_flDamage		= sk_dmg_homer_grenade.GetFloat();
	m_DmgRadius		= sk_homer_grenade_radius.GetFloat();
	m_takedamage	= DAMAGE_YES;
	m_iHealth		= 1;

	SetGravity( 1.0 );
	SetFriction( 0.8 );
	SetSequence( 1 );

	m_flHomingStrength	= 0;
	m_flHomingDelay		= 0;
	m_flHomingDuration	= 0;

	SetCollisionGroup( HL2COLLISION_GROUP_HOMING_MISSILE ); 
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenadeHomer::SetSpin(float flSpinMagnitude, float flSpinSpeed)
{
	m_flSpinMagnitude	= flSpinMagnitude;
	m_flSpinSpeed		= flSpinSpeed;
	m_flSpinOffset		= random->RandomInt((int)-m_flSpinSpeed, (int)m_flSpinSpeed);
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenadeHomer::SetHoming(float flStrength, float flDelay, float flRampUp, float flDuration, float flRampDown)
{
	m_flHomingStrength	= flStrength;
	m_flHomingDelay		= flDelay;
	m_flHomingRampUp	= flRampUp;
	m_flHomingDuration	= flDuration;
	m_flHomingRampDown	= flRampDown;
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenadeHomer::StartRocketTrail(void)
{
	RocketTrail *pRocketTrail =  RocketTrail::CreateRocketTrail();
	if(pRocketTrail)
	{
		pRocketTrail->m_SpawnRate = 80;
		pRocketTrail->m_ParticleLifetime = 2;
		if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN )
		{
			pRocketTrail->m_StartColor.Init(0.5, 0.0, 0.5);
		}
		else
		{
			pRocketTrail->m_StartColor.Init(0.75, 0.75, 0.75);
		}
		pRocketTrail->m_Opacity = 0.35f;
		pRocketTrail->m_EndColor.Init(0.4,0.4,0.4);
		pRocketTrail->m_StartSize = 8;
		pRocketTrail->m_EndSize = 16;
		pRocketTrail->m_SpawnRadius = 3;
		pRocketTrail->m_MinSpeed = 2;
		pRocketTrail->m_MaxSpeed = 10;
		pRocketTrail->SetLifetime(120);
		pRocketTrail->FollowEntity(this);

		m_hRocketTrail[0] = pRocketTrail;
	}
	/*
	pRocketTrail = RocketTrail::CreateRocketTrail();
	if(pRocketTrail)
	{
		pRocketTrail->m_SpawnRate = 100;
		pRocketTrail->m_ParticleLifetime = HOMER_TRAIL1_LIFE;
		if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN )
		{
			pRocketTrail->m_StartColor.Init(0.0, 0.0, 0.5);
		}
		else
		{
			pRocketTrail->m_StartColor.Init(0.5, 0.5, 0.0);
		}
		pRocketTrail->m_EndColor.Init(0.5,0.5,0.5);
		pRocketTrail->m_StartSize = 3;
		pRocketTrail->m_EndSize = 6;
		pRocketTrail->m_SpawnRadius = 1;
		pRocketTrail->m_MinSpeed = 15;
		pRocketTrail->m_MaxSpeed = 25;
		pRocketTrail->SetLifetime(120);
		pRocketTrail->FollowEntity(this);

		m_hRocketTrail[1] = pRocketTrail;
	}
	pRocketTrail = RocketTrail::CreateRocketTrail();
	if(pRocketTrail)
	{
		pRocketTrail->m_SpawnRate = 50;
		pRocketTrail->m_ParticleLifetime = HOMER_TRAIL2_LIFE;
		if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN )
		{
			pRocketTrail->m_StartColor.Init(0.1, 0.0, 0.1);
		}
		else
		{
			pRocketTrail->m_StartColor.Init(0.1, 0.1, 0.1);
		}
		pRocketTrail->m_EndColor.Init(0.5,0.5,0.5);
		pRocketTrail->m_StartSize = 8;
		pRocketTrail->m_EndSize = 20;
		pRocketTrail->m_SpawnRadius = 1;
		pRocketTrail->m_MinSpeed = 15;
		pRocketTrail->m_MaxSpeed = 25;
		pRocketTrail->SetLifetime(120);
		pRocketTrail->FollowEntity(this);

		m_hRocketTrail[2] = pRocketTrail;
	}
	*/
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenadeHomer::UpdateRocketTrail(float fScale)
{
	if (m_hRocketTrail[0] == NULL)
	{
		StartRocketTrail();
	}

	if (m_hRocketTrail[0]) 
	{
		m_hRocketTrail[0]->m_ParticleLifetime = fScale*HOMER_TRAIL0_LIFE;
	}
	if (m_hRocketTrail[1])
	{
		m_hRocketTrail[1]->m_ParticleLifetime = fScale*HOMER_TRAIL1_LIFE;
	}

	if (m_hRocketTrail[2]) 
	{
		m_hRocketTrail[2]->m_ParticleLifetime = fScale*HOMER_TRAIL2_LIFE;
	}
}

void CGrenadeHomer::StopRocketTrail()
{
	// Stop emitting smoke
	for (int i=0;i<3;i++)
	{
		if(m_hRocketTrail[i])
		{
			m_hRocketTrail[i]->SetEmit(false);
			UTIL_Remove( m_hRocketTrail[i] );
			m_hRocketTrail[i] = NULL;
		}
	}	
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenadeHomer::Launch( CBaseEntity*		pOwner, 
							CBaseEntity*		pTarget, 
							const Vector&		vInitVelocity,
							float				flHomingSpeed,
							float				flGravity,
							int					nRocketTrailType)
{
	SetOwnerEntity( pOwner );
	m_hTarget					= pTarget;
	SetAbsVelocity( vInitVelocity );
	m_flHomingSpeed				= flHomingSpeed;
	SetGravity( flGravity );
	m_nRocketTrailType			= nRocketTrailType;

	// ----------------------------
	// Initialize homing parameters
	// ----------------------------
	m_flHomingLaunchTime	= gpGlobals->curtime;

	// -------------
	// Smoke trail.
	// -------------
	if ( (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ON) || (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN) )
	{
		StartRocketTrail();
	}

	SetUse( &CGrenadeHomer::DetonateUse );
	SetTouch( &CGrenadeHomer::GrenadeHomerTouch );
	SetThink( &CGrenadeHomer::AimThink );
	AimThink();
	SetNextThink( gpGlobals->curtime );

	// Issue danger!
	if ( pTarget )
	{
		// Figure out how long it'll take for me to reach the target.
		float flDist = ( pTarget->WorldSpaceCenter() - WorldSpaceCenter() ).Length();
		float flTime = max( 0.5, flDist / GetAbsVelocity().Length() );

		CSoundEnt::InsertSound ( SOUND_DANGER, m_hTarget->GetAbsOrigin(), 300, flTime, pOwner );
	}
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenadeHomer::Event_Killed( const CTakeDamageInfo &info )
{
	Detonate( );
}

void CGrenadeHomer::GrenadeHomerTouch( CBaseEntity *pOther )
{
	Assert( pOther );

	// Don't take damage from other homing grenades so can shoot in vollies
	if (FClassnameIs( pOther, "grenade_homer") || !pOther->IsSolid() )
	{
		return;
	}

	// ----------------------------------
	// If I hit the sky, don't explode
	// ----------------------------------
	trace_t tr;
	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity(),  MASK_SOLID_BRUSHONLY, 
		this, COLLISION_GROUP_NONE, &tr);

	if (tr.surface.flags & SURF_SKY)
	{
		StopRocketTrail();
		UTIL_Remove( this );
	}
	else
	{
		Detonate();
	}
}

void CGrenadeHomer::Detonate(void)
{
	StopRocketTrail();

	StopSound(entindex(), CHAN_BODY, STRING(m_sFlySound));

	m_takedamage	= DAMAGE_NO;	

	CPASFilter filter( GetAbsOrigin() );

	te->Explosion( filter, 0.0,
		&GetAbsOrigin(), 
		g_sModelIndexFireball,
		2.0, 
		15,
		TE_EXPLFLAG_NONE,
		m_DmgRadius,
		m_flDamage );

//	int magnitude = 1.0;
//	int	colorRamp = random->RandomInt( 128, 255 );


	if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN )
	{
		// Add a shockring
		CBroadcastRecipientFilter filter3;
		te->BeamRingPoint( filter3, 0, 
			GetAbsOrigin(),	//origin
			16,			//start radius
			1000,		//end radius
			m_spriteTexture, //texture
			0,			//halo index
			0,			//start frame
			2,			//framerate
			0.3f,		//life
			128,		//width
			16,			//spread
			0,			//amplitude
			100,		//r
			0,			//g
			200,		//b
			50,			//a
			128			//speed
			);


		// Add a shockring
		CBroadcastRecipientFilter filter4;
		te->BeamRingPoint( filter4, 0, 
			GetAbsOrigin(),	//origin
			16,			//start radius
			500,		//end radius
			m_spriteTexture, //texture
			0,			//halo index
			0,			//start frame
			2,			//framerate
			0.3f,		//life
			128,		//width
			16,			//spread
			0,			//amplitude
			200,		//r
			0,			//g
			100,		//b
			50,			//a
			128			//speed
			);



	}


	Vector vecForward = GetAbsVelocity();
	VectorNormalize(vecForward);
	trace_t		tr;
	UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward,  MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, & tr);

	UTIL_DecalTrace( &tr, "Scorch" );

	UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START );

	RadiusDamage ( CTakeDamageInfo( this, GetOwnerEntity(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL );
	CPASAttenuationFilter filter2( this, "GrenadeHomer.StopSounds" );
	EmitSound( filter2, entindex(), "GrenadeHomer.StopSounds" );
	UTIL_Remove( this );
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CGrenadeHomer::PlayFlySound(void)
{
	if (gpGlobals->curtime > m_flNextFlySoundTime)
	{
		CPASAttenuationFilter filter( this, 0.8 );

		EmitSound_t ep;
		ep.m_nChannel = CHAN_BODY;
		ep.m_pSoundName = STRING(m_sFlySound);
		ep.m_flVolume = 1.0f;
		ep.m_SoundLevel = SNDLVL_NORM;
		ep.m_nPitch = 100;

		EmitSound( filter, entindex(), ep );

		m_flNextFlySoundTime	= gpGlobals->curtime + 1.0;
	}
}

//------------------------------------------------------------------------------
// Purpose : Move toward targetmap 
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenadeHomer::AimThink( void )
{ 
	// Blow up the missile if we have an explicit detonate time that
	// has been reached
	if (m_flDetonateTime != 0 &&
		gpGlobals->curtime > m_flDetonateTime)
	{
		Detonate();
		return;
	}

	PlayFlySound();

	Vector		vTargetPos	= vec3_origin;
	Vector		vTargetDir;
	float		flCurHomingStrength = 0;

	// ------------------------------------------------
	//  If I'm homing
	// ------------------------------------------------
	if (m_hTarget != NULL)
	{
		vTargetPos		= m_hTarget->EyePosition();
		vTargetDir		= vTargetPos - GetAbsOrigin();
		VectorNormalize(vTargetDir);

		// --------------------------------------------------
		//  If my target is far away do some primitive
		//  obstacle avoidance
		// --------------------------------------------------
		if ((vTargetPos - GetAbsOrigin()).Length() > 200)
		{
			Vector  vTravelDir	= GetAbsVelocity();
			VectorNormalize(vTravelDir);
			vTravelDir *= 50;

			trace_t tr;
			UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vTravelDir, MASK_SHOT, m_hTarget, COLLISION_GROUP_NONE, &tr );
			if (tr.fraction != 1.0)
			{
				// Head off in normal 
				float dotPr			=  DotProduct(vTravelDir,tr.plane.normal);
				Vector vBounce		=  -dotPr * tr.plane.normal;
				vBounce.z			=  0;
				VectorNormalize(vBounce);
				vTargetDir			+= vBounce;
				VectorNormalize(vTargetDir);
				// DEBUG TOOL
				//NDebugOverlay::Line(GetOrigin(), GetOrigin()+vTravelDir, 255,0,0, true, 20);
				//NDebugOverlay::Line(GetOrigin(), GetOrigin()+(12*tr.plane.normal), 0,0,255, true, 20);
				//NDebugOverlay::Line(GetOrigin(), GetOrigin()+(vTargetDir), 0,255,0, true, 20);
			}
		}

		float	flTargetSpeed					= GetAbsVelocity().Length();
		float	flHomingRampUpStartTime			= m_flHomingLaunchTime		+ m_flHomingDelay;
		float	flHomingSustainStartTime		= flHomingRampUpStartTime	+ m_flHomingRampUp;
		float	flHomingRampDownStartTime		= flHomingSustainStartTime	+ m_flHomingDuration;
		float	flHomingEndHomingTime			= flHomingRampDownStartTime + m_flHomingRampDown;
		// ---------
		// Delay
		// ---------
		if		(gpGlobals->curtime < flHomingRampUpStartTime)
		{
			flCurHomingStrength = 0;
			flTargetSpeed		= 0;
		}
		// ----------
		//  Ramp Up
		// ----------
		else if (gpGlobals->curtime < flHomingSustainStartTime)
		{
			float flAge			= gpGlobals->curtime - flHomingRampUpStartTime;
			flCurHomingStrength = m_flHomingStrength * (flAge/m_flHomingRampUp);
			flTargetSpeed		= flCurHomingStrength * m_flHomingSpeed;
		}
		// ----------
		//  Sustain
		// ----------
		else if (gpGlobals->curtime < flHomingRampDownStartTime)
		{
			flCurHomingStrength = m_flHomingStrength;
			flTargetSpeed		= m_flHomingSpeed;
		}
		// -----------
		//  Ramp Down
		// -----------
		else if (gpGlobals->curtime < flHomingEndHomingTime)
		{
			float flAge			= gpGlobals->curtime - flHomingRampDownStartTime;
			flCurHomingStrength = m_flHomingStrength * (1-(flAge/m_flHomingRampDown));
			flTargetSpeed		= m_flHomingSpeed;
		}
		// ---------------
		//  Set Homing
		// ---------------
		if (flCurHomingStrength > 0)
		{	
			// -------------
			// Smoke trail.
			// -------------
			if (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ON_HOMING)
			{
				UpdateRocketTrail(flCurHomingStrength);
			}

			// Extract speed and direction
			Vector	vCurDir		= GetAbsVelocity();
			float flCurSpeed = VectorNormalize(vCurDir);
			flTargetSpeed = max(flTargetSpeed, flCurSpeed);

			// Add in homing direction
			Vector vecNewVelocity = GetAbsVelocity();
			float flTimeToUse = gpGlobals->frametime;
			while (flTimeToUse > 0)
			{
				vecNewVelocity = (flCurHomingStrength * vTargetDir) + ((1 - flCurHomingStrength) * vCurDir);
				flTimeToUse =- 0.1;
			}
			VectorNormalize(vecNewVelocity);
			vecNewVelocity *= flTargetSpeed;
			SetAbsVelocity( vecNewVelocity );
		}
	}
	
	// ----------------------------------------------------------------------------------------
	// Add time-coherent noise to the current velocity 
	// ----------------------------------------------------------------------------------------
	Vector vecImpulse( 0, 0, 0 );
	if (m_flSpinMagnitude > 0)
	{
		vecImpulse.x += m_flSpinMagnitude*sin(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset);
		vecImpulse.y += m_flSpinMagnitude*cos(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset);
		vecImpulse.z -= m_flSpinMagnitude*cos(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset);
	}

	// Add in gravity
	vecImpulse.z -= GetGravity() * sv_gravity.GetFloat() * gpGlobals->frametime;
	ApplyAbsVelocityImpulse( vecImpulse );

	QAngle angles;
	VectorAngles( GetAbsVelocity(), angles );
	SetLocalAngles( angles );

#if 0 // BUBBLE
	if( gpGlobals->curtime > m_flNextWarnTime )
	{
		// Make a bubble of warning sound in front of me.
		const float WARN_INTERVAL = 0.25f;
		float flSpeed = GetAbsVelocity().Length();
		Vector vecWarnLocation;

		// warn a little bit ahead of us, please.
		vecWarnLocation = GetAbsOrigin() + GetAbsVelocity() * 0.75;

		// Make a bubble of warning ahead of the missile.
		CSoundEnt::InsertSound ( SOUND_DANGER, vecWarnLocation, flSpeed * WARN_INTERVAL, 0.5 );

#if 0
		Vector vecRight, vecForward;

		AngleVectors( GetAbsAngles(), &vecForward, &vecRight, NULL );

		NDebugOverlay::Line( vecWarnLocation, vecWarnLocation + vecForward * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10);
		NDebugOverlay::Line( vecWarnLocation, vecWarnLocation - vecForward * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10);

		NDebugOverlay::Line( vecWarnLocation, vecWarnLocation + vecRight * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10);
		NDebugOverlay::Line( vecWarnLocation, vecWarnLocation - vecRight * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10);
#endif
		m_flNextWarnTime = gpGlobals->curtime + WARN_INTERVAL;
	}
#endif // BUBBLE

	SetNextThink( gpGlobals->curtime + 0.1f );
}

//------------------------------------------------------------------------------
// Purpose : 
// Input   :
// Output  :
//------------------------------------------------------------------------------
int CGrenadeHomer::OnTakeDamage( const CTakeDamageInfo &info )
{
	// Don't take damage from other homing grenades so can shoot in vollies
	if (FClassnameIs( info.GetInflictor(), "grenade_homer"))
	{
		return 0;
	}
	return BaseClass::OnTakeDamage( info );
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
CGrenadeHomer::CGrenadeHomer(void)
{
	for (int i=0;i<3;i++)
	{
		m_hRocketTrail[i]  = NULL;
	}
}
