mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 14:46:53 +00:00
697 lines
19 KiB
C++
697 lines
19 KiB
C++
|
//========= Copyright 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(-m_flSpinSpeed,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() * GetCurrentGravity() * 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;
|
||
|
}
|
||
|
}
|